diff options
author | Charles Krinke | 2008-07-16 01:00:40 +0000 |
---|---|---|
committer | Charles Krinke | 2008-07-16 01:00:40 +0000 |
commit | 620f7926f3f2ad05fdb72050a87e49d0fa2357dd (patch) | |
tree | 848c3c4071ff70f6e24c7e46741bca67b39495c4 /OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs | |
parent | add migration for SceneGroupID to char(36) plus add an index. This (diff) | |
download | opensim-SC-620f7926f3f2ad05fdb72050a87e49d0fa2357dd.zip opensim-SC-620f7926f3f2ad05fdb72050a87e49d0fa2357dd.tar.gz opensim-SC-620f7926f3f2ad05fdb72050a87e49d0fa2357dd.tar.bz2 opensim-SC-620f7926f3f2ad05fdb72050a87e49d0fa2357dd.tar.xz |
Mantis#1753. Thank you kindly, Kinoc for a patch that:
Brings Yield Prolog up to date with sourceforge version 0.9.10
Patched applies to both DotNet and XEngine.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs | 107 |
1 files changed, 100 insertions, 7 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs index e1efda8..bba7d03 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/YieldProlog/IndexedAnswers.cs | |||
@@ -39,6 +39,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog | |||
39 | /// </summary> | 39 | /// </summary> |
40 | public class IndexedAnswers : YP.IClause | 40 | public class IndexedAnswers : YP.IClause |
41 | { | 41 | { |
42 | private int _arity; | ||
42 | // addAnswer adds the answer here and indexes it later. | 43 | // addAnswer adds the answer here and indexes it later. |
43 | private List<object[]> _allAnswers = new List<object[]>(); | 44 | 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 | 45 | // The key has the arity of answers with non-null values for each indexed arg. The value |
@@ -49,17 +50,43 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog | |||
49 | private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>(); | 50 | private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>(); |
50 | private const int MAX_INDEX_ARGS = 31; | 51 | private const int MAX_INDEX_ARGS = 31; |
51 | 52 | ||
52 | public IndexedAnswers() | 53 | public IndexedAnswers(int arity) |
53 | { | 54 | { |
55 | _arity = arity; | ||
54 | } | 56 | } |
55 | 57 | ||
56 | /// <summary> | 58 | /// <summary> |
59 | /// Append the answer to the list and update the indexes, if any. | ||
57 | /// Elements of answer must be ground, since arguments with unbound variables make this | 60 | /// Elements of answer must be ground, since arguments with unbound variables make this |
58 | /// into a dynamic rule which we don't index. | 61 | /// into a dynamic rule which we don't index. |
59 | /// </summary> | 62 | /// </summary> |
60 | /// <param name="answer"></param> | 63 | /// <param name="answer"></param> |
61 | public void addAnswer(object[] answer) | 64 | public void addAnswer(object[] answer) |
62 | { | 65 | { |
66 | addOrPrependAnswer(answer, false); | ||
67 | } | ||
68 | |||
69 | /// <summary> | ||
70 | /// Prepend the answer to the list and clear the indexes so that they must be re-computed | ||
71 | /// on the next call to match. (Only addAnswer will maintain the indexes while adding answers.) | ||
72 | /// Elements of answer must be ground, since arguments with unbound variables make this | ||
73 | /// into a dynamic rule which we don't index. | ||
74 | /// </summary> | ||
75 | /// <param name="answer"></param> | ||
76 | public void prependAnswer(object[] answer) | ||
77 | { | ||
78 | addOrPrependAnswer(answer, true); | ||
79 | } | ||
80 | |||
81 | /// <summary> | ||
82 | /// Do the work of addAnswer or prependAnswer. | ||
83 | /// </summary> | ||
84 | /// <param name="answer"></param> | ||
85 | private void addOrPrependAnswer(object[] answer, bool prepend) | ||
86 | { | ||
87 | if (answer.Length != _arity) | ||
88 | return; | ||
89 | |||
63 | // Store a copy of the answer array. | 90 | // Store a copy of the answer array. |
64 | object[] answerCopy = new object[answer.Length]; | 91 | object[] answerCopy = new object[answer.Length]; |
65 | Variable.CopyStore copyStore = new Variable.CopyStore(); | 92 | Variable.CopyStore copyStore = new Variable.CopyStore(); |
@@ -69,12 +96,20 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog | |||
69 | throw new InvalidOperationException | 96 | throw new InvalidOperationException |
70 | ("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() + | 97 | ("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() + |
71 | " unbound variables"); | 98 | " unbound variables"); |
72 | _allAnswers.Add(answerCopy); | ||
73 | 99 | ||
74 | // If match has already indexed answers for a signature, we need to add | 100 | if (prepend) |
75 | // this to the existing indexed answers. | 101 | { |
76 | foreach (int signature in _gotAnswersForSignature.Keys) | 102 | _allAnswers.Insert(0, answerCopy); |
77 | indexAnswerForSignature(answerCopy, signature); | 103 | clearIndexes(); |
104 | } | ||
105 | else | ||
106 | { | ||
107 | _allAnswers.Add(answerCopy); | ||
108 | // If match has already indexed answers for a signature, we need to add | ||
109 | // this to the existing indexed answers. | ||
110 | foreach (int signature in _gotAnswersForSignature.Keys) | ||
111 | indexAnswerForSignature(answerCopy, signature); | ||
112 | } | ||
78 | } | 113 | } |
79 | 114 | ||
80 | private void indexAnswerForSignature(object[] answer, int signature) | 115 | private void indexAnswerForSignature(object[] answer, int signature) |
@@ -119,6 +154,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog | |||
119 | 154 | ||
120 | public IEnumerable<bool> match(object[] arguments) | 155 | public IEnumerable<bool> match(object[] arguments) |
121 | { | 156 | { |
157 | if (arguments.Length != _arity) | ||
158 | yield break; | ||
159 | |||
122 | // Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for | 160 | // Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for |
123 | // each non-null index arg. | 161 | // each non-null index arg. |
124 | HashedList indexArgs = new HashedList(arguments.Length); | 162 | HashedList indexArgs = new HashedList(arguments.Length); |
@@ -166,6 +204,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog | |||
166 | 204 | ||
167 | // Find matches in answers. | 205 | // Find matches in answers. |
168 | IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length]; | 206 | IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length]; |
207 | // Debug: If the caller asserts another answer into this same predicate during yield, the iterator | ||
208 | // over clauses will be corrupted. Should we take the time to copy answers? | ||
169 | foreach (object[] answer in answers) | 209 | foreach (object[] answer in answers) |
170 | { | 210 | { |
171 | bool gotMatch = true; | 211 | bool gotMatch = true; |
@@ -201,6 +241,59 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog | |||
201 | } | 241 | } |
202 | } | 242 | } |
203 | 243 | ||
244 | public IEnumerable<bool> clause(object Head, object Body) | ||
245 | { | ||
246 | Head = YP.getValue(Head); | ||
247 | if (Head is Variable) | ||
248 | throw new PrologException("instantiation_error", "Head is an unbound variable"); | ||
249 | object[] arguments = YP.getFunctorArgs(Head); | ||
250 | |||
251 | // We always match Head from _allAnswers, and the Body is Atom.a("true"). | ||
252 | foreach (bool l1 in YP.unify(Body, Atom.a("true"))) | ||
253 | { | ||
254 | // The caller can assert another answer into this same predicate during yield, so we have to | ||
255 | // make a copy of the answers. | ||
256 | foreach (object[] answer in _allAnswers.ToArray()) | ||
257 | { | ||
258 | foreach (bool l2 in YP.unifyArrays(arguments, answer)) | ||
259 | yield return false; | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | public IEnumerable<bool> retract(object Head, object Body) | ||
265 | { | ||
266 | Head = YP.getValue(Head); | ||
267 | if (Head is Variable) | ||
268 | throw new PrologException("instantiation_error", "Head is an unbound variable"); | ||
269 | object[] arguments = YP.getFunctorArgs(Head); | ||
270 | |||
271 | // We always match Head from _allAnswers, and the Body is Atom.a("true"). | ||
272 | foreach (bool l1 in YP.unify(Body, Atom.a("true"))) | ||
273 | { | ||
274 | // The caller can assert another answer into this same predicate during yield, so we have to | ||
275 | // make a copy of the answers. | ||
276 | foreach (object[] answer in _allAnswers.ToArray()) | ||
277 | { | ||
278 | foreach (bool l2 in YP.unifyArrays(arguments, answer)) | ||
279 | { | ||
280 | _allAnswers.Remove(answer); | ||
281 | clearIndexes(); | ||
282 | yield return false; | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | /// <summary> | ||
289 | /// After retracting or prepending an answer in _allAnswers, the indexes are invalid, so clear them. | ||
290 | /// </summary> | ||
291 | private void clearIndexes() | ||
292 | { | ||
293 | _indexedAnswers.Clear(); | ||
294 | _gotAnswersForSignature.Clear(); | ||
295 | } | ||
296 | |||
204 | /// <summary> | 297 | /// <summary> |
205 | /// A HashedList extends an ArrayList with methods to get a hash and to check equality | 298 | /// A HashedList extends an ArrayList with methods to get a hash and to check equality |
206 | /// based on the elements of the list. | 299 | /// based on the elements of the list. |