From 388f4fb78207eb2c0685da7fdd127d0ac14e9d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 2 Aug 2010 19:48:17 +0100 Subject: [PATCH] expand C-interface to allow access to common term operations (request from Ingo Molnar). --- C/c_interface.c | 82 ++++++++++++++++++++++++++++++++++-------- C/inlines.c | 18 ++++++++-- C/utilpreds.c | 53 +++++++++++++++++++++++---- H/Yapproto.h | 6 ++-- docs/yap.tex | 70 ++++++++++++++++++++++++++++++++++-- include/YapInterface.h | 10 ++++++ 6 files changed, 211 insertions(+), 28 deletions(-) diff --git a/C/c_interface.c b/C/c_interface.c index 8d0a12285..69dc79708 100755 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -509,9 +509,14 @@ X_API Term STD_PROTO(YAP_ExtendList,(Term, Term)); X_API int STD_PROTO(YAP_CloseList,(Term, Term)); X_API int STD_PROTO(YAP_IsAttVar,(Term)); X_API Term STD_PROTO(YAP_AttsOfVar,(Term)); -X_API Term STD_PROTO(YAP_TermHash,(Term)); X_API int STD_PROTO(YAP_FileNoFromStream,(Term)); X_API void *STD_PROTO(YAP_FileDescriptorFromStream,(Term)); +X_API void *STD_PROTO(YAP_Record,(Term)); +X_API Term STD_PROTO(YAP_Recorded,(void *)); +X_API int STD_PROTO(YAP_Erase,(void *)); +X_API int STD_PROTO(YAP_Variant,(Term, Term)); +X_API int STD_PROTO(YAP_ExactlyEqual,(Term, Term)); +X_API Int STD_PROTO(YAP_TermHash,(Term, Int, Int, int)); static int (*do_getf)(void); @@ -1050,6 +1055,46 @@ YAP_Unify(Term t1, Term t2) return out; } +/* == */ +X_API int +YAP_ExactlyEqual(Term t1, Term t2) +{ + int out; + BACKUP_MACHINE_REGS(); + + out = Yap_eq(t1, t2); + + RECOVER_MACHINE_REGS(); + return out; +} + +/* =@= */ +X_API int +YAP_Variant(Term t1, Term t2) +{ + int out; + BACKUP_MACHINE_REGS(); + + out = Yap_Variant(Deref(t1), Deref(t2)); + + RECOVER_MACHINE_REGS(); + return out; +} + +/* =@= */ +X_API Int +YAP_TermHash(Term t, Int sz, Int depth, int variant) +{ + Int out; + + BACKUP_MACHINE_REGS(); + + out = Yap_TermHash(t, sz, depth, variant); + + RECOVER_MACHINE_REGS(); + return out; +} + X_API Int YAP_CurrentSlot(void) { @@ -2992,20 +3037,6 @@ YAP_AttsOfVar(Term t) return attv->Atts; } -X_API Term -YAP_TermHash(Term t) -{ - attvar_record *attv; - - t = Deref(t); - if (!IsVarTerm(t)) - return TermNil; - if (IsAttVar(VarOfTerm(t))) - return TermNil; - attv = (attvar_record *)VarOfTerm(t); - return attv->Atts; -} - X_API int YAP_FileNoFromStream(Term t) { @@ -3026,3 +3057,24 @@ YAP_FileDescriptorFromStream(Term t) return Yap_FileDescriptorFromStream(t); } +X_API void * +YAP_Record(Term t) +{ + + return (void *)Yap_StoreTermInDB(Deref(t), 0); +} + +X_API Term +YAP_Recorded(void *handle) +{ + return Yap_FetchTermFromDB((DBTerm *)handle); +} + +X_API int +YAP_Erase(void *handle) +{ + Yap_ReleaseTermFromDB((DBTerm *)handle); + return 1; +} + + diff --git a/C/inlines.c b/C/inlines.c index 4244798d6..83474494f 100755 --- a/C/inlines.c +++ b/C/inlines.c @@ -282,15 +282,15 @@ p_equal(void) } static Int -p_eq(void) +eq(Term t1, Term t2) { /* ? == ? */ BEGD(d0); - d0 = ARG1; + d0 = t1; deref_head(d0, p_eq_unk1); p_eq_nvar1: /* first argument is bound */ BEGD(d1); - d1 = ARG2; + d1 = t2; deref_head(d1, p_eq_nvar1_unk2); p_eq_nvar1_nvar2: /* both arguments are bound */ @@ -365,6 +365,18 @@ p_eq(void) ENDD(d0); } +static Int +p_eq(void) +{ /* ? == ? */ + return eq(ARG1,ARG2); +} + +int +Yap_eq(Term t1, Term t2) +{ /* ? == ? */ + return eq(t1,t2); +} + static Int p_dif(void) { /* ? \= ? */ diff --git a/C/utilpreds.c b/C/utilpreds.c index bdedb4e11..4b4a0e485 100644 --- a/C/utilpreds.c +++ b/C/utilpreds.c @@ -2936,6 +2936,37 @@ hash_complex_term(register CELL *pt0, return (CELL *) -2; } +Int +Yap_TermHash(Term t, Int size, Int depth, int variant) +{ + unsigned int i1; + Term t1 = Deref(t); + + while (TRUE) { + CELL *ar = hash_complex_term(&t1-1, &t1, depth, H, FALSE); + if (ar == (CELL *)-1) { + if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) { + Yap_Error(OUT_OF_AUXSPACE_ERROR, ARG1, "overflow in term_hash"); + return FALSE; + } + t1 = Deref(ARG1); + } else if(ar == (CELL *)-2) { + if (!Yap_gcl((ASP-H)*sizeof(CELL), 0, ENV, gc_P(P,CP))) { + Yap_Error(OUT_OF_STACK_ERROR, TermNil, "in term_hash"); + return FALSE; + } + t1 = Deref(ARG1); + } else if (ar == NULL) { + return FALSE; + } else { + i1 = MurmurHashNeutral2((const void *)H, CellSize*(ar-H),0x1a3be34a); + break; + } + } + /* got the seed and hash from SWI-Prolog */ + return i1 % size; +} + static Int p_term_hash(void) { @@ -3239,11 +3270,9 @@ static int variant_complex(register CELL *pt0, register CELL *pt0_end, register return FALSE; } -static Int -p_variant(void) /* variant terms t1 and t2 */ +static int +is_variant(Term t1, Term t2, int parity) { - Term t1 = Deref(ARG1); - Term t2 = Deref(ARG2); int out; if (t1 == t2) @@ -3284,15 +3313,27 @@ p_variant(void) /* variant terms t1 and t2 */ } error: if (out == -1) { - if (!Yap_gcl((ASP-H)*sizeof(CELL), 2, ENV, gc_P(P,CP))) { + if (!Yap_gcl((ASP-H)*sizeof(CELL), parity, ENV, gc_P(P,CP))) { Yap_Error(OUT_OF_STACK_ERROR, TermNil, "in variant"); return FALSE; } - return p_variant(); + return is_variant(t1, t2, parity); } return FALSE; } +int +Yap_Variant(Term t1, Term t2) +{ + return is_variant(t1, t2, 0); +} + +static Int +p_variant(void) /* variant terms t1 and t2 */ +{ + return is_variant(Deref(ARG1), Deref(ARG2), 2); +} + static int subsumes_complex(register CELL *pt0, register CELL *pt0_end, register CELL *pt1) diff --git a/H/Yapproto.h b/H/Yapproto.h index 4231cb006..f5e0812c0 100755 --- a/H/Yapproto.h +++ b/H/Yapproto.h @@ -247,7 +247,8 @@ int STD_PROTO(Yap_OpDec,(int,char *,Atom,Term)); void STD_PROTO(Yap_CloseScratchPad,(void)); /* inlines.c */ -void STD_PROTO(Yap_InitInlines,(void)); +void STD_PROTO(Yap_InitInlines,(void)); +int STD_PROTO(Yap_eq,(Term, Term)); /* iopreds.c */ void STD_PROTO(Yap_InitPlIO,(void)); @@ -372,6 +373,7 @@ void STD_PROTO(Yap_InitUserBacks,(void)); /* utilpreds.c */ Term STD_PROTO(Yap_CopyTerm,(Term)); +int STD_PROTO(Yap_Variant,(Term, Term)); int STD_PROTO(Yap_ExportTerm,(Term, char *, size_t)); Term STD_PROTO(Yap_ImportTerm,(char *)); int STD_PROTO(Yap_IsListTerm,(Term)); @@ -379,7 +381,7 @@ Term STD_PROTO(Yap_CopyTermNoShare,(Term)); int STD_PROTO(Yap_SizeGroundTerm,(Term, int)); int STD_PROTO(Yap_IsGroundTerm,(Term)); void STD_PROTO(Yap_InitUtilCPreds,(void)); - +Int STD_PROTO(Yap_TermHash,(Term, Int, Int, int)); /* yap.c */ /* MYDDAS */ diff --git a/docs/yap.tex b/docs/yap.tex index a1bd4a805..c81e1f644 100644 --- a/docs/yap.tex +++ b/docs/yap.tex @@ -296,6 +296,7 @@ Subnodes of C-Interface * Manipulating Strings:: From character arrays to Lists of codes and back * Memory Allocation:: Stealing Memory From YAP * Controlling Streams:: Control How YAP sees Streams +* Utility Functions:: From character arrays to Lists of codes and back * Calling YAP From C:: From C to YAP to C to YAP * Module Manipulation in C:: Create and Test Modules from within C * Writing C:: Writing Predicates in C @@ -15140,6 +15141,7 @@ The rest of this appendix describes exhaustively how to interface C to YAP. * Manipulating Strings:: From character arrays to Lists of codes and back * Memory Allocation:: Stealing Memory From YAP * Controlling Streams:: Control How YAP sees Streams +* Utility Functions:: From character arrays to Lists of codes and back * Calling YAP From C:: From C to YAP to C to YAP * Module Manipulation in C:: Create and Test Modules from within C * Writing C:: Writing Predicates in C @@ -15509,7 +15511,7 @@ The routine releases a buffer allocated from the code area. The system may crash if @code{buf} is not a valid pointer to a buffer in the code area. -@node Controlling Streams, Calling YAP From C, Memory Allocation, C-Interface +@node Controlling Streams, Utility Functions, Memory Allocation, C-Interface @section Controlling YAP Streams from @code{C} @findex YAP_StreamToFileNo (C-Interface function) @@ -15561,7 +15563,71 @@ The available flags are @code{YAP_INPUT_STREAM}, stream is supposed to be at position 0. The argument @var{name} gives the name by which YAP should know the new stream. -@node Calling YAP From C, Module Manipulation in C, Controlling Streams, C-Interface +@node Utility Functions, Calling YAP From C, Controlling Streams, C-Interface +@section Utility Functions in @code{C} + + +The C-Interface provides the C-application with a a number of utility +functions that are useful. + + +@findex YAP_Record (C-Interface function) +The first provides a way to insert a term into the data-base +@example + void *YAP_Record(YAP_Term @var{t}) +@end example +@noindent +This function returns a pointer to a copy of the term in the database +(or to @t{NULL} if the operation fails. + +@findex YAP_Recorded (C-Interface function) +The next functions provides a way to recover the term from the data-base: +@example + YAP_Term YAP_Recorded(void *@var{handle}) +@end example +@noindent +Notice that the semantics are the same as for @code{recorded/3}: this +function creates a new copy of the term in the stack, with fresh +variables. The function returns @t{0L} if it cannot create a new term. + +@findex YAP_Erase (C-Interface function) +Last, the next function allows one to recover space: +@example + int YAP_Erase(void *@var{handle}) +@end example +@noindent +Notice that any accesses using @var{handle} after this operation may +lead to a crash. + +The following functions are often required to compare terms. + +@findex YAP_ExactlyEqual (C-Interface function) +The first function succeeds if two terms are actually the same term, as +@code{==/2}: +@example + int YAP_ExactlyEqual(YAP_Term t1, YAP_Term t2) +@end example +@noindent + +The second function succeeds if two terms are variant terms, and returns +0 otherwise, as +@code{=@=/2}: +@example + int YAP_Variant(YAP_Term t1, YAP_Term t2) +@end example +@noindent + +The second function computes a hash function for a term, as in +@code{term_hash/4}. +@example + YAP_Int YAP_TermHash(YAP_Term t, YAP_Int range, YAP_Int depth, int ignore_variables)); +@end example +@noindent +The first three arguments follow @code{term_has/4}. The last argument +indicates what to do if we find a variable: if @code{0} fail, otherwise +ignore the variable. + +@node Calling YAP From C, Module Manipulation in C, Utility Functions, C-Interface @section From @code{C} back to Prolog @findex YAP_RunGoal (C-Interface function) diff --git a/include/YapInterface.h b/include/YapInterface.h index 2d06302f5..02df70f08 100755 --- a/include/YapInterface.h +++ b/include/YapInterface.h @@ -494,6 +494,16 @@ extern X_API YAP_Term PROTO(YAP_AttsOfVar,(YAP_Term)); extern X_API void *PROTO(YAP_FileDescriptorFromStream,(YAP_Term)); extern X_API int PROTO(YAP_FileNoFromStream,(YAP_Term)); +/* store and recover terms */ +extern X_API void *PROTO(YAP_Record,(YAP_Term)); +extern X_API YAP_Term PROTO(YAP_Recorded,(void *)); +extern X_API int PROTO(YAP_Erase,(void *)); + +/* term utilities */ +extern X_API int PROTO(YAP_Variant,(YAP_Term,YAP_Term)); +extern X_API int PROTO(YAP_ExactlyEqual,(YAP_Term,YAP_Term)); +extern X_API YAP_Int PROTO(YAP_TermHash,(YAP_Term, YAP_Int, YAP_Int, int)); + #define YAP_InitCPred(N,A,F) YAP_UserCPredicate(N,F,A) __END_DECLS