/* SWI-Prolog Interface for .NET
*
* Written by Uwe Lesta, SBS-Softwaresysteme 2003
* Modified by Aelij Arbel, 2004
*/
using System;
namespace Swi
{
#region Private Wraper Class for libpl.dll
using System.Runtime.InteropServices;
///
/// This is a port of the C++ interface (SWI-cpp.h) from Jan Wielemaker
/// to CSharp. The interface to the native prolog interface (SWI.Prolog.h)
/// is in class libpl.
/// Note: Make sure 'DllFileName' points to the right location.
///
class LibPl
{
private const string DllFileName = @"LibPl.dll";
public const int PL_Q_NORMAL = 0x02;
public const int PL_Q_NODEBUG = 0x04;
public const int PL_Q_CATCH_EXCEPTION = 0x08;
public const int PL_Q_PASS_EXCEPTION = 0x10;
/*******************************
* CHAR BUFFERS *
*******************************/
public const int CVT_ATOM = 0x0001;
public const int CVT_STRING = 0x0002;
public const int CVT_LIST = 0x0004;
public const int CVT_INTEGER = 0x0008;
public const int CVT_FLOAT = 0x0010;
public const int CVT_VARIABLE = 0x0020;
public const int CVT_NUMBER = (CVT_INTEGER | CVT_FLOAT);
public const int CVT_ATOMIC = (CVT_NUMBER | CVT_ATOM | CVT_STRING);
public const int CVT_WRITE = 0x0040; // as of version 3.2.10
public const int CVT_ALL = (CVT_ATOMIC | CVT_LIST);
public const int CVT_MASK = 0x00ff;
public const int BUF_DISCARDABLE = 0x0000;
public const int BUF_RING = 0x0100;
public const int BUF_MALLOC = 0x0200;
// ENGINES (MT-ONLY)
public const int PL_ENGINE_MAIN = 0x1; // ((PL_engine_t)0x1)
public const int PL_ENGINE_CURRENT = 0x2; // ((PL_engine_t)0x2)
public const int PL_ENGINE_SET = 0; // engine set successfully
public const int PL_ENGINE_INVAL = 2; // engine doesn't exist
public const int PL_ENGINE_INUSE = 3; // engine is in use
public LibPl()
{ // TODO: Add constructor logic here
}
~LibPl()
{
LibPl.PL_cleanup(0);
}
[DllImport(DllFileName)]
internal static extern int PL_initialise(int argc, String[] argv);
[DllImport(DllFileName)]
// PL_EXPORT(int) PL_is_initialised(int *argc, char ***argv);
internal static extern int PL_is_initialised([In, Out] ref int argc, [In, Out] ref String[] argv);
[DllImport(DllFileName)]
internal static extern int PL_is_initialised(IntPtr argc, IntPtr argv);
[DllImport(DllFileName)]
internal static extern int PL_halt(int i);
[DllImport(DllFileName)]
internal static extern int PL_cleanup(int status);
// ENGINES (MT-ONLY)
// TYPES : PL_engine_t -> void *
// PL_thread_attr_t -> struct
[DllImport(DllFileName)]
// PL_EXPORT(PL_engine_t) PL_create_engine(PL_thread_attr_t *attributes);
internal static extern IntPtr PL_create_engine(IntPtr attr);
[DllImport(DllFileName)] // PL_EXPORT(int) PL_set_engine(PL_engine_t engine, PL_engine_t *old);
internal static extern int PL_set_engine(IntPtr engine, [In, Out] ref IntPtr old);
[DllImport(DllFileName)] // PL_EXPORT(int) PL_destroy_engine(PL_engine_t engine);
internal static extern int PL_destroy_engine(IntPtr engine);
[DllImport(DllFileName)]
internal static extern uint PL_new_atom(string text);
[DllImport(DllFileName)] // return const char *
internal static extern string PL_atom_chars(uint t_atom);
// PlFrame
[DllImport(DllFileName)]
internal static extern uint PL_open_foreign_frame();
[DllImport(DllFileName)]
internal static extern void PL_close_foreign_frame(uint fid_t);
[DllImport(DllFileName)]
internal static extern void PL_rewind_foreign_frame(uint fid_t);
// PlQuery
[DllImport(DllFileName)]
internal static extern int PL_next_solution(uint qid_t);
[DllImport(DllFileName)]
internal static extern IntPtr PL_predicate(string name, int arity, string module);
[DllImport(DllFileName)]
//qid_t PL_open_query(module_t m, int flags, predicate_t pred, term_t t0);
internal static extern uint PL_open_query(IntPtr module, int flags, IntPtr pred, uint term);
[DllImport(DllFileName)]
internal static extern void PL_cut_query(uint qid);
// PlTerm
[DllImport(DllFileName)] // return term_t
internal static extern void PL_put_atom_chars(uint term, string chars);
//__pl_export term_t PL_new_term_ref(void);
[DllImport(DllFileName)] // return term_t
internal static extern uint PL_new_term_ref();
//__pl_export void PL_put_integer(term_t t, long i);
[DllImport(DllFileName)]
internal static extern void PL_put_integer(uint term, int i);
[DllImport(DllFileName)]
internal static extern void PL_put_float(uint term, double i);
// __pl_export void PL_put_atom(term_t t, atom_t a);
[DllImport(DllFileName)]
internal static extern void PL_put_atom(uint term, uint atom_handle);
// __pl_export int PL_get_chars(term_t t, char **s, unsigned int flags);
[DllImport(DllFileName)]
internal static extern int PL_get_chars(uint term, ref string s, uint flags);
// __pl_export int PL_get_long(term_t t, long *i);
[DllImport(DllFileName)]
internal static extern int PL_get_long(uint term, [In, Out] ref int i);
// __pl_export int PL_get_float(term_t t, double *f);
[DllImport(DllFileName)]
internal static extern int PL_get_float(uint term, [In, Out] ref double i);
// __pl_export int PL_get_atom(term_t t, atom_t *a);
[DllImport(DllFileName)]
internal static extern int PL_get_atom(uint term, [In, Out] ref uint atom_t);
//__pl_export int PL_term_type(term_t t);
[DllImport(DllFileName)]
internal static extern int PL_term_type(uint t);
// COMPARE
//__pl_export int PL_compare(term_t t1, term_t t2);
[DllImport(DllFileName)]
internal static extern int PL_compare(uint term1, uint term2);
// PlTermv
[DllImport(DllFileName)] // return term_t
internal static extern uint PL_new_term_refs(int n);
//__pl_export void PL_put_term(term_t t1, term_t t2);
[DllImport(DllFileName)]
internal static extern void PL_put_term(uint t1, uint t2);
// PlCompound
// __pl_export int PL_chars_to_term(const char *chars, term_t term);
//__pl_export void PL_cons_functor_v(term_t h, functor_t fd, term_t a0);
//__pl_export functor_t PL_new_functor(atom_t f, int a);
[DllImport(DllFileName)]
internal static extern int PL_chars_to_term(string chars, uint term);
[DllImport(DllFileName)]
internal static extern void PL_cons_functor_v(uint term, uint functor_t, uint term_a0);
[DllImport(DllFileName)]
internal static extern uint PL_new_functor(uint atom_a, int a);
//__pl_export void PL_put_string_chars(term_t t, const char *chars);
//__pl_export void PL_put_string_nchars(term_t t, unsigned int len, const char *chars);
//__pl_export void PL_put_list_codes(term_t t, const char *chars);
//__pl_export void PL_put_list_chars(term_t t, const char *chars);
[DllImport(DllFileName)]
internal static extern void PL_put_string_chars(uint term_t, string chars);
[DllImport(DllFileName)]
internal static extern void PL_put_string_nchars(uint term_t, int len, string chars);
[DllImport(DllFileName)]
internal static extern void PL_put_list_codes(uint term_t, string chars);
[DllImport(DllFileName)]
internal static extern void PL_put_list_chars(uint term_t, string chars);
// LISTS (PlTail)
//__pl_export int PL_is_variable(term_t t);
//__pl_export int PL_is_list(term_t t);
//__pl_export term_t PL_copy_term_ref(term_t from);
//__pl_export int PL_unify_list(term_t l, term_t h, term_t t);
//__pl_export int PL_unify_nil(term_t l);
//__pl_export int PL_get_list(term_t l, term_t h, term_t t);
//__pl_export int PL_get_nil(term_t l);
// __pl_export int PL_unify(term_t t1, term_t t2);
[DllImport(DllFileName)]
internal static extern int PL_is_variable(uint term_t);
[DllImport(DllFileName)]
internal static extern int PL_is_list(uint term_t);
[DllImport(DllFileName)]
internal static extern uint PL_copy_term_ref(uint term_t);
[DllImport(DllFileName)]
internal static extern int PL_unify_list(uint term_t_l, uint term_t_h, uint term_t_t);
[DllImport(DllFileName)]
internal static extern int PL_unify_nil(uint term_t);
[DllImport(DllFileName)]
internal static extern int PL_get_list(uint term_t_l, uint term_t_h, uint term_t_t);
[DllImport(DllFileName)]
internal static extern int PL_get_nil(uint term_t);
[DllImport(DllFileName)]
internal static extern int PL_unify(uint t1, uint t2);
[DllImport(DllFileName)]
internal static extern int PL_unify_integer(uint t1, Int32 n);
// Exceptions
// Handling exceptions
//__pl_export term_t PL_exception(qid_t qid);
//__pl_export int PL_raise_exception(term_t exception);
//__pl_export int PL_throw(term_t exception);
[DllImport(DllFileName)]
internal static extern uint PL_exception(uint qid);
[DllImport(DllFileName)]
internal static extern int PL_raise_exception(uint exception_term);
//__pl_export int PL_get_arg(int index, term_t t, term_t a);
[DllImport(DllFileName)]
internal static extern int PL_get_arg(int index, uint t, uint a);
//__pl_export int PL_get_name_arity(term_t t, atom_t *name, int *arity);
[DllImport(DllFileName)]
internal static extern int PL_get_name_arity(uint t, ref uint name, ref int arity);
// ******************************
// * PROLOG THREADS *
// ******************************
// from file pl-itf.h
/*
typedef struct
{
unsigned long local_size; // Stack sizes
unsigned long global_size;
unsigned long trail_size;
unsigned long argument_size;
char * alias; // alias name
} PL_thread_attr_t;
*/
//PL_EXPORT(int) PL_thread_self(void); /* Prolog thread id (-1 if none) */
//PL_EXPORT(int) PL_thread_attach_engine(PL_thread_attr_t *attr);
//PL_EXPORT(int) PL_thread_destroy_engine(void);
//PL_EXPORT(int) PL_thread_at_exit(void (*function)(void *), void *closure, int global);
[DllImport(DllFileName)]
internal static extern int PL_thread_self();
[DllImport(DllFileName)]
internal static extern int PL_thread_attach_engine(IntPtr attr);
//internal static extern int PL_thread_attach_engine(ref PL_thread_attr_t attr);
[DllImport(DllFileName)]
internal static extern int PL_thread_destroy_engine();
}
#endregion
#region PrologAtom
public class PrologAtom
{
public uint handle; // t_atom
PrologAtom(uint h)
{
handle = h;
}
public PrologAtom(string text) // const
{
handle = LibPl.PL_new_atom(text);
}
//public operator const char *(void)
public static explicit operator string(PrologAtom a)
{
return LibPl.PL_atom_chars(a.handle);
}
override public string ToString()
{
return LibPl.PL_atom_chars(handle);
}
// operator == for PrologAtom and string
public override int GetHashCode()
{
return this.handle.GetHashCode();
}
public override bool Equals(Object obj)
{
if (obj is PrologAtom)
return this.handle == ((PrologAtom)obj).handle;
else if (obj is string)
return LibPl.PL_atom_chars(this.handle) == (string)obj;
else
return false;
}
public static bool operator ==(PrologAtom a, string s)
{
return s == LibPl.PL_atom_chars(a.handle);
}
public static bool operator !=(PrologAtom a, string s)
{
return s != LibPl.PL_atom_chars(a.handle);
}
public static bool operator ==(PrologAtom a, PrologAtom b)
{
return b.handle == a.handle;
}
public static bool operator !=(PrologAtom a, PrologAtom b)
{
return b.handle != a.handle;
}
}
#endregion
#region PrologTerm
public class PrologTerm
{
protected uint m_term_ref; // term_t
// Properties
public uint TermRef
{
get { return m_term_ref; }
set { m_term_ref = (uint)value; }
}
// constructors
public PrologTerm()
{
m_term_ref = LibPl.PL_new_term_ref();
}
public PrologTerm(uint t)// PrologTerm(term_t t)
{
m_term_ref = t;
}
// C# --> PrologTerm
public PrologTerm(string text)
{
m_term_ref = LibPl.PL_new_term_ref();
LibPl.PL_put_atom_chars(m_term_ref, text);
}
public PrologTerm(int val)
{
m_term_ref = LibPl.PL_new_term_ref();
LibPl.PL_put_integer(m_term_ref, val);
}
public PrologTerm(double val)
{
m_term_ref = LibPl.PL_new_term_ref();
LibPl.PL_put_float(m_term_ref, val);
}
//public PrologTerm(const PrologAtom &a)
public PrologTerm(ref PrologAtom a)
{
m_term_ref = LibPl.PL_new_term_ref();
LibPl.PL_put_atom(m_term_ref, a.handle);
}
// PrologTerm --> C#
//operator term_t(void)
//public static implicit operator uint (PrologTerm t)
override public string ToString()
{
return (string)this;
}
public static explicit operator string(PrologTerm t)
{
String s = "";
if (0 != LibPl.PL_get_chars(t.m_term_ref, ref s, LibPl.CVT_ALL | LibPl.CVT_WRITE | LibPl.BUF_RING))
return s;
throw new PrologTypeError("text", t);
}
public static explicit operator int(PrologTerm t)
{
int v = 0;
if (0 != LibPl.PL_get_long(t.m_term_ref, ref v))
return v;
throw new PrologTypeError("long", t);
}
public static explicit operator double(PrologTerm t)
{
double v = 0;
if (0 != LibPl.PL_get_float(t.m_term_ref, ref v))
return v;
throw new PrologTypeError("float", t);
}
public int Arity
{
get
{
uint name = 0; // atom_t
int arity = 0;
if (0 != LibPl.PL_get_name_arity(m_term_ref, ref name, ref arity))
return arity;
throw new PrologTypeError("compound", this);
}
}
public string Name
{
get
{
uint name = 0; // atom_t
int arity = 0;
if (0 != LibPl.PL_get_name_arity(m_term_ref, ref name, ref arity))
return LibPl.PL_atom_chars(name);
throw new PrologTypeError("compound", this);
}
}
// Comparison standard order terms
public override int GetHashCode()
{
return this.m_term_ref.GetHashCode();
}
public override bool Equals(Object obj)
{
if (obj is PrologAtom)
return false;
else if (obj is PrologTerm)
return this == ((PrologTerm)obj);
else if (obj is int)
return this == ((int)obj);
else
return false;
}
public static bool operator ==([In]PrologTerm t1, [In]PrologTerm t2)
{
return LibPl.PL_compare(t1.TermRef, t2.TermRef) == 0;
}
public static bool operator !=([In]PrologTerm t1, [In]PrologTerm t2)
{
return LibPl.PL_compare(t1.TermRef, t2.TermRef) != 0;
}
// comparison (long)
public static bool operator ==([In]PrologTerm t1, [In]int lng)
{
int v0 = 0;
if (0 != LibPl.PL_get_long(t1.TermRef, ref v0))
return v0 == lng;
else
throw new PrologTypeError("integer", t1);
}
public static bool operator ==([In]int lng, [In]PrologTerm t1)
{
return t1 == lng;
}
public static bool operator !=([In]PrologTerm t1, [In]int lng)
{
int v0 = 0;
if (0 != LibPl.PL_get_long(t1.TermRef, ref v0))
return v0 != lng;
else
throw new PrologTypeError("integer", t1);
}
public static bool operator !=([In]int lng, [In]PrologTerm t1)
{
return t1 != lng;
}
/*
int operator <(long v);
int operator >(long v);
int operator <=(long v);
int operator >=(long v);
*/
// comparison (string)
public static bool operator ==([In]PrologTerm t1, [In]string str)
{
string s0 = "";
if (0 != LibPl.PL_get_chars(t1.TermRef, ref s0, LibPl.CVT_ALL))
return s0 == str;
else
throw new PrologTypeError("text", t1);
}
public static bool operator ==([In]string str, [In]PrologTerm t1)
{
return t1 == str;
}
public static bool operator !=([In]PrologTerm t1, [In]string str)
{
return !(t1 == str);
}
public static bool operator !=([In]string str, [In]PrologTerm t1)
{
return t1 != str;
}
// comparison (atom)
public static bool operator ==([In]PrologTerm t1, [In]PrologAtom atom)
{
uint a0 = 0;
if (0 != LibPl.PL_get_atom(t1.TermRef, ref a0))
return a0 == atom.handle;
else
throw new PrologTypeError("atom", t1);
}
public static bool operator ==([In]PrologAtom atom, [In]PrologTerm t1)
{
return t1 == atom;
}
public static bool operator !=([In]PrologTerm t1, [In]PrologAtom atom)
{
return !(t1 == atom);
}
public static bool operator !=([In]PrologAtom atom, [In]PrologTerm t1)
{
return t1 != atom;
}
} // class PrologTerm
#endregion
#region PrologTermList
public class PrologTermList
{
private uint m_a0; // term_t
private int m_size;
public PrologTermList()
{
m_a0 = 0;
m_size = 0;
}
public PrologTermList(int n)
{
m_a0 = LibPl.PL_new_term_refs(n);
m_size = n;
}
//public PrologTermList(int n, term_t t0)
public PrologTermList(int n, uint t0)
{
m_a0 = t0;
m_size = n;
}
// Properties
public uint A0
{
get { return m_a0; }
// set { a0 = value; }
}
public int Size
{
get { return m_size; }
// set { size = value; }
}
// create from args
public PrologTermList(PrologTerm m0)
{
m_size = 1;
m_a0 = m0.TermRef;
}
public PrologTermList(PrologTerm m0, PrologTerm m1)
{
m_size = 2;
m_a0 = LibPl.PL_new_term_refs(2);
LibPl.PL_put_term(m_a0 + 0, m0.TermRef);
LibPl.PL_put_term(m_a0 + 1, m1.TermRef);
}
PrologTermList(PrologTerm m0, PrologTerm m1, PrologTerm m2)
{
m_size = 3;
m_a0 = LibPl.PL_new_term_refs(3);
LibPl.PL_put_term(m_a0 + 0, m0.TermRef);
LibPl.PL_put_term(m_a0 + 1, m1.TermRef);
LibPl.PL_put_term(m_a0 + 2, m2.TermRef);
}
public PrologTerm this[int n]
{
get
{
if (n < 0 || n >= Size)
throw new PrologTermListDomainError(Size, n);
else
return new PrologTerm(A0 + (uint)n);
}
set
{
if (n < 0 || n >= Size)
throw new PrologTermListDomainError(Size, n);
else
LibPl.PL_put_term(m_a0 + (uint)n, ((PrologTerm)value).TermRef);
}
}
} // class PrologTermList
#endregion
#region PrologCompound
public class PrologCompound : PrologTerm
{
public PrologCompound(string text)
{
// term_t
uint t = LibPl.PL_new_term_ref();
if (0 == LibPl.PL_chars_to_term(text, t))
throw new PrologException(new PrologTerm(t));
LibPl.PL_put_term(m_term_ref, t);
}
public PrologCompound(string functor, [In] PrologTermList args)
{
LibPl.PL_cons_functor_v(m_term_ref, LibPl.PL_new_functor(LibPl.PL_new_atom(functor), args.Size), args.A0);
}
} // class PrologCompound
#endregion
#region PrologString
public class PrologString : PrologTerm
{
public PrologString(string text) : base()
{
LibPl.PL_put_string_chars(base.m_term_ref, text);
}
public PrologString(string text, int len) : base()
{
LibPl.PL_put_string_nchars(base.m_term_ref, len, text);
}
} // class PrologString
#endregion
#region PrologCodeList
public class PrologCodeList : PrologTerm
{
public PrologCodeList(string text) : base()
{
LibPl.PL_put_list_codes(base.m_term_ref, text);
}
} // class PrologCodeList
#endregion
#region PrologCharList
public class PrologCharList : PrologTerm
{
public PrologCharList(string text) : base()
{
LibPl.PL_put_list_chars(base.m_term_ref, text);
}
} // class PrologCharList
#endregion
#region PrologTail
public class PrologTail : PrologTerm // LISTS
{
public PrologTail([In] PrologTerm l)
{
if (0 != LibPl.PL_is_variable(l.TermRef) || 0 != LibPl.PL_is_list(l.TermRef))
TermRef = LibPl.PL_copy_term_ref(l.TermRef);
else
throw new PrologTypeError("list", l);
}
// building
public bool Append([In] PrologTerm e)
{
//term_t tmp = PL_new_term_ref();
uint tmp = LibPl.PL_new_term_ref();
if (0 != LibPl.PL_unify_list(TermRef, tmp, TermRef) && 0 != LibPl.PL_unify(tmp, e.TermRef))
return true;
return false;
}
public int Close()
{
return LibPl.PL_unify_nil(TermRef);
}
// enumerating
public bool Next(ref PrologTerm t)
{
t = new PrologTerm();
if (0 != LibPl.PL_get_list(this.TermRef, t.TermRef, this.TermRef))
{
return true;
}
if (0 != LibPl.PL_get_nil(this.TermRef))
{
return false;
}
throw new PrologTypeError("list", this);
}
} // class PrologTail
#endregion
#region PrologQuery
public class PrologFrame
{
private uint m_fid; // fid_t
public PrologFrame()
{
m_fid = LibPl.PL_open_foreign_frame();
}
~PrologFrame()
{
if (m_fid > 0)
LibPl.PL_close_foreign_frame(m_fid);
}
public void Free()
{
LibPl.PL_rewind_foreign_frame(m_fid);
LibPl.PL_close_foreign_frame(m_fid);
m_fid = 0;
}
public void Rewind()
{
LibPl.PL_rewind_foreign_frame(m_fid);
}
} // PrologFrame
public class PrologQuery
{
private uint qid; // qid_t
// Properties DEBUG dump only
public uint DumpQid
{
get { return qid; }
// set { a0 = value; }
}
// public PrologQuery(const char *name, const PrologTermList &av)
public PrologQuery(string name, PrologTermList av)
{
// predicate_t is a void * --> System.IntPtr
System.IntPtr p = LibPl.PL_predicate(name, av.Size, "user");
qid = LibPl.PL_open_query((IntPtr)0, LibPl.PL_Q_CATCH_EXCEPTION, p, av.A0);
}
public PrologQuery(string module, string name, PrologTermList av)
{
// predicate_t
IntPtr p = LibPl.PL_predicate(name, av.Size, module);
qid = LibPl.PL_open_query((IntPtr)0, LibPl.PL_Q_CATCH_EXCEPTION, p, av.A0);
}
~PrologQuery()
{
//if (qid > 0)
// LibPl.PL_cut_query(qid);
}
public void Free()
{
if (qid > 0)
LibPl.PL_cut_query(qid);
qid = 0;
}
public bool NextSolution()
{
int rval = LibPl.PL_next_solution(qid);
if (0 == rval)
{ // error
uint ex; // term_t
if ((ex = LibPl.PL_exception(qid)) > 0)
{
PrologException etmp = new PrologException(new PrologTerm(ex));
etmp.CppThrow();
}
}
return rval > 0;
}
// STATIC PLCALL
public static bool PlCall(string predicate, [In] PrologTermList args)
{
bool bRet = false;
PrologQuery q = new PrologQuery(predicate, args);
bRet = q.NextSolution();
q.Free();
return bRet;
}
public static bool PlCall(string Module, string predicate, [In] PrologTermList args)
{
bool bRet = false;
PrologQuery q = new PrologQuery(Module, predicate, args);
bRet = q.NextSolution();
q.Free();
return bRet;
}
public static bool PlCall(string goal)
{
bool bRet = false;
PrologQuery q = new PrologQuery("call", new PrologTermList(new PrologCompound(goal)));
bRet = q.NextSolution();
q.Free();
return bRet;
}
} // class PrologQuery
#endregion
#region PrologException
public class PrologException : Exception
{
protected PrologTerm m_ExTerm;
public PrologException(PrologTerm t)
{
m_ExTerm = new PrologTerm(t.TermRef);
}
public override string Message
{
get { return this.ToString(); }
}
//operator char *(void);
override public string ToString()
{
string strRet = "[ERROR: Failed to generate message. Internal error]\n";
PrologFrame fr = new PrologFrame();
#if USE_PRINT_MESSAGE
PrologTermList av = new PrologTermList(2);
av[0] = new PrologCompound("print_message", new PrologTermList("error", m_ExTerm.term_ref));
PrologQuery q = new PrologQuery("$write_on_string", av);
if ( q.NextSolution() )
strRet = (string)av[1];
q.Free();
#else
PrologTermList av = new PrologTermList(2);
av[0] = new PrologTerm(m_ExTerm.TermRef);
PrologQuery q = new PrologQuery("$messages", "message_to_string", av);
if (q.NextSolution())
strRet = (string)av[1];
q.Free();
#endif
fr.Free();
return strRet;
}
public int PlThrow()
{
return LibPl.PL_raise_exception(m_ExTerm.TermRef);
}
public void CppThrow()
{
// term_t
uint a = LibPl.PL_new_term_ref();
// atom_t
uint name = 0;
int arity = 0;
if (0 != LibPl.PL_get_arg(1, m_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 PrologTypeError(m_ExTerm);
else if (str == "domain_error")
throw new PrologDomainError(m_ExTerm);
}
throw this;
}
} // class PrologException
public class PrologTypeError : PrologException
{
public PrologTypeError([In] PrologTerm t) : base (t)
{
}
public PrologTypeError(string expected, PrologTerm actual) : base(
new PrologCompound("error",
new PrologTermList(new PrologCompound("type_error",
new PrologTermList(new PrologTerm(expected), actual)),
new PrologTerm())
))
{
}
}
public class PrologDomainError : PrologException
{
public PrologDomainError([In] PrologTerm t) : base(t)
{ }
PrologDomainError(string expected, PrologTerm actual) :
base(new PrologCompound("error",
new PrologTermList(new PrologCompound("domain_error",
new PrologTermList(new PrologTerm(expected), actual)),
new PrologTerm())
)
)
{ }
}
public class PrologTermListDomainError : PrologException
{
public PrologTermListDomainError(int size, int n) :
base(new PrologCompound("error",
new PrologTermList(new PrologCompound("domain_error",
new PrologTermList(new PrologCompound("argv", new PrologTermList(size)), new PrologTerm(n))
),
new PrologTerm())
)
)
{ }
}
#endregion
#region PrologError
class PrologError : Exception
{
public PrologError()
{ }
public PrologError(string message) : base(message)
{ }
public PrologError(string message, Exception inner) : base(message, inner)
{ }
}
#endregion
#region PrologEngine
public class PrologEngine
{
static public bool IsInitialised(int argc, string[] argv)
{
int i = LibPl.PL_is_initialised(ref argc, ref argv);
if (0 == i)
return false;
else
return true;
}
public PrologEngine(params string[] args)
{
int argc = args.Length;
if (0 != LibPl.PL_is_initialised(ref argc, ref args))
{
throw (new PrologError("PrologEngine is already initialised"));
}
else
{
if (0 == LibPl.PL_initialise(argc, args))
throw (new PrologError("failed to initialise"));
}
}
public PrologEngine(string arg) // @todo so umbauen das ...
{
String[] av = { arg };
if (0 == LibPl.PL_initialise(1, av))
throw (new PrologError("failed to initialise"));
}
// Destructor is in static library wrapper libpl
//~PrologEngine()
//{
// libpl.PL_cleanup(0);
//}
public void PlCleanup()
{
LibPl.PL_cleanup(0);
}
// *****************************
// Multi Threading
// *****************************
///
/// Reference count of the engine.
/// If an error occurs, -1 is returned.
/// If this Prolog is not compiled for multi-threading, -2 is returned.
///
public static int PlThreadAttachEngine()
{
try
{
return LibPl.PL_thread_attach_engine(IntPtr.Zero);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return -1;
}
// Returns the integer Prolog identifier of the engine or
// -1 if the calling thread has no Prolog engine.
// This function is also provided in the single-threaded version of SWI-Prolog, where it returns -2.
public static int PlThreadSelf
{
get
{
return LibPl.PL_thread_self();
}
}
// Returns TRUE on success and FALSE if the calling thread has no
// engine or this Prolog does not support threads.
public static bool PlThreadDestroyEngine
{
get
{
return 0 != LibPl.PL_thread_destroy_engine();
}
}
}
#endregion
#region PrologMtEngine
public class PrologMtEngine
{
private IntPtr m_iEngineNumber = IntPtr.Zero;
private IntPtr m_iEngineNumberStore = IntPtr.Zero;
override public string ToString()
{
return m_iEngineNumber.ToString();
}
public PrologMtEngine()
{
if (0 != LibPl.PL_is_initialised(IntPtr.Zero, IntPtr.Zero))
{
try
{
m_iEngineNumber = LibPl.PL_create_engine(IntPtr.Zero);
}
catch (Exception ex)
{
throw (new PrologError("PL_create_engine : " + ex.Message));
}
}
else
{
throw (new PrologError("There is no PrologEngine initialised"));
}
}
public void PlSetEngine()
{
IntPtr pNullPointer = IntPtr.Zero;
int iRet = LibPl.PL_set_engine(m_iEngineNumber, ref pNullPointer);
switch (iRet)
{
case LibPl.PL_ENGINE_SET: break; // all is fine
case LibPl.PL_ENGINE_INVAL: throw (new PrologError("PL_set_engine returns Invalid")); //break;
case LibPl.PL_ENGINE_INUSE: throw (new PrologError("PL_set_engine returns it is used by an other thread")); //break;
default: throw (new PrologError("Unknown return from PL_set_engine"));
}
}
public void PlDetachEngine()
{
int iRet = LibPl.PL_set_engine(m_iEngineNumber, ref m_iEngineNumberStore);
switch (iRet)
{
case LibPl.PL_ENGINE_SET: break; // all is fine
case LibPl.PL_ENGINE_INVAL: throw (new PrologError("PL_set_engine(detach) returns Invalid")); //break;
case LibPl.PL_ENGINE_INUSE: throw (new PrologError("PL_set_engine(detach) returns it is used by an other thread")); //break;
default: throw (new PrologError("Unknown return from PL_set_engine(detach)"));
}
}
public void Free()
{
if (0 == LibPl.PL_destroy_engine(m_iEngineNumber))
throw (new PrologError("failed to destroy engine"));
m_iEngineNumber = IntPtr.Zero;
}
~PrologMtEngine()
{
if (IntPtr.Zero != m_iEngineNumber)
Free();
}
} // class PrologMtEngine
#endregion
}