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.0.6.0-stable
parent
2f46ab5096
commit
620f7926f3
|
@ -486,6 +486,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
|
||||||
", Error Number: " + CompErr.ErrorNumber +
|
", Error Number: " + CompErr.ErrorNumber +
|
||||||
", '" + CompErr.ErrorText + "'\r\n";
|
", '" + CompErr.ErrorText + "'\r\n";
|
||||||
}
|
}
|
||||||
|
Console.WriteLine("[COMPILER ERROR]:" + errtext);
|
||||||
if (!File.Exists(OutFile))
|
if (!File.Exists(OutFile))
|
||||||
{
|
{
|
||||||
throw new Exception(errtext);
|
throw new Exception(errtext);
|
||||||
|
|
|
@ -59,6 +59,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
|
||||||
dataTypes.Add("rotation", "LSL_Types.Quaternion");
|
dataTypes.Add("rotation", "LSL_Types.Quaternion");
|
||||||
dataTypes.Add("list", "LSL_Types.list");
|
dataTypes.Add("list", "LSL_Types.list");
|
||||||
dataTypes.Add("null", "null");
|
dataTypes.Add("null", "null");
|
||||||
|
dataTypes.Add("Int32", "LSL_Types.LSLInteger");
|
||||||
|
dataTypes.Add("int", "LSL_Types.LSLInteger");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Convert(string Script)
|
public string Convert(string Script)
|
||||||
|
|
|
@ -96,6 +96,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
|
||||||
@"YP.script_event\(Atom.a\(\@\""(.*?)""\)\,",
|
@"YP.script_event\(Atom.a\(\@\""(.*?)""\)\,",
|
||||||
@"this.$1(",
|
@"this.$1(",
|
||||||
RegexOptions.Compiled | RegexOptions.Singleline);
|
RegexOptions.Compiled | RegexOptions.Singleline);
|
||||||
|
finalcode = Regex.Replace(finalcode,
|
||||||
|
@"YP.script_event\(Atom.a\(\""(.*?)""\)\,",
|
||||||
|
@"this.$1(",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Singleline);
|
||||||
finalcode = Regex.Replace(finalcode,
|
finalcode = Regex.Replace(finalcode,
|
||||||
@" static ",
|
@" static ",
|
||||||
@" ",
|
@" ",
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class IndexedAnswers : YP.IClause
|
public class IndexedAnswers : YP.IClause
|
||||||
{
|
{
|
||||||
|
private int _arity;
|
||||||
// addAnswer adds the answer here and indexes it later.
|
// addAnswer adds the answer here and indexes it later.
|
||||||
private List<object[]> _allAnswers = new List<object[]>();
|
private List<object[]> _allAnswers = new List<object[]>();
|
||||||
// The key has the arity of answers with non-null values for each indexed arg. The value
|
// 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
|
||||||
private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>();
|
private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>();
|
||||||
private const int MAX_INDEX_ARGS = 31;
|
private const int MAX_INDEX_ARGS = 31;
|
||||||
|
|
||||||
public IndexedAnswers()
|
public IndexedAnswers(int arity)
|
||||||
{
|
{
|
||||||
|
_arity = arity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Append the answer to the list and update the indexes, if any.
|
||||||
/// Elements of answer must be ground, since arguments with unbound variables make this
|
/// Elements of answer must be ground, since arguments with unbound variables make this
|
||||||
/// into a dynamic rule which we don't index.
|
/// into a dynamic rule which we don't index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="answer"></param>
|
/// <param name="answer"></param>
|
||||||
public void addAnswer(object[] answer)
|
public void addAnswer(object[] answer)
|
||||||
{
|
{
|
||||||
|
addOrPrependAnswer(answer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepend the answer to the list and clear the indexes so that they must be re-computed
|
||||||
|
/// on the next call to match. (Only addAnswer will maintain the indexes while adding answers.)
|
||||||
|
/// Elements of answer must be ground, since arguments with unbound variables make this
|
||||||
|
/// into a dynamic rule which we don't index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="answer"></param>
|
||||||
|
public void prependAnswer(object[] answer)
|
||||||
|
{
|
||||||
|
addOrPrependAnswer(answer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Do the work of addAnswer or prependAnswer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="answer"></param>
|
||||||
|
private void addOrPrependAnswer(object[] answer, bool prepend)
|
||||||
|
{
|
||||||
|
if (answer.Length != _arity)
|
||||||
|
return;
|
||||||
|
|
||||||
// Store a copy of the answer array.
|
// Store a copy of the answer array.
|
||||||
object[] answerCopy = new object[answer.Length];
|
object[] answerCopy = new object[answer.Length];
|
||||||
Variable.CopyStore copyStore = new Variable.CopyStore();
|
Variable.CopyStore copyStore = new Variable.CopyStore();
|
||||||
|
@ -69,13 +96,21 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||||
throw new InvalidOperationException
|
throw new InvalidOperationException
|
||||||
("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() +
|
("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() +
|
||||||
" unbound variables");
|
" unbound variables");
|
||||||
_allAnswers.Add(answerCopy);
|
|
||||||
|
|
||||||
|
if (prepend)
|
||||||
|
{
|
||||||
|
_allAnswers.Insert(0, answerCopy);
|
||||||
|
clearIndexes();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_allAnswers.Add(answerCopy);
|
||||||
// If match has already indexed answers for a signature, we need to add
|
// If match has already indexed answers for a signature, we need to add
|
||||||
// this to the existing indexed answers.
|
// this to the existing indexed answers.
|
||||||
foreach (int signature in _gotAnswersForSignature.Keys)
|
foreach (int signature in _gotAnswersForSignature.Keys)
|
||||||
indexAnswerForSignature(answerCopy, signature);
|
indexAnswerForSignature(answerCopy, signature);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void indexAnswerForSignature(object[] answer, int signature)
|
private void indexAnswerForSignature(object[] answer, int signature)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +154,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||||
|
|
||||||
public IEnumerable<bool> match(object[] arguments)
|
public IEnumerable<bool> match(object[] arguments)
|
||||||
{
|
{
|
||||||
|
if (arguments.Length != _arity)
|
||||||
|
yield break;
|
||||||
|
|
||||||
// Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for
|
// Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for
|
||||||
// each non-null index arg.
|
// each non-null index arg.
|
||||||
HashedList indexArgs = new HashedList(arguments.Length);
|
HashedList indexArgs = new HashedList(arguments.Length);
|
||||||
|
@ -166,6 +204,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||||
|
|
||||||
// Find matches in answers.
|
// Find matches in answers.
|
||||||
IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length];
|
IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length];
|
||||||
|
// Debug: If the caller asserts another answer into this same predicate during yield, the iterator
|
||||||
|
// over clauses will be corrupted. Should we take the time to copy answers?
|
||||||
foreach (object[] answer in answers)
|
foreach (object[] answer in answers)
|
||||||
{
|
{
|
||||||
bool gotMatch = true;
|
bool gotMatch = true;
|
||||||
|
@ -201,6 +241,59 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<bool> clause(object Head, object Body)
|
||||||
|
{
|
||||||
|
Head = YP.getValue(Head);
|
||||||
|
if (Head is Variable)
|
||||||
|
throw new PrologException("instantiation_error", "Head is an unbound variable");
|
||||||
|
object[] arguments = YP.getFunctorArgs(Head);
|
||||||
|
|
||||||
|
// We always match Head from _allAnswers, and the Body is Atom.a("true").
|
||||||
|
foreach (bool l1 in YP.unify(Body, Atom.a("true")))
|
||||||
|
{
|
||||||
|
// The caller can assert another answer into this same predicate during yield, so we have to
|
||||||
|
// make a copy of the answers.
|
||||||
|
foreach (object[] answer in _allAnswers.ToArray())
|
||||||
|
{
|
||||||
|
foreach (bool l2 in YP.unifyArrays(arguments, answer))
|
||||||
|
yield return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<bool> retract(object Head, object Body)
|
||||||
|
{
|
||||||
|
Head = YP.getValue(Head);
|
||||||
|
if (Head is Variable)
|
||||||
|
throw new PrologException("instantiation_error", "Head is an unbound variable");
|
||||||
|
object[] arguments = YP.getFunctorArgs(Head);
|
||||||
|
|
||||||
|
// We always match Head from _allAnswers, and the Body is Atom.a("true").
|
||||||
|
foreach (bool l1 in YP.unify(Body, Atom.a("true")))
|
||||||
|
{
|
||||||
|
// The caller can assert another answer into this same predicate during yield, so we have to
|
||||||
|
// make a copy of the answers.
|
||||||
|
foreach (object[] answer in _allAnswers.ToArray())
|
||||||
|
{
|
||||||
|
foreach (bool l2 in YP.unifyArrays(arguments, answer))
|
||||||
|
{
|
||||||
|
_allAnswers.Remove(answer);
|
||||||
|
clearIndexes();
|
||||||
|
yield return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// After retracting or prepending an answer in _allAnswers, the indexes are invalid, so clear them.
|
||||||
|
/// </summary>
|
||||||
|
private void clearIndexes()
|
||||||
|
{
|
||||||
|
_indexedAnswers.Clear();
|
||||||
|
_gotAnswersForSignature.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A HashedList extends an ArrayList with methods to get a hash and to check equality
|
/// A HashedList extends an ArrayList with methods to get a hash and to check equality
|
||||||
/// based on the elements of the list.
|
/// based on the elements of the list.
|
||||||
|
|
|
@ -43,7 +43,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||||
/// Create a PrologException with the given Term. The printable exception message is the full Term.
|
/// Create a PrologException with the given Term. The printable exception message is the full Term.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="Term">the term of the exception</param>
|
/// <param name="Term">the term of the exception</param>
|
||||||
/// </param>
|
|
||||||
public PrologException(object Term)
|
public PrologException(object Term)
|
||||||
: base(YP.getValue(Term).ToString())
|
: base(YP.getValue(Term).ToString())
|
||||||
{
|
{
|
||||||
|
@ -54,18 +53,107 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog
|
||||||
/// Create a PrologException where the Term is error(ErrorTerm, Message).
|
/// Create a PrologException where the Term is error(ErrorTerm, Message).
|
||||||
/// This uses YP.makeCopy to copy the ErrorTerm and Message so that they are valid after unbinding.
|
/// This uses YP.makeCopy to copy the ErrorTerm and Message so that they are valid after unbinding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ErrorTerm">the term of the exception</param>
|
/// <param name="ErrorTerm">the error term of the error</param>
|
||||||
/// <param name="Messsage">the message, converted to a string, to use as the printable exception message
|
/// <param name="Messsage">the message term of the error. If this is a string, it is converted to an
|
||||||
|
/// Atom so it can be used by Prolog code.
|
||||||
|
/// Message, converted to a string, is use as the printable exception message.
|
||||||
/// </param>
|
/// </param>
|
||||||
public PrologException(object ErrorTerm, object Message)
|
public PrologException(object ErrorTerm, object Message)
|
||||||
: base(YP.getValue(Message).ToString())
|
: base(YP.getValue(Message).ToString())
|
||||||
{
|
{
|
||||||
|
if (Message is string)
|
||||||
|
Message = Atom.a((string)Message);
|
||||||
_term = YP.makeCopy(new Functor2(Atom.a("error"), ErrorTerm, Message), new Variable.CopyStore());
|
_term = YP.makeCopy(new Functor2(Atom.a("error"), ErrorTerm, Message), new Variable.CopyStore());
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Term
|
public class TypeErrorInfo
|
||||||
{
|
{
|
||||||
get { return _term; }
|
public readonly Atom _Type;
|
||||||
|
public readonly object _Culprit;
|
||||||
|
public readonly object _Message;
|
||||||
|
|
||||||
|
public TypeErrorInfo(Atom Type, object Culprit, object Message)
|
||||||
|
{
|
||||||
|
_Type = Type;
|
||||||
|
_Culprit = Culprit;
|
||||||
|
_Message = Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Return the TypeErrorInfo for this exception, or null if _term does not match
|
||||||
|
/// error(type_error(Type, Culprit), Message).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TypeErrorInfo getTypeErrorInfo()
|
||||||
|
{
|
||||||
|
if (!(_term is Functor2 && ((Functor2)_term)._name._name == "error"))
|
||||||
|
return null;
|
||||||
|
object errorTerm = ((Functor2)_term)._arg1;
|
||||||
|
if (!(errorTerm is Functor2 && ((Functor2)errorTerm)._name._name == "type_error"))
|
||||||
|
return null;
|
||||||
|
if (!(((Functor2)errorTerm)._arg1 is Atom))
|
||||||
|
return null;
|
||||||
|
return new TypeErrorInfo
|
||||||
|
((Atom)((Functor2)errorTerm)._arg1, ((Functor2)errorTerm)._arg2, ((Functor2)_term)._arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExistenceErrorInfo
|
||||||
|
{
|
||||||
|
public readonly Atom _Type;
|
||||||
|
public readonly object _Culprit;
|
||||||
|
public readonly object _Message;
|
||||||
|
|
||||||
|
public ExistenceErrorInfo(Atom Type, object Culprit, object Message)
|
||||||
|
{
|
||||||
|
_Type = Type;
|
||||||
|
_Culprit = Culprit;
|
||||||
|
_Message = Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If _Type is procedure and _Culprit is name/artity, return the name. Otherwise return null.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public object getProcedureName()
|
||||||
|
{
|
||||||
|
if (!(_Type._name == "procedure" &&
|
||||||
|
_Culprit is Functor2 && ((Functor2)_Culprit)._name == Atom.SLASH))
|
||||||
|
return null;
|
||||||
|
return ((Functor2)_Culprit)._arg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If _Type is procedure and _Culprit is name/arity and arity is an integer, return the arity.
|
||||||
|
/// Otherwise return -1.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int getProcedureArity()
|
||||||
|
{
|
||||||
|
if (!(_Type._name == "procedure" &&
|
||||||
|
_Culprit is Functor2 && ((Functor2)_Culprit)._name == Atom.SLASH))
|
||||||
|
return -1;
|
||||||
|
if (!(((Functor2)_Culprit)._arg2 is int))
|
||||||
|
return -1;
|
||||||
|
return (int)((Functor2)_Culprit)._arg2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Return the ExistenceErrorInfo for this exception, or null if _term does not match
|
||||||
|
/// error(existence_error(Type, Culprit), Message). If the returned ExistenceErrorInfo _Culprit is
|
||||||
|
/// procedure, you can use its getProcedureName and getProcedureArity.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ExistenceErrorInfo getExistenceErrorInfo()
|
||||||
|
{
|
||||||
|
if (!(_term is Functor2 && ((Functor2)_term)._name._name == "error"))
|
||||||
|
return null;
|
||||||
|
object errorTerm = ((Functor2)_term)._arg1;
|
||||||
|
if (!(errorTerm is Functor2 && ((Functor2)errorTerm)._name._name == "existence_error"))
|
||||||
|
return null;
|
||||||
|
if (!(((Functor2)errorTerm)._arg1 is Atom))
|
||||||
|
return null;
|
||||||
|
return new ExistenceErrorInfo
|
||||||
|
((Atom)((Functor2)errorTerm)._arg1, ((Functor2)errorTerm)._arg2, ((Functor2)_term)._arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -39,6 +39,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class IndexedAnswers : YP.IClause
|
public class IndexedAnswers : YP.IClause
|
||||||
{
|
{
|
||||||
|
private int _arity;
|
||||||
// addAnswer adds the answer here and indexes it later.
|
// addAnswer adds the answer here and indexes it later.
|
||||||
private List<object[]> _allAnswers = new List<object[]>();
|
private List<object[]> _allAnswers = new List<object[]>();
|
||||||
// The key has the arity of answers with non-null values for each indexed arg. The value
|
// 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.Shared.YieldProlog
|
||||||
private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>();
|
private Dictionary<int, object> _gotAnswersForSignature = new Dictionary<int, object>();
|
||||||
private const int MAX_INDEX_ARGS = 31;
|
private const int MAX_INDEX_ARGS = 31;
|
||||||
|
|
||||||
public IndexedAnswers()
|
public IndexedAnswers(int arity)
|
||||||
{
|
{
|
||||||
|
_arity = arity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Append the answer to the list and update the indexes, if any.
|
||||||
/// Elements of answer must be ground, since arguments with unbound variables make this
|
/// Elements of answer must be ground, since arguments with unbound variables make this
|
||||||
/// into a dynamic rule which we don't index.
|
/// into a dynamic rule which we don't index.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="answer"></param>
|
/// <param name="answer"></param>
|
||||||
public void addAnswer(object[] answer)
|
public void addAnswer(object[] answer)
|
||||||
{
|
{
|
||||||
|
addOrPrependAnswer(answer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepend the answer to the list and clear the indexes so that they must be re-computed
|
||||||
|
/// on the next call to match. (Only addAnswer will maintain the indexes while adding answers.)
|
||||||
|
/// Elements of answer must be ground, since arguments with unbound variables make this
|
||||||
|
/// into a dynamic rule which we don't index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="answer"></param>
|
||||||
|
public void prependAnswer(object[] answer)
|
||||||
|
{
|
||||||
|
addOrPrependAnswer(answer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Do the work of addAnswer or prependAnswer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="answer"></param>
|
||||||
|
private void addOrPrependAnswer(object[] answer, bool prepend)
|
||||||
|
{
|
||||||
|
if (answer.Length != _arity)
|
||||||
|
return;
|
||||||
|
|
||||||
// Store a copy of the answer array.
|
// Store a copy of the answer array.
|
||||||
object[] answerCopy = new object[answer.Length];
|
object[] answerCopy = new object[answer.Length];
|
||||||
Variable.CopyStore copyStore = new Variable.CopyStore();
|
Variable.CopyStore copyStore = new Variable.CopyStore();
|
||||||
|
@ -69,13 +96,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
throw new InvalidOperationException
|
throw new InvalidOperationException
|
||||||
("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() +
|
("Elements of answer must be ground, but found " + copyStore.getNUniqueVariables() +
|
||||||
" unbound variables");
|
" unbound variables");
|
||||||
_allAnswers.Add(answerCopy);
|
|
||||||
|
|
||||||
|
if (prepend)
|
||||||
|
{
|
||||||
|
_allAnswers.Insert(0, answerCopy);
|
||||||
|
clearIndexes();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_allAnswers.Add(answerCopy);
|
||||||
// If match has already indexed answers for a signature, we need to add
|
// If match has already indexed answers for a signature, we need to add
|
||||||
// this to the existing indexed answers.
|
// this to the existing indexed answers.
|
||||||
foreach (int signature in _gotAnswersForSignature.Keys)
|
foreach (int signature in _gotAnswersForSignature.Keys)
|
||||||
indexAnswerForSignature(answerCopy, signature);
|
indexAnswerForSignature(answerCopy, signature);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void indexAnswerForSignature(object[] answer, int signature)
|
private void indexAnswerForSignature(object[] answer, int signature)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +154,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
|
|
||||||
public IEnumerable<bool> match(object[] arguments)
|
public IEnumerable<bool> match(object[] arguments)
|
||||||
{
|
{
|
||||||
|
if (arguments.Length != _arity)
|
||||||
|
yield break;
|
||||||
|
|
||||||
// Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for
|
// Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for
|
||||||
// each non-null index arg.
|
// each non-null index arg.
|
||||||
HashedList indexArgs = new HashedList(arguments.Length);
|
HashedList indexArgs = new HashedList(arguments.Length);
|
||||||
|
@ -166,6 +204,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
|
|
||||||
// Find matches in answers.
|
// Find matches in answers.
|
||||||
IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length];
|
IEnumerator<bool>[] iterators = new IEnumerator<bool>[arguments.Length];
|
||||||
|
// Debug: If the caller asserts another answer into this same predicate during yield, the iterator
|
||||||
|
// over clauses will be corrupted. Should we take the time to copy answers?
|
||||||
foreach (object[] answer in answers)
|
foreach (object[] answer in answers)
|
||||||
{
|
{
|
||||||
bool gotMatch = true;
|
bool gotMatch = true;
|
||||||
|
@ -201,6 +241,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<bool> clause(object Head, object Body)
|
||||||
|
{
|
||||||
|
Head = YP.getValue(Head);
|
||||||
|
if (Head is Variable)
|
||||||
|
throw new PrologException("instantiation_error", "Head is an unbound variable");
|
||||||
|
object[] arguments = YP.getFunctorArgs(Head);
|
||||||
|
|
||||||
|
// We always match Head from _allAnswers, and the Body is Atom.a("true").
|
||||||
|
foreach (bool l1 in YP.unify(Body, Atom.a("true")))
|
||||||
|
{
|
||||||
|
// The caller can assert another answer into this same predicate during yield, so we have to
|
||||||
|
// make a copy of the answers.
|
||||||
|
foreach (object[] answer in _allAnswers.ToArray())
|
||||||
|
{
|
||||||
|
foreach (bool l2 in YP.unifyArrays(arguments, answer))
|
||||||
|
yield return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<bool> retract(object Head, object Body)
|
||||||
|
{
|
||||||
|
Head = YP.getValue(Head);
|
||||||
|
if (Head is Variable)
|
||||||
|
throw new PrologException("instantiation_error", "Head is an unbound variable");
|
||||||
|
object[] arguments = YP.getFunctorArgs(Head);
|
||||||
|
|
||||||
|
// We always match Head from _allAnswers, and the Body is Atom.a("true").
|
||||||
|
foreach (bool l1 in YP.unify(Body, Atom.a("true")))
|
||||||
|
{
|
||||||
|
// The caller can assert another answer into this same predicate during yield, so we have to
|
||||||
|
// make a copy of the answers.
|
||||||
|
foreach (object[] answer in _allAnswers.ToArray())
|
||||||
|
{
|
||||||
|
foreach (bool l2 in YP.unifyArrays(arguments, answer))
|
||||||
|
{
|
||||||
|
_allAnswers.Remove(answer);
|
||||||
|
clearIndexes();
|
||||||
|
yield return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// After retracting or prepending an answer in _allAnswers, the indexes are invalid, so clear them.
|
||||||
|
/// </summary>
|
||||||
|
private void clearIndexes()
|
||||||
|
{
|
||||||
|
_indexedAnswers.Clear();
|
||||||
|
_gotAnswersForSignature.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A HashedList extends an ArrayList with methods to get a hash and to check equality
|
/// A HashedList extends an ArrayList with methods to get a hash and to check equality
|
||||||
/// based on the elements of the list.
|
/// based on the elements of the list.
|
||||||
|
|
|
@ -44,9 +44,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
yield return false;
|
yield return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable warning: don't see how we can code this differently short
|
// disable warning on l1, don't see how we can
|
||||||
// of rewriting the whole thing
|
// code this differently
|
||||||
#pragma warning disable 0168, 0219
|
#pragma warning disable 0168, 0219
|
||||||
|
|
||||||
// Debug: Hand-modify this central predicate to do tail recursion.
|
// Debug: Hand-modify this central predicate to do tail recursion.
|
||||||
public static IEnumerable<bool> read_tokens(object arg1, object arg2, object arg3)
|
public static IEnumerable<bool> read_tokens(object arg1, object arg2, object arg3)
|
||||||
|
@ -228,12 +228,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
if (YP.termEqual(Term, Atom.a(@"end_of_file")))
|
if (YP.termEqual(Term, Atom.a(@"end_of_file")))
|
||||||
{
|
{
|
||||||
yield break;
|
yield break;
|
||||||
// unreachable code:
|
|
||||||
// goto cutIf1;
|
// goto cutIf1;
|
||||||
}
|
}
|
||||||
yield return false;
|
yield return false;
|
||||||
// cutIf1:
|
// cutIf1:
|
||||||
{ }
|
// { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4457,6 +4456,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore 0168
|
#pragma warning restore 0168, 0219
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
/// Create a PrologException with the given Term. The printable exception message is the full Term.
|
/// Create a PrologException with the given Term. The printable exception message is the full Term.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="Term">the term of the exception</param>
|
/// <param name="Term">the term of the exception</param>
|
||||||
/// </param>
|
|
||||||
public PrologException(object Term)
|
public PrologException(object Term)
|
||||||
: base(YP.getValue(Term).ToString())
|
: base(YP.getValue(Term).ToString())
|
||||||
{
|
{
|
||||||
|
@ -54,18 +53,107 @@ namespace OpenSim.Region.ScriptEngine.Shared.YieldProlog
|
||||||
/// Create a PrologException where the Term is error(ErrorTerm, Message).
|
/// Create a PrologException where the Term is error(ErrorTerm, Message).
|
||||||
/// This uses YP.makeCopy to copy the ErrorTerm and Message so that they are valid after unbinding.
|
/// This uses YP.makeCopy to copy the ErrorTerm and Message so that they are valid after unbinding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ErrorTerm">the term of the exception</param>
|
/// <param name="ErrorTerm">the error term of the error</param>
|
||||||
/// <param name="Messsage">the message, converted to a string, to use as the printable exception message
|
/// <param name="Messsage">the message term of the error. If this is a string, it is converted to an
|
||||||
|
/// Atom so it can be used by Prolog code.
|
||||||
|
/// Message, converted to a string, is use as the printable exception message.
|
||||||
/// </param>
|
/// </param>
|
||||||
public PrologException(object ErrorTerm, object Message)
|
public PrologException(object ErrorTerm, object Message)
|
||||||
: base(YP.getValue(Message).ToString())
|
: base(YP.getValue(Message).ToString())
|
||||||
{
|
{
|
||||||
|
if (Message is string)
|
||||||
|
Message = Atom.a((string)Message);
|
||||||
_term = YP.makeCopy(new Functor2(Atom.a("error"), ErrorTerm, Message), new Variable.CopyStore());
|
_term = YP.makeCopy(new Functor2(Atom.a("error"), ErrorTerm, Message), new Variable.CopyStore());
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Term
|
public class TypeErrorInfo
|
||||||
{
|
{
|
||||||
get { return _term; }
|
public readonly Atom _Type;
|
||||||
|
public readonly object _Culprit;
|
||||||
|
public readonly object _Message;
|
||||||
|
|
||||||
|
public TypeErrorInfo(Atom Type, object Culprit, object Message)
|
||||||
|
{
|
||||||
|
_Type = Type;
|
||||||
|
_Culprit = Culprit;
|
||||||
|
_Message = Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Return the TypeErrorInfo for this exception, or null if _term does not match
|
||||||
|
/// error(type_error(Type, Culprit), Message).
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TypeErrorInfo getTypeErrorInfo()
|
||||||
|
{
|
||||||
|
if (!(_term is Functor2 && ((Functor2)_term)._name._name == "error"))
|
||||||
|
return null;
|
||||||
|
object errorTerm = ((Functor2)_term)._arg1;
|
||||||
|
if (!(errorTerm is Functor2 && ((Functor2)errorTerm)._name._name == "type_error"))
|
||||||
|
return null;
|
||||||
|
if (!(((Functor2)errorTerm)._arg1 is Atom))
|
||||||
|
return null;
|
||||||
|
return new TypeErrorInfo
|
||||||
|
((Atom)((Functor2)errorTerm)._arg1, ((Functor2)errorTerm)._arg2, ((Functor2)_term)._arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExistenceErrorInfo
|
||||||
|
{
|
||||||
|
public readonly Atom _Type;
|
||||||
|
public readonly object _Culprit;
|
||||||
|
public readonly object _Message;
|
||||||
|
|
||||||
|
public ExistenceErrorInfo(Atom Type, object Culprit, object Message)
|
||||||
|
{
|
||||||
|
_Type = Type;
|
||||||
|
_Culprit = Culprit;
|
||||||
|
_Message = Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If _Type is procedure and _Culprit is name/artity, return the name. Otherwise return null.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public object getProcedureName()
|
||||||
|
{
|
||||||
|
if (!(_Type._name == "procedure" &&
|
||||||
|
_Culprit is Functor2 && ((Functor2)_Culprit)._name == Atom.SLASH))
|
||||||
|
return null;
|
||||||
|
return ((Functor2)_Culprit)._arg1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If _Type is procedure and _Culprit is name/arity and arity is an integer, return the arity.
|
||||||
|
/// Otherwise return -1.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int getProcedureArity()
|
||||||
|
{
|
||||||
|
if (!(_Type._name == "procedure" &&
|
||||||
|
_Culprit is Functor2 && ((Functor2)_Culprit)._name == Atom.SLASH))
|
||||||
|
return -1;
|
||||||
|
if (!(((Functor2)_Culprit)._arg2 is int))
|
||||||
|
return -1;
|
||||||
|
return (int)((Functor2)_Culprit)._arg2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Return the ExistenceErrorInfo for this exception, or null if _term does not match
|
||||||
|
/// error(existence_error(Type, Culprit), Message). If the returned ExistenceErrorInfo _Culprit is
|
||||||
|
/// procedure, you can use its getProcedureName and getProcedureArity.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ExistenceErrorInfo getExistenceErrorInfo()
|
||||||
|
{
|
||||||
|
if (!(_term is Functor2 && ((Functor2)_term)._name._name == "error"))
|
||||||
|
return null;
|
||||||
|
object errorTerm = ((Functor2)_term)._arg1;
|
||||||
|
if (!(errorTerm is Functor2 && ((Functor2)errorTerm)._name._name == "existence_error"))
|
||||||
|
return null;
|
||||||
|
if (!(((Functor2)errorTerm)._arg1 is Atom))
|
||||||
|
return null;
|
||||||
|
return new ExistenceErrorInfo
|
||||||
|
((Atom)((Functor2)errorTerm)._arg1, ((Functor2)errorTerm)._arg2, ((Functor2)_term)._arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -544,6 +544,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
", Error Number: " + CompErr.ErrorNumber +
|
", Error Number: " + CompErr.ErrorNumber +
|
||||||
", '" + CompErr.ErrorText + "'\r\n";
|
", '" + CompErr.ErrorText + "'\r\n";
|
||||||
}
|
}
|
||||||
|
Console.WriteLine("[COMPILER ERROR]:" + errtext);
|
||||||
if (!File.Exists(OutFile))
|
if (!File.Exists(OutFile))
|
||||||
{
|
{
|
||||||
throw new Exception(errtext);
|
throw new Exception(errtext);
|
||||||
|
|
|
@ -97,6 +97,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
@"YP.script_event\(Atom.a\(\@\""(.*?)""\)\,",
|
@"YP.script_event\(Atom.a\(\@\""(.*?)""\)\,",
|
||||||
@"this.$1(",
|
@"this.$1(",
|
||||||
RegexOptions.Compiled | RegexOptions.Singleline);
|
RegexOptions.Compiled | RegexOptions.Singleline);
|
||||||
|
finalcode = Regex.Replace(finalcode,
|
||||||
|
@"YP.script_event\(Atom.a\(\""(.*?)""\)\,",
|
||||||
|
@"this.$1(",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Singleline);
|
||||||
finalcode = Regex.Replace(finalcode,
|
finalcode = Regex.Replace(finalcode,
|
||||||
@" static ",
|
@" static ",
|
||||||
@" ",
|
@" ",
|
||||||
|
|
Loading…
Reference in New Issue