mirror of
https://github.com/opensim/opensim.git
synced 2026-08-01 06:06:06 +08:00
Mantis#1314. Thank you kindly, Kinoc for YieldProlog.
I have added everything *except* the patch to .../LSL/Compiler.cs. The Compiler.cs patch has a namespace issue. Lets make a second patch to close the gap.
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2008, Jeff Thompson
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||
{
|
||||
public interface IUnifiable
|
||||
{
|
||||
IEnumerable<bool> unify(object arg);
|
||||
void addUniqueVariables(List<Variable> variableSet);
|
||||
object makeCopy(Variable.CopyStore copyStore);
|
||||
bool termEqual(object term);
|
||||
bool ground();
|
||||
}
|
||||
|
||||
public class Variable : IUnifiable
|
||||
{
|
||||
// Use _isBound separate from _value so that it can be bound to any value,
|
||||
// including null.
|
||||
private bool _isBound = false;
|
||||
private object _value;
|
||||
|
||||
public object getValue()
|
||||
{
|
||||
if (!_isBound)
|
||||
return this;
|
||||
|
||||
object result = _value;
|
||||
while (result is Variable)
|
||||
{
|
||||
if (!((Variable)result)._isBound)
|
||||
return result;
|
||||
|
||||
// Keep following the Variable chain.
|
||||
result = ((Variable)result)._value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IEnumerable<bool> unify(object arg)
|
||||
{
|
||||
if (!_isBound)
|
||||
{
|
||||
_value = YP.getValue(arg);
|
||||
if (_value == this)
|
||||
// We are unifying this unbound variable with itself, so leave it unbound.
|
||||
yield return false;
|
||||
else
|
||||
{
|
||||
_isBound = true;
|
||||
try
|
||||
{
|
||||
yield return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Remove the binding.
|
||||
_isBound = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (bool l1 in YP.unify(this, arg))
|
||||
yield return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
object value = getValue();
|
||||
if (value == this)
|
||||
return "Variable";
|
||||
else
|
||||
return getValue().ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If bound, call YP.addUniqueVariables on the value. Otherwise, if this unbound
|
||||
/// variable is not already in variableSet, add it.
|
||||
/// </summary>
|
||||
/// <param name="variableSet"></param>
|
||||
public void addUniqueVariables(List<Variable> variableSet)
|
||||
{
|
||||
if (_isBound)
|
||||
YP.addUniqueVariables(getValue(), variableSet);
|
||||
else
|
||||
{
|
||||
if (variableSet.IndexOf(this) < 0)
|
||||
variableSet.Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If bound, return YP.makeCopy for the value, else return copyStore.getCopy(this).
|
||||
/// However, if copyStore is null, just return this.
|
||||
/// </summary>
|
||||
/// <param name="copyStore"></param>
|
||||
/// <returns></returns>
|
||||
public object makeCopy(Variable.CopyStore copyStore)
|
||||
{
|
||||
if (_isBound)
|
||||
return YP.makeCopy(getValue(), copyStore);
|
||||
else
|
||||
return copyStore == null ? this : copyStore.getCopy(this);
|
||||
}
|
||||
|
||||
public bool termEqual(object term)
|
||||
{
|
||||
if (_isBound)
|
||||
return YP.termEqual(getValue(), term);
|
||||
else
|
||||
return this == YP.getValue(term);
|
||||
}
|
||||
|
||||
public bool ground()
|
||||
{
|
||||
if (_isBound)
|
||||
// This is usually called by YP.ground which already did getValue, so this
|
||||
// should never be reached, but check anyway.
|
||||
return YP.ground(getValue());
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A CopyStore is used by makeCopy to track which Variable objects have
|
||||
/// been copied.
|
||||
/// </summary>
|
||||
public class CopyStore
|
||||
{
|
||||
private List<Variable> _inVariableSet = new List<Variable>();
|
||||
private List<Variable> _outVariableSet = new List<Variable>();
|
||||
|
||||
/// <summary>
|
||||
/// If inVariable has already been copied, return its copy. Otherwise,
|
||||
/// return a fresh Variable associated with inVariable.
|
||||
/// </summary>
|
||||
/// <param name="inVariable"></param>
|
||||
/// <returns></returns>
|
||||
public Variable getCopy(Variable inVariable)
|
||||
{
|
||||
int index = _inVariableSet.IndexOf(inVariable);
|
||||
if (index >= 0)
|
||||
return _outVariableSet[index];
|
||||
else
|
||||
{
|
||||
Variable outVariable = new Variable();
|
||||
_inVariableSet.Add(inVariable);
|
||||
_outVariableSet.Add(outVariable);
|
||||
return outVariable;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of unique variables that have been copied.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int getNUniqueVariables()
|
||||
{
|
||||
return _inVariableSet.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user