Mercurial Hosting > luan
diff src/luan/Luan.java @ 1333:25746915a241
merge Luan and LuanState
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 12 Feb 2019 22:33:40 -0700 |
parents | f41919741100 |
children | c88b486a9511 |
line wrap: on
line diff
--- a/src/luan/Luan.java Tue Feb 12 21:50:26 2019 -0700 +++ b/src/luan/Luan.java Tue Feb 12 22:33:40 2019 -0700 @@ -1,25 +1,185 @@ package luan; +import java.lang.reflect.Array; +import java.io.Closeable; import java.util.List; import java.util.ArrayList; import java.util.Map; +import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.Set; +import java.util.Iterator; import java.util.Arrays; -import java.util.Iterator; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import luan.modules.BasicLuan; -import luan.modules.Utils; +import luan.modules.JavaLuan; +import luan.modules.PackageLuan; import luan.impl.LuanCompiler; -public final class Luan { +public final class Luan implements LuanCloneable { + private static final Logger logger = LoggerFactory.getLogger(Luan.class); + + private final List<LuanClosure> stack = new ArrayList<LuanClosure>(); + private Map registry; + public boolean isLocked = false; + + public interface OnClose extends Closeable { + public void onClose(Closeable c); + } + public OnClose onClose; + + public Luan() { + registry = new HashMap(); + } + + private Luan(Luan luan) {} + + @Override public Luan shallowClone() { + return new Luan(this); + } + + @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { + Luan clone = (Luan)dc; + clone.registry = cloner.clone(registry); + if( cloner.type == LuanCloner.Type.INCREMENTAL ) + isLocked = true; + } + + public LuanClosure peek() { + return peek(1); + } + + public LuanClosure peek(int i) { + int n = stack.size(); + return n < i ? null : stack.get(n-i); + } + + void push(LuanClosure closure) { + stack.add(closure); + } + + void pop() { + stack.remove(stack.size()-1); + } + + public Map registry() { + return registry; + } + + public void onClose(Closeable c) { + if( onClose != null ) + onClose.onClose(c); + } + + public Object eval(String cmd,Object... args) throws LuanException { + return Luan.load(cmd,"eval").call(this,args); + } + + public Object require(String modName) throws LuanException { + return PackageLuan.require(this,modName); + } + + public String toString(Object obj) throws LuanException { + if( obj instanceof LuanTable ) { + LuanTable tbl = (LuanTable)obj; + return tbl.toStringLuan(); + } + if( obj == null ) + return "nil"; + if( obj instanceof Number ) + return Luan.toString((Number)obj); + if( obj instanceof byte[] ) + return "binary: " + Integer.toHexString(obj.hashCode()); + return obj.toString(); + } + + public Object index(Object obj,Object key) throws LuanException { + if( obj instanceof LuanTable ) { + LuanTable tbl = (LuanTable)obj; + return tbl.get(key); + } + if( obj != null && peek().javaOk ) + return JavaLuan.__index(this,obj,key); + throw new LuanException("attempt to index a " + Luan.type(obj) + " value" ); + } + + + public boolean isLessThan(Object o1,Object o2) throws LuanException { + if( o1 instanceof Number && o2 instanceof Number ) { + Number n1 = (Number)o1; + Number n2 = (Number)o2; + return n1.doubleValue() < n2.doubleValue(); + } + if( o1 instanceof String && o2 instanceof String ) { + String s1 = (String)o1; + String s2 = (String)o2; + return s1.compareTo(s2) < 0; + } + LuanFunction fn = getBinHandler("__lt",o1,o2); + if( fn != null ) + return Luan.checkBoolean( Luan.first(fn.call(this,new Object[]{o1,o2})) ); + throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); + } + + public LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException { + if( o1 instanceof LuanTable ) { + LuanFunction f1 = getHandlerFunction(op,(LuanTable)o1); + if( f1 != null ) + return f1; + } + return o2 instanceof LuanTable ? getHandlerFunction(op,(LuanTable)o2) : null; + } + + public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException { + Object f = t.getHandler(op); + if( f == null ) + return null; + return Luan.checkFunction(f); + } + + public LuanTable toTable(Object obj) { + if( obj == null ) + return null; + if( obj instanceof LuanTable ) + return (LuanTable)obj; + if( obj instanceof List ) { + return new LuanTable(this,(List)obj); + } + if( obj instanceof Map ) { + return new LuanTable(this,(Map)obj); + } + if( obj instanceof Set ) { + return new LuanTable(this,(Set)obj); + } + Class cls = obj.getClass(); + if( cls.isArray() ) { + if( cls.getComponentType().isPrimitive() ) { + int len = Array.getLength(obj); + List list = new ArrayList(); + for( int i=0; i<len; i++ ) { + list.add(Array.get(obj,i)); + } + return new LuanTable(this,list); + } else { + Object[] a = (Object[])obj; + return new LuanTable(this,Arrays.asList(a)); + } + } + return null; + } + + + + // static public static void main(String[] args) throws LuanException { doFile( "classpath:luan/cmd_line.luan", args ); } public static void doFile(String uri,String... args) throws LuanException { - LuanState luan = new LuanState(); + Luan luan = new Luan(); LuanFunction fn = (LuanFunction)BasicLuan.load_file(luan,uri); fn.call(luan,args); } @@ -98,8 +258,6 @@ } - // from LuanState - public static Boolean checkBoolean(Object obj) throws LuanException { if( obj instanceof Boolean ) return (Boolean)obj; @@ -130,51 +288,6 @@ return load(text,sourceName,null); } -/* - public static Object toLuan(Object obj) throws LuanException { - if( !type(obj).equals("java") ) - return obj; - LuanTable tbl = new LuanTable(); - if( obj instanceof Map ) { - Map map = (Map)obj; - for( Object stupid : map.entrySet() ) { - Map.Entry entry = (Map.Entry)stupid; - Object key = entry.getKey(); - Object value = entry.getValue(); - if( key != null && value != null ) - tbl.rawPut(toLuan(key),toLuan(value)); - } - return tbl; - } - if( obj instanceof Set ) { - Set set = (Set)obj; - for( Object el : set ) { - if( el != null ) - tbl.rawPut(toLuan(el),Boolean.TRUE); - } - return tbl; - } - List list; - if( obj instanceof List ) { - list = (List)obj; - } else { - Class cls = obj.getClass(); - if( cls.isArray() && !cls.getComponentType().isPrimitive() ) { - Object[] a = (Object[])obj; - list = Arrays.asList(a); - } else - throw new LuanException("can't convert type "+obj.getClass().getName()+" to luan"); - } - int n = list.size(); - for( int i=0; i<n; i++ ) { - Object val = list.get(i); - if( val != null ) - tbl.rawPut(i+1,toLuan(val)); - } - return tbl; - } -*/ - public static Object toJava(Object obj) throws LuanException { if( !(obj instanceof LuanTable) ) return obj; @@ -195,41 +308,32 @@ return map; } } -/* - public static LuanTable table(LuanTable v) throws LuanException { - Utils.checkNotNull(v); - return v; - } -*/ - // security public interface Security { - public void check(LuanState luan,LuanClosure closure,String op,Object... args) throws LuanException; + public void check(Luan luan,LuanClosure closure,String op,Object... args) throws LuanException; } private static String SECURITY_KEY = "Luan.Security"; - public static void checkSecurity(LuanState luan,String op,Object... args) throws LuanException { + public static void checkSecurity(Luan luan,String op,Object... args) throws LuanException { check(luan,1,op,args); } - public static void checkCallerSecurity(LuanState luan,String op,Object... args) throws LuanException { + public static void checkCallerSecurity(Luan luan,String op,Object... args) throws LuanException { check(luan,2,op,args); } - private static void check(LuanState luan,int i,String op,Object... args) throws LuanException { + private static void check(Luan luan,int i,String op,Object... args) throws LuanException { Security s = (Security)luan.registry().get(SECURITY_KEY); if( s!=null ) s.check(luan,luan.peek(),op,args); } - public static Security setSecurity(LuanState luan,Security s) { + public static Security setSecurity(Luan luan,Security s) { return (Security)luan.registry().put(SECURITY_KEY,s); } - - private Luan() {} // never }