/* $Id$ * * Project: Swicli.Library - Two Way Interface for .NET and MONO to SWI-Prolog * Author: Douglas R. Miles * Uwe Lesta (SbsSW.SwiPlCs classes) * E-mail: logicmoo@gmail.com * WWW: http://www.logicmoo.com * Copyright (C): 2008, Uwe Lesta SBS-Softwaresysteme GmbH, * 2010-2012 LogicMOO Developement * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *********************************************************/ using System; using System.Runtime.Serialization; using System.Security.Permissions; using SbsSW.DesignByContract; using Swicli.Library; // Exception implementation // SecurityPermissionAttribute for GetObjectData namespace SbsSW.SwiPlCs.Exceptions { #region namspace documentation /// /// These are the namespace comments for SbsSW.SwiPlCs.Exceptions. /// The namespace SbsSW.SwiPlCs.Exceptions provides the Exception classes to catch a prolog exception /// see SWI-Prolog Manual - 4.9 ISO compliant Exception handling /// /// Prolog exceptions are mapped to C# exceptions using the subclass PlException of /// to represent the Prolog exception term. /// All type-conversion functions of the interface raise Prolog-compliant exceptions, /// providing decent error-handling support at no extra work for the programmer. /// For some commonly used exceptions, subclasses of PlException have been created to exploit /// both their constructors for easy creation of these exceptions as well as selective trapping in C#. /// Currently, these are and . /// /// /// /// To throw an exception, create an instance of PlException and use throw() or cppThrow(). The latter refines the C# exception class according to the represented Prolog exception before calling throw(). /// [System.Runtime.CompilerServices.CompilerGenerated()] class NamespaceDoc { } #endregion namspace documentation #region class PlLibException /// This exception is thrown if something in the interface went wrong. [Serializable] public class PlLibException : Exception, ISerializable { /// public PlLibException() : base() { BP(); } static private void BP() { libpl.PL_open_foreign_frame(); PrologCLR.BP(); return; } /// public PlLibException(string message) : base(message) { BP(); } /// public PlLibException(string message, Exception innerException) : base(message, innerException) { BP(); } #region implementation of ISerializable // ISerializable Constructor /// protected PlLibException(SerializationInfo info, StreamingContext context) : base(info, context) { BP(); } // see http://msdnwiki.microsoft.com/en-us/mtpswiki/f1d0010b-14fb-402f-974f-16318f0bc19f.aspx /// [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); base.GetObjectData(info, context); } #endregion implementation of ISerializable } #endregion class PlLibException #region class PlException /// /// /// This class is the base class to catch exceptions thrown by prolog in C#. /// /// /// /// /// /// SWI-Prolog Manual - 4.9 ISO compliant Exception handling [Serializable] public class PlException : Exception, ISerializable { private string _messagePl; private PlTerm _exTerm; /// provide somtimes some additional information about the exceptions reason. public string MessagePl { get { return _messagePl; } } /// public PlException() : base() { EnsureExFrame(); _exTerm = PlTerm.PlVar(); } /// public PlException(string message) : base(message) { EnsureExFrame(); _messagePl = message; _exTerm = PlTerm.PlAtom(message); //_exTerm = new PlTerm(message); } /// public PlException(string message, Exception innerException) : base(message, innerException) { EnsureExFrame(); _messagePl = message + "; innerExeption:" + innerException.Message; _exTerm = PlTerm.PlAtom(message); //_exTerm = new PlTerm(message); } #region implementation of ISerializable // ISerializable Constructor /// protected PlException(SerializationInfo info, StreamingContext context) : base(info, context) { EnsureExFrame(); if (info == null) throw new ArgumentNullException("info"); _messagePl = (string)info.GetValue("_messagePl", typeof(string)); _exTerm = (PlTerm)info.GetValue("_exTerm", typeof(PlTerm)); } // see http://msdnwiki.microsoft.com/en-us/mtpswiki/f1d0010b-14fb-402f-974f-16318f0bc19f.aspx /// [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); base.GetObjectData(info, context); info.AddValue("_messagePl", _messagePl); info.AddValue("_exTerm", this._exTerm); } #endregion implementation of ISerializable /// /// To catch a exception thrown by prolog /// For a example see . /// /// A PlTerm containing the Prolog exception /// public PlException(PlTerm term) { EnsureExFrame(); Check.Require(term.TermRefIntern != 0); _exTerm = new PlTerm(term.TermRef); // If this line is deleted -> update comment in PlTern(term_ref) _messagePl = "" + _exTerm; } private void EnsureExFrame() { libpl.PL_open_foreign_frame(); PrologCLR.BP(); } /// /// Get the of this exception. /// public PlTerm Term { get { return _exTerm; } } /// public override string Message { get { return this.ToString(); } } //operator char *(void); /// /// /// The exception is translated into a message as produced by print_message/2. The character data is stored in a ring. /// /// override public string ToString() { if (_messagePl != null) return GetType() + ": " + _messagePl; if (!PlEngine.IsInitialized) return "A PlException was thrown but it can't formatted because PlEngine is not Initialized."; string strRet = "[ERROR: Failed to generate message. Internal error]\n"; if (libpl.NoToString) return "[ERROR: Failed to generate message. NoToString presently]\n"; using (PlFrame fr = new PlFrame()) { #if USE_PRINT_MESSAGE PlTermV av = new PlTermV(2); av[0] = PlTerm.PlCompound("print_message", new PlTermV(new PlTerm("error"), new PlTerm( _exTerm.TermRef))); PlQuery q = new PlQuery("$write_on_string", av); if ( q.NextSolution() ) strRet = (string)av[1]; q.Free(); #else PlTermV av = new PlTermV(2); av[0] = new PlTerm(_exTerm.TermRef); PlQuery q = new PlQuery("$messages", "message_to_string", av); if (q.NextSolution()) strRet = av[1].ToString(); //q.Free(); return strRet; q.Dispose(); #endif } return strRet; } /// /// TODO /// /// Used in the PREDICATE() wrapper to pass the exception to Prolog. See PL_raise_exeption(). /// public int PlThrow() { return libpl.PL_raise_exception(_exTerm.TermRef); } /// /// TODO /// /// see public void Throw() { // term_t uint a = libpl.PL_new_term_ref(); // atom_t uint name = 0; int arity = 0; if (0 != libpl.PL_get_arg(1, _exTerm.TermRef, a) && 0 != libpl.PL_get_name_arity(a, ref name, ref arity)) { string str = libpl.PL_atom_chars(name); if (str == "type_error") throw new PlTypeException(_exTerm); else if (str == "domain_error") throw new PlDomainException(_exTerm); } this._messagePl = this.Message; throw this; } } // class PlException #endregion #region class PlTypeException /// /// /// A type error expresses that a term does not satisfy the expected basic Prolog type. /// /// /// This sample demonstrate how to catch a PlTypeException in C# that is thrown somewhere int the prolog code. /// /// [Serializable] public class PlTypeException : PlException { /// public PlTypeException() : base() { } /// public PlTypeException(string message) : base(message) { } /// public PlTypeException(string message, Exception innerException) : base(message, innerException) { } /// protected PlTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { } /// public PlTypeException(PlTerm term) : base(term) { } /// /// Creates an ISO standard Prolog error term expressing the expected type and actual term that does not satisfy this type. /// /// The type which was expected /// The actual term public PlTypeException(string expected, PlTerm actual) : base( PlTerm.PlCompound("error", new PlTermV(PlTerm.PlCompound("type_error", new PlTermV(new PlTerm(expected), actual)), PlTerm.PlVar()) )) { } } // class PlTypeException #endregion class PlTypeException #region class PlDomainException /// /// A domain exception expresses that a term satisfies the basic Prolog type expected, but is unacceptable /// to the restricted domain expected by some operation. /// /// /// For example, the standard Prolog open/3 call expect an IO-Mode (read, write, append, ...). /// If an integer is provided, this is a type error, if an atom other than one of the defined IO-modes is provided it is a domain error. /// /// [Serializable] internal class PlDomainException : PlException { /// public PlDomainException() : base() { } /* public PlDomainException(string message) : base(message) { } public PlDomainException(string message, Exception innerException) : base(message, innerException) { } */ /// protected PlDomainException(SerializationInfo info, StreamingContext context) : base(info, context) { } /// public PlDomainException(PlTerm t) : base(t) { } /* PlDomainException(string expected, PlTerm actual) : base(new PlCompound("error", new PlTermV(new PlCompound("domain_error", new PlTermV(new PlTerm(expected), actual)), PlTerm.PlVar()) ) ) { } */ } #endregion class PlDomainException } // namespace SbsSW.SwiPlCs