Mercurial Hosting > luan
changeset 1335:e0cf0d108a77
major cleanup
line wrap: on
line diff
--- a/conv.txt Tue Feb 12 22:53:57 2019 -0700 +++ b/conv.txt Thu Feb 14 03:10:45 2019 -0700 @@ -1,3 +1,4 @@ +call LuanState LuanLogger
--- a/src/luan/Luan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/Luan.java Thu Feb 14 03:10:45 2019 -0700 @@ -23,7 +23,7 @@ private final List<LuanClosure> stack = new ArrayList<LuanClosure>(); private Map registry; - public boolean isLocked = false; + private boolean isLocked = false; public interface OnClose extends Closeable { public void onClose(Closeable c); @@ -57,6 +57,8 @@ } void push(LuanClosure closure) { + if( isLocked ) + throw new RuntimeException(this+" is locked "+closure); stack.add(closure); } @@ -74,7 +76,7 @@ } public Object eval(String cmd,Object... args) throws LuanException { - return Luan.load(cmd,"eval").call(this,args); + return load(cmd,"eval").call(args); } public Object require(String modName) throws LuanException { @@ -106,7 +108,7 @@ } - public boolean isLessThan(Object o1,Object o2) throws LuanException { + public static boolean isLessThan(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) { Number n1 = (Number)o1; Number n2 = (Number)o2; @@ -119,7 +121,7 @@ } LuanFunction fn = getBinHandler("__lt",o1,o2); if( fn != null ) - return Luan.checkBoolean( Luan.first(fn.call(this,new Object[]{o1,o2})) ); + return Luan.checkBoolean( Luan.first(fn.call(o1,o2)) ); throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); } @@ -181,7 +183,7 @@ public static void doFile(String uri,String... args) throws LuanException { Luan luan = new Luan(); LuanFunction fn = (LuanFunction)BasicLuan.load_file(luan,uri); - fn.call(luan,args); + fn.call((Object[])args); } public static Object first(Object obj) { @@ -276,13 +278,13 @@ throw new LuanException("attempt to call a " + Luan.type(obj) + " value" ); } - public static LuanFunction load(String text,String sourceName,LuanTable env) + public LuanFunction load(String text,String sourceName,LuanTable env) throws LuanException { - return LuanCompiler.compile(text,sourceName,env); + return LuanCompiler.compile(this,text,sourceName,env); } - public static LuanFunction load(String text,String sourceName) + public LuanFunction load(String text,String sourceName) throws LuanException { return load(text,sourceName,null);
--- a/src/luan/LuanCloner.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/LuanCloner.java Thu Feb 14 03:10:45 2019 -0700 @@ -1,7 +1,7 @@ package luan; import java.util.Map; -import java.util.HashMap; +import java.util.Collection; import java.util.IdentityHashMap; @@ -10,6 +10,7 @@ public final Type type; private final Map cloned = new IdentityHashMap(); + private Luan luan = null; public LuanCloner(Type type) { this.type = type; @@ -20,6 +21,11 @@ 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); @@ -42,11 +48,15 @@ } public Map clone(Map obj) { - if( !obj.getClass().equals(HashMap.class) ) - throw new RuntimeException("can only clone HashMap"); Map rtn = (Map)cloned.get(obj); if( rtn == null ) { - rtn = new HashMap(); + 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( get(entry.getKey()), get(entry.getValue()) ); @@ -55,6 +65,23 @@ return rtn; } + public Collection clone(Collection obj) { + 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); @@ -62,6 +89,8 @@ 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 Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/LuanClosure.java Thu Feb 14 03:10:45 2019 -0700 @@ -3,51 +3,26 @@ import luan.impl.Pointer; -public abstract class LuanClosure extends LuanFunction implements LuanCloneable, Cloneable { +public abstract class LuanClosure extends LuanFunction { public Pointer[] upValues; public boolean javaOk; public final String sourceName; - private LuanCloner cloner; - public LuanClosure(int nUpValues,boolean javaOk,String sourceName) throws LuanException { + public LuanClosure(Luan luan,int nUpValues,boolean javaOk,String sourceName) throws LuanException { + super(luan); this.upValues = new Pointer[nUpValues]; this.javaOk = javaOk; this.sourceName = sourceName; } - @Override public LuanClosure shallowClone() { - check(); - try { - return (LuanClosure)clone(); - } catch(CloneNotSupportedException e) { - throw new RuntimeException(e); - } + @Override protected void completeClone(LuanFunction dc,LuanCloner cloner) { + LuanClosure clone = (LuanClosure)dc; + clone.upValues = (Pointer[])cloner.clone(upValues); + super.completeClone(dc,cloner); } - @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { - LuanClosure clone = (LuanClosure)dc; - switch( cloner.type ) { - case COMPLETE: - clone.upValues = (Pointer[])cloner.clone(upValues); - return; - case INCREMENTAL: - clone.cloner = cloner; - clone.upValues = upValues; - return; - } - } - - private void check() { - if( cloner != null ) { - upValues = (Pointer[])cloner.clone(upValues); - cloner = null; - } - } - - @Override public final Object call(Luan luan,Object[] args) throws LuanException { - if( luan.isLocked ) - throw new RuntimeException("luan is locked"); - check(); + @Override public final Object call(Object[] args) throws LuanException { + Luan luan = luan(); luan.push(this); try { return doCall(luan,args); @@ -58,5 +33,9 @@ } } + @Override public String toString() { + return super.toString()+"="+sourceName; + } + public abstract Object doCall(Luan luan,Object[] args) throws LuanException; }
--- a/src/luan/LuanException.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/LuanException.java Thu Feb 14 03:10:45 2019 -0700 @@ -5,10 +5,13 @@ import java.io.PrintStream; import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; public final class LuanException extends Exception implements LuanCloneable { private LuanTable table; + private Map extra = new HashMap(); public LuanException(String msg,Throwable cause) { super(msg,cause); @@ -29,13 +32,26 @@ @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { LuanException clone = (LuanException)dc; clone.table = (LuanTable)cloner.clone(table); + clone.extra = (Map)cloner.clone(extra); + } + + public void put(String key,Object value) throws LuanException { + if( table == null ) { + extra.put(key,value); + } else { + table.put(key,value); + } } public LuanTable table(Luan luan) { if( table==null ) { try { LuanTable Boot = (LuanTable)luan.require("luan:Boot.luan"); - table = (LuanTable)Boot.call( "new_error_table", this ); + table = (LuanTable)Boot.fn("new_error_table").call(this ); + for( Object stupid : extra.entrySet() ) { + Map.Entry entry = (Map.Entry)stupid; + table.put( entry.getKey(), entry.getValue() ); + } } catch(LuanException e) { throw new RuntimeException(e); }
--- a/src/luan/LuanFunction.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/LuanFunction.java Thu Feb 14 03:10:45 2019 -0700 @@ -1,16 +1,72 @@ package luan; -public abstract class LuanFunction { +public abstract class LuanFunction implements LuanCloneable, Cloneable { + private Luan luan; + private LuanCloner cloner; + private boolean clone; + + public LuanFunction(Luan luan) { + if( luan==null ) throw new NullPointerException(); + this.luan = luan; + this.clone = true; + } + + public LuanFunction(boolean clone) { + this.clone = clone; + } + + // for LuanJavaFunction + void dontClone() { + luan = null; + clone = false; + } + + @Override public LuanFunction shallowClone() { + if( !clone ) + return this; + check(); + try { + return (LuanFunction)clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } - public abstract Object call(Luan luan,Object[] args) throws LuanException; + private void check() { + if( cloner != null ) { + completeClone(this,cloner); + cloner = null; + } + } + + @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { + if( !clone ) + return; + LuanFunction clone = (LuanFunction)dc; + switch( cloner.type ) { + case COMPLETE: + completeClone(clone,cloner); + return; + case INCREMENTAL: + clone.cloner = cloner; + return; + } + } + + protected void completeClone(LuanFunction clone,LuanCloner cloner) { + clone.luan = (Luan)cloner.clone(luan); + } + + public Luan luan() { + check(); + return luan; + } + + public abstract Object call(Object... args) throws LuanException; public static final Object[] NOTHING = new Object[0]; - public final Object call(Luan luan) throws LuanException { - return call(luan,NOTHING); - } - @Override public String toString() { return "function: " + Integer.toHexString(hashCode()); }
--- a/src/luan/LuanJavaFunction.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/LuanJavaFunction.java Thu Feb 14 03:10:45 2019 -0700 @@ -17,30 +17,33 @@ private final JavaMethod method; private Object obj; private final RtnConverter rtnConverter; - private final boolean takesLuaState; + private final boolean takesLuan; private final ArgConverter[] argConverters; private final Class varArgCls; - public LuanJavaFunction(Method method,Object obj) { - this( JavaMethod.of(method), obj ); + public LuanJavaFunction(Luan luan,Method method,Object obj) { + this( luan, JavaMethod.of(method), obj ); } - public LuanJavaFunction(Constructor constr,Object obj) { - this( JavaMethod.of(constr), obj ); + public LuanJavaFunction(Luan luan,Constructor constr,Object obj) { + this( luan, JavaMethod.of(constr), obj ); } - private LuanJavaFunction(JavaMethod method,Object obj) { + private LuanJavaFunction(Luan luan,JavaMethod method,Object obj) { + super(luan); this.method = method; this.obj = obj; this.rtnConverter = getRtnConverter(method); - this.takesLuaState = takesLuaState(method); - this.argConverters = getArgConverters(takesLuaState,method); + this.takesLuan = takesLuan(method); + this.argConverters = getArgConverters(takesLuan,method); if( method.isVarArgs() ) { Class[] paramTypes = method.getParameterTypes(); this.varArgCls = paramTypes[paramTypes.length-1].getComponentType(); } else { this.varArgCls = null; } + if( !takesLuan ) + dontClone(); } @Override public String toString() { @@ -55,22 +58,22 @@ return method.isVarArgs(); } - @Override public Object call(Luan luan,Object[] args) throws LuanException { + @Override public Object call(Object[] args) throws LuanException { try { - args = fixArgs(luan,args); - return doCall(luan,args); + args = fixArgs(args); + return doCall(args); } catch(IllegalArgumentException e) { checkArgs(args); throw e; } } - public Object rawCall(Luan luan,Object[] args) throws LuanException { - args = fixArgs(luan,args); - return doCall(luan,args); + public Object rawCall(Object[] args) throws LuanException { + args = fixArgs(args); + return doCall(args); } - private Object doCall(Luan luan,Object[] args) throws LuanException { + private Object doCall(Object[] args) throws LuanException { Object rtn; try { rtn = method.invoke(obj,args); @@ -86,7 +89,7 @@ } catch(InstantiationException e) { throw new RuntimeException(e); } - return rtnConverter.convert(luan,rtn); + return rtnConverter.convert(rtn); } private static final Map primitiveMap = new HashMap(); @@ -104,7 +107,7 @@ private void checkArgs(Object[] args) throws LuanException { Class[] a = method.getParameterTypes(); - int start = takesLuaState ? 1 : 0; + int start = takesLuan ? 1 : 0; for( int i=start; i<a.length; i++ ) { Class paramType = a[i]; Class type = paramType; @@ -146,18 +149,18 @@ return type; } - private Object[] fixArgs(Luan luan,Object[] args) throws LuanException { + private Object[] fixArgs(Object[] args) throws LuanException { int n = argConverters.length; Object[] rtn; int start = 0; - if( !takesLuaState && varArgCls==null && args.length == n ) { + if( !takesLuan && varArgCls==null && args.length == n ) { rtn = args; } else { - if( takesLuaState ) + if( takesLuan ) n++; rtn = new Object[n]; - if( takesLuaState ) { - rtn[start++] = luan; + if( takesLuan ) { + rtn[start++] = luan(); } n = argConverters.length; if( varArgCls == null ) { @@ -174,7 +177,7 @@ Object varArgs = Array.newInstance(varArgCls,len); ArgConverter ac = argConverters[n]; for( int i=0; i<len; i++ ) { - Array.set( varArgs, i, ac.convert(luan,args[n+i]) ); + Array.set( varArgs, i, ac.convert(args[n+i]) ); } rtn[rtn.length-1] = varArgs; } @@ -182,28 +185,28 @@ System.arraycopy(args,0,rtn,start,Math.min(args.length,n)); } for( int i=0; i<n; i++ ) { - rtn[start+i] = argConverters[i].convert(luan,rtn[start+i]); + rtn[start+i] = argConverters[i].convert(rtn[start+i]); } return rtn; } private interface RtnConverter { - public Object convert(Luan luan,Object obj); + public Object convert(Object obj); } private static final RtnConverter RTN_NOTHING = new RtnConverter() { - @Override public Object[] convert(Luan luan,Object obj) { + @Override public Object[] convert(Object obj) { return NOTHING; } }; private static final RtnConverter RTN_SAME = new RtnConverter() { - @Override public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { return obj; } }; - +/* private static final RtnConverter RTN_ARRAY = new RtnConverter() { @Override public Object convert(Luan luan,Object obj) { if( obj == null ) @@ -215,23 +218,25 @@ return new LuanTable(luan,new ArrayList<Object>(Arrays.asList(a))); } }; - +*/ private static RtnConverter getRtnConverter(JavaMethod m) { Class rtnType = m.getReturnType(); if( rtnType == Void.TYPE ) return RTN_NOTHING; +/* if( !m.isLuan() && rtnType.isArray() && !rtnType.getComponentType().isPrimitive() ) { return RTN_ARRAY; } +*/ return RTN_SAME; } private interface ArgConverter { - public Object convert(Luan luan,Object obj) throws LuanException; + public Object convert(Object obj) throws LuanException; } private static final ArgConverter ARG_SAME = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { return obj; } @Override public String toString() { @@ -240,7 +245,7 @@ }; private static final ArgConverter ARG_DOUBLE = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof Double ) return obj; if( obj instanceof Number ) { @@ -255,7 +260,7 @@ }; private static final ArgConverter ARG_FLOAT = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof Float ) return obj; if( obj instanceof Number ) { @@ -270,7 +275,7 @@ }; private static final ArgConverter ARG_LONG = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof Long ) return obj; if( obj instanceof Number ) { @@ -287,7 +292,7 @@ }; private static final ArgConverter ARG_INTEGER = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof Integer ) return obj; if( obj instanceof Number ) { @@ -304,7 +309,7 @@ }; private static final ArgConverter ARG_SHORT = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof Short ) return obj; if( obj instanceof Number ) { @@ -321,7 +326,7 @@ }; private static final ArgConverter ARG_BYTE = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof Byte ) return obj; if( obj instanceof Number ) { @@ -336,9 +341,9 @@ return "ARG_BYTE"; } }; - +/* private static final ArgConverter ARG_TABLE = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Luan luan,Object obj) { LuanTable tbl = luan.toTable(obj); return tbl!=null ? tbl : obj; } @@ -346,9 +351,9 @@ return "ARG_TABLE"; } }; - +*/ private static final ArgConverter ARG_MAP = new ArgConverter() { - public Object convert(Luan luan,Object obj) throws LuanException { + @Override public Object convert(Object obj) throws LuanException { if( obj instanceof LuanTable ) { LuanTable t = (LuanTable)obj; return t.asMap(); @@ -361,7 +366,7 @@ }; private static final ArgConverter ARG_LIST = new ArgConverter() { - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof LuanTable ) { LuanTable t = (LuanTable)obj; if( t.isList() ) @@ -375,7 +380,7 @@ }; private static final ArgConverter ARG_SET = new ArgConverter() { - public Object convert(Luan luan,Object obj) throws LuanException { + @Override public Object convert(Object obj) throws LuanException { if( obj instanceof LuanTable ) { LuanTable t = (LuanTable)obj; if( t.isSet() ) @@ -389,7 +394,7 @@ }; private static final ArgConverter ARG_COLLECTION = new ArgConverter() { - public Object convert(Luan luan,Object obj) throws LuanException { + @Override public Object convert(Object obj) throws LuanException { if( obj instanceof LuanTable ) { LuanTable t = (LuanTable)obj; if( t.isList() ) @@ -411,7 +416,7 @@ a = (Object[])Array.newInstance(cls.getComponentType(),0); } - public Object convert(Luan luan,Object obj) { + @Override public Object convert(Object obj) { if( obj instanceof LuanTable ) { LuanTable t = (LuanTable)obj; if( t.isList() ) { @@ -424,15 +429,15 @@ } } - private static boolean takesLuaState(JavaMethod m) { + private static boolean takesLuan(JavaMethod m) { Class[] paramTypes = m.getParameterTypes(); return paramTypes.length > 0 && paramTypes[0].equals(Luan.class); } - private static ArgConverter[] getArgConverters(boolean takesLuaState,JavaMethod m) { + private static ArgConverter[] getArgConverters(boolean takesLuan,JavaMethod m) { final boolean isVarArgs = m.isVarArgs(); Class[] paramTypes = m.getParameterTypes(); - if( takesLuaState ) { + if( takesLuan ) { Class[] t = new Class[paramTypes.length-1]; System.arraycopy(paramTypes,1,t,0,t.length); paramTypes = t; @@ -460,8 +465,8 @@ return ARG_SHORT; if( cls == Byte.TYPE || cls.equals(Byte.class) ) return ARG_BYTE; - if( cls.equals(LuanTable.class) ) - return ARG_TABLE; +// if( cls.equals(LuanTable.class) ) +// return ARG_TABLE; if( cls.equals(Map.class) ) return ARG_MAP; if( cls.equals(List.class) ) @@ -483,7 +488,7 @@ abstract Object invoke(Object obj,Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException; abstract Class getReturnType(); - abstract boolean isLuan(); + abstract String getName(); static JavaMethod of(final Method m) { return new JavaMethod() { @@ -501,8 +506,8 @@ @Override Class getReturnType() { return m.getReturnType(); } - @Override boolean isLuan() { - return m.getAnnotation(LuanMethod.class) != null; + @Override public String getName() { + return m.getName(); } @Override public String toString() { return m.toString(); @@ -526,8 +531,8 @@ @Override Class getReturnType() { return c.getDeclaringClass(); } - @Override boolean isLuan() { - return false; + @Override public String getName() { + return c.getName(); } @Override public String toString() { return c.toString();
--- a/src/luan/LuanMethod.java Tue Feb 12 22:53:57 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -package luan; - -import java.lang.annotation.*; - - -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface LuanMethod {}
--- a/src/luan/LuanTable.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/LuanTable.java Thu Feb 14 03:10:45 2019 -0700 @@ -73,7 +73,7 @@ clone.security = security; switch( cloner.type ) { case COMPLETE: - deepenClone(clone,cloner); + completeClone(clone,cloner); return; case INCREMENTAL: clone.cloner = cloner; @@ -87,12 +87,17 @@ private void check() { if( cloner != null ) { - deepenClone(this,cloner); + completeClone(this,cloner); cloner = null; } } - private void deepenClone(LuanTable clone,LuanCloner cloner) { + public Luan luan() { + check(); + return luan; + } + + private void completeClone(LuanTable clone,LuanCloner cloner) { clone.luan = (Luan)cloner.clone(luan); if( map != null ) { Map newMap = newMap(); @@ -132,7 +137,7 @@ if( h == null ) return rawToString(); LuanFunction fn = Luan.checkFunction(h); - return Luan.checkString( Luan.first( fn.call(luan,new Object[]{this}) ) ); + return Luan.checkString( Luan.first( fn.call(this) ) ); } public String rawToString() { @@ -148,7 +153,7 @@ return null; if( h instanceof LuanFunction ) { LuanFunction fn = (LuanFunction)h; - return Luan.first(fn.call(luan,new Object[]{this,key})); + return Luan.first(fn.call(this,key)); } return luan.index(h,key); } @@ -180,7 +185,7 @@ } if( h instanceof LuanFunction ) { LuanFunction fn = (LuanFunction)h; - fn.call(luan,new Object[]{this,key,value}); + fn.call(this,key,value); return; } if( h instanceof LuanTable ) { @@ -286,7 +291,7 @@ Object h = getHandler("__len"); if( h != null ) { LuanFunction fn = Luan.checkFunction(h); - return (Integer)Luan.first(fn.call(luan,new Object[]{this})); + return (Integer)Luan.first(fn.call(this)); } return rawLength(); } @@ -323,7 +328,7 @@ private Map.Entry<Object,Object> getNext() { try { - Object obj = fn.call(luan); + Object obj = fn.call(); if( obj==null ) return null; Object[] a = (Object[])obj; @@ -356,7 +361,7 @@ if( h != null ) { if( h instanceof LuanFunction ) { LuanFunction fn = (LuanFunction)h; - Object obj = Luan.first(fn.call(luan,new Object[]{this})); + Object obj = Luan.first(fn.call(this)); if( !(obj instanceof LuanFunction) ) throw new LuanException( "metamethod __pairs should return function but returned " + Luan.type(obj) ); return (LuanFunction)obj; @@ -367,10 +372,10 @@ } private LuanFunction rawPairs() { - return new LuanFunction() { + return new LuanFunction(false) { // ??? final Iterator<Map.Entry> iter = rawIterator(); - @Override public Object[] call(Luan luan,Object[] args) { + @Override public Object[] call(Object[] args) { if( !iter.hasNext() ) return LuanFunction.NOTHING; Map.Entry<Object,Object> entry = iter.next(); @@ -517,14 +522,13 @@ Object h = getHandler("__gc"); if( h != null ) { LuanFunction fn = Luan.checkFunction(h); - fn.call(luan,new Object[]{this}); + fn.call(this); } super.finalize(); } - public Object call(String fnName,Object... args) throws LuanException { - LuanFunction fn = (LuanFunction)get(fnName); - return fn.call(luan,args); + public LuanFunction fn(String fnName) throws LuanException { + return (LuanFunction)get(fnName); } public static void setSecurity(LuanTable tbl,String security) {
--- a/src/luan/host/WebHandler.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/host/WebHandler.java Thu Feb 14 03:10:45 2019 -0700 @@ -12,6 +12,7 @@ import luan.LuanTable; import luan.LuanFunction; import luan.LuanClosure; +import luan.LuanRuntimeException; import luan.modules.BasicLuan; import luan.modules.http.LuanHandler; import luan.modules.logging.Log4j; @@ -20,14 +21,6 @@ public class WebHandler implements Handler { private static final Logger logger = LoggerFactory.getLogger(WebHandler.class); - private static final class LuanRuntimeException extends RuntimeException { - final LuanException e; - - LuanRuntimeException(LuanException e) { - this.e = e; - } - } - private static final DomainHandler.Factory factory = new DomainHandler.Factory() { public Handler newHandler(String domain) { File dir = new File(sitesDir,domain); @@ -103,7 +96,7 @@ security(luan,dir); try { LuanFunction fn = BasicLuan.load_file(luan,"classpath:luan/host/init.luan"); - fn.call(luan,new Object[]{dir,domain,logging}); + fn.call(dir,domain,logging); } catch(LuanException e) { throw new LuanRuntimeException(e); } @@ -117,7 +110,7 @@ try { domainHandler.getHandler(domain); } catch(LuanRuntimeException e) { - throw e.e; + throw (LuanException)e.getCause(); } }
--- a/src/luan/impl/LuanCompiler.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/impl/LuanCompiler.java Thu Feb 14 03:10:45 2019 -0700 @@ -4,6 +4,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.HashMap; +import luan.Luan; import luan.LuanFunction; import luan.LuanException; import luan.LuanTable; @@ -15,14 +16,14 @@ public final class LuanCompiler { private static final Map<String,WeakReference<Class>> map = new HashMap<String,WeakReference<Class>>(); - public static LuanFunction compile(String sourceText,String sourceName,LuanTable env) throws LuanException { + public static LuanFunction compile(Luan luan,String sourceText,String sourceName,LuanTable env) throws LuanException { Class fnClass = env==null ? getClass(sourceText,sourceName) : getClass(sourceText,sourceName,env); boolean javaOk = false; if( env != null && env.closure != null ) javaOk = env.closure.javaOk; LuanClosure closure; try { - closure = (LuanClosure)fnClass.getConstructor(Boolean.TYPE,String.class).newInstance(javaOk,sourceName); + closure = (LuanClosure)fnClass.getConstructor(Luan.class,Boolean.TYPE,String.class).newInstance(luan,javaOk,sourceName); } catch(NoSuchMethodException e) { throw new RuntimeException(e); } catch(InstantiationException e) { @@ -32,8 +33,8 @@ } catch(InvocationTargetException e) { throw new RuntimeException(e); } - closure.upValues[0].o = JavaLuan.javaFn; - closure.upValues[1].o = PackageLuan.requireFn; + closure.upValues[0].o = JavaLuan.javaFn(luan); + closure.upValues[1].o = PackageLuan.requireFn(luan); if( env != null ) { closure.upValues[2].o = env; env.closure = closure;
--- a/src/luan/impl/LuanImpl.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/impl/LuanImpl.java Thu Feb 14 03:10:45 2019 -0700 @@ -29,75 +29,75 @@ throw new LuanException( "attempt to get length of a " + Luan.type(o) + " value" ); } - public static Object unm(Luan luan,Object o) throws LuanException { + public static Object unm(Object o) throws LuanException { if( o instanceof Number ) return -((Number)o).doubleValue(); if( o instanceof LuanTable ) { LuanFunction fn = Luan.getHandlerFunction("__unm",(LuanTable)o); if( fn != null ) { - return Luan.first(fn.call(luan,new Object[]{o})); + return Luan.first(fn.call(o)); } } throw new LuanException("attempt to perform arithmetic on a "+Luan.type(o)+" value"); } - private static Object arithmetic(Luan luan,String op,Object o1,Object o2) throws LuanException { + private static Object arithmetic(String op,Object o1,Object o2) throws LuanException { LuanFunction fn = Luan.getBinHandler(op,o1,o2); if( fn != null ) - return Luan.first(fn.call(luan,new Object[]{o1,o2})); + return Luan.first(fn.call(o1,o2)); String type = !(o1 instanceof Number) ? Luan.type(o1) : Luan.type(o2); throw new LuanException("attempt to perform arithmetic on a "+type+" value"); } - public static Object pow(Luan luan,Object o1,Object o2) throws LuanException { + public static Object pow(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) return Math.pow( ((Number)o1).doubleValue(), ((Number)o2).doubleValue() ); - return arithmetic(luan,"__pow",o1,o2); + return arithmetic("__pow",o1,o2); } - public static Object mul(Luan luan,Object o1,Object o2) throws LuanException { + public static Object mul(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) return ((Number)o1).doubleValue() * ((Number)o2).doubleValue(); - return arithmetic(luan,"__mul",o1,o2); + return arithmetic("__mul",o1,o2); } - public static Object div(Luan luan,Object o1,Object o2) throws LuanException { + public static Object div(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) return ((Number)o1).doubleValue() / ((Number)o2).doubleValue(); - return arithmetic(luan,"__div",o1,o2); + return arithmetic("__div",o1,o2); } - public static Object mod(Luan luan,Object o1,Object o2) throws LuanException { + public static Object mod(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) { double d1 = ((Number)o1).doubleValue(); double d2 = ((Number)o2).doubleValue(); return d1 - Math.floor(d1/d2)*d2; } - return arithmetic(luan,"__mod",o1,o2); + return arithmetic("__mod",o1,o2); } - public static Object add(Luan luan,Object o1,Object o2) throws LuanException { + public static Object add(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) return ((Number)o1).doubleValue() + ((Number)o2).doubleValue(); - return arithmetic(luan,"__add",o1,o2); + return arithmetic("__add",o1,o2); } - public static Object sub(Luan luan,Object o1,Object o2) throws LuanException { + public static Object sub(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) return ((Number)o1).doubleValue() - ((Number)o2).doubleValue(); - return arithmetic(luan,"__sub",o1,o2); + return arithmetic("__sub",o1,o2); } - public static Object concat(Luan luan,Object o1,Object o2) throws LuanException { + public static Object concat(Object o1,Object o2) throws LuanException { LuanFunction fn = Luan.getBinHandler("__concat",o1,o2); if( fn != null ) - return Luan.first(fn.call(luan,new Object[]{o1,o2})); + return Luan.first(fn.call(o1,o2)); String s1 = Luan.luanToString(o1); String s2 = Luan.luanToString(o2); return s1 + s2; } - public static boolean eq(Luan luan,Object o1,Object o2) throws LuanException { + public static boolean eq(Object o1,Object o2) throws LuanException { if( o1 == o2 || o1 != null && o1.equals(o2) ) return true; if( o1 instanceof Number && o2 instanceof Number ) { @@ -122,10 +122,10 @@ if( f == null || !f.equals(mt2.rawGet("__eq")) ) return false; LuanFunction fn = Luan.checkFunction(f); - return Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o1,o2})) ); + return Luan.checkBoolean( Luan.first(fn.call(o1,o2)) ); } - public static boolean le(Luan luan,Object o1,Object o2) throws LuanException { + public static boolean le(Object o1,Object o2) throws LuanException { if( o1 instanceof Number && o2 instanceof Number ) { Number n1 = (Number)o1; Number n2 = (Number)o2; @@ -138,15 +138,15 @@ } LuanFunction fn = Luan.getBinHandler("__le",o1,o2); if( fn != null ) - return Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o1,o2})) ); + return Luan.checkBoolean( Luan.first(fn.call(o1,o2)) ); fn = Luan.getBinHandler("__lt",o1,o2); if( fn != null ) - return !Luan.checkBoolean( Luan.first(fn.call(luan,new Object[]{o2,o1})) ); + return !Luan.checkBoolean( Luan.first(fn.call(o2,o1)) ); throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); } - public static boolean lt(Luan luan,Object o1,Object o2) throws LuanException { - return luan.isLessThan(o1,o2); + public static boolean lt(Object o1,Object o2) throws LuanException { + return Luan.isLessThan(o1,o2); } public static boolean cnd(Object o) throws LuanException {
--- a/src/luan/impl/LuanParser.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/impl/LuanParser.java Thu Feb 14 03:10:45 2019 -0700 @@ -366,7 +366,7 @@ Expr exp = new Expr(null,true); exp.add( "Luan.checkFunction(" ); exp.addAll( fn.single() ); - exp.add( ").call(luan," ); + exp.add( ").call(" ); exp.addAll( args.array() ); exp.add( ")" ); return exp; @@ -377,7 +377,7 @@ if( exprs == null ) return null; Stmts stmt = new Stmts(); - stmt.add( "Luan.checkFunction(luan.index(PackageLuan.require(luan,\"luan:Io.luan\"),\"template_write\")).call(luan," ); + stmt.add( "Luan.checkFunction(luan.index(PackageLuan.require(luan,\"luan:Io.luan\"),\"template_write\")).call(" ); stmt.addAll( exprs.array() ); stmt.add( "); " ); return stmt; @@ -508,7 +508,7 @@ String fnVar = "fn"+ ++forCounter; Expr fnExp = new Expr(null,false); - fnExp.add( fnVar + ".call(luan)" ); + fnExp.add( fnVar + ".call()" ); Stmts stmt = new Stmts(); stmt.add( "" +"LuanFunction "+fnVar+" = Luan.checkFunction(" @@ -828,7 +828,7 @@ exp = exp.single(); Expr exp2 = required(ConcatExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.eq(luan," ); + newExp.add( "LuanImpl.eq(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -839,7 +839,7 @@ exp = exp.single(); Expr exp2 = required(ConcatExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "!LuanImpl.eq(luan," ); + newExp.add( "!LuanImpl.eq(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -850,7 +850,7 @@ exp = exp.single(); Expr exp2 = required(ConcatExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.le(luan," ); + newExp.add( "LuanImpl.le(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -861,7 +861,7 @@ exp = exp.single(); Expr exp2 = required(ConcatExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.le(luan," ); + newExp.add( "LuanImpl.le(" ); newExp.addAll( exp2 ); newExp.add( "," ); newExp.addAll( exp ); @@ -872,7 +872,7 @@ exp = exp.single(); Expr exp2 = required(ConcatExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.lt(luan," ); + newExp.add( "LuanImpl.lt(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -883,7 +883,7 @@ exp = exp.single(); Expr exp2 = required(ConcatExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.lt(luan," ); + newExp.add( "LuanImpl.lt(" ); newExp.addAll( exp2 ); newExp.add( "," ); newExp.addAll( exp ); @@ -905,7 +905,7 @@ exp = exp.single(); Expr exp2 = required(ConcatExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.concat(luan," ); + newExp.add( "LuanImpl.concat(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -926,7 +926,7 @@ exp = exp.single(); Expr exp2 = required(TermExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.add(luan," ); + newExp.add( "LuanImpl.add(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -937,7 +937,7 @@ exp = exp.single(); Expr exp2 = required(TermExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.sub(luan," ); + newExp.add( "LuanImpl.sub(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -965,7 +965,7 @@ exp = exp.single(); Expr exp2 = required(UnaryExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.mul(luan," ); + newExp.add( "LuanImpl.mul(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -976,7 +976,7 @@ exp = exp.single(); Expr exp2 = required(UnaryExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.div(luan," ); + newExp.add( "LuanImpl.div(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -987,7 +987,7 @@ exp = exp.single(); Expr exp2 = required(UnaryExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.mod(luan," ); + newExp.add( "LuanImpl.mod(" ); newExp.addAll( exp ); newExp.add( "," ); newExp.addAll( exp2 ); @@ -1019,7 +1019,7 @@ Spaces(); Expr exp = required(UnaryExpr(in)).single(); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.unm(luan," ); + newExp.add( "LuanImpl.unm(" ); newExp.addAll( exp ); newExp.add( ")" ); return parser.success(newExp); @@ -1048,7 +1048,7 @@ Spaces(); Expr exp2 = required(PowExpr(in)); Expr newExp = new Expr(Val.SINGLE,false); - newExp.add( "LuanImpl.pow(luan," ); + newExp.add( "LuanImpl.pow(" ); newExp.addAll( exp1.single() ); newExp.add( "," ); newExp.addAll( exp2.single() ); @@ -2015,8 +2015,8 @@ +"import luan.modules.PackageLuan; " +"public class " + className +" extends LuanClosure { " - +"public "+className+"(boolean javaOk,String sourceName) throws LuanException { " - +"super("+upValueSymbols.size()+",javaOk,sourceName); " + +"public "+className+"(Luan luan,boolean javaOk,String sourceName) throws LuanException { " + +"super(luan,"+upValueSymbols.size()+",javaOk,sourceName); " + init(upValueSymbols) +"} " @@ -2036,7 +2036,7 @@ stmt.add( "return LuanFunction.NOTHING; " ); Expr exp = new Expr(Val.SINGLE,false); exp.add( "" - +"new LuanClosure("+upValueSymbols.size()+",javaOk,sourceName) { " + +"new LuanClosure(luan(),"+upValueSymbols.size()+",javaOk,sourceName) { " +"{ " + init(upValueSymbols) +"} "
--- a/src/luan/modules/BasicLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/BasicLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -12,7 +12,7 @@ import luan.LuanTable; import luan.LuanFunction; import luan.LuanException; -import luan.LuanMethod; +import luan.LuanCloner; import luan.modules.parsers.LuanToString; @@ -22,12 +22,12 @@ return Luan.type(obj); } - public static LuanFunction load(String text,String sourceName,LuanTable env) + public static LuanFunction load(Luan luan,String text,String sourceName,LuanTable env) throws LuanException { Utils.checkNotNull(text); Utils.checkNotNull(sourceName,1); - return Luan.load(text,sourceName,env); + return luan.load(text,sourceName,env); } public static LuanFunction load_file(Luan luan,String fileName) throws LuanException { @@ -39,7 +39,7 @@ String src = PackageLuan.read(luan,fileName); if( src == null ) return null; - return load(src,fileName,null); + return load(luan,src,fileName,null); } public static LuanFunction pairs(final LuanTable t) throws LuanException { @@ -47,20 +47,34 @@ return t.pairs(); } - public static LuanFunction ipairs(final LuanTable t) throws LuanException { - Utils.checkNotNull(t); - return new LuanFunction() { - List<Object> list = t.asList(); - int i = 0; - final int size = list.size(); + private static class Ipairs extends LuanFunction { + List<Object> list; + int i = 0; + final int size; + + Ipairs(LuanTable t) { + super(true); + list = t.asList(); + size = list.size(); + } - @Override public Object[] call(Luan luan,Object[] args) { - if( i >= size ) - return LuanFunction.NOTHING; - Object val = list.get(i++); - return new Object[]{i,val}; - } - }; + @Override public Object[] call(Object[] args) { + if( i >= size ) + return LuanFunction.NOTHING; + Object val = list.get(i++); + return new Object[]{i,val}; + } + + @Override protected void completeClone(LuanFunction dc,LuanCloner cloner) { + Ipairs clone = (Ipairs)dc; + clone.list = (List)cloner.clone(list); + super.completeClone(dc,cloner); + } + } + + public static LuanFunction ipairs(LuanTable t) throws LuanException { + Utils.checkNotNull(t); + return new Ipairs(t); } public static Object get_metatable(LuanTable table) throws LuanException { @@ -134,10 +148,10 @@ final double step = stepV==null ? 1.0 : stepV; if( step == 0.0 ) throw new LuanException("bad argument #3 (step may not be zero)"); - return new LuanFunction() { + return new LuanFunction(false) { double v = from; - @Override public Object call(Luan luan,Object[] args) { + @Override public Object call(Object[] args) { if( step > 0.0 && v > to || step < 0.0 && v < to ) return LuanFunction.NOTHING; double rtn = v; @@ -147,24 +161,38 @@ }; } - public static LuanFunction values(final Object... args) throws LuanException { - return new LuanFunction() { - int i = 0; + private static class Values extends LuanFunction { + Object[] args; + int i = 0; + + Values(Object[] args) { + super(true); + this.args = args; + } - @Override public Object call(Luan luan,Object[] unused) { - if( i >= args.length ) - return LuanFunction.NOTHING; - Object val = args[i++]; - return new Object[]{i,val}; - } - }; + @Override public Object[] call(Object[] args) { + if( i >= args.length ) + return LuanFunction.NOTHING; + Object val = args[i++]; + return new Object[]{i,val}; + } + + @Override protected void completeClone(LuanFunction dc,LuanCloner cloner) { + Values clone = (Values)dc; + clone.args = (Object[])cloner.clone(args); + super.completeClone(dc,cloner); + } + } + + public static LuanFunction values(final Object... args) throws LuanException { + return new Values(args); } private LuanFunction fn(Object obj) { return obj instanceof LuanFunction ? (LuanFunction)obj : null; } - public static Object try_(Luan luan,LuanTable blocks,Object... args) throws LuanException { + public static Object try_(LuanTable blocks,Object... args) throws LuanException { Utils.checkNotNull(blocks); Object obj = blocks.get(1); if( obj == null ) @@ -187,20 +215,20 @@ finallyFn = (LuanFunction)obj; } try { - return tryFn.call(luan,args); + return tryFn.call(args); } catch(LuanException e) { if( catchFn == null ) throw e; - return catchFn.call(luan,new Object[]{e.table(luan)}); + return catchFn.call(e.table(blocks.luan())); } finally { if( finallyFn != null ) - finallyFn.call(luan); + finallyFn.call(); } } - @LuanMethod public static Object[] pcall(Luan luan,LuanFunction f,Object... args) { + public static Object[] pcall(LuanFunction f,Object... args) { try { - Object[] r = Luan.array(f.call(luan,args)); + Object[] r = Luan.array(f.call(args)); Object[] rtn = new Object[r.length+1]; rtn[0] = true; for( int i=0; i<r.length; i++ ) { @@ -208,7 +236,7 @@ } return rtn; } catch(LuanException e) { - return new Object[]{false,e.table(luan)}; + return new Object[]{false,e.table(f.luan())}; } }
--- a/src/luan/modules/BinaryLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/BinaryLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -5,7 +5,6 @@ import luan.LuanTable; import luan.LuanFunction; import luan.LuanException; -import luan.LuanMethod; public final class BinaryLuan { @@ -28,7 +27,7 @@ return i==null ? dflt : end(binary,i); } - @LuanMethod public static Byte[] byte_(byte[] binary,Integer i,Integer j) throws LuanException { + public static Byte[] byte_(byte[] binary,Integer i,Integer j) throws LuanException { Utils.checkNotNull(binary); int start = start(binary,i,1); int end = end(binary,j,start+1); @@ -39,7 +38,7 @@ return bytes; } - @LuanMethod public static byte[] binary(byte... bytes) { + public static byte[] binary(byte... bytes) { return bytes; }
--- a/src/luan/modules/IoLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/IoLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -89,8 +89,8 @@ } static LuanFunction lines(final BufferedReader in) { - return new LuanFunction() { - @Override public Object call(Luan luan,Object[] args) throws LuanException { + return new LuanFunction(false) { + @Override public Object call(Object[] args) throws LuanException { try { if( args.length > 0 ) { if( args.length > 1 || !"close".equals(args[0]) ) @@ -110,10 +110,10 @@ } static LuanFunction blocks(final InputStream in,final int blockSize) { - return new LuanFunction() { + return new LuanFunction(false) { final byte[] a = new byte[blockSize]; - @Override public Object call(Luan luan,Object[] args) throws LuanException { + @Override public Object call(Object[] args) throws LuanException { try { if( args.length > 0 ) { if( args.length > 1 || !"close".equals(args[0]) ) @@ -153,41 +153,41 @@ public static abstract class LuanIn { protected String charset = null; - public abstract InputStream inputStream(Luan luan) throws IOException, LuanException; + public abstract InputStream inputStream() throws IOException, LuanException; public abstract String to_string(); public abstract String to_uri_string(); - public Reader reader(Luan luan) throws IOException, LuanException { - InputStream in = inputStream(luan); + public Reader reader() throws IOException, LuanException { + InputStream in = inputStream(); return charset==null ? new InputStreamReader(in) : new InputStreamReader(in,charset); } - public String read_text(Luan luan) throws IOException, LuanException { - Reader in = reader(luan); + public String read_text() throws IOException, LuanException { + Reader in = reader(); String s = Utils.readAll(in); in.close(); return s; } - public byte[] read_binary(Luan luan) throws IOException, LuanException { - InputStream in = inputStream(luan); + public byte[] read_binary() throws IOException, LuanException { + InputStream in = inputStream(); byte[] a = Utils.readAll(in); in.close(); return a; } - public LuanFunction read_lines(Luan luan) throws IOException, LuanException { - return lines(new BufferedReader(reader(luan))); + public LuanFunction read_lines() throws IOException, LuanException { + return lines(new BufferedReader(reader())); } - public LuanFunction read_blocks(Luan luan,Integer blockSize) throws IOException, LuanException { + public LuanFunction read_blocks(Integer blockSize) throws IOException, LuanException { int n = blockSize!=null ? blockSize : Utils.bufSize; - return blocks(inputStream(luan),n); + return blocks(inputStream(),n); } - public boolean exists(Luan luan) throws IOException, LuanException { + public boolean exists() throws IOException, LuanException { try { - inputStream(luan).close(); + inputStream().close(); return true; } catch(FileNotFoundException e) { return false; @@ -196,9 +196,9 @@ } } - public long checksum(Luan luan) throws IOException, LuanException { + public long checksum() throws IOException, LuanException { long cs = 0; - InputStream in = new BufferedInputStream(inputStream(luan)); + InputStream in = new BufferedInputStream(inputStream()); int c; while( (c=in.read()) != -1 ) { cs = 31 * cs + c; @@ -218,7 +218,7 @@ public static final LuanIn defaultStdin = new LuanIn() { - @Override public InputStream inputStream(Luan luan) { + @Override public InputStream inputStream() { return System.in; } @@ -230,15 +230,15 @@ return "stdin:"; } - @Override public String read_text(Luan luan) throws IOException { + @Override public String read_text() throws IOException { return Utils.readAll(new InputStreamReader(System.in)); } - @Override public byte[] read_binary(Luan luan) throws IOException { + @Override public byte[] read_binary() throws IOException { return Utils.readAll(System.in); } - @Override public boolean exists(Luan luan) { + @Override public boolean exists() { return true; } }; @@ -251,7 +251,7 @@ return charset==null ? new OutputStreamWriter(out) : new OutputStreamWriter(out,charset); } - public void write(Luan luan,Object obj) throws LuanException, IOException { + public void write(Object obj) throws LuanException, IOException { if( obj instanceof String ) { String s = (String)obj; Writer out = writer(); @@ -271,7 +271,7 @@ Object java = t.rawGet("java"); if( java instanceof LuanIn ) { LuanIn luanIn = (LuanIn)java; - InputStream in = luanIn.inputStream(luan); + InputStream in = luanIn.inputStream(); OutputStream out = outputStream(); Utils.copyAll(in,out); out.close(); @@ -290,9 +290,9 @@ return new BufferedOutputStream(outputStream()); } - public void write_text(Luan luan,Object... args) throws LuanException, IOException { + public void write_text(Object... args) throws LuanException, IOException { LuanWriter luanWriter = luanWriter(new BufferedWriter(writer())); - luanWriter.write(luan,args); + luanWriter.write(args); luanWriter.close(); } } @@ -307,7 +307,7 @@ @Override public void write(int b) {} }; - @Override public InputStream inputStream(Luan luan) { + @Override public InputStream inputStream() { return in; } @@ -333,7 +333,7 @@ this.s = s; } - @Override public InputStream inputStream(Luan luan) { + @Override public InputStream inputStream() { throw new UnsupportedOperationException(); } @@ -349,15 +349,15 @@ return "string:" + s; } - @Override public Reader reader(Luan luan) { + @Override public Reader reader() { return new StringReader(s); } - @Override public String read_text(Luan luan) { + @Override public String read_text() { return s; } - @Override public boolean exists(Luan luan) { + @Override public boolean exists() { return true; } @@ -398,7 +398,7 @@ this.file = file; } - @Override public InputStream inputStream(Luan luan) throws IOException { + @Override public InputStream inputStream() throws IOException { return new FileInputStream(file); } @@ -436,7 +436,7 @@ return new LuanFile(luan,parent); } - @Override public boolean exists(Luan luan) { + @Override public boolean exists() { return file.exists(); } @@ -546,7 +546,7 @@ this.dir = dir; } - @Override public InputStream inputStream(Luan luan) throws IOException { + @Override public InputStream inputStream() throws IOException { return proc.getInputStream(); } @@ -562,7 +562,7 @@ throw new UnsupportedOperationException(); } - @Override public boolean exists(Luan luan) { + @Override public boolean exists() { return true; } @@ -583,8 +583,8 @@ } } - @Override public String read_text(Luan luan) throws IOException, LuanException { - String s = super.read_text(luan); + @Override public String read_text() throws IOException, LuanException { + String s = super.read_text(); wait_for(); return s; } @@ -614,7 +614,7 @@ this.in = in; } - @Override public InputStream inputStream(Luan luan) { + @Override public InputStream inputStream() { return in; } @@ -626,7 +626,7 @@ throw new UnsupportedOperationException(); } - @Override public boolean exists(Luan luan) { + @Override public boolean exists() { return true; } };
--- a/src/luan/modules/JavaLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/JavaLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -22,6 +22,7 @@ import luan.LuanException; import luan.LuanFunction; import luan.LuanJavaFunction; +import luan.LuanCloner; public final class JavaLuan { @@ -31,13 +32,17 @@ luan.peek().javaOk = true; } - public static final LuanFunction javaFn; - static { - try { - javaFn = new LuanJavaFunction(JavaLuan.class.getMethod("java",Luan.class),null); - } catch(NoSuchMethodException e) { - throw new RuntimeException(e); + public static LuanFunction javaFn(Luan luan) { + LuanFunction fn = (LuanFunction)luan.registry().get("JavaLuan.java"); + if( fn == null ) { + try { + fn = new LuanJavaFunction(luan,JavaLuan.class.getMethod("java",Luan.class),null); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + luan.registry().put("JavaLuan.java",fn); } + return fn; } private static void checkJava(Luan luan) throws LuanException { @@ -59,11 +64,11 @@ Constructor[] constructors = cls.getConstructors(); if( constructors.length > 0 ) { if( constructors.length==1 ) { - return new LuanJavaFunction(constructors[0],null); + return new LuanJavaFunction(luan,constructors[0],null); } else { List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>(); for( Constructor constructor : constructors ) { - fns.add(new LuanJavaFunction(constructor,null)); + fns.add(new LuanJavaFunction(luan,constructor,null)); } return new AmbiguousJavaFunction(fns); } @@ -73,11 +78,11 @@ return new LuanJavaFunction(assertClass,new AssertClass(cls)); */ } else if( "luan_proxy".equals(name) ) { - return new LuanJavaFunction(luan_proxyMethod,st); + return new LuanJavaFunction(luan,luan_proxyMethod,st); } else { List<Member> members = getStaticMembers(cls,name); if( !members.isEmpty() ) { - return member(null,members); + return member(luan,null,members); } } } @@ -95,11 +100,11 @@ } else if( key instanceof String ) { String name = (String)key; if( "instanceof".equals(name) ) { - return new LuanJavaFunction(instanceOf,new InstanceOf(obj)); + return new LuanJavaFunction(luan,instanceOf,new InstanceOf(obj)); } else { List<Member> members = getMembers(cls,name); if( !members.isEmpty() ) { - return member(obj,members); + return member(luan,obj,members); } } } @@ -108,7 +113,7 @@ throw new LuanException( "invalid index '"+key+"' for java "+cls ); } - private static Object member(Object obj,List<Member> members) throws LuanException { + private static Object member(Luan luan,Object obj,List<Member> members) throws LuanException { try { if( members.size()==1 ) { Member member = members.get(0); @@ -120,13 +125,13 @@ return rtn instanceof Object[] ? Arrays.asList((Object[])rtn) : rtn; } else { Method method = (Method)member; - return new LuanJavaFunction(method,obj); + return new LuanJavaFunction(luan,method,obj); } } else { List<LuanJavaFunction> fns = new ArrayList<LuanJavaFunction>(); for( Member member : members ) { Method method = (Method)member; - fns.add(new LuanJavaFunction(method,obj)); + fns.add(new LuanJavaFunction(luan,method,obj)); } return new AmbiguousJavaFunction(fns); } @@ -309,7 +314,7 @@ return cls.isSynthetic(); } - public Object luan_proxy(final Luan luan,final LuanTable t) throws LuanException { + public Object luan_proxy(final LuanTable t) throws LuanException { return Proxy.newProxyInstance( cls.getClassLoader(), new Class[]{cls}, @@ -324,7 +329,7 @@ if( fnObj == null ) throw new NullPointerException("luan_proxy couldn't find method '"+name+"'"); LuanFunction fn = Luan.checkFunction(fnObj); - return Luan.first(fn.call(luan,args)); + return Luan.first(fn.call(args)); } } ); @@ -333,7 +338,7 @@ private static final Method luan_proxyMethod; static { try { - luan_proxyMethod = Static.class.getMethod("luan_proxy",Luan.class,LuanTable.class); + luan_proxyMethod = Static.class.getMethod("luan_proxy",LuanTable.class); luan_proxyMethod.setAccessible(true); } catch(NoSuchMethodException e) { throw new RuntimeException(e); @@ -361,11 +366,12 @@ } }; - private static class AmbiguousJavaFunction extends LuanFunction { - private final Map<Integer,List<LuanJavaFunction>> fnMap = new HashMap<Integer,List<LuanJavaFunction>>(); + private static final class AmbiguousJavaFunction extends LuanFunction { + private Map<Integer,List<LuanJavaFunction>> fnMap = new HashMap<Integer,List<LuanJavaFunction>>(); private List<LuanJavaFunction> varArgs = new ArrayList<LuanJavaFunction>(); AmbiguousJavaFunction(List<LuanJavaFunction> fns) { + super(true); for( LuanJavaFunction fn : fns ) { if( fn.isVarArgs() ) { varArgs.add(fn); @@ -382,18 +388,24 @@ Collections.sort(varArgs,varArgsSorter); } - @Override public Object call(Luan luan,Object[] args) throws LuanException { + @Override protected void completeClone(LuanFunction dc,LuanCloner cloner) { + AmbiguousJavaFunction clone = (AmbiguousJavaFunction)dc; + clone.fnMap = (Map)cloner.clone(fnMap); + clone.varArgs = (List)cloner.clone(varArgs); + } + + @Override public Object call(Object[] args) throws LuanException { List<LuanJavaFunction> list = fnMap.get(args.length); if( list != null ) { for( LuanJavaFunction fn : list ) { try { - return fn.rawCall(luan,args); + return fn.rawCall(args); } catch(IllegalArgumentException e) {} } } for( LuanJavaFunction fn : varArgs ) { try { - return fn.rawCall(luan,args); + return fn.rawCall(args); } catch(IllegalArgumentException e) {} } throw new LuanException("no method matched args: "+Arrays.asList(args));
--- a/src/luan/modules/PackageLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/PackageLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -15,13 +15,17 @@ public final class PackageLuan { - public static final LuanFunction requireFn; - static { - try { - requireFn = new LuanJavaFunction(PackageLuan.class.getMethod("require",Luan.class,String.class),null); - } catch(NoSuchMethodException e) { - throw new RuntimeException(e); + public static LuanFunction requireFn(Luan luan) { + LuanFunction fn = (LuanFunction)luan.registry().get("Package.require"); + if( fn == null ) { + try { + fn = new LuanJavaFunction(luan,PackageLuan.class.getMethod("require",Luan.class,String.class),null); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + luan.registry().put("Package.require",fn); } + return fn; } public static LuanTable loaded(Luan luan) { @@ -53,9 +57,9 @@ } catch(IOException e) { throw new RuntimeException(e); } - LuanFunction loader = Luan.load(src,modName); + LuanFunction loader = luan.load(src,modName); mod = Luan.first( - loader.call(luan,new Object[]{modName}) + loader.call(modName) ); if( mod == null ) throw new RuntimeException(); @@ -68,9 +72,9 @@ if( src == null ) { mod = Boolean.FALSE; } else { - LuanFunction loader = Luan.load(src,modName); + LuanFunction loader = luan.load(src,modName); mod = Luan.first( - loader.call(luan,new Object[]{modName}) + loader.call(modName) ); if( mod == null ) { mod = loaded.rawGet(modName); @@ -94,7 +98,7 @@ } Luan.Security security = Luan.setSecurity(luan,null); try { - return (String)Luan.first(boot.call("read",uri)); + return (String)Luan.first(boot.fn("read").call(uri)); } catch(LuanException e) { return null; } finally { @@ -103,17 +107,4 @@ } } - public static void enableLoad(Luan luan,String... mods) throws LuanException { - if( !luan.isLocked ) - return; - LuanTable loaded = loaded(luan); - for( String mod : mods ) { - if( loaded.rawGet(mod) == null ) { - luan.isLocked = false; - luan.deepenClone(luan,new LuanCloner(LuanCloner.Type.COMPLETE)); - break; - } - } - } - }
--- a/src/luan/modules/StringLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/StringLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -7,7 +7,6 @@ import luan.LuanTable; import luan.LuanFunction; import luan.LuanException; -import luan.LuanMethod; public final class StringLuan { @@ -30,7 +29,7 @@ return i==null ? dflt : end(s,i); } - @LuanMethod public static Integer[] unicode(String s,Integer i,Integer j) throws LuanException { + public static Integer[] unicode(String s,Integer i,Integer j) throws LuanException { Utils.checkNotNull(s); int start = start(s,i,1); int end = end(s,j,start+1); @@ -49,7 +48,7 @@ return new String(a); } - @LuanMethod public static byte[] to_binary(String s) { + public static byte[] to_binary(String s) { return s.getBytes(); } @@ -92,7 +91,7 @@ return s.substring(start,end); } - @LuanMethod public static Object[] find(String s,String pattern,Integer init,Boolean plain) { + public static Object[] find(String s,String pattern,Integer init,Boolean plain) { int start = start(s,init,0); if( Boolean.TRUE.equals(plain) ) { int i = s.indexOf(pattern,start); @@ -111,7 +110,7 @@ return rtn; } - @LuanMethod public static String[] match(String s,String pattern,Integer init) { + public static String[] match(String s,String pattern,Integer init) { int start = start(s,init,0); Matcher m = Pattern.compile(pattern).matcher(s); if( !m.find(start) ) @@ -129,8 +128,8 @@ public static LuanFunction gmatch(String s,String pattern) throws LuanException { Utils.checkNotNull(s); final Matcher m = Pattern.compile(pattern).matcher(s); - return new LuanFunction() { - @Override public Object call(Luan luan,Object[] args) { + return new LuanFunction(false) { + @Override public Object call(Object[] args) { if( !m.find() ) return null; final int n = m.groupCount(); @@ -145,7 +144,7 @@ }; } - @LuanMethod public static Object[] gsub(Luan luan,String s,String pattern,Object repl,Integer n) throws LuanException { + public static Object[] gsub(String s,String pattern,Object repl,Integer n) throws LuanException { Utils.checkNotNull(s); int max = n==null ? Integer.MAX_VALUE : n; final Matcher m = Pattern.compile(pattern).matcher(s); @@ -191,7 +190,7 @@ args[j] = m.group(j+1); } } - Object val = Luan.first( fn.call(luan,args) ); + Object val = Luan.first( fn.call(args) ); if( val != null ) { String replacement = Luan.luanToString(val); m.appendReplacement(sb,replacement); @@ -238,7 +237,7 @@ return Pattern.compile(pattern).matcher(s).find(); } - @LuanMethod public static String[] split(String s,String pattern,Integer limit) throws LuanException { + public static String[] split(String s,String pattern,Integer limit) throws LuanException { Utils.checkNotNull(s); int n = limit==null ? -1 : limit; return s.split(pattern,n);
--- a/src/luan/modules/TableLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/TableLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -9,7 +9,6 @@ import luan.LuanFunction; import luan.LuanException; import luan.LuanRuntimeException; -import luan.LuanMethod; public final class TableLuan { @@ -47,7 +46,7 @@ public boolean isLessThan(Object o1,Object o2); } - public static void sort(final Luan luan,LuanTable list,final LuanFunction comp) throws LuanException { + public static void sort(LuanTable list,final LuanFunction comp) throws LuanException { if( list.getMetatable() != null ) throw new LuanException("can't sort a table with a metatable"); final LessThan lt; @@ -55,7 +54,7 @@ lt = new LessThan() { public boolean isLessThan(Object o1,Object o2) { try { - return luan.isLessThan(o1,o2); + return Luan.isLessThan(o1,o2); } catch(LuanException e) { throw new LuanRuntimeException(e); } @@ -65,7 +64,7 @@ lt = new LessThan() { public boolean isLessThan(Object o1,Object o2) { try { - return Luan.checkBoolean(Luan.first(comp.call(luan,new Object[]{o1,o2}))); + return Luan.checkBoolean(Luan.first(comp.call(o1,o2))); } catch(LuanException e) { throw new LuanRuntimeException(e); } @@ -89,7 +88,7 @@ return tbl; } - @LuanMethod public static Object[] unpack(LuanTable tbl,Integer iFrom,Integer iTo) throws LuanException { + public static Object[] unpack(LuanTable tbl,Integer iFrom,Integer iTo) throws LuanException { int from = iFrom!=null ? iFrom : 1; int to; if( iTo != null ) { @@ -105,7 +104,7 @@ return list.toArray(); } - public static LuanTable copy(Luan luan,LuanTable list,Integer from,Integer to) { + public static LuanTable copy(LuanTable list,Integer from,Integer to) { if( from == null ) return new LuanTable(list); if( to == null )
--- a/src/luan/modules/ThreadLuan.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/ThreadLuan.java Thu Feb 14 03:10:45 2019 -0700 @@ -23,13 +23,12 @@ private static final Executor exec = Executors.newCachedThreadPool(); public static final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(1); - public static void fork(Luan luan,LuanFunction fn) { + public static void fork(LuanFunction fn) { LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - final Luan newLuan = (Luan)cloner.clone(luan); final LuanFunction newFn = (LuanFunction)cloner.get(fn); exec.execute(new Runnable(){public void run() { try { - newFn.call(newLuan); + newFn.call(); } catch(LuanException e) { e.printStackTrace(); } @@ -47,15 +46,16 @@ }; } */ - public static void schedule(Luan luan,long delay,LuanFunction fn,String repeating) + public static void schedule(long delay,LuanFunction fn,String repeating) throws LuanException { + Luan luan = fn.luan(); LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); final Luan newLuan = (Luan)cloner.clone(luan); final LuanFunction newFn = (LuanFunction)cloner.get(fn); Runnable r = new Runnable(){public void run() { try { - newFn.call(newLuan); + newFn.call(); } catch(LuanException e) { e.printStackTrace(); } @@ -166,7 +166,7 @@ private final Luan luan = new Luan(); private final LuanTable fns; - Callable(Luan luan,LuanTable fns) { + Callable(LuanTable fns) { LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); this.fns = (LuanTable)cloner.get(fns); } @@ -182,7 +182,7 @@ if( !(f instanceof LuanFunction) ) throw new LuanException("value of '"+fnName+"' not a function in global_callable"); LuanFunction fn = (LuanFunction)f; - Object rtn = fn.call(luan,args); + Object rtn = fn.call(args); rtn = makeSafe(callerLuan,rtn); if( rtn instanceof Unsafe ) throw new LuanException("can't return "+((Unsafe)rtn).reason+" from global_callable"); @@ -201,11 +201,11 @@ } } - public static synchronized Callable globalCallable(Luan luan,String name,LuanTable fns,long timeout) { + public static synchronized Callable globalCallable(String name,LuanTable fns,long timeout) { Callable callable = callableMap.get(name); if( callable == null ) { sweep(); - callable = new Callable(luan,fns); + callable = new Callable(fns); callableMap.put(name,callable); } callable.expires = System.currentTimeMillis() + timeout;
--- a/src/luan/modules/http/HttpServicer.java Tue Feb 12 22:53:57 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -package luan.modules.http; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import luan.webserver.Request; -import luan.webserver.Response; -import luan.Luan; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanTable; -import luan.LuanCloner; -import luan.modules.PackageLuan; - - -public final class HttpServicer { - private static final Logger logger = LoggerFactory.getLogger(HttpServicer.class); - - public static Response service(Luan luan,Request request,String modName) - throws LuanException - { - try { - return serviceLuan(luan,request,modName); - } catch(LuanException e) { - return handleError(luan,request,e); - } - } - - private static Response handleError(Luan luan,Request request,LuanException e) - throws LuanException - { -//e.printStackTrace(); - synchronized(luan) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (Luan)cloner.clone(luan); - } - LuanTable module = (LuanTable)luan.require("luan:http/Http.luan"); - return (Response)module.call( "handle_error", request, e.table(luan) ); - } - - private static Response serviceLuan(Luan luan,Request request,String modName) - throws LuanException - { - LuanFunction fn; - synchronized(luan) { - PackageLuan.enableLoad(luan,"luan:http/Http.luan",modName); - PackageLuan.require(luan,"luan:http/Http.luan"); - Object mod = PackageLuan.load(luan,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(luan); - fn = (LuanFunction)cloner.get(mod); - } - - LuanTable module = (LuanTable)luan.require("luan:http/Http.luan"); - module.call( "new_request", request ); - module.call( "new_response" ); - - fn.call(luan); - - return (Response)module.call( "finish" ); - } - - private HttpServicer() {} // never -}
--- a/src/luan/modules/http/LuanHandler.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/http/LuanHandler.java Thu Feb 14 03:10:45 2019 -0700 @@ -56,9 +56,9 @@ this.logger = LuanLogger.getLogger(luanInit,LuanHandler.class.getName()); try { LuanTable Http = (LuanTable)luanInit.require("luan:http/Http.luan"); - Http.put( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) ); - Http.put( "eval_in_root", new LuanJavaFunction(evalInRootMethod,this) ); - Http.put( "disable_luan", new LuanJavaFunction(disableLuanMethod,this) ); + Http.put( "reset_luan", new LuanJavaFunction(luanInit,resetLuanMethod,this) ); + Http.put( "eval_in_root", new LuanJavaFunction(luanInit,evalInRootMethod,this) ); + Http.put( "disable_luan", new LuanJavaFunction(luanInit,disableLuanMethod,this) ); } catch(LuanException e) { throw new RuntimeException(e); } @@ -66,8 +66,11 @@ } private Luan newLuan() { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - Luan luan = (Luan)cloner.clone(luanInit); + Luan luan; + synchronized(luanInit) { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); + luan = (Luan)cloner.clone(luanInit); + } luan.onClose = this; try { PackageLuan.load(luan,"site:/init.luan"); @@ -99,7 +102,7 @@ thread.setName(request.headers.get("host")+request.path); lock.readLock().lock(); try { - return HttpServicer.service(currentLuan,request,modName); + return service(request,modName); } catch(LuanException e) { String err = e.getLuanStackTraceString(); logger.error(err+"\n"+request.rawHead.trim()+"\n"); @@ -137,19 +140,17 @@ lock.readLock().lock(); try { LuanFunction fn; - Luan luan = currentLuan; - synchronized(luan) { - PackageLuan.enableLoad(luan,"luan:Rpc.luan"); - LuanTable rpc = (LuanTable)luan.require("luan:Rpc.luan"); + synchronized(luanInit) { + enableLoad("luan:Rpc.luan"); + LuanTable rpc = (LuanTable)currentLuan.require("luan:Rpc.luan"); LuanTable fns = (LuanTable)rpc.get("functions"); fn = (LuanFunction)fns.get(fnName); if( fn == null ) throw new LuanException( "function not found: " + fnName ); LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (Luan)cloner.clone(luan); fn = (LuanFunction)cloner.get(fn); } - return fn.call(luan,args); + return fn.call(args); } finally { lock.readLock().unlock(); } @@ -176,12 +177,12 @@ public Object runLuan(String sourceText,String sourceName) throws LuanException { lock.readLock().lock(); try { - LuanFunction fn = Luan.load(sourceText,sourceName); Luan luan = currentLuan; - synchronized(luan) { + synchronized(luanInit) { LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); Luan luan2 = (Luan)cloner.clone(luan); - return fn.call(luan2); + LuanFunction fn = luan2.load(sourceText,sourceName); + return fn.call(); } } finally { lock.readLock().unlock(); @@ -189,14 +190,13 @@ } public void eval_in_root(String text) throws LuanException { - Luan oldLuan = currentLuan; Luan luan; - synchronized(oldLuan) { + synchronized(luanInit) { LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - luan = (Luan)cloner.clone(oldLuan); + luan = (Luan)cloner.clone(currentLuan); } luan.onClose = this; - BasicLuan.load(text,"<eval_in_root>",null).call(luan); + luan.load(text,"<eval_in_root>",null).call(); currentLuan = luan; } @@ -208,4 +208,69 @@ } } + + + // from HttpServicer + + private Response service(Request request,String modName) + throws LuanException + { + try { + return serviceLuan(request,modName); + } catch(LuanException e) { + return handleError(request,e); + } + } + + private Response handleError(Request request,LuanException e) + throws LuanException + { +//e.printStackTrace(); + Luan luan; + synchronized(luanInit) { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + luan = (Luan)cloner.clone(currentLuan); + } + LuanTable module = (LuanTable)luan.require("luan:http/Http.luan"); + return (Response)module.fn("handle_error").call( request, e.table(luan) ); + } + + private Response serviceLuan(Request request,String modName) + throws LuanException + { + LuanFunction fn; + Luan luan; + synchronized(luanInit) { + enableLoad("luan:http/Http.luan",modName); + PackageLuan.require(currentLuan,"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); + } + + LuanTable module = (LuanTable)luan.require("luan:http/Http.luan"); + module.fn("new_request").call(request); + module.fn("new_response").call(); + + fn.call(); + + return (Response)module.fn("finish").call(); + } + + 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/logging/Log4j.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/logging/Log4j.java Thu Feb 14 03:10:45 2019 -0700 @@ -19,7 +19,7 @@ LoggerRepository lr = new Hierarchy(new RootLogger(Level.DEBUG)); luan.registry().put(KEY,lr); LuanTable module = (LuanTable)luan.require("luan:logging/Log4j.luan"); - module.call( "init_root" ); + module.fn("init_root").call(); } private static final LoggerRepository defaultLoggerRepository = LogManager.getLoggerRepository();
--- a/src/luan/modules/lucene/LuceneIndex.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/lucene/LuceneIndex.java Thu Feb 14 03:10:45 2019 -0700 @@ -200,7 +200,7 @@ for( Map.Entry<String,LuanFunction> entry : map.entrySet() ) { String name = entry.getKey(); LuanFunction fn = entry.getValue(); - Object value = Luan.first(fn.call(luan,new Object[]{doc})); + Object value = Luan.first(fn.call(doc)); doc.put( name, value ); indexedOnlySet.add(name); } @@ -230,11 +230,11 @@ } } - public void update_in_transaction(Luan luan,LuanFunction fn) throws IOException, LuanException { + public void update_in_transaction(LuanFunction fn) throws IOException, LuanException { boolean commit = !writeLock.isHeldByCurrentThread(); writeLock.lock(); try { - fn.call(luan); + fn.call(); if(commit) writer.commit(); } finally { wrote(); @@ -242,13 +242,13 @@ } } - public void run_in_lock(Luan luan,LuanFunction fn) throws IOException, LuanException { + public void run_in_lock(LuanFunction fn) throws IOException, LuanException { if( writeLock.isHeldByCurrentThread() ) throw new RuntimeException(); writeLock.lock(); try { synchronized(this) { - fn.call(luan); + fn.call(); } } finally { wrote(); @@ -318,7 +318,7 @@ try { String dir = fileDir.toString(); LuanTable fileNames = new LuanTable(luan,new ArrayList(ic.getFileNames())); - return fn.call(luan,new Object[]{dir,fileNames}); + return fn.call(dir,fileNames); } finally { snapshotDeletionPolicy.release(ic); } @@ -352,13 +352,14 @@ final IndexSearcher searcher; int docID; - DocFn(IndexSearcher searcher) { + DocFn(Luan luan,IndexSearcher searcher) { + super(luan); this.searcher = searcher; } - @Override public Object call(Luan luan,Object[] args) throws LuanException { + @Override public Object call(Object[] args) throws LuanException { try { - return toTable(luan,searcher.doc(docID)); + return toTable(luan(),searcher.doc(docID)); } catch(IOException e) { throw new LuanException(e); } @@ -413,12 +414,12 @@ if( fn!=null && n==null ) { if( sortStr != null ) throw new LuanException("sort must be nil when n is nil"); - final DocFn docFn = new DocFn(searcher); + final DocFn docFn = new DocFn(luan,searcher); MyCollector col = new MyCollector() { @Override public void collect(int doc) { try { docFn.docID = docBase + doc; - fn.call(luan,new Object[]{++i,docFn}); + fn.call(++i,docFn); } catch(LuanException e) { throw new LuanRuntimeException(e); } @@ -439,10 +440,10 @@ Sort sort = sortStr==null ? null : SaneQueryParser.parseSort(mfp,sortStr); TopDocs td = sort==null ? searcher.search(query,n) : searcher.search(query,n,sort); final ScoreDoc[] scoreDocs = td.scoreDocs; - DocFn docFn = new DocFn(searcher); + DocFn docFn = new DocFn(luan,searcher); for( int i=0; i<scoreDocs.length; i++ ) { docFn.docID = scoreDocs[i].doc; - fn.call(luan,new Object[]{i+1,docFn}); + fn.call(i+1,docFn); } return td.totalHits; } finally { @@ -451,13 +452,13 @@ } } - public Object search_in_transaction(Luan luan,LuanFunction fn) throws LuanException, IOException { + public Object search_in_transaction(LuanFunction fn) throws LuanException, IOException { if( threadLocalSearcher.get() != null ) throw new LuanException("can't nest search_in_transaction calls"); IndexSearcher searcher = openSearcher(); threadLocalSearcher.set(searcher); try { - return fn.call(luan); + return fn.call(); } finally { threadLocalSearcher.set(null); close(searcher); @@ -588,14 +589,14 @@ } }; - public LuanFunction highlighter(Luan luan,String queryStr,LuanFunction formatter,final Integer fragmentSize,String dotdotdot) throws ParseException { + public LuanFunction highlighter(String queryStr,LuanFunction formatter,final Integer fragmentSize,String dotdotdot) throws ParseException { Query query = SaneQueryParser.parseQuery(mfp,queryStr); Formatter fmt = new Formatter() { public String highlightTerm(String originalText,TokenGroup tokenGroup) { if( tokenGroup.getTotalScore() <= 0 ) return originalText; try { - return (String)Luan.first(formatter.call(luan,new Object[]{originalText})); + return (String)Luan.first(formatter.call(originalText)); } catch(LuanException e) { throw new LuanRuntimeException(e); } @@ -607,8 +608,8 @@ chooser.setTextFragmenter( new SimpleSpanFragmenter(queryScorer,fragmentSize) ); final Highlighter hl = new Highlighter(fmt,queryScorer); hl.setTextFragmenter( new NullFragmenter() ); - return new LuanFunction() { - @Override public String call(Luan luan,Object[] args) throws LuanException { + return new LuanFunction(false) { // ??? + @Override public String call(Object[] args) throws LuanException { String text = (String)args[0]; try { if( chooser != null ) {
--- a/src/luan/modules/parsers/BBCode.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/parsers/BBCode.java Thu Feb 14 03:10:45 2019 -0700 @@ -12,23 +12,21 @@ public final class BBCode { - public static String toHtml(Luan luan,String bbcode,LuanFunction quoter) throws LuanException { - return new BBCode(luan,bbcode,quoter,true).parse(); + public static String toHtml(String bbcode,LuanFunction quoter) throws LuanException { + return new BBCode(bbcode,quoter,true).parse(); } - public static String toText(Luan luan,String bbcode,LuanFunction quoter) throws LuanException { - return new BBCode(luan,bbcode,quoter,false).parse(); + public static String toText(String bbcode,LuanFunction quoter) throws LuanException { + return new BBCode(bbcode,quoter,false).parse(); } - private final Luan luan; private final Parser parser; private final LuanFunction quoter; private final boolean toHtml; - private BBCode(Luan luan,String text,LuanFunction quoter,boolean toHtml) throws LuanException { + private BBCode(String text,LuanFunction quoter,boolean toHtml) throws LuanException { Utils.checkNotNull(text,1); // Utils.checkNotNull(quoter,2); - this.luan = luan; this.parser = new Parser(text); this.quoter = quoter; this.toHtml = toHtml; @@ -285,7 +283,7 @@ else return ""; } - Object obj = quoter.call(luan,args); + Object obj = quoter.call(args); if( !(obj instanceof String) ) throw new LuanException("BBCode quoter function returned "+Luan.type(obj)+" but string required"); return (String)obj;
--- a/src/luan/modules/url/LuanUrl.java Tue Feb 12 22:53:57 2019 -0700 +++ b/src/luan/modules/url/LuanUrl.java Thu Feb 14 03:10:45 2019 -0700 @@ -195,19 +195,19 @@ return t==null ? null : t.asMap(); } - @Override public InputStream inputStream(Luan luan) throws IOException, LuanException { + @Override public InputStream inputStream() throws IOException, LuanException { try { - return inputStream(luan,null); + return inputStream(null); } catch(AuthException e) { try { - return inputStream(luan,e.authorization); + return inputStream(e.authorization); } catch(AuthException e2) { throw new RuntimeException(e2); // never } } } - private InputStream inputStream(Luan luan,String authorization) + private InputStream inputStream(String authorization) throws IOException, LuanException, AuthException { URLConnection con = url.openConnection(); @@ -238,12 +238,12 @@ HttpURLConnection httpCon = (HttpURLConnection)con; if( method==Method.GET ) { - return getInputStream(luan,httpCon,authorization); + return getInputStream(httpCon,authorization); } if( method==Method.DELETE ) { httpCon.setRequestMethod("DELETE"); - return getInputStream(luan,httpCon,authorization); + return getInputStream(httpCon,authorization); } // POST @@ -263,13 +263,13 @@ } out.flush(); try { - return getInputStream(luan,httpCon,authorization); + return getInputStream(httpCon,authorization); } finally { out.close(); } } - private InputStream getInputStream(Luan luan,HttpURLConnection httpCon,String authorization) + private InputStream getInputStream(HttpURLConnection httpCon,String authorization) throws IOException, LuanException, AuthException { try { @@ -335,9 +335,8 @@ String msg = Utils.readAll(in); in.close(); LuanException le = new LuanException(msg,e); - LuanTable tbl = le.table(luan); - tbl.rawPut("response_code",responseCode); - tbl.rawPut("response_message",responseMessage); + le.put("response_code",responseCode); + le.put("response_message",responseMessage); throw le; } }