remove a crufty folder that's done nothing for quite a while...
[supercollider.git] / build / SCClassLibrary / JITLib / ProxySpace / EnvironmentRedirect.sc
blob92091c189082ad0de468ae82f95bbc330cd5a9d4
3 // abstract class that dispatches assignment / reference in environments.
5 EnvironmentRedirect {
7         var <envir;
8         var <dispatch;
9         
10         *new { arg envir;
11                 ^super.newCopyArgs(envir ?? { Environment.new(32, Environment.new) })
12         }
13         *make { arg function;
14                 ^this.new.make(function)
15         }
16         *use { arg function;
17                 ^this.new.use(function)
18         }
19         *newFrom { arg aCollection;
20                 var newCollection = this.new;
21                 aCollection.keysValuesDo({ arg k,v, i; newCollection.put(k,v) });
22                 ^newCollection
23         }
24         
25         // override in subclasses
26         
27         at { arg key;
28                 ^envir.at(key)
29         }
30         
31         put { arg key, obj;
32                 envir.put(key, obj);
33                 dispatch.value(key, obj);
34         }
35         
36         localPut { arg key, obj;
37         envir.put(key, obj)
38      }
39         
40         removeAt { arg key;
41                 ^envir.removeAt(key)
42         }
43         
44         // behave like environment
45         
46         
47         *push {
48                 ^this.new.push;
49         }
50         
51         *pop {
52                 ^Environment.pop;
53         }
54         
55         pop {
56                 ^Environment.pop
57         }
58         
59         push { 
60                 if(currentEnvironment !== this) {
61                         Environment.push(this)
62                 } { "this environment is already current".warn } 
63         }
64         
65         
66         make { arg function;
67                 // pushes the Envir, executes function, returns the Envir
68                 // usually used to create an environment by adding new variables to it.
69                 var result, saveEnvir;
70                 
71                 saveEnvir = currentEnvironment;
72                 currentEnvironment = this;
73                 protect {
74                         function.value(this);
75                 }{
76                         currentEnvironment = saveEnvir;
77                 };
78         }
79         
80         use { arg function;
81                 // temporarily replaces the currentEnvironment with this, 
82                 // executes function, returns the result of the function
83                 var result, saveEnvir;
84                 
85                 saveEnvir = currentEnvironment;
86                 currentEnvironment = this;
87                 protect {
88                         result = function.value(this);
89                 }{
90                         currentEnvironment = saveEnvir;
91                 };
92                 ^result
93         }
94                 
95         do { arg function;
96                 envir.do(function)
97         }
99         keysValuesDo { arg function;
100                 envir.keysValuesDo(function);
101         }
102         
103         keysValuesArrayDo { arg argArray, function;
104                 envir.keysValuesArrayDo(argArray, function);
105         }
106         findKeyForValue { arg val;
107                 ^envir.findKeyForValue(val)
108         }
109         sortedKeysValuesDo { arg function;
110                 envir.sortedKeysValuesDo(function);
111         }
112         putAll { arg ... dictionaries; 
113                 dictionaries.do {|dict| 
114                         dict.keysValuesDo { arg key, value; 
115                                 this.put(key, value) 
116                         }
117                 }
118         }
119         
120         choose {
121         ^envir.choose
122      }
123      
124      clear { envir.clear }
125      
126      know_ { arg flag; envir.know = flag }
127      know { ^envir.know }
128         
129         doesNotUnderstand { arg selector ... args;
130                 var func;
131                 if (this.know) {
132                         if (selector.isSetter) {
133                                 selector = selector.asGetter;
134                                 ^this[selector] = args[0];
135                         };
136                         ^this.doFunctionPerform(selector, args)
138                 };
139                 ^this.superPerformList(\doesNotUnderstand, selector, args);
140         }
141         
142         doFunctionPerform { arg selector, args;
143                 envir[\forward] !? {
144                         if(envir[selector].isNil) { 
145                                 ^envir[\forward].functionPerformList(\value, this, selector, args);
146                         }
147                 };
148                 ^this[selector].functionPerformList(\value, this, args);
149         }
150                   
151      linkDoc { arg doc, pushNow=true;
152         doc = doc ? Document.current;
153         doc.envir_(this);
154         if(pushNow and: { currentEnvironment !== this }) { this.push };
155      }
156      
157      unlinkDoc { arg doc, popNow = false;
158         doc = doc ? Document.current;
159         if(doc.envir === this) { doc.envir_(nil) };
160         if(popNow and:  { currentEnvironment === this }) { this.pop };
161      }
162      
163      // networking
164      dispatch_ { arg disp;
165              dispatch = disp.envir_(this);
166         }
167         envir_ { arg argEnvir;
168                 envir = argEnvir;
169                 if(dispatch.notNil) { this.dispatch = dispatch };
170         }
171         
177 LazyEnvir : EnvironmentRedirect {
178         var <>proxyClass=\Maybe;
179         
180         makeProxy {
181                 ^proxyClass.asClass.new
182         }
183         
184         at { arg key;
185                 var proxy;
186                 proxy = super.at(key);
187                 if(proxy.isNil) {
188                         proxy = this.makeProxy(key);
189                         envir.put(key, proxy);
190                 };
191                 ^proxy
192         
193         }
194         
195         put { arg key, obj;
196                 this.at(key).source_(obj);
197                 dispatch.value(key, obj); // forward to dispatch for networking
198         }
199         
200         removeAt { arg key;
201                 var proxy;
202                 proxy = envir.removeAt(key);
203                 if(proxy.notNil) { proxy.clear };
204         }
205         
206         localPut { arg key, obj;
207         this.at(key).source_(obj);
208      }
209      
210