clockwerk-opensim-stable – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (C) 2007-2008, Jeff Thompson
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
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
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
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
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
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.
29 */
30  
31 using System;
32 using System.Collections;
33 using System.Collections.Generic;
34  
35 namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
36 {
37 public interface IUnifiable
38 {
39 IEnumerable<bool> unify(object arg);
40 void addUniqueVariables(List<Variable> variableSet);
41 object makeCopy(Variable.CopyStore copyStore);
42 bool termEqual(object term);
43 bool ground();
44 }
45  
46 /// <summary>
47 /// A Variable is passed to a function so that it can be unified with
48 /// value or another Variable. See getValue and unify for details.
49 /// </summary>
50 public class Variable : IUnifiable
51 {
52 // Use _isBound separate from _value so that it can be bound to any value,
53 // including null.
54 private bool _isBound = false;
55 private object _value;
56  
57 /// <summary>
58 /// If this Variable is unbound, then just return this Variable.
59 /// Otherwise, if this has been bound to a value with unify, return the value.
60 /// If the bound value is another Variable, this follows the "variable chain"
61 /// to the end and returns the final value, or the final Variable if it is unbound.
62 /// For more details, see http://yieldprolog.sourceforge.net/tutorial1.html
63 /// </summary>
64 /// <returns></returns>
65 public object getValue()
66 {
67 if (!_isBound)
68 return this;
69  
70 object result = _value;
71 while (result is Variable)
72 {
73 if (!((Variable)result)._isBound)
74 return result;
75  
76 // Keep following the Variable chain.
77 result = ((Variable)result)._value;
78 }
79  
80 return result;
81 }
82  
83 /// <summary>
84 /// If this Variable is bound, then just call YP.unify to unify this with arg.
85 /// (Note that if arg is an unbound Variable, then YP.unify will bind it to
86 /// this Variable's value.)
87 /// Otherwise, bind this Variable to YP.getValue(arg) and yield once. After the
88 /// yield, return this Variable to the unbound state.
89 /// For more details, see http://yieldprolog.sourceforge.net/tutorial1.html
90 /// </summary>
91 /// <param name="arg"></param>
92 /// <returns></returns>
93 public IEnumerable<bool> unify(object arg)
94 {
95 if (!_isBound)
96 {
97 _value = YP.getValue(arg);
98 if (_value == this)
99 // We are unifying this unbound variable with itself, so leave it unbound.
100 yield return false;
101 else
102 {
103 _isBound = true;
104 try
105 {
106 yield return false;
107 }
108 finally
109 {
110 // Remove the binding.
111 _isBound = false;
112 }
113 }
114 }
115 else
116 {
117 // disable warning on l1, don't see how we can
118 // code this differently
119 #pragma warning disable 0168, 0219
120 foreach (bool l1 in YP.unify(this, arg))
121 yield return false;
122 #pragma warning restore 0168, 0219
123 }
124 }
125  
126 public override string ToString()
127 {
128 object value = getValue();
129 if (value == this)
130 return "_Variable";
131 else
132 return getValue().ToString();
133 }
134  
135 /// <summary>
136 /// If bound, call YP.addUniqueVariables on the value. Otherwise, if this unbound
137 /// variable is not already in variableSet, add it.
138 /// </summary>
139 /// <param name="variableSet"></param>
140 public void addUniqueVariables(List<Variable> variableSet)
141 {
142 if (_isBound)
143 YP.addUniqueVariables(getValue(), variableSet);
144 else
145 {
146 if (variableSet.IndexOf(this) < 0)
147 variableSet.Add(this);
148 }
149 }
150  
151 /// <summary>
152 /// If bound, return YP.makeCopy for the value, else return copyStore.getCopy(this).
153 /// However, if copyStore is null, just return this.
154 /// </summary>
155 /// <param name="copyStore"></param>
156 /// <returns></returns>
157 public object makeCopy(Variable.CopyStore copyStore)
158 {
159 if (_isBound)
160 return YP.makeCopy(getValue(), copyStore);
161 else
162 return copyStore == null ? this : copyStore.getCopy(this);
163 }
164  
165 public bool termEqual(object term)
166 {
167 if (_isBound)
168 return YP.termEqual(getValue(), term);
169 else
170 return this == YP.getValue(term);
171 }
172  
173 public bool ground()
174 {
175 if (_isBound)
176 // This is usually called by YP.ground which already did getValue, so this
177 // should never be reached, but check anyway.
178 return YP.ground(getValue());
179 else
180 return false;
181 }
182  
183 /// <summary>
184 /// A CopyStore is used by makeCopy to track which Variable objects have
185 /// been copied.
186 /// </summary>
187 public class CopyStore
188 {
189 private List<Variable> _inVariableSet = new List<Variable>();
190 private List<Variable> _outVariableSet = new List<Variable>();
191  
192 /// <summary>
193 /// If inVariable has already been copied, return its copy. Otherwise,
194 /// return a fresh Variable associated with inVariable.
195 /// </summary>
196 /// <param name="inVariable"></param>
197 /// <returns></returns>
198 public Variable getCopy(Variable inVariable)
199 {
200 int index = _inVariableSet.IndexOf(inVariable);
201 if (index >= 0)
202 return _outVariableSet[index];
203 else
204 {
205 Variable outVariable = new Variable();
206 _inVariableSet.Add(inVariable);
207 _outVariableSet.Add(outVariable);
208 return outVariable;
209 }
210 }
211  
212 /// <summary>
213 /// Return the number of unique variables that have been copied.
214 /// </summary>
215 /// <returns></returns>
216 public int getNUniqueVariables()
217 {
218 return _inVariableSet.Count;
219 }
220 }
221 }
222 }