aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs576
1 files changed, 288 insertions, 288 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs
index 3eac5fa..05b0a01 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs
@@ -1,288 +1,288 @@
1/* 1/*
2 * Copyright (C) 2007-2008, Jeff Thompson 2 * Copyright (C) 2007-2008, Jeff Thompson
3 * 3 *
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright 11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of the copyright holder nor the names of its contributors 14 * * Neither the name of the copyright holder nor the names of its contributors
15 * may be used to endorse or promote products derived from this software 15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission. 16 * without specific prior written permission.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31using System; 31using System;
32using System.Collections; 32using System.Collections;
33using System.Collections.Generic; 33using System.Collections.Generic;
34 34
35namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog 35namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
36{ 36{
37 /// <summary> 37 /// <summary>
38 /// An IndexedAnswers holds answers to a query based on the values of index arguments. 38 /// An IndexedAnswers holds answers to a query based on the values of index arguments.
39 /// </summary> 39 /// </summary>
40 public class IndexedAnswers : YP.IClause 40 public class IndexedAnswers : YP.IClause
41 { 41 {
42 // addAnswer adds the answer here and indexes it later. 42 // addAnswer adds the answer here and indexes it later.
43 private List<object[]> _allAnswers = new List<object[]>(); 43 private List<object[]> _allAnswers = new List<object[]>();
44 // The key has the arity of answers with non-null values for each indexed arg. The value 44 // The key has the arity of answers with non-null values for each indexed arg. The value
45 // is a list of the matching answers. The signature is implicit in the pattern on non-null index args. 45 // is a list of the matching answers. The signature is implicit in the pattern on non-null index args.
46 private Dictionary<HashedList, List<object[]>> _indexedAnswers = 46 private Dictionary<HashedList, List<object[]>> _indexedAnswers =
47 new Dictionary<HashedList, List<object[]>>(); 47 new Dictionary<HashedList, List<object[]>>();
48 // Keeps track of whether we have started adding entries to _indexedAnswers for the signature. 48 // Keeps track of whether we have started adding entries to _indexedAnswers for the signature.
49 private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>(); 49 private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>();
50 private const int MAX_INDEX_ARGS = 31; 50 private const int MAX_INDEX_ARGS = 31;
51 51
52 public IndexedAnswers() 52 public IndexedAnswers()
53 { 53 {
54 } 54 }
55 55
56 /// <summary> 56 /// <summary>
57 /// Elements of answer must be ground, since arguments with unbound variables make this 57 /// Elements of answer must be ground, since arguments with unbound variables make this
58 /// into a dynamic rule which we don't index. 58 /// into a dynamic rule which we don't index.
59 /// </summary> 59 /// </summary>
60 /// <param name="answer"></param> 60 /// <param name="answer"></param>
61 public void addAnswer(object[] answer) 61 public void addAnswer(object[] answer)
62 { 62 {
63 // Store a copy of the answer array. 63 // Store a copy of the answer array.
64 object[] answerCopy = new object[answer.Length]; 64 object[] answerCopy = new object[answer.Length];
65 Variable.CopyStore copyStore = new Variable.CopyStore(); 65 Variable.CopyStore copyStore = new Variable.CopyStore();
66 for (int i = 0; i < answer.Length; ++i) 66 for (int i = 0; i < answer.Length; ++i)
67 answerCopy[i] = YP.makeCopy(answer[i], copyStore); 67 answerCopy[i] = YP.makeCopy(answer[i], copyStore);
68 if (copyStore.getNUniqueVariables() > 0) 68 if (copyStore.getNUniqueVariables() > 0)
69 throw new InvalidOperationException 69 throw new InvalidOperationException
70 ("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() + 70 ("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() +
71 " unbound variables"); 71 " unbound variables");
72 _allAnswers.Add(answerCopy); 72 _allAnswers.Add(answerCopy);
73 73
74 // If match has already indexed answers for a signature, we need to add 74 // If match has already indexed answers for a signature, we need to add
75 // this to the existing indexed answers. 75 // this to the existing indexed answers.
76 foreach(int signature in _gotAnswersForSignature.Keys) 76 foreach(int signature in _gotAnswersForSignature.Keys)
77 indexAnswerForSignature(answerCopy, signature); 77 indexAnswerForSignature(answerCopy, signature);
78 } 78 }
79 79
80 private void indexAnswerForSignature(object[] answer, int signature) 80 private void indexAnswerForSignature(object[] answer, int signature)
81 { 81 {
82 // First find out which of the answer values can be used as an index. 82 // First find out which of the answer values can be used as an index.
83 object[] indexValues = new object[answer.Length]; 83 object[] indexValues = new object[answer.Length];
84 for (int i = 0; i < answer.Length; ++i) 84 for (int i = 0; i < answer.Length; ++i)
85 { 85 {
86 // We limit the number of indexed args in a 32-bit signature. 86 // We limit the number of indexed args in a 32-bit signature.
87 if (i >= MAX_INDEX_ARGS) 87 if (i >= MAX_INDEX_ARGS)
88 indexValues[i] = null; 88 indexValues[i] = null;
89 else 89 else
90 indexValues[i] = getIndexValue(YP.getValue(answer[i])); 90 indexValues[i] = getIndexValue(YP.getValue(answer[i]));
91 } 91 }
92 92
93 // We need an entry in indexArgs from indexValues for each 1 bit in signature. 93 // We need an entry in indexArgs from indexValues for each 1 bit in signature.
94 HashedList indexArgs = new HashedList(indexValues.Length); 94 HashedList indexArgs = new HashedList(indexValues.Length);
95 for (int i = 0; i < indexValues.Length; ++i) 95 for (int i = 0; i < indexValues.Length; ++i)
96 { 96 {
97 if ((signature & (1 << i)) == 0) 97 if ((signature & (1 << i)) == 0)
98 indexArgs.Add(null); 98 indexArgs.Add(null);
99 else 99 else
100 { 100 {
101 if (indexValues[i] == null) 101 if (indexValues[i] == null)
102 // The signature wants an index value here, but we don't have one so 102 // The signature wants an index value here, but we don't have one so
103 // we can't add it as an answer for this signature. 103 // we can't add it as an answer for this signature.
104 return; 104 return;
105 else 105 else
106 indexArgs.Add(indexValues[i]); 106 indexArgs.Add(indexValues[i]);
107 } 107 }
108 } 108 }
109 109
110 // Add the answer to the answers list for indexArgs, creating the entry if needed. 110 // Add the answer to the answers list for indexArgs, creating the entry if needed.
111 List<object[]> answers; 111 List<object[]> answers;
112 if (!_indexedAnswers.TryGetValue(indexArgs, out answers)) 112 if (!_indexedAnswers.TryGetValue(indexArgs, out answers))
113 { 113 {
114 answers = new List<object[]>(); 114 answers = new List<object[]>();
115 _indexedAnswers[indexArgs] = answers; 115 _indexedAnswers[indexArgs] = answers;
116 } 116 }
117 answers.Add(answer); 117 answers.Add(answer);
118 } 118 }
119 119
120 public IEnumerable<bool> match(object[] arguments) 120 public IEnumerable<bool> match(object[] arguments)
121 { 121 {
122 // Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for 122 // Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for
123 // each non-null index arg. 123 // each non-null index arg.
124 HashedList indexArgs = new HashedList(arguments.Length); 124 HashedList indexArgs = new HashedList(arguments.Length);
125 bool gotAllIndexArgs = true; 125 bool gotAllIndexArgs = true;
126 int signature = 0; 126 int signature = 0;
127 for (int i = 0; i < arguments.Length; ++i) 127 for (int i = 0; i < arguments.Length; ++i)
128 { 128 {
129 object indexValue = null; 129 object indexValue = null;
130 if (i < MAX_INDEX_ARGS) 130 if (i < MAX_INDEX_ARGS)
131 { 131 {
132 // We limit the number of args in a 32-bit signature. 132 // We limit the number of args in a 32-bit signature.
133 indexValue = getIndexValue(YP.getValue(arguments[i])); 133 indexValue = getIndexValue(YP.getValue(arguments[i]));
134 if (indexValue != null) 134 if (indexValue != null)
135 signature += (1 << i); 135 signature += (1 << i);
136 } 136 }
137 if (indexValue == null) 137 if (indexValue == null)
138 gotAllIndexArgs = false; 138 gotAllIndexArgs = false;
139 indexArgs.Add(indexValue); 139 indexArgs.Add(indexValue);
140 } 140 }
141 141
142 List<object[]> answers; 142 List<object[]> answers;
143 if (signature == 0) 143 if (signature == 0)
144 // No index args, so we have to match from _allAnswers. 144 // No index args, so we have to match from _allAnswers.
145 answers = _allAnswers; 145 answers = _allAnswers;
146 else 146 else
147 { 147 {
148 if (!_gotAnswersForSignature.ContainsKey(signature)) 148 if (!_gotAnswersForSignature.ContainsKey(signature))
149 { 149 {
150 // We need to create the entry in _indexedAnswers. 150 // We need to create the entry in _indexedAnswers.
151 foreach (object[] answer in _allAnswers) 151 foreach (object[] answer in _allAnswers)
152 indexAnswerForSignature(answer, signature); 152 indexAnswerForSignature(answer, signature);
153 // Mark that we did this signature. 153 // Mark that we did this signature.
154 _gotAnswersForSignature[signature] = null; 154 _gotAnswersForSignature[signature] = null;
155 } 155 }
156 if (!_indexedAnswers.TryGetValue(indexArgs, out answers)) 156 if (!_indexedAnswers.TryGetValue(indexArgs, out answers))
157 yield break; 157 yield break;
158 } 158 }
159 159
160 if (gotAllIndexArgs) 160 if (gotAllIndexArgs)
161 { 161 {
162 // All the arguments were already bound, so we don't need to do bindings. 162 // All the arguments were already bound, so we don't need to do bindings.
163 yield return false; 163 yield return false;
164 yield break; 164 yield break;
165 } 165 }
166 166
167 // Find matches in answers. 167 // Find matches in answers.
168 IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length]; 168 IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length];
169 foreach (object[] answer in answers) 169 foreach (object[] answer in answers)
170 { 170 {
171 bool gotMatch = true; 171 bool gotMatch = true;
172 int nIterators = 0; 172 int nIterators = 0;
173 // Try to bind all the arguments. 173 // Try to bind all the arguments.
174 for (int i = 0; i < arguments.Length; ++i) 174 for (int i = 0; i < arguments.Length; ++i)
175 { 175 {
176 if (indexArgs[i] != null) 176 if (indexArgs[i] != null)
177 // We already matched this argument by looking up _indexedAnswers. 177 // We already matched this argument by looking up _indexedAnswers.
178 continue; 178 continue;
179 179
180 IEnumerator<bool> iterator = YP.unify(arguments[i], answer[i]).GetEnumerator(); 180 IEnumerator<bool> iterator = YP.unify(arguments[i], answer[i]).GetEnumerator();
181 iterators[nIterators++] = iterator; 181 iterators[nIterators++] = iterator;
182 // MoveNext() is true if YP.unify succeeds. 182 // MoveNext() is true if YP.unify succeeds.
183 if (!iterator.MoveNext()) 183 if (!iterator.MoveNext())
184 { 184 {
185 gotMatch = false; 185 gotMatch = false;
186 break; 186 break;
187 } 187 }
188 } 188 }
189 189
190 try 190 try
191 { 191 {
192 if (gotMatch) 192 if (gotMatch)
193 yield return false; 193 yield return false;
194 } 194 }
195 finally 195 finally
196 { 196 {
197 // Manually finalize all the iterators. 197 // Manually finalize all the iterators.
198 for (int i = 0; i < nIterators; ++i) 198 for (int i = 0; i < nIterators; ++i)
199 iterators[i].Dispose(); 199 iterators[i].Dispose();
200 } 200 }
201 } 201 }
202 } 202 }
203 203
204 /// <summary> 204 /// <summary>
205 /// A HashedList extends an ArrayList with methods to get a hash and to check equality 205 /// A HashedList extends an ArrayList with methods to get a hash and to check equality
206 /// based on the elements of the list. 206 /// based on the elements of the list.
207 /// </summary> 207 /// </summary>
208 public class HashedList : ArrayList 208 public class HashedList : ArrayList
209 { 209 {
210 private bool _gotHashCode = false; 210 private bool _gotHashCode = false;
211 private int _hashCode; 211 private int _hashCode;
212 212
213 public HashedList() 213 public HashedList()
214 : base() 214 : base()
215 { 215 {
216 } 216 }
217 217
218 public HashedList(int capacity) 218 public HashedList(int capacity)
219 : base(capacity) 219 : base(capacity)
220 { 220 {
221 } 221 }
222 222
223 public HashedList(ICollection c) 223 public HashedList(ICollection c)
224 : base(c) 224 : base(c)
225 { 225 {
226 } 226 }
227 227
228 // Debug: Should override all the other methods that change this. 228 // Debug: Should override all the other methods that change this.
229 public override int Add(object value) 229 public override int Add(object value)
230 { 230 {
231 _gotHashCode = false; 231 _gotHashCode = false;
232 return base.Add(value); 232 return base.Add(value);
233 } 233 }
234 234
235 public override int GetHashCode() 235 public override int GetHashCode()
236 { 236 {
237 if (!_gotHashCode) 237 if (!_gotHashCode)
238 { 238 {
239 int hashCode = 1; 239 int hashCode = 1;
240 foreach (object obj in this) 240 foreach (object obj in this)
241 hashCode = 31 * hashCode + (obj == null ? 0 : obj.GetHashCode()); 241 hashCode = 31 * hashCode + (obj == null ? 0 : obj.GetHashCode());
242 _hashCode = hashCode; 242 _hashCode = hashCode;
243 _gotHashCode = true; 243 _gotHashCode = true;
244 } 244 }
245 return _hashCode; 245 return _hashCode;
246 } 246 }
247 247
248 public override bool Equals(object obj) 248 public override bool Equals(object obj)
249 { 249 {
250 if (!(obj is ArrayList)) 250 if (!(obj is ArrayList))
251 return false; 251 return false;
252 252
253 ArrayList objList = (ArrayList)obj; 253 ArrayList objList = (ArrayList)obj;
254 if (objList.Count != Count) 254 if (objList.Count != Count)
255 return false; 255 return false;
256 256
257 for (int i = 0; i < Count; ++i) 257 for (int i = 0; i < Count; ++i)
258 { 258 {
259 object value = objList[i]; 259 object value = objList[i];
260 if (value == null) 260 if (value == null)
261 { 261 {
262 if (this[i] != null) 262 if (this[i] != null)
263 return false; 263 return false;
264 } 264 }
265 else 265 else
266 { 266 {
267 if (!value.Equals(this[i])) 267 if (!value.Equals(this[i]))
268 return false; 268 return false;
269 } 269 }
270 } 270 }
271 return true; 271 return true;
272 } 272 }
273 } 273 }
274 274
275 /// <summary> 275 /// <summary>
276 /// If we keep an index on value, return the value, or null if we don't index it. 276 /// If we keep an index on value, return the value, or null if we don't index it.
277 /// </summary> 277 /// </summary>
278 /// <param name="value">the term to examine. Assume you already called YP.getValue(value)</param> 278 /// <param name="value">the term to examine. Assume you already called YP.getValue(value)</param>
279 /// <returns></returns> 279 /// <returns></returns>
280 public static object getIndexValue(object value) 280 public static object getIndexValue(object value)
281 { 281 {
282 if (value is Atom || value is string || value is Int32 || value is DateTime) 282 if (value is Atom || value is string || value is Int32 || value is DateTime)
283 return value; 283 return value;
284 else 284 else
285 return null; 285 return null;
286 } 286 }
287 } 287 }
288} 288}