aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs
diff options
context:
space:
mode:
authorUbitUmarov2018-02-23 14:52:34 +0000
committerUbitUmarov2018-02-23 14:52:34 +0000
commit2129d941acbc5f83aca4dc4c30a62d3226888136 (patch)
treee12f2391978c923ef780f558ee5a32d857ee9124 /OpenSim/Region/ScriptEngine/YEngine/MMRScriptVarDict.cs
parentMerge branch 'master' into httptests (diff)
downloadopensim-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.cs434
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31
32/**
33 * @brief Collection of variable/function/method definitions
34 */
35
36namespace 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}