comparison 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
comparison
equal deleted inserted replaced
1332:11b7e11f9ed5 1333:25746915a241
1 package luan; 1 package luan;
2 2
3 import java.lang.reflect.Array;
4 import java.io.Closeable;
3 import java.util.List; 5 import java.util.List;
4 import java.util.ArrayList; 6 import java.util.ArrayList;
5 import java.util.Map; 7 import java.util.Map;
8 import java.util.HashMap;
6 import java.util.LinkedHashMap; 9 import java.util.LinkedHashMap;
10 import java.util.Iterator;
11 import java.util.Arrays;
7 import java.util.Set; 12 import java.util.Set;
8 import java.util.Arrays; 13 import org.slf4j.Logger;
9 import java.util.Iterator; 14 import org.slf4j.LoggerFactory;
10 import luan.modules.BasicLuan; 15 import luan.modules.BasicLuan;
11 import luan.modules.Utils; 16 import luan.modules.JavaLuan;
17 import luan.modules.PackageLuan;
12 import luan.impl.LuanCompiler; 18 import luan.impl.LuanCompiler;
13 19
14 20
15 public final class Luan { 21 public final class Luan implements LuanCloneable {
22 private static final Logger logger = LoggerFactory.getLogger(Luan.class);
23
24 private final List<LuanClosure> stack = new ArrayList<LuanClosure>();
25 private Map registry;
26 public boolean isLocked = false;
27
28 public interface OnClose extends Closeable {
29 public void onClose(Closeable c);
30 }
31 public OnClose onClose;
32
33 public Luan() {
34 registry = new HashMap();
35 }
36
37 private Luan(Luan luan) {}
38
39 @Override public Luan shallowClone() {
40 return new Luan(this);
41 }
42
43 @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) {
44 Luan clone = (Luan)dc;
45 clone.registry = cloner.clone(registry);
46 if( cloner.type == LuanCloner.Type.INCREMENTAL )
47 isLocked = true;
48 }
49
50 public LuanClosure peek() {
51 return peek(1);
52 }
53
54 public LuanClosure peek(int i) {
55 int n = stack.size();
56 return n < i ? null : stack.get(n-i);
57 }
58
59 void push(LuanClosure closure) {
60 stack.add(closure);
61 }
62
63 void pop() {
64 stack.remove(stack.size()-1);
65 }
66
67 public Map registry() {
68 return registry;
69 }
70
71 public void onClose(Closeable c) {
72 if( onClose != null )
73 onClose.onClose(c);
74 }
75
76 public Object eval(String cmd,Object... args) throws LuanException {
77 return Luan.load(cmd,"eval").call(this,args);
78 }
79
80 public Object require(String modName) throws LuanException {
81 return PackageLuan.require(this,modName);
82 }
83
84 public String toString(Object obj) throws LuanException {
85 if( obj instanceof LuanTable ) {
86 LuanTable tbl = (LuanTable)obj;
87 return tbl.toStringLuan();
88 }
89 if( obj == null )
90 return "nil";
91 if( obj instanceof Number )
92 return Luan.toString((Number)obj);
93 if( obj instanceof byte[] )
94 return "binary: " + Integer.toHexString(obj.hashCode());
95 return obj.toString();
96 }
97
98 public Object index(Object obj,Object key) throws LuanException {
99 if( obj instanceof LuanTable ) {
100 LuanTable tbl = (LuanTable)obj;
101 return tbl.get(key);
102 }
103 if( obj != null && peek().javaOk )
104 return JavaLuan.__index(this,obj,key);
105 throw new LuanException("attempt to index a " + Luan.type(obj) + " value" );
106 }
107
108
109 public boolean isLessThan(Object o1,Object o2) throws LuanException {
110 if( o1 instanceof Number && o2 instanceof Number ) {
111 Number n1 = (Number)o1;
112 Number n2 = (Number)o2;
113 return n1.doubleValue() < n2.doubleValue();
114 }
115 if( o1 instanceof String && o2 instanceof String ) {
116 String s1 = (String)o1;
117 String s2 = (String)o2;
118 return s1.compareTo(s2) < 0;
119 }
120 LuanFunction fn = getBinHandler("__lt",o1,o2);
121 if( fn != null )
122 return Luan.checkBoolean( Luan.first(fn.call(this,new Object[]{o1,o2})) );
123 throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) );
124 }
125
126 public LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException {
127 if( o1 instanceof LuanTable ) {
128 LuanFunction f1 = getHandlerFunction(op,(LuanTable)o1);
129 if( f1 != null )
130 return f1;
131 }
132 return o2 instanceof LuanTable ? getHandlerFunction(op,(LuanTable)o2) : null;
133 }
134
135 public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException {
136 Object f = t.getHandler(op);
137 if( f == null )
138 return null;
139 return Luan.checkFunction(f);
140 }
141
142 public LuanTable toTable(Object obj) {
143 if( obj == null )
144 return null;
145 if( obj instanceof LuanTable )
146 return (LuanTable)obj;
147 if( obj instanceof List ) {
148 return new LuanTable(this,(List)obj);
149 }
150 if( obj instanceof Map ) {
151 return new LuanTable(this,(Map)obj);
152 }
153 if( obj instanceof Set ) {
154 return new LuanTable(this,(Set)obj);
155 }
156 Class cls = obj.getClass();
157 if( cls.isArray() ) {
158 if( cls.getComponentType().isPrimitive() ) {
159 int len = Array.getLength(obj);
160 List list = new ArrayList();
161 for( int i=0; i<len; i++ ) {
162 list.add(Array.get(obj,i));
163 }
164 return new LuanTable(this,list);
165 } else {
166 Object[] a = (Object[])obj;
167 return new LuanTable(this,Arrays.asList(a));
168 }
169 }
170 return null;
171 }
172
173
174
175 // static
16 176
17 public static void main(String[] args) throws LuanException { 177 public static void main(String[] args) throws LuanException {
18 doFile( "classpath:luan/cmd_line.luan", args ); 178 doFile( "classpath:luan/cmd_line.luan", args );
19 } 179 }
20 180
21 public static void doFile(String uri,String... args) throws LuanException { 181 public static void doFile(String uri,String... args) throws LuanException {
22 LuanState luan = new LuanState(); 182 Luan luan = new Luan();
23 LuanFunction fn = (LuanFunction)BasicLuan.load_file(luan,uri); 183 LuanFunction fn = (LuanFunction)BasicLuan.load_file(luan,uri);
24 fn.call(luan,args); 184 fn.call(luan,args);
25 } 185 }
26 186
27 public static Object first(Object obj) { 187 public static Object first(Object obj) {
96 s = s.replace("\'","\\'"); 256 s = s.replace("\'","\\'");
97 return s; 257 return s;
98 } 258 }
99 259
100 260
101 // from LuanState
102
103 public static Boolean checkBoolean(Object obj) throws LuanException { 261 public static Boolean checkBoolean(Object obj) throws LuanException {
104 if( obj instanceof Boolean ) 262 if( obj instanceof Boolean )
105 return (Boolean)obj; 263 return (Boolean)obj;
106 throw new LuanException("attempt to use a " + Luan.type(obj) + " value as a boolean" ); 264 throw new LuanException("attempt to use a " + Luan.type(obj) + " value as a boolean" );
107 } 265 }
127 public static LuanFunction load(String text,String sourceName) 285 public static LuanFunction load(String text,String sourceName)
128 throws LuanException 286 throws LuanException
129 { 287 {
130 return load(text,sourceName,null); 288 return load(text,sourceName,null);
131 } 289 }
132
133 /*
134 public static Object toLuan(Object obj) throws LuanException {
135 if( !type(obj).equals("java") )
136 return obj;
137 LuanTable tbl = new LuanTable();
138 if( obj instanceof Map ) {
139 Map map = (Map)obj;
140 for( Object stupid : map.entrySet() ) {
141 Map.Entry entry = (Map.Entry)stupid;
142 Object key = entry.getKey();
143 Object value = entry.getValue();
144 if( key != null && value != null )
145 tbl.rawPut(toLuan(key),toLuan(value));
146 }
147 return tbl;
148 }
149 if( obj instanceof Set ) {
150 Set set = (Set)obj;
151 for( Object el : set ) {
152 if( el != null )
153 tbl.rawPut(toLuan(el),Boolean.TRUE);
154 }
155 return tbl;
156 }
157 List list;
158 if( obj instanceof List ) {
159 list = (List)obj;
160 } else {
161 Class cls = obj.getClass();
162 if( cls.isArray() && !cls.getComponentType().isPrimitive() ) {
163 Object[] a = (Object[])obj;
164 list = Arrays.asList(a);
165 } else
166 throw new LuanException("can't convert type "+obj.getClass().getName()+" to luan");
167 }
168 int n = list.size();
169 for( int i=0; i<n; i++ ) {
170 Object val = list.get(i);
171 if( val != null )
172 tbl.rawPut(i+1,toLuan(val));
173 }
174 return tbl;
175 }
176 */
177 290
178 public static Object toJava(Object obj) throws LuanException { 291 public static Object toJava(Object obj) throws LuanException {
179 if( !(obj instanceof LuanTable) ) 292 if( !(obj instanceof LuanTable) )
180 return obj; 293 return obj;
181 LuanTable tbl = (LuanTable)obj; 294 LuanTable tbl = (LuanTable)obj;
193 map.put( toJava(entry.getKey()), toJava(entry.getValue()) ); 306 map.put( toJava(entry.getKey()), toJava(entry.getValue()) );
194 } 307 }
195 return map; 308 return map;
196 } 309 }
197 } 310 }
198 /*
199 public static LuanTable table(LuanTable v) throws LuanException {
200 Utils.checkNotNull(v);
201 return v;
202 }
203 */
204
205 311
206 312
207 // security 313 // security
208 314
209 public interface Security { 315 public interface Security {
210 public void check(LuanState luan,LuanClosure closure,String op,Object... args) throws LuanException; 316 public void check(Luan luan,LuanClosure closure,String op,Object... args) throws LuanException;
211 } 317 }
212 318
213 private static String SECURITY_KEY = "Luan.Security"; 319 private static String SECURITY_KEY = "Luan.Security";
214 320
215 public static void checkSecurity(LuanState luan,String op,Object... args) throws LuanException { 321 public static void checkSecurity(Luan luan,String op,Object... args) throws LuanException {
216 check(luan,1,op,args); 322 check(luan,1,op,args);
217 } 323 }
218 324
219 public static void checkCallerSecurity(LuanState luan,String op,Object... args) throws LuanException { 325 public static void checkCallerSecurity(Luan luan,String op,Object... args) throws LuanException {
220 check(luan,2,op,args); 326 check(luan,2,op,args);
221 } 327 }
222 328
223 private static void check(LuanState luan,int i,String op,Object... args) throws LuanException { 329 private static void check(Luan luan,int i,String op,Object... args) throws LuanException {
224 Security s = (Security)luan.registry().get(SECURITY_KEY); 330 Security s = (Security)luan.registry().get(SECURITY_KEY);
225 if( s!=null ) 331 if( s!=null )
226 s.check(luan,luan.peek(),op,args); 332 s.check(luan,luan.peek(),op,args);
227 } 333 }
228 334
229 public static Security setSecurity(LuanState luan,Security s) { 335 public static Security setSecurity(Luan luan,Security s) {
230 return (Security)luan.registry().put(SECURITY_KEY,s); 336 return (Security)luan.registry().put(SECURITY_KEY,s);
231 } 337 }
232 338
233
234 private Luan() {} // never
235 } 339 }