Mercurial Hosting > luan
comparison src/luan/Luan.java @ 1578:c922446f53aa
immutable threading
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 08 Feb 2021 14:16:19 -0700 |
parents | 8fbcc4747091 |
children | 2975c932864d |
comparison
equal
deleted
inserted
replaced
1577:60e5c324adf9 | 1578:c922446f53aa |
---|---|
8 import java.util.HashMap; | 8 import java.util.HashMap; |
9 import java.util.LinkedHashMap; | 9 import java.util.LinkedHashMap; |
10 import java.util.Iterator; | 10 import java.util.Iterator; |
11 import java.util.Arrays; | 11 import java.util.Arrays; |
12 import java.util.Set; | 12 import java.util.Set; |
13 import java.util.Collection; | |
13 import goodjava.logging.Logger; | 14 import goodjava.logging.Logger; |
14 import goodjava.logging.LoggerFactory; | 15 import goodjava.logging.LoggerFactory; |
15 import luan.modules.JavaLuan; | 16 import luan.modules.JavaLuan; |
16 import luan.modules.PackageLuan; | 17 import luan.modules.PackageLuan; |
17 import luan.modules.IoLuan; | 18 import luan.modules.IoLuan; |
18 import luan.modules.logging.LuanLogger; | 19 import luan.modules.logging.LuanLogger; |
19 import luan.impl.LuanCompiler; | 20 import luan.impl.LuanCompiler; |
20 | 21 |
21 | 22 |
22 public final class Luan implements LuanCloneable { | 23 public final class Luan { |
23 private static final Logger logger = LoggerFactory.getLogger(Luan.class); | 24 private static final Logger logger = LoggerFactory.getLogger(Luan.class); |
24 | 25 |
25 private final List<LuanClosure> stack = new ArrayList<LuanClosure>(); | 26 private final List<LuanClosure> stack = new ArrayList<LuanClosure>(); |
26 private Map registry; | 27 private final Map registry; |
27 private boolean isLocked = false; | 28 private final Map localOnly = new HashMap(); |
28 | 29 |
29 public Luan() { | 30 public Luan() { |
30 registry = new HashMap(); | 31 registry = new HashMap(); |
31 } | 32 } |
32 | 33 |
33 private Luan(Luan luan) {} | 34 public Luan(Luan luan) { |
34 | 35 LuanMutable.makeImmutable(luan.registry); |
35 @Override public Luan shallowClone() { | 36 this.registry = clone(luan.registry); |
36 return new Luan(this); | 37 } |
37 } | 38 |
38 | 39 private static Object[] clone(Object[] obj) { |
39 @Override public void deepenClone(LuanCloneable dc,LuanCloner cloner) { | 40 if( obj.length == 0 ) |
40 Luan clone = (Luan)dc; | 41 return obj; |
41 clone.registry = cloner.clone(registry); | 42 Object[] rtn = obj.clone(); |
42 if( cloner.type == LuanCloner.Type.INCREMENTAL ) | 43 for( int i=0; i<rtn.length; i++ ) { |
43 isLocked = true; | 44 rtn[i] = clone(rtn[i]); |
44 } | 45 } |
45 | 46 return rtn; |
46 @Override public void makeImmutable(LuanImmutabler immutabler) {} | 47 } |
48 | |
49 private static Map clone(Map obj) { | |
50 Map rtn; | |
51 try { | |
52 rtn = obj.getClass().newInstance(); | |
53 } catch(InstantiationException e) { | |
54 throw new RuntimeException(e); | |
55 } catch(IllegalAccessException e) { | |
56 throw new RuntimeException(e); | |
57 } | |
58 for( Object stupid : obj.entrySet() ) { | |
59 Map.Entry entry = (Map.Entry)stupid; | |
60 rtn.put( clone(entry.getKey()), clone(entry.getValue()) ); | |
61 } | |
62 return rtn; | |
63 } | |
64 | |
65 private static Collection clone(Collection obj) { | |
66 Collection rtn; | |
67 try { | |
68 rtn = obj.getClass().newInstance(); | |
69 } catch(InstantiationException e) { | |
70 throw new RuntimeException(e); | |
71 } catch(IllegalAccessException e) { | |
72 throw new RuntimeException(e); | |
73 } | |
74 for( Object entry : (Collection)obj ) { | |
75 rtn.add( clone(entry) ); | |
76 } | |
77 return rtn; | |
78 } | |
79 | |
80 private static Object clone(Object obj) { | |
81 if( obj instanceof Object[] ) | |
82 return clone((Object[])obj); | |
83 if( obj instanceof Map ) | |
84 return clone((Map)obj); | |
85 if( obj instanceof Collection ) | |
86 return clone((Collection)obj); | |
87 return obj; | |
88 } | |
89 | |
90 private Map clonedLocals(Object obj) { | |
91 Map locals = (Map)registry.get("Luan.local"); | |
92 if( locals==null ) { | |
93 locals = new HashMap(); | |
94 registry.put("Luan.local",locals); | |
95 } | |
96 Map local = (Map)locals.get(obj); | |
97 if( local==null ) { | |
98 local = new HashMap(); | |
99 locals.put(obj,local); | |
100 } | |
101 return local; | |
102 } | |
103 | |
104 public Object getLocalCloned(Object obj,Object key) { | |
105 return clonedLocals(obj).get(key); | |
106 } | |
107 | |
108 public void setLocalCloned(Object obj,Object key,Object value) { | |
109 if( value==null ) | |
110 clonedLocals(obj).remove(key); | |
111 else | |
112 clonedLocals(obj).put(key,value); | |
113 } | |
114 | |
115 private Map onlyLocals(Object obj) { | |
116 Map local = (Map)localOnly.get(obj); | |
117 if( local==null ) { | |
118 local = new HashMap(); | |
119 localOnly.put(obj,local); | |
120 } | |
121 return local; | |
122 } | |
123 | |
124 public Object getLocalOnly(Object obj,Object key) { | |
125 return onlyLocals(obj).get(key); | |
126 } | |
127 | |
128 public void setLocalOnly(Object obj,Object key,Object value) { | |
129 if( value==null ) | |
130 onlyLocals(obj).remove(key); | |
131 else | |
132 onlyLocals(obj).put(key,value); | |
133 } | |
47 | 134 |
48 public LuanClosure peek() { | 135 public LuanClosure peek() { |
49 return peek(1); | 136 return peek(1); |
50 } | 137 } |
51 | 138 |
53 int n = stack.size(); | 140 int n = stack.size(); |
54 return n < i ? null : stack.get(n-i); | 141 return n < i ? null : stack.get(n-i); |
55 } | 142 } |
56 | 143 |
57 void push(LuanClosure closure) { | 144 void push(LuanClosure closure) { |
58 if( isLocked ) | |
59 throw new RuntimeException(this+" is locked "+closure); | |
60 stack.add(closure); | 145 stack.add(closure); |
61 } | 146 } |
62 | 147 |
63 void pop() { | 148 void pop() { |
64 stack.remove(stack.size()-1); | 149 stack.remove(stack.size()-1); |
116 if( fn != null ) | 201 if( fn != null ) |
117 return Luan.checkBoolean( Luan.first(fn.call(this,o1,o2)) ); | 202 return Luan.checkBoolean( Luan.first(fn.call(this,o1,o2)) ); |
118 throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); | 203 throw new LuanException( "attempt to compare " + Luan.type(o1) + " with " + Luan.type(o2) ); |
119 } | 204 } |
120 | 205 |
121 public static LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException { | 206 public LuanFunction getBinHandler(String op,Object o1,Object o2) throws LuanException { |
122 if( o1 instanceof LuanTable ) { | 207 if( o1 instanceof LuanTable ) { |
123 LuanFunction f1 = getHandlerFunction(op,(LuanTable)o1); | 208 LuanFunction f1 = getHandlerFunction(op,(LuanTable)o1); |
124 if( f1 != null ) | 209 if( f1 != null ) |
125 return f1; | 210 return f1; |
126 } | 211 } |
127 return o2 instanceof LuanTable ? getHandlerFunction(op,(LuanTable)o2) : null; | 212 return o2 instanceof LuanTable ? getHandlerFunction(op,(LuanTable)o2) : null; |
128 } | 213 } |
129 | 214 |
130 public static LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException { | 215 public LuanFunction getHandlerFunction(String op,LuanTable t) throws LuanException { |
131 Object f = t.getHandler(op); | 216 Object f = t.getHandler(this,op); |
132 if( f == null ) | 217 if( f == null ) |
133 return null; | 218 return null; |
134 return Luan.checkFunction(f); | 219 return Luan.checkFunction(f); |
135 } | 220 } |
136 | 221 |