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
Charles Krinke 2008-07-16 01:00:40 +00:00
parent 2f46ab5096
commit 620f7926f3
14 changed files with 5367 additions and 2550 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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 ",
@" ", @" ",

View File

@ -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,12 +96,20 @@ 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 match has already indexed answers for a signature, we need to add if (prepend)
// this to the existing indexed answers. {
foreach (int signature in _gotAnswersForSignature.Keys) _allAnswers.Insert(0, answerCopy);
indexAnswerForSignature(answerCopy, signature); clearIndexes();
}
else
{
_allAnswers.Add(answerCopy);
// If match has already indexed answers for a signature, we need to add
// this to the existing indexed answers.
foreach (int signature in _gotAnswersForSignature.Keys)
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.

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2007-2008, Jeff Thompson * Copyright (C) 2007-2008, Jeff Thompson
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its contributors * * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -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);
} }
} }
} }

View File

@ -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,12 +96,20 @@ 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 match has already indexed answers for a signature, we need to add if (prepend)
// this to the existing indexed answers. {
foreach (int signature in _gotAnswersForSignature.Keys) _allAnswers.Insert(0, answerCopy);
indexAnswerForSignature(answerCopy, signature); clearIndexes();
}
else
{
_allAnswers.Add(answerCopy);
// If match has already indexed answers for a signature, we need to add
// this to the existing indexed answers.
foreach (int signature in _gotAnswersForSignature.Keys)
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.

View File

@ -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
} }
} }

View File

@ -1,20 +1,20 @@
/* /*
* Copyright (C) 2007-2008, Jeff Thompson * Copyright (C) 2007-2008, Jeff Thompson
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its contributors * * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -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);
} }
} }
} }

View File

@ -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);

View File

@ -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 ",
@" ", @" ",