diff options
author | UbitUmarov | 2018-02-23 14:52:34 +0000 |
---|---|---|
committer | UbitUmarov | 2018-02-23 14:52:34 +0000 |
commit | 2129d941acbc5f83aca4dc4c30a62d3226888136 (patch) | |
tree | e12f2391978c923ef780f558ee5a32d857ee9124 /OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs | |
parent | Merge branch 'master' into httptests (diff) | |
download | opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.zip opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.gz opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.bz2 opensim-SC-2129d941acbc5f83aca4dc4c30a62d3226888136.tar.xz |
rename XMREngine as Yengine (still not all done), big mess source formating changes, move state files to proper folder, fix a source file locking on errors, more changes for cross platform including from Mike,... yes yes i know a messy commit
Diffstat (limited to 'OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs new file mode 100644 index 0000000..2561d02 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs | |||
@@ -0,0 +1,434 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | |||
32 | /** | ||
33 | * @brief Collection of variable/function/method definitions | ||
34 | */ | ||
35 | |||
36 | namespace OpenSim.Region.ScriptEngine.Yengine | ||
37 | { | ||
38 | public class VarDict: IEnumerable | ||
39 | { | ||
40 | public VarDict outerVarDict; // next outer VarDict to search | ||
41 | public TokenDeclSDTypeClass thisClass; // this VarDict is for members of thisClass | ||
42 | |||
43 | private struct ArgTypes | ||
44 | { | ||
45 | public TokenType[] argTypes; | ||
46 | |||
47 | public bool CanBeCalledBy(TokenType[] calledBy) | ||
48 | { | ||
49 | if((argTypes == null) && (calledBy == null)) | ||
50 | return true; | ||
51 | if((argTypes == null) || (calledBy == null)) | ||
52 | return false; | ||
53 | if(argTypes.Length != calledBy.Length) | ||
54 | return false; | ||
55 | for(int i = argTypes.Length; --i >= 0;) | ||
56 | { | ||
57 | if(!TypeCast.IsAssignableFrom(argTypes[i], calledBy[i])) | ||
58 | return false; | ||
59 | } | ||
60 | return true; | ||
61 | } | ||
62 | |||
63 | public override bool Equals(Object that) | ||
64 | { | ||
65 | if(that == null) | ||
66 | return false; | ||
67 | if(that.GetType() != typeof(ArgTypes)) | ||
68 | return false; | ||
69 | TokenType[] at = this.argTypes; | ||
70 | TokenType[] bt = ((ArgTypes)that).argTypes; | ||
71 | if((at == null) && (bt == null)) | ||
72 | return true; | ||
73 | if((at == null) || (bt == null)) | ||
74 | return false; | ||
75 | if(at.Length != bt.Length) | ||
76 | return false; | ||
77 | for(int i = at.Length; --i >= 0;) | ||
78 | { | ||
79 | if(at[i].ToString() != bt[i].ToString()) | ||
80 | return false; | ||
81 | } | ||
82 | return true; | ||
83 | } | ||
84 | |||
85 | public override int GetHashCode() | ||
86 | { | ||
87 | TokenType[] at = this.argTypes; | ||
88 | if(at == null) | ||
89 | return -1; | ||
90 | int hc = 0; | ||
91 | for(int i = at.Length; --i >= 0;) | ||
92 | { | ||
93 | int c = (hc < 0) ? 1 : 0; | ||
94 | hc = hc * 2 + c; | ||
95 | hc ^= at[i].ToString().GetHashCode(); | ||
96 | } | ||
97 | return hc; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | private struct TDVEntry | ||
102 | { | ||
103 | public int count; | ||
104 | public TokenDeclVar var; | ||
105 | } | ||
106 | |||
107 | private bool isFrozen = false; | ||
108 | private bool locals; | ||
109 | private Dictionary<string, Dictionary<ArgTypes, TDVEntry>> master = new Dictionary<string, Dictionary<ArgTypes, TDVEntry>>(); | ||
110 | private int count = 0; | ||
111 | private VarDict frozenLocals = null; | ||
112 | |||
113 | /** | ||
114 | * @brief Constructor. | ||
115 | * @param locals = false: cannot be frozen, allows forward references | ||
116 | * true: can be frozen, thus forbidding forward references | ||
117 | */ | ||
118 | public VarDict(bool locals) | ||
119 | { | ||
120 | this.locals = locals; | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * @brief Add new variable to the dictionary. | ||
125 | */ | ||
126 | public bool AddEntry(TokenDeclVar var) | ||
127 | { | ||
128 | if(isFrozen) | ||
129 | { | ||
130 | throw new Exception("var dict is frozen"); | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * Make sure we have a sub-dictionary based on the bare name (ie, no signature) | ||
135 | */ | ||
136 | Dictionary<ArgTypes, TDVEntry> typedic; | ||
137 | if(!master.TryGetValue(var.name.val, out typedic)) | ||
138 | { | ||
139 | typedic = new Dictionary<ArgTypes, TDVEntry>(); | ||
140 | master.Add(var.name.val, typedic); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * See if there is an entry in the sub-dictionary that matches the argument signature. | ||
145 | * Note that fields have null argument lists. | ||
146 | * Methods always have a non-null argument list, even if only 0 entries long. | ||
147 | */ | ||
148 | ArgTypes types; | ||
149 | types.argTypes = (var.argDecl == null) ? null : KeyTypesToStringTypes(var.argDecl.types); | ||
150 | if(typedic.ContainsKey(types)) | ||
151 | return false; | ||
152 | |||
153 | /* | ||
154 | * It is unique, add to its name-specific sub-dictionary. | ||
155 | */ | ||
156 | TDVEntry entry; | ||
157 | entry.count = ++count; | ||
158 | entry.var = var; | ||
159 | typedic.Add(types, entry); | ||
160 | return true; | ||
161 | } | ||
162 | |||
163 | public int Count | ||
164 | { | ||
165 | get | ||
166 | { | ||
167 | return count; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * @brief If this is not a local variable frame, just return the frame as is. | ||
173 | * If this is a local variable frame, return a version that is frozen, | ||
174 | * ie, one that does not contain any future additions. | ||
175 | */ | ||
176 | public VarDict FreezeLocals() | ||
177 | { | ||
178 | /* | ||
179 | * If not local var frame, return original frame as is. | ||
180 | * This will allow forward references as the future additions | ||
181 | * will be seen by lookups done in this dictionary. | ||
182 | */ | ||
183 | if(!locals) | ||
184 | return this; | ||
185 | |||
186 | /* | ||
187 | * If local var frame, return a copy frozen at this point. | ||
188 | * This disallows forward referenes as those future additions | ||
189 | * will not be seen by lookups done in the frozen dictionary. | ||
190 | */ | ||
191 | if((frozenLocals == null) || (frozenLocals.count != this.count)) | ||
192 | { | ||
193 | |||
194 | /* | ||
195 | * Make a copy of the current var dictionary frame. | ||
196 | * We copy a reference to the dictionary, and though it may | ||
197 | * contain additions made after this point, those additions | ||
198 | * will have a count .gt. frozen count and will be ignored. | ||
199 | */ | ||
200 | frozenLocals = new VarDict(true); | ||
201 | |||
202 | frozenLocals.outerVarDict = this.outerVarDict; | ||
203 | frozenLocals.thisClass = this.thisClass; | ||
204 | frozenLocals.master = this.master; | ||
205 | frozenLocals.count = this.count; | ||
206 | frozenLocals.frozenLocals = frozenLocals; | ||
207 | |||
208 | /* | ||
209 | * Mark it as being frozen. | ||
210 | * - assert fail if any attempt is made to add to it | ||
211 | * - ignore any additions to the dictionary with greater count | ||
212 | */ | ||
213 | frozenLocals.isFrozen = true; | ||
214 | } | ||
215 | return frozenLocals; | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * @brief Find all functions/variables that are callable | ||
220 | * @param name = name of function/variable to look for | ||
221 | * @param argTypes = the argument types the function is being called with | ||
222 | * null to look for a variable | ||
223 | * @returns null: no matching function/variable found | ||
224 | * else: list of matching functions/variables | ||
225 | * for variables, always of length 1 | ||
226 | */ | ||
227 | private List<TokenDeclVar> found = new List<TokenDeclVar>(); | ||
228 | public TokenDeclVar[] FindCallables(string name, TokenType[] argTypes) | ||
229 | { | ||
230 | argTypes = KeyTypesToStringTypes(argTypes); | ||
231 | TokenDeclVar var = FindExact(name, argTypes); | ||
232 | if(var != null) | ||
233 | return new TokenDeclVar[] { var }; | ||
234 | |||
235 | Dictionary<ArgTypes, TDVEntry> typedic; | ||
236 | if(!master.TryGetValue(name, out typedic)) | ||
237 | return null; | ||
238 | |||
239 | found.Clear(); | ||
240 | foreach(KeyValuePair<ArgTypes, TDVEntry> kvp in typedic) | ||
241 | { | ||
242 | if((kvp.Value.count <= this.count) && kvp.Key.CanBeCalledBy(argTypes)) | ||
243 | { | ||
244 | found.Add(kvp.Value.var); | ||
245 | } | ||
246 | } | ||
247 | return (found.Count > 0) ? found.ToArray() : null; | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * @brief Find exact matching function/variable | ||
252 | * @param name = name of function to look for | ||
253 | * @param argTypes = argument types the function was declared with | ||
254 | * null to look for a variable | ||
255 | * @returns null: no matching function/variable found | ||
256 | * else: the matching function/variable | ||
257 | */ | ||
258 | public TokenDeclVar FindExact(string name, TokenType[] argTypes) | ||
259 | { | ||
260 | /* | ||
261 | * Look for list of stuff that matches the given name. | ||
262 | */ | ||
263 | Dictionary<ArgTypes, TDVEntry> typedic; | ||
264 | if(!master.TryGetValue(name, out typedic)) | ||
265 | return null; | ||
266 | |||
267 | /* | ||
268 | * Loop through all fields/methods declared by that name, regardless of arg signature. | ||
269 | */ | ||
270 | foreach(TDVEntry entry in typedic.Values) | ||
271 | { | ||
272 | if(entry.count > this.count) | ||
273 | continue; | ||
274 | TokenDeclVar var = entry.var; | ||
275 | |||
276 | /* | ||
277 | * Get argument types of declaration. | ||
278 | * fields are always null | ||
279 | * methods are always non-null, though may be zero-length | ||
280 | */ | ||
281 | TokenType[] declArgs = (var.argDecl == null) ? null : var.argDecl.types; | ||
282 | |||
283 | /* | ||
284 | * Convert any key args to string args. | ||
285 | */ | ||
286 | declArgs = KeyTypesToStringTypes(declArgs); | ||
287 | |||
288 | /* | ||
289 | * If both are null, they are signature-less (ie, both are fields), and so match. | ||
290 | */ | ||
291 | if((declArgs == null) && (argTypes == null)) | ||
292 | return var; | ||
293 | |||
294 | /* | ||
295 | * If calling a delegate, it is a match, regardless of delegate arg types. | ||
296 | * If it turns out the arg types do not match, the compiler will give an error | ||
297 | * trying to cast the arguments to the delegate arg types. | ||
298 | * We don't allow overloading same field name with different delegate types. | ||
299 | */ | ||
300 | if((declArgs == null) && (argTypes != null)) | ||
301 | { | ||
302 | TokenType fieldType = var.type; | ||
303 | if(fieldType is TokenTypeSDTypeDelegate) | ||
304 | return var; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * If not both null, no match, keep looking. | ||
309 | */ | ||
310 | if((declArgs == null) || (argTypes == null)) | ||
311 | continue; | ||
312 | |||
313 | /* | ||
314 | * Both not null, match argument types to make sure we have correct overload. | ||
315 | */ | ||
316 | int i = declArgs.Length; | ||
317 | if(i != argTypes.Length) | ||
318 | continue; | ||
319 | while(--i >= 0) | ||
320 | { | ||
321 | string da = declArgs[i].ToString(); | ||
322 | string ga = argTypes[i].ToString(); | ||
323 | if(da == "key") | ||
324 | da = "string"; | ||
325 | if(ga == "key") | ||
326 | ga = "string"; | ||
327 | if(da != ga) | ||
328 | break; | ||
329 | } | ||
330 | if(i < 0) | ||
331 | return var; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * No match. | ||
336 | */ | ||
337 | return null; | ||
338 | } | ||
339 | |||
340 | /** | ||
341 | * @brief Replace any TokenTypeKey elements with TokenTypeStr so that | ||
342 | * it doesn't matter if functions are declared with key or string, | ||
343 | * they will accept either. | ||
344 | * @param argTypes = argument types as declared in source code | ||
345 | * @returns argTypes with any key replaced by string | ||
346 | */ | ||
347 | private static TokenType[] KeyTypesToStringTypes(TokenType[] argTypes) | ||
348 | { | ||
349 | if(argTypes != null) | ||
350 | { | ||
351 | int i; | ||
352 | int nats = argTypes.Length; | ||
353 | for(i = nats; --i >= 0;) | ||
354 | { | ||
355 | if(argTypes[i] is TokenTypeKey) | ||
356 | break; | ||
357 | } | ||
358 | if(i >= 0) | ||
359 | { | ||
360 | TokenType[] at = new TokenType[nats]; | ||
361 | for(i = nats; --i >= 0;) | ||
362 | { | ||
363 | at[i] = argTypes[i]; | ||
364 | if(argTypes[i] is TokenTypeKey) | ||
365 | { | ||
366 | at[i] = new TokenTypeStr(argTypes[i]); | ||
367 | } | ||
368 | } | ||
369 | return at; | ||
370 | } | ||
371 | } | ||
372 | return argTypes; | ||
373 | } | ||
374 | |||
375 | // foreach goes through all the TokenDeclVars that were added | ||
376 | |||
377 | // IEnumerable | ||
378 | public IEnumerator GetEnumerator() | ||
379 | { | ||
380 | return new VarDictEnumerator(this.master, this.count); | ||
381 | } | ||
382 | |||
383 | private class VarDictEnumerator: IEnumerator | ||
384 | { | ||
385 | private IEnumerator masterEnum; | ||
386 | private IEnumerator typedicEnum; | ||
387 | private int count; | ||
388 | |||
389 | public VarDictEnumerator(Dictionary<string, Dictionary<ArgTypes, TDVEntry>> master, int count) | ||
390 | { | ||
391 | masterEnum = master.Values.GetEnumerator(); | ||
392 | this.count = count; | ||
393 | } | ||
394 | |||
395 | // IEnumerator | ||
396 | public void Reset() | ||
397 | { | ||
398 | masterEnum.Reset(); | ||
399 | typedicEnum = null; | ||
400 | } | ||
401 | |||
402 | // IEnumerator | ||
403 | public bool MoveNext() | ||
404 | { | ||
405 | while(true) | ||
406 | { | ||
407 | if(typedicEnum != null) | ||
408 | { | ||
409 | while(typedicEnum.MoveNext()) | ||
410 | { | ||
411 | if(((TDVEntry)typedicEnum.Current).count <= this.count) | ||
412 | return true; | ||
413 | } | ||
414 | typedicEnum = null; | ||
415 | } | ||
416 | if(!masterEnum.MoveNext()) | ||
417 | return false; | ||
418 | Dictionary<ArgTypes, TDVEntry> ctd; | ||
419 | ctd = (Dictionary<ArgTypes, TDVEntry>)masterEnum.Current; | ||
420 | typedicEnum = ctd.Values.GetEnumerator(); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | // IEnumerator | ||
425 | public object Current | ||
426 | { | ||
427 | get | ||
428 | { | ||
429 | return ((TDVEntry)typedicEnum.Current).var; | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | } | ||
434 | } | ||