From 8eec3113be639a1dd324054800356bbd66576284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 15 Sep 2014 03:13:50 -0500 Subject: [PATCH] improve docs --- C/arrays.c | 273 +++---- C/atomic.c | 2 +- C/cmppreds.c | 261 +++---- C/eval.c | 38 +- C/init.c | 89 +++ C/parser.c | 91 +++ C/scanner.c | 361 +++++++++ H/eval.h | 12 +- config.h.in | 36 +- docs/chr.md | 127 +-- docs/clpqr.md | 7 +- docs/doxygen.rc | 6 +- docs/threads.md | 179 ----- docs/yap.md | 81 +- library/apply.yap | 5 +- library/atts.yap | 3 +- library/dialect/swi.yap | 73 +- library/lineutils.yap | 24 +- misc/sysgraph | 11 +- os/pl-ctype.c | 80 +- os/pl-file.c | 484 ++++++------ os/pl-fmt.c | 217 ++++++ os/pl-locale.c | 22 +- os/pl-write.c | 153 ++++ packages/CLPBN/pfl.yap | 326 ++++++++ packages/ProbLog/problog.yap | 465 +++++++++++ .../problog_examples/aProbLog_examples.pl | 2 +- packages/archive | 2 +- packages/clib | 2 +- packages/clpqr | 2 +- packages/http | 2 +- packages/myddas/pl/myddas.ypp | 210 ++--- packages/plunit | 2 +- packages/prosqlite/prolog/prosqlite.pl | 1 + packages/real | 2 +- packages/yap-lbfgs/lbfgs.pl | 150 ++++ packages/yap-lbfgs/yap_lbfgs.c | 74 +- packages/zlib | 2 +- pl/attributes.yap | 133 ++-- pl/tabling.yap | 2 +- pl/threads.yap | 727 +++++++++++------- pl/yio.yap | 2 +- swi/library/url.pl | 1 + 43 files changed, 3307 insertions(+), 1435 deletions(-) delete mode 100644 docs/threads.md diff --git a/C/arrays.c b/C/arrays.c index 3171e5aeb..22d2a6154 100644 --- a/C/arrays.c +++ b/C/arrays.c @@ -17,7 +17,7 @@ /** @defgroup YAPArrays Arrays -@ingroup YAPBuiltins +@ingroup YAPExtensions @{ The YAP system includes experimental support for arrays. The @@ -124,7 +124,8 @@ static Int p_compile_array_refs( USES_REGS1 ); static Int p_array_refs_compiled( USES_REGS1 ); static Int p_sync_mmapped_arrays( USES_REGS1 ); -/* +/** + * === Implementation Notes * * This file works together with pl/arrays.yap and arrays.h. * @@ -136,7 +137,7 @@ static Int p_sync_mmapped_arrays( USES_REGS1 ); * object. Any term can be an argument to a dynamic array. * * Dynamic arrays are named as a free variable and are - * initialised with free variables. + * initialized with free variables. * * o named arrays are created during execution but allocated * in the code space. They have the lifetime of an heap @@ -145,13 +146,13 @@ static Int p_sync_mmapped_arrays( USES_REGS1 ); * Named arrays are named with atoms and are initialised with * free variables. * - * o static arrays are allocated in the heap. Their space is - * never recovered unless explictly said so by the + * + static arrays are allocated in the heap. Their space is + * never recovered unless explicitly said so by the * program. Arguments to these arrays must have fixed size, * and can only be atomic (at least for now). * * Static arrays can be named through an atom. They are - * initialised with []. + * initialized with []. * * Users create arrays by a declaration X array Arity. If X is an atom * A, then this it is a static array and A's the array name, otherwise @@ -165,16 +166,17 @@ static Int p_sync_mmapped_arrays( USES_REGS1 ); * of array X. The mechanism used to implement this is the same * mechanism used to implement suspension variables. * - * Representation: + * ==== Representation: * * Dynamic Arrays are represented as a compound term of arity N, where * N is the size of the array. Even so, I will not include array bound * checking for now. * + * ~~~~ * |--------------------------------------------------------------| * | $ARRAY/N|.... * |______________________________________________________________ - * + * ~~~~ * * Unbound Var is used as a place to point to. * @@ -184,27 +186,7 @@ static Int p_sync_mmapped_arrays( USES_REGS1 ); * A term of the form X[I] is represented as a Reference pointing to * the compound term: * - * '$array_arg'(X,I) - * - * Dereferecing will automatically find X[I]. - * - * The only exception is the compiler, which uses a different - * dereferencing routine. The clause cl(a[2], Y[X], Y) will be - * compiled as: - * - * cl(A, B, Y) :- '$access_array'(a, A, 2), '$access_array'(Y, B, X). - * - * There are three operations to access arrays: - * - * X[I] = A, This is normal unification. - * - * X[I] := A, This is multiassignment, and therefore - * backtrackable. - * - * X[I] ::= A, This is non-backtrackable multiassignment, ans most - * useful for static arrays. - * - * The LHS of := and of ::= must be an array element! + * []([I],X) * */ @@ -534,6 +516,17 @@ AccessNamedArray(Atom a, Int indx USES_REGS) } +/** @pred array_element(+ _Name_, + _Index_, ? _Element_) + + +Unify _Element_ with _Name_[ _Index_]. It works for both +static and dynamic arrays, but it is read-only for static arrays, while +it can be used to unify with an element of a dynamic array. + + +*/ + +/// @memberof array_element/3 static Int p_access_array( USES_REGS1 ) { @@ -1049,6 +1042,15 @@ p_create_array( USES_REGS1 ) /* create an array (+Name, + Size, +Props) */ static Int +/** @pred static_array(+ _Name_, + _Size_, + _Type_) + + +Create a new static array with name _Name_. Note that the _Name_ +must be an atom (named array). The _Size_ must evaluate to an +integer. The _Type_ must be bound to one of types mentioned +previously. +*/ +/// @memberof static_array/3 p_create_static_array( USES_REGS1 ) { Term ti = Deref(ARG2); @@ -1258,6 +1260,14 @@ p_resize_static_array( USES_REGS1 ) /* resize a static array (+Name, + Size, +Props) */ /* does not work for mmap arrays yet */ +/** @pred reset_static_array(+ _Name_) + + +Reset static array with name _Name_ to its initial value. + + +*/ +/// @memberof reset_static_array/1 static Int p_clear_static_array( USES_REGS1 ) { @@ -1288,6 +1298,16 @@ p_clear_static_array( USES_REGS1 ) } /* Close a named array (+Name) */ +/** @pred close_static_array(+ _Name_) + + +Close an existing static array of name _Name_. The _Name_ must +be an atom (named array). Space for the array will be recovered and +further accesses to the array will return an error. + + +*/ +/// @memberof close_static_array/1 static Int p_close_static_array( USES_REGS1 ) { @@ -1337,7 +1357,20 @@ p_close_static_array( USES_REGS1 ) } } -/* create an array (+Name, + Size, +Props) */ +/** @pred mmapped_array(+ _Name_, + _Size_, + _Type_, + _File_) + + +Similar to static_array/3, but the array is memory mapped to file + _File_. This means that the array is initialized from the file, and +that any changes to the array will also be stored in the file. + +This built-in is only available in operating systems that support the +system call `mmap`. Moreover, mmapped arrays do not store generic +terms (type `term`). + + +*/ +/// @memberof mmapped_array/4 static Int p_create_mmapped_array( USES_REGS1 ) { @@ -1634,6 +1667,24 @@ p_array_references( USES_REGS1 ) return (Yap_unify(t1, ARG2) && Yap_unify(t2, ARG3)); } +/** @pred update_array(+ _Name_, + _Index_, ? _Value_) + + +Attribute value _Value_ to _Name_[ _Index_]. Type +restrictions must be respected for static arrays. This operation is +available for dynamic arrays if `MULTI_ASSIGNMENT_VARIABLES` is +enabled (true by default). Backtracking undoes _update_array/3_ for +dynamic arrays, but not for static arrays. + +Note that update_array/3 actually uses `setarg/3` to update +elements of dynamic arrays, and `setarg/3` spends an extra cell for +every update. For intensive operations we suggest it may be less +expensive to unify each element of the array with a mutable terms and +to use the operations on mutable terms. + + +*/ +/// @memberof update_array/3 static Int p_assign_static( USES_REGS1 ) { @@ -2106,6 +2157,30 @@ p_assign_dynamic( USES_REGS1 ) return TRUE; } +/** @pred add_to_array_element(+ _Name_, + _Index_, + _Number_, ? _NewValue_) + + +Add _Number_ _Name_[ _Index_] and unify _NewValue_ with +the incremented value. Observe that _Name_[ _Index_] must be an +number. If _Name_ is a static array the type of the array must be +`int` or `float`. If the type of the array is `int` you +only may add integers, if it is `float` you may add integers or +floats. If _Name_ corresponds to a dynamic array the array element +must have been previously bound to a number and `Number` can be +any kind of number. + +The `add_to_array_element/3` built-in actually uses +`setarg/3` to update elements of dynamic arrays. For intensive +operations we suggest it may be less expensive to unify each element +of the array with a mutable terms and to use the operations on mutable +terms. + + + + + */ +/// @memberof add_to_array_element/4 + static Int p_add_to_array_element( USES_REGS1 ) { @@ -2327,6 +2402,18 @@ p_sync_mmapped_arrays( USES_REGS1 ) return(TRUE); } +/** @pred static_array_to_term(? _Name_, ? _Term_) + + +Convert a static array with name + _Name_ to a compound term of name _Name_. + +This built-in will silently fail if the there is no static array with +that name. + + +*/ +/// @memberof static_array_to_term/2 static Int p_static_array_to_term( USES_REGS1 ) { @@ -2490,6 +2577,13 @@ p_static_array_to_term( USES_REGS1 ) return FALSE; } +/** @pred static_array_location(+ _Name_, - _Ptr_) + + +Give the location or memory address for a static array with name + _Name_. The result is observed as an integer. +*/ +/// @memberof static_array_location/2 static Int p_static_array_location( USES_REGS1 ) { @@ -2526,139 +2620,20 @@ Yap_InitArrayPreds( void ) Yap_InitCPred("$array_references", 3, p_array_references, SafePredFlag); Yap_InitCPred("$array_arg", 3, p_array_arg, SafePredFlag); Yap_InitCPred("static_array", 3, p_create_static_array, SafePredFlag|SyncPredFlag); -/** @pred static_array(+ _Name_, + _Size_, + _Type_) - - -Create a new static array with name _Name_. Note that the _Name_ -must be an atom (named array). The _Size_ must evaluate to an -integer. The _Type_ must be bound to one of types mentioned -previously. - - -*/ Yap_InitCPred("resize_static_array", 3, p_resize_static_array, SafePredFlag|SyncPredFlag); -/** @pred resize_static_array(+ _Name_, - _OldSize_, + _NewSize_) - - -Expand or reduce a static array, The _Size_ must evaluate to an -integer. The _Name_ must be an atom (named array). The _Type_ -must be bound to one of `int`, `dbref`, `float` or -`atom`. - -Note that if the array is a mmapped array the size of the mmapped file -will be actually adjusted to correspond to the size of the array. - - -*/ Yap_InitCPred("mmapped_array", 4, p_create_mmapped_array, SafePredFlag|SyncPredFlag); -/** @pred mmapped_array(+ _Name_, + _Size_, + _Type_, + _File_) - - -Similar to static_array/3, but the array is memory mapped to file - _File_. This means that the array is initialized from the file, and -that any changes to the array will also be stored in the file. - -This built-in is only available in operating systems that support the -system call `mmap`. Moreover, mmapped arrays do not store generic -terms (type `term`). - - -*/ Yap_InitCPred("update_array", 3, p_assign_static, SafePredFlag); -/** @pred update_array(+ _Name_, + _Index_, ? _Value_) - - -Attribute value _Value_ to _Name_[ _Index_]. Type -restrictions must be respected for static arrays. This operation is -available for dynamic arrays if `MULTI_ASSIGNMENT_VARIABLES` is -enabled (true by default). Backtracking undoes _update_array/3_ for -dynamic arrays, but not for static arrays. - -Note that update_array/3 actually uses `setarg/3` to update -elements of dynamic arrays, and `setarg/3` spends an extra cell for -every update. For intensive operations we suggest it may be less -expensive to unify each element of the array with a mutable terms and -to use the operations on mutable terms. - - -*/ Yap_InitCPred("dynamic_update_array", 3, p_assign_dynamic, SafePredFlag); Yap_InitCPred("add_to_array_element", 4, p_add_to_array_element, SafePredFlag); -/** @pred add_to_array_element(+ _Name_, + _Index_, + _Number_, ? _NewValue_) - - -Add _Number_ _Name_[ _Index_] and unify _NewValue_ with -the incremented value. Observe that _Name_[ _Index_] must be an -number. If _Name_ is a static array the type of the array must be -`int` or `float`. If the type of the array is `int` you -only may add integers, if it is `float` you may add integers or -floats. If _Name_ corresponds to a dynamic array the array element -must have been previously bound to a number and `Number` can be -any kind of number. - -The `add_to_array_element/3` built-in actually uses -`setarg/3` to update elements of dynamic arrays. For intensive -operations we suggest it may be less expensive to unify each element -of the array with a mutable terms and to use the operations on mutable -terms. - - - - - */ Yap_InitCPred("array_element", 3, p_access_array, 0); -/** @pred array_element(+ _Name_, + _Index_, ? _Element_) - - -Unify _Element_ with _Name_[ _Index_]. It works for both -static and dynamic arrays, but it is read-only for static arrays, while -it can be used to unify with an element of a dynamic array. - - -*/ Yap_InitCPred("reset_static_array", 1, p_clear_static_array, SafePredFlag); -/** @pred reset_static_array(+ _Name_) - - -Reset static array with name _Name_ to its initial value. - - -*/ Yap_InitCPred("close_static_array", 1, p_close_static_array, SafePredFlag); -/** @pred close_static_array(+ _Name_) - - -Close an existing static array of name _Name_. The _Name_ must -be an atom (named array). Space for the array will be recovered and -further accesses to the array will return an error. - - -*/ Yap_InitCPred("$sync_mmapped_arrays", 0, p_sync_mmapped_arrays, SafePredFlag); Yap_InitCPred("$compile_array_refs", 0, p_compile_array_refs, SafePredFlag); Yap_InitCPred("$array_refs_compiled", 0, p_array_refs_compiled, SafePredFlag); Yap_InitCPred("$static_array_properties", 3, p_static_array_properties, SafePredFlag); Yap_InitCPred("static_array_to_term", 2, p_static_array_to_term, 0L); -/** @pred static_array_to_term(? _Name_, ? _Term_) - - -Convert a static array with name - _Name_ to a compound term of name _Name_. - -This built-in will silently fail if the there is no static array with -that name. - - -*/ Yap_InitCPred("static_array_location", 2, p_static_array_location, 0L); -/** @pred static_array_location(+ _Name_, - _Ptr_) - - -Give the location for a static array with name - _Name_. - - -*/ } diff --git a/C/atomic.c b/C/atomic.c index c50d5326c..02853e24d 100644 --- a/C/atomic.c +++ b/C/atomic.c @@ -24,7 +24,7 @@ static char SccsId[] = "%W% %G%"; The following predicates are used to manipulate atoms: - +\toc */ diff --git a/C/cmppreds.c b/C/cmppreds.c index d9802ffaf..693d33f00 100644 --- a/C/cmppreds.c +++ b/C/cmppreds.c @@ -20,7 +20,6 @@ /** @defgroup Comparing_Terms Comparing Terms @ingroup YAPBuiltins -@{ The following predicates are used to compare and order terms, using the standard ordering: @@ -45,7 +44,7 @@ Compound terms are ordered first by arity of the main functor, then by the name of the main functor, and finally by their arguments in left-to-right order. - +@{ @@ -537,7 +536,21 @@ Int Yap_compare_terms(Term d0, Term d1) return compare(Deref(d0),Deref(d1)); } -static Int +/** @pred compare( _C_, _X_, _Y_) is iso + + +As a result of comparing _X_ and _Y_, _C_ may take one of +the following values: + ++ +`=` if _X_ and _Y_ are identical; ++ +`<` if _X_ precedes _Y_ in the defined order; ++ +`>` if _Y_ precedes _X_ in the defined order; + +*/ +Int p_compare( USES_REGS1 ) { /* compare(?Op,?T1,?T2) */ Int r = compare(Deref(ARG2), Deref(ARG3)); @@ -552,6 +565,70 @@ p_compare( USES_REGS1 ) return Yap_unify_constant(ARG1, MkAtomTerm(p)); } + +/** @pred _X_ \== _Y_ is iso + +Terms _X_ and _Y_ are not strictly identical. +*/ +static Int +a_noteq(Term t1, Term t2) +{ + return (compare(t1, t2) != 0); +} + +static Int +a_gen_lt(Term t1, Term t2) +{ + return (compare(t1, t2) < 0); +} + +/** @pred _X_ @=< _Y_ is iso + + +Term _X_ does not follow term _Y_ in the standard order. + +*/ +static Int +a_gen_le(Term t1, Term t2) +{ + return (compare(t1, t2) <= 0); +} + +/** @pred _X_ @> _Y_ is iso + + +Term _X_ does not follow term _Y_ in the standard order +*/ +static Int +a_gen_gt(Term t1, Term t2) +{ + return compare(t1, t2) > 0; +} + +/** @pred _X_ @>= _Y_ is iso + +Term _X_ does not precede term _Y_ in the standard order. +*/ +static Int +a_gen_ge(Term t1, Term t2) +{ + return compare(t1, t2) >= 0; +} + + +/** +@} +*/ + +/** + + @defgroup arithmetic_cmps Arithmetic Comparison Predicates + @ingroup arithmetic + + Comparison of Numeric Expressions. Both arguments must be valid ground expressions at time of call. + + @{ +*/ inline static Int int_cmp(Int dif) { @@ -685,17 +762,6 @@ a_cmp(Term t1, Term t2 USES_REGS) } } -/** - - @defgroup arithmetic_cmps Arithmetic Comparison Predicates - @ingroup arithmetic - - Comparison of Numeric Expressions. Both arguments must be valid ground expressions at time of call. - - @{ -*/ - - Int Yap_acmp(Term t1, Term t2 USES_REGS) { @@ -717,15 +783,12 @@ p_acomp( USES_REGS1 ) } /** - @[ - @class arith_eq_2 - @brief =:=/2: Equality of arithmetic expressions + @pred +_X_ =:= _Y_ is iso + Equality of arithmetic expressions - + _X_ =:= + _Y_ [ISO]

@anchor ar_eq_2 - - - The value of the expression _X_ is less than the value of expression _Y_. + The value of the expression _X_ is equal to the value of expression _Y_. */ +/// @memberof =:=/2 static Int a_eq(Term t1, Term t2) { @@ -760,17 +823,14 @@ a_eq(Term t1, Term t2) return out == 0; } -/** - @} - - @class arith_dif_2 - @brief =\\=/2: Difference of arithmetic expressions - - + _X_ =\\= + _Y_ [ISO]

@anchor ar_dif_2 +/* + @pred +_X_ =\\= _Y_ is iso + Difference of arithmetic expressions The value of the expression _X_ is different from the value of expression _Y_. */ +/// @memberof =\\=/2 static Int a_dif(Term t1, Term t2) { @@ -781,11 +841,8 @@ a_dif(Term t1, Term t2) } /** - @class arith_gt_2 - @brief \>/2: Greater than arithmetic expressions - - + _X_ \> + _Y_ [ISO]

@anchor qQlg_2 - + @pred +_X_ \> +_Y_ is iso + Greater than arithmetic expressions The value of the expression _X_ is less than or equal to the value of expression _Y_. @@ -800,11 +857,8 @@ a_gt(Term t1, Term t2) } /** - @class arith_ge_2 - @brief \>=/2: Greater than or equal to arithmetic expressions - - + _X_ \>= + _Y_ [ISO]

@anchor gGqQ_2 - + @pred +_X_ >= +_Y_ is iso + Greater than or equal to arithmetic expressions The value of the expression _X_ is greater than or equal to the value of expression _Y_. @@ -819,15 +873,13 @@ a_ge(Term t1, Term t2) } /** - @class arith_lt_2 - @brief \+ _X_ \< + _Y_ [ISO]

@anchor sS_2 - + @pred +_X_ \< +_Y_ is iso + Lesser than arithmetic expressions The value of the expression _X_ is less than the value of expression _Y_. */ +/// @memberof + _X_ =\< + _Y_ [ISO]

@anchor qQsS_2 - + @pred _X_ =< + _Y_ + Lesser than or equal to arithmetic expressions + The value of the expression _X_ is less than or equal to the value of expression _Y_. */ +/// @memberof = 0; -} - -static Int -a_gen_ge(Term t1, Term t2) -{ - return compare(t1, t2) >= 0; -} - +/** + @} +*/ void Yap_InitCmpPreds(void) @@ -901,90 +923,11 @@ Yap_InitCmpPreds(void) Yap_InitCmpPred(">=", 2, a_ge, SafePredFlag | BinaryPredFlag); Yap_InitCPred("$a_compare", 3, p_acomp, TestPredFlag | SafePredFlag); Yap_InitCmpPred("\\==", 2, a_noteq, BinaryPredFlag | SafePredFlag); -/** @pred _X_ \== _Y_ is iso - - -Terms _X_ and _Y_ are not strictly identical. - - -*/ Yap_InitCmpPred("@<", 2, a_gen_lt, BinaryPredFlag | SafePredFlag); -/** @pred _X_ @< _Y_ is iso - - -Term _X_ precedes term _Y_ in the standard order. - - -*/ Yap_InitCmpPred("@=<", 2, a_gen_le, BinaryPredFlag | SafePredFlag); -/** @pred _X_ @=< _Y_ is iso - - -Term _X_ does not follow term _Y_ in the standard order. - - -*/ Yap_InitCmpPred("@>", 2, a_gen_gt, BinaryPredFlag | SafePredFlag); -/** @pred _X_ @> _Y_ is iso - - -Term _X_ follows term _Y_ in the standard order. - - -*/ Yap_InitCmpPred("@>=", 2, a_gen_ge, BinaryPredFlag | SafePredFlag); -/** @pred _X_ @>= _Y_ is iso - - -Term _X_ does not precede term _Y_ in the standard order. - - -*/ Yap_InitCPred("compare", 3, p_compare, TestPredFlag | SafePredFlag); -/** @pred compare( _C_, _X_, _Y_) is iso - - -As a result of comparing _X_ and _Y_, _C_ may take one of -the following values: - -+ -`=` if _X_ and _Y_ are identical; -+ -`<` if _X_ precedes _Y_ in the defined order; -+ -`>` if _Y_ precedes _X_ in the defined order; - - -+ _X_ == _Y_ is iso - - -Succeeds if terms _X_ and _Y_ are strictly identical. The -difference between this predicate and =/2 is that, if one of the -arguments is a free variable, it only succeeds when they have already -been unified. - -~~~~~{.prolog} -?- X == Y. -~~~~~ -fails, but, - -~~~~~{.prolog} -?- X = Y, X == Y. -~~~~~ -succeeds. - -~~~~~{.prolog} -?- X == 2. -~~~~~ -fails, but, - -~~~~~{.prolog} -?- X = 2, X == 2. -~~~~~ -succeeds. - - -*/ } /** diff --git a/C/eval.c b/C/eval.c index f6648e685..83c02ac41 100644 --- a/C/eval.c +++ b/C/eval.c @@ -191,6 +191,7 @@ BEAM_is(void) #endif /** +@{ @pred is( X:number, + Y:ground) is det This predicate succeeds iff the result of evaluating the expression @@ -201,8 +202,11 @@ X is 2+3*4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ succeeds with `X = 14`. + Consult @ref arithmetic_operators for the complete list of arithmetic_operators + */ +/// @memberof is/2 static Int p_is( USES_REGS1 ) { /* X is Y */ @@ -223,15 +227,18 @@ p_is( USES_REGS1 ) return Yap_unify_constant(ARG1,out); } +//@} + /** @pred isnan(? X:float) is det Interface to the IEE754 `isnan` test. */ +/// @memberof isnan/1 static Int p_isnan( USES_REGS1 ) -{ /* X is Y */ +{ /* X isnan Y */ Term out = 0L; while (!(out = Eval(Deref(ARG1) PASS_REGS))) { @@ -263,7 +270,7 @@ p_isnan( USES_REGS1 ) Interface to the IEE754 `isinf` test. */ - +/// @memberof isnan/1 static Int p_isinf( USES_REGS1 ) { /* X is Y */ @@ -293,13 +300,15 @@ p_isinf( USES_REGS1 ) } /** - @pred logsum(+ Log1:float, + Log2:float, - Out:float ) is det +@{ @pred logsum(+ Log1:float, + Log2:float, - Out:float ) is det True if _Log1_ is the logarithm of the positive number _A1_, _Log2_ is the logarithm of the positive number _A2_, and _Out_ is the logarithm of the sum of the numbers _A1_ and _A2_. Useful in probability computation. */ + +/// @memberof logsum/3 static Int p_logsum( USES_REGS1 ) { /* X is Y */ @@ -372,6 +381,8 @@ p_logsum( USES_REGS1 ) } } +// @} + Int Yap_ArithError(yap_error_number type, Term where, char *format,...) { @@ -413,6 +424,7 @@ Yap_ArithError(yap_error_number type, Term where, char *format,...) */ +/// @memberof between/3 static Int cont_between( USES_REGS1 ) { Term t1 = EXTRA_CBACK_ARG(3,1); @@ -447,6 +459,7 @@ static Int cont_between( USES_REGS1 ) } } +/// @memberof between/3 static Int init_between( USES_REGS1 ) { @@ -542,6 +555,11 @@ init_between( USES_REGS1 ) return cont_between( PASS_REGS1 ); } +/** + * + * @} +*/ + void Yap_InitEval(void) { @@ -554,20 +572,6 @@ Yap_InitEval(void) Yap_InitCPred("isinf", 1, p_isinf, TestPredFlag); Yap_InitCPred("logsum", 3, p_logsum, TestPredFlag); Yap_InitCPredBack("between", 3, 2, init_between, cont_between, 0); -/** @pred between(+ _Low_,+ _High_,? _Value_) - - - - _Low_ and _High_ are integers, _High_ less or equal than - _Low_. If _Value_ is an integer, _Low_ less or equal than - _Value_ less or equal than _High_. When _Value_ is a -variable it is successively bound to all integers between _Low_ and - _High_. If _High_ is `inf`, between/3 is true iff - _Value_ less or equal than _Low_, a feature that is particularly -interesting for generating integers from a certain value. - - -*/ } /** diff --git a/C/init.c b/C/init.c index d28e1085c..8c6392359 100755 --- a/C/init.c +++ b/C/init.c @@ -101,6 +101,93 @@ int Yap_Portray_delays = FALSE; #endif #endif + +/** + +@defgroup Operators Summary of YAP Predefined Operators +@ingroup Syntax +@{ + + + +The Prolog syntax caters for operators of three main kinds: + + + prefix; + + infix; + + postfix. + + +Each operator has precedence in the range 1 to 1200, and this +precedence is used to disambiguate expressions where the structure of the +term denoted is not made explicit using brackets. The operator of higher +precedence is the main functor. + +If there are two operators with the highest precedence, the ambiguity +is solved analyzing the types of the operators. The possible infix types are: + _xfx_, _xfy_, and _yfx_. + +With an operator of type _xfx_ both sub-expressions must have lower +precedence than the operator itself, unless they are bracketed (which +assigns to them zero precedence). With an operator type _xfy_ only the +left-hand sub-expression must have lower precedence. The opposite happens +for _yfx_ type. + +A prefix operator can be of type _fx_ or _fy_. +A postfix operator can be of type _xf_ or _yf_. +The meaning of the notation is analogous to the above. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a + b * c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +means + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a + (b * c) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +as + and \* have the following types and precedences: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:-op(500,yfx,'+'). +:-op(400,yfx,'*'). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now defining + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:-op(700,xfy,'++'). +:-op(700,xfx,'=:='). +a ++ b =:= c +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + means + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a ++ (b =:= c) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following is the list of the declarations of the predefined operators: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:-op(1200,fx,['?-', ':-']). +:-op(1200,xfx,[':-','-->']). +:-op(1150,fx,[block,dynamic,mode,public,multifile,meta_predicate, + sequential,table,initialization]). +:-op(1100,xfy,[';','|']). +:-op(1050,xfy,->). +:-op(1000,xfy,','). +:-op(999,xfy,'.'). +:-op(900,fy,['\+', not]). +:-op(900,fx,[nospy, spy]). +:-op(700,xfx,[@>=,@=<,@<,@>,<,=,>,=:=,=\=,\==,>=,=<,==,\=,=..,is]). +:-op(500,yfx,['\/','/\','+','-']). +:-op(500,fx,['+','-']). +:-op(400,yfx,['<<','>>','//','*','/']). +:-op(300,xfx,mod). +:-op(200,xfy,['^','**']). +:-op(50,xfx,same). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +*/ + #define xfx 1 #define xfy 2 #define yfx 3 @@ -330,6 +417,8 @@ InitOps(void) SetOp(Ops[i].opPrio, Ops[i].opType, Ops[i].opName, PROLOG_MODULE); } +/// @} + #if DEBUG #ifdef HAVE_ISATTY #include diff --git a/C/parser.c b/C/parser.c index 7c920c530..6b2baa05b 100755 --- a/C/parser.c +++ b/C/parser.c @@ -17,6 +17,97 @@ #ifdef SCCS static char SccsId[] = "%W% %G%"; #endif + +/** + +@defgroup Syntax YAP Syntax +@ingroup YAPProgramming +@{ + +We will describe the syntax of YAP at two levels. We first will +describe the syntax for Prolog terms. In a second level we describe +the \a tokens from which Prolog \a terms are +built. + +@defgroup Formal_Syntax Syntax of Terms +@ingroup Syntax +@{ + +Below, we describe the syntax of YAP terms from the different +classes of tokens defined above. The formalism used will be BNF, +extended where necessary with attributes denoting integer precedence or +operator type. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + term ----> subterm(1200) end_of_term_marker + + subterm(N) ----> term(M) [M <= N] + + term(N) ----> op(N, fx) subterm(N-1) + | op(N, fy) subterm(N) + | subterm(N-1) op(N, xfx) subterm(N-1) + | subterm(N-1) op(N, xfy) subterm(N) + | subterm(N) op(N, yfx) subterm(N-1) + | subterm(N-1) op(N, xf) + | subterm(N) op(N, yf) + + term(0) ----> atom '(' arguments ')' + | '(' subterm(1200) ')' + | '{' subterm(1200) '}' + | list + | string + | number + | atom + | variable + + arguments ----> subterm(999) + | subterm(999) ',' arguments + + list ----> '[]' + | '[' list_expr ']' + + list_expr ----> subterm(999) + | subterm(999) list_tail + + list_tail ----> ',' list_expr + | ',..' subterm(999) + | '|' subterm(999) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Notes: + + + \a op(N,T) denotes an atom which has been previously declared with type + \a T and base precedence \a N. + + + Since ',' is itself a pre-declared operator with type \a xfy and + precedence 1000, is \a subterm starts with a '(', \a op must be + followed by a space to avoid ambiguity with the case of a functor + followed by arguments, e.g.: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ (a,b) [the same as '+'(','(a,b)) of arity one] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + versus + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++(a,b) [the same as '+'(a,b) of arity two] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +In the first rule for term(0) no blank space should exist between +\a atom and '('. + + + +Each term to be read by the YAP parser must end with a single +dot, followed by a blank (in the sense mentioned in the previous +paragraph). When a name consisting of a single dot could be taken for +the end of term marker, the ambiguity should be avoided by surrounding the +dot with single quotes. + +@} + +*/ + /* * Description: * diff --git a/C/scanner.c b/C/scanner.c index d18db1923..a7fbf300f 100755 --- a/C/scanner.c +++ b/C/scanner.c @@ -32,6 +32,365 @@ * */ +/** + +@defgroup Formal_Syntax Syntax of Terms +@ingroup Syntax +@{ + + +Prolog tokens are grouped into the following categories: + ++ Numbers + +Numbers can be further subdivided into integer and floating-point numbers. + + + Integers + +Integer numbers +are described by the following regular expression: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + := {+|0{xXo}}+ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +where {...} stands for optionality, \a + optional repetition (one or +more times), \a \\\ denotes one of the characters 0 ... 9, \a | +denotes or, and \a \\\ denotes the character "'". The digits +before the \a \\\ character, when present, form the number +basis, that can go from 0, 1 and up to 36. Letters from `A` to +`Z` are used when the basis is larger than 10. + +Note that if no basis is specified then base 10 is assumed. Note also +that the last digit of an integer token can not be immediately followed +by one of the characters 'e', 'E', or '.'. + +Following the ISO standard, YAP also accepts directives of the +form `0x` to represent numbers in hexadecimal base and of the form +`0o` to represent numbers in octal base. For usefulness, +YAP also accepts directives of the form `0X` to represent +numbers in hexadecimal base. + +Example: +the following tokens all denote the same integer + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +10 2'1010 3'101 8'12 16'a 36'a 0xa 0o12 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Numbers of the form `0'a` are used to represent character +constants. So, the following tokens denote the same integer: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +0'd 100 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +YAP (version 6.3.4) supports integers that can fit +the word size of the machine. This is 32 bits in most current machines, +but 64 in some others, such as the Alpha running Linux or Digital +Unix. The scanner will read larger or smaller integers erroneously. + + + Floats + +Floating-point numbers are described by: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + := +{+} + {}+ + |++ + {{}+} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +where \a \\\ denotes the decimal-point character '.', +\a \\\ denotes one of 'e' or 'E', and \a \\\ denotes +one of '+' or '-'. + +Examples: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +10.0 10e3 10e-3 3.1415e+3 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Floating-point numbers are represented as a double in the target +machine. This is usually a 64-bit number. + ++ Strings Character Strings + +Strings are described by the following rules: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + string --> '"' string_quoted_characters '"' + + string_quoted_characters --> '"' '"' string_quoted_characters + string_quoted_characters --> '\' + escape_sequence string_quoted_characters + string_quoted_characters --> + string_character string_quoted_characters + + escape_sequence --> 'a' | 'b' | 'r' | 'f' | 't' | 'n' | 'v' + escape_sequence --> '\' | '"' | ''' | '`' + escape_sequence --> at_most_3_octal_digit_seq_char '\' + escape_sequence --> 'x' at_most_2_hexa_digit_seq_char '\' +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +where `string_character` in any character except the double quote +and escape characters. + +Examples: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +"" "a string" "a double-quote:""" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The first string is an empty string, the last string shows the use of +double-quoting. The implementation of YAP represents strings as +lists of integers. Since YAP 4.3.0 there is no static limit on string +size. + +Escape sequences can be used to include the non-printable characters +`a` (alert), `b` (backspace), `r` (carriage return), +`f` (form feed), `t` (horizontal tabulation), `n` (new +line), and `v` (vertical tabulation). Escape sequences also be +include the meta-characters `\\`, `"`, `'`, and +```. Last, one can use escape sequences to include the characters +either as an octal or hexadecimal number. + +The next examples demonstrates the use of escape sequences in YAP: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +"\x0c\" "\01\" "\f" "\\" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The first three examples return a list including only character 12 (form +feed). The last example escapes the escape character. + +Escape sequences were not available in C-Prolog and in original +versions of YAP up to 4.2.0. Escape sequences can be disable by using: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:- yap_flag(character_escapes,false). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++ Atoms Atoms + +Atoms are defined by one of the following rules: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + atom --> solo-character + atom --> lower-case-letter name-character* + atom --> symbol-character+ + atom --> single-quote single-quote + atom --> ''' atom_quoted_characters ''' + + atom_quoted_characters --> ''' ''' atom_quoted_characters + atom_quoted_characters --> '\' atom_sequence string_quoted_characters + atom_quoted_characters --> character string_quoted_characters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +where: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + denotes one of: ! ; + denotes one of: # & * + - . / : < + = > ? @ \ ^ ~ ` + denotes one of: a...z + denotes one of: _ a...z A...Z 0....9 + denotes: ' +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +and `string_character` denotes any character except the double quote +and escape characters. Note that escape sequences in strings and atoms +follow the same rules. + +Examples: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +a a12x '$a' ! => '1 2' +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Version `4.2.0` of YAP removed the previous limit of 256 +characters on an atom. Size of an atom is now only limited by the space +available in the system. + ++ Variables Variables + +Variables are described by: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +where + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + denotes one of: _ A...Z + denotes one of: _ a...z A...Z +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If a variable is referred only once in a term, it needs not to be named +and one can use the character `_` to represent the variable. These +variables are known as anonymous variables. Note that different +occurrences of `_` on the same term represent different +anonymous variables. + ++ Punctuation Tokens + +Punctuation tokens consist of one of the following characters: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +( ) , [ ] { } | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These characters are used to group terms. + +@subsection Layout Layout +Any characters with ASCII code less than or equal to 32 appearing before +a token are ignored. + +All the text appearing in a line after the character \a % is taken to +be a comment and ignored (including \a %). Comments can also be +inserted by using the sequence `/\*` to start the comment and +`\*` followed by `/` to finish it. In the presence of any sequence of comments or +layout characters, the YAP parser behaves as if it had found a +single blank character. The end of a file also counts as a blank +character for this purpose. + ++ Encoding Wide Character Support + +YAP now implements a SWI-Prolog compatible interface to wide +characters and the Universal Character Set (UCS). The following text +was adapted from the SWI-Prolog manual. + +YAP now supports wide characters, characters with character +codes above 255 that cannot be represented in a single byte. +Universal Character Set (UCS) is the ISO/IEC 10646 standard +that specifies a unique 31-bits unsigned integer for any character in +any language. It is a superset of 16-bit Unicode, which in turn is +a superset of ISO 8859-1 (ISO Latin-1), a superset of US-ASCII. UCS +can handle strings holding characters from multiple languages and +character classification (uppercase, lowercase, digit, etc.) and +operations such as case-conversion are unambiguously defined. + +For this reason YAP, following SWI-Prolog, has two representations for +atoms. If the text fits in ISO Latin-1, it is represented as an array +of 8-bit characters. Otherwise the text is represented as an array of +wide chars, which may take 16 or 32 bits. This representational issue +is completely transparent to the Prolog user. Users of the foreign +language interface sometimes need to be aware of these issues though. + +Character coding comes into view when characters of strings need to be +read from or written to file or when they have to be communicated to +other software components using the foreign language interface. In this +section we only deal with I/O through streams, which includes file I/O +as well as I/O through network sockets. + + + Stream_Encoding Wide character encodings on streams + +Although characters are uniquely coded using the UCS standard +internally, streams and files are byte (8-bit) oriented and there are a +variety of ways to represent the larger UCS codes in an 8-bit octet +stream. The most popular one, especially in the context of the web, is +UTF-8. Bytes 0...127 represent simply the corresponding US-ASCII +character, while bytes 128...255 are used for multi-byte +encoding of characters placed higher in the UCS space. Especially on +MS-Windows the 16-bit Unicode standard, represented by pairs of bytes is +also popular. + +Prolog I/O streams have a property called encoding which +specifies the used encoding that influence `get_code/2` and +`put_code/2` as well as all the other text I/O predicates. + +The default encoding for files is derived from the Prolog flag +`encoding`, which is initialised from the environment. If the +environment variable `LANG` ends in "UTF-8", this encoding is +assumed. Otherwise the default is `text` and the translation is +left to the wide-character functions of the C-library (note that the +Prolog native UTF-8 mode is considerably faster than the generic +`mbrtowc()` one). The encoding can be specified explicitly in +load_files/2 for loading Prolog source with an alternative +encoding, `open/4` when opening files or using `set_stream/2` on +any open stream (not yet implemented). For Prolog source files we also +provide the `encoding/1` directive that can be used to switch +between encodings that are compatible to US-ASCII (`ascii`, +`iso_latin_1`, `utf8` and many locales). + + + +For +additional information and Unicode resources, please visit +. + +YAP currently defines and supports the following encodings: + + + octet +Default encoding for binary streams. This causes +the stream to be read and written fully untranslated. + + + ascii +7-bit encoding in 8-bit bytes. Equivalent to `iso_latin_1`, +but generates errors and warnings on encountering values above +127. + + + iso_latin_1 +8-bit encoding supporting many western languages. This causes +the stream to be read and written fully untranslated. + + + text +C-library default locale encoding for text files. Files are read and +written using the C-library functions `mbrtowc()` and +`wcrtomb()`. This may be the same as one of the other locales, +notably it may be the same as `iso_latin_1` for western +languages and `utf8` in a UTF-8 context. + + + utf8 +Multi-byte encoding of full UCS, compatible to `ascii`. +See above. + + + unicode_be +Unicode Big Endian. Reads input in pairs of bytes, most +significant byte first. Can only represent 16-bit characters. + + + unicode_le +Unicode Little Endian. Reads input in pairs of bytes, least +significant byte first. Can only represent 16-bit characters. + + +Note that not all encodings can represent all characters. This implies +that writing text to a stream may cause errors because the stream +cannot represent these characters. The behaviour of a stream on these +errors can be controlled using `open/4` or `set_stream/2` (not +implemented). Initially the terminal stream write the characters using +Prolog escape sequences while other streams generate an I/O exception. + + + BOM BOM: Byte Order Mark + +From Stream Encoding, you may have got the impression that +text-files are complicated. This section deals with a related topic, +making live often easier for the user, but providing another worry to +the programmer. *BOM* or Byte Order Marker is a technique +for identifying Unicode text-files as well as the encoding they +use. Such files start with the Unicode character `0xFEFF`, a +non-breaking, zero-width space character. This is a pretty unique +sequence that is not likely to be the start of a non-Unicode file and +uniquely distinguishes the various Unicode file formats. As it is a +zero-width blank, it even doesn't produce any output. This solves all +problems, or ... + +Some formats start of as US-ASCII and may contain some encoding mark to +switch to UTF-8, such as the `encoding="UTF-8"` in an XML header. +Such formats often explicitly forbid the the use of a UTF-8 BOM. In +other cases there is additional information telling the encoding making +the use of a BOM redundant or even illegal. + +The BOM is handled by the `open/4` predicate. By default, text-files are +probed for the BOM when opened for reading. If a BOM is found, the +encoding is set accordingly and the property `bom(true)` is +available through stream_property/2. When opening a file for +writing, writing a BOM can be requested using the option +`bom(true)` with `open/4`. + + */ + + #include "Yap.h" #include "Yatom.h" #include "YapHeap.h" @@ -1505,3 +1864,5 @@ Yap_clean_tokenizer(TokEntry *tokstart, VarEntry *vartable, VarEntry *anonvartab LOCAL_CommentsBuffLim = 0; } + +/// @} diff --git a/H/eval.h b/H/eval.h index ff06e88a5..f23049dca 100644 --- a/H/eval.h +++ b/H/eval.h @@ -25,9 +25,7 @@ + See @ref arithmetic_cmps for the arithmetic comparisons supported in YAP - + See @ref arithmetic_operators for how to call arithmetic operations in YAP - - + + See @ref arithmetic_operators for what arithmetic operations are supported in YAP @tableofcontents @@ -61,7 +59,7 @@ used. Rational numbers that are returned from is/2 are canonical, which means the denominator _M_ is positive and that the numerator _N_ and _M_ have no common divisors. Rational numbers are introduced in the computation using the [rational/1][@ref rational_1], -[rationalize/1][@ref rationalize_1] or the [rdiv/2][@ref rdiv_2] +[rationalize/1][@ref rationalize/1] or the [rdiv/2][@ref rdiv/2] (rational division) function. @@ -69,7 +67,7 @@ the computation using the [rational/1][@ref rational_1], Floating point numbers are represented using the C-type double. On most today platforms these are 64-bit IEEE-754 floating point -numbers. YAP now includes the built-in predicates [isinf/1][@ref isinf_1] and to [isnan/1][@ref isnan_1] tests. +numbers. YAP now includes the built-in predicates [isinf/1][@ref isinf/1] and to [isnan/1][@ref isnan/1] tests. @@ -97,8 +95,8 @@ exceptions: @exception "evaluation_error(overflow( V ), Call)" result is arithmetic overflow @secreflist -@refitem is_2 -@refitem isnan_1 +@refitem is/2 +@refitem isnan/1 @endsecreflist diff --git a/config.h.in b/config.h.in index a62069c12..34fa419cb 100644 --- a/config.h.in +++ b/config.h.in @@ -57,6 +57,9 @@ /* Define to 1 if you have the `acosh' function. */ #undef HAVE_ACOSH +/* Define to 1 if you have the `add_history' function. */ +#undef HAVE_ADD_HISTORY + /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM @@ -171,6 +174,22 @@ /* Define to 1 if you have the header file. */ #undef HAVE_CUDD_UTIL_H +/* Define to 1 if you have the declaration of `rl_catch_signals ', and to 0 if + you don't. */ +#undef HAVE_DECL_RL_CATCH_SIGNALS_ + +/* Define to 1 if you have the declaration of `rl_done ', and to 0 if you + don't. */ +#undef HAVE_DECL_RL_DONE_ + +/* Define to 1 if you have the declaration of `rl_event_hook', and to 0 if you + don't. */ +#undef HAVE_DECL_RL_EVENT_HOOK + +/* Define to 1 if you have the declaration of `rl_readline_state', and to 0 if + you don't. */ +#undef HAVE_DECL_RL_READLINE_STATE + /* Define to 1 if you have the header file. */ #undef HAVE_DIRECT_H @@ -574,11 +593,8 @@ /* Define to 1 if you have the header file. */ #undef HAVE_RINTERFACE_H -/* Defined if you can turn off readline's signal handling. */ -#undef HAVE_RL_CATCH_SIGNAL - -/* Define to 1 if you have the `rl_cleanup_after_signal' function. */ -#undef HAVE_RL_CLEANUP_AFTER_SIGNAL +/* Define to 1 if you have the `rl_begin_undo_group' function. */ +#undef HAVE_RL_BEGIN_UNDO_GROUP /* Define to 1 if you have the `rl_clear_pending_input' function. */ #undef HAVE_RL_CLEAR_PENDING_INPUT @@ -589,8 +605,8 @@ /* Define to 1 if you have the `rl_completion_matches' function. */ #undef HAVE_RL_COMPLETION_MATCHES -/* Define to 1 if you have the `rl_event_hook' function. */ -#undef HAVE_RL_EVENT_HOOK +/* Define to 1 if you have the `rl_discard_argument' function. */ +#undef HAVE_RL_DISCARD_ARGUMENT /* Define to 1 if you have the `rl_filename_completion_function' function. */ #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION @@ -604,12 +620,12 @@ /* Define to 1 if you have the `rl_insert_close' function. */ #undef HAVE_RL_INSERT_CLOSE +/* Define to 1 if you have the `rl_reset_after_signal' function. */ +#undef HAVE_RL_RESET_AFTER_SIGNAL + /* Define to 1 if you have the `rl_set_prompt' function. */ #undef HAVE_RL_SET_PROMPT -/* Define to 1 if you have the `rl_state_initialized' function. */ -#undef HAVE_RL_STATE_INITIALIZED - /* Define to 1 if you have the `sbrk' function. */ #undef HAVE_SBRK diff --git a/docs/chr.md b/docs/chr.md index 57655920f..03046bf0f 100644 --- a/docs/chr.md +++ b/docs/chr.md @@ -1,10 +1,9 @@ +/** @defgroup CHR CHR: Constraint Handling Rules @ingroup SWILibrary -@{ - This chapter is written by Tom Schrijvers, K.U. Leuven for the hProlog system. Adjusted by Jan Wielemaker to fit the SWI-Prolog documentation infrastructure and remove hProlog specific references. @@ -19,9 +18,7 @@ The main reference for SWI-Prolog's CHR system is: + T. Schrijvers, and B. Demoen, The K.U.Leuven CHR System: Implementation and Application, First Workshop on Constraint Handling Rules: Selected Contributions (Fruwirth, T. and Meister, M., eds.), pp. 1--5, 2004. -@defgroup CHR_Introduction Introduction -@ingroup CHR - +# Introduction Constraint Handling Rules (CHR) is a committed-choice bottom-up language embedded in Prolog. It is designed for writing constraint solvers and is @@ -38,16 +35,12 @@ of CHR in general and mainly focus on elements specific to this implementation. For a more thorough review of CHR we refer the reader to [Freuhwirth:98]. More background on CHR can be found at the CHR web site. -@defgroup CHR_Syntax_and_Semantics Syntax and Semantics -@ingroup CHR -@{ +### Syntax and Semantics We present informally the syntax and semantics of CHR. -@defgroup CHR_Syntax CHR Syntax -@ingroup CHR_Syntax_and_Semantics -@{ +#### CHR Syntax The syntax of CHR rules in hProlog is the following: @@ -98,12 +91,7 @@ Additional syntax-related terminology: the arrow (either `<=>` or `==>`) -@} - -@defgroup Semantics Semantics -@ingroup CHR_Syntax_and_Semantics -@{ - +#### Semantics Semantics In this subsection the operational semantics of CHR in Prolog are presented informally. They do not differ essentially from other CHR systems. @@ -137,13 +125,7 @@ or another variable involved in one or more constraints. In that case the constraint is triggered, i.e. it becomes an active constraint and all the rules are tried. -@} - - - -@defgroup CHR_Rule_Types Rules -@ingroup CHR -@{ +### Rules There are three different kinds of rules, each with their specific semantics: @@ -168,18 +150,12 @@ constraints are not called in the body. - @defgroup CHR_Rule_Names Rule Names -@ingroup CHR_Rule_Types - +#### Rule Names Naming a rule is optional and has no semantical meaning. It only functions as documentation for the programmer. -@} - -@defgroup CHRPragmas Pragmas -@ingroup CHR -@{ +### Pragmas The semantics of the pragmas are: @@ -190,13 +166,7 @@ passive constraint in that rule. Additional pragmas may be released in the future. - -@} - - -@defgroup CHR_Options Options -@ingroup CHR -@{ +### CHR_Options Options It is possible to specify options that apply to all the CHR rules in the module. Options are specified with the `option/2` declaration: @@ -297,11 +267,7 @@ for backward compatibility. The new syntax is described below. -@} - -@defgroup CHR_in_YAP_Programs CHR in Prolog Programs -@ingroup CHR -@{ +### CHR in Prolog Programs The CHR constraints defined in a particulary chr file are @@ -310,9 +276,7 @@ never load different chr files with the same CHR module name. -@defgroup Constraint_declaration Constraint Declarations -@ingroup CHR_in_YAP_Programs -@{ +#### Constraint Declarations Every constraint used in CHR rules has to be declared. @@ -334,8 +298,7 @@ The new style is as follows: -@defgroup Compilation Compilation -@ingroup CHR_in_YAP_Programs +#### Compilation The SWI-Prolog CHR compiler exploits term_expansion/2 rules to translate @@ -367,10 +330,7 @@ leak into modules where they might cause conflicts. - @defgroup CHR_Debugging CHR Debugging -@ingroup CHR_in_YAP_Programs -@{ - +#### CHR Debugging The CHR debugging facilities are currently rather limited. Only tracing is currently available. To use the CHR debugging facilities for a CHR @@ -379,9 +339,7 @@ controlled by the CHR option debug, whose default is derived from the SWI-Prolog flag `generate_debug_info`. Therefore debug info is provided unless the `-nodebug` is used. -@defgroup Ports Ports -@ingroup CHR_Debugging - +#### Ports For CHR constraints the four standard ports are defined: @@ -416,9 +374,7 @@ An active constraints commits to a rule with possibly some passive constraints. The apply port is entered just after committing to the rule. -@defgroup Tracing Tracing -@ingroup CHR_Debugging - +#### Tracing Tracing is enabled with the chr_trace/0 predicate and disabled with the chr_notrace/0 predicate. @@ -462,12 +418,7 @@ Insert failure in execution. Print the above available debug options. - - - - - @defgroup CHR_Debugging_Predicates CHR Debugging Predicates -@ingroup CHR_Debugging +#### CHR Debugging Predicates The chr module contains several predicates that allow @@ -478,15 +429,7 @@ Activate the CHR tracer. By default the CHR tracer is activated and deactivated automatically by the Prolog predicates trace/0 and notrace/0. -@} - - - -@defgroup CHR_Examples Examples -@ingroup CHR -@{ - - +### CHR_Examples Examples Here are two example constraint solvers written in CHR. @@ -534,14 +477,7 @@ intersection([_|T],L2,L3) :- -@} - - - - @defgroup CHR_Compatibility Compatibility with SICStus CHR -@ingroup CHR -@{ - +### Compatibility with SICStus CHR There are small differences between CHR in SWI-Prolog and newer @@ -566,19 +502,7 @@ SICStus uses a two-step compiler, where chr files are first translated into pl files. For SWI-Prolog CHR rules may be defined in a file with any extension. -@} - -@} - - - - - - @defgroup CHR_Guidelines Guidelines -@ingroup CHR -@{ - - +### Guidelines In this section we cover several guidelines on how to use CHR to write constraint solvers and how to do so efficiently. @@ -603,15 +527,4 @@ Provide mode and type declarations to get more efficient program execution. Make sure to disable debug (`-nodebug`) and enable optimization (`-O`). -@} - - -@} - -@} - -@} - -@} - -@} +*/ diff --git a/docs/clpqr.md b/docs/clpqr.md index aa31be306..613c5fdf4 100644 --- a/docs/clpqr.md +++ b/docs/clpqr.md @@ -1,5 +1,5 @@ -/** @defgroup clpr Constraint Logic Programming over Rationals and Reals +@defgroup clpr Constraint Logic Programming over Rationals and Reals @ingroup SWILibrary @{ @@ -74,6 +74,7 @@ result in an exception. | max(, ) \ maximum \ ~~~~~ +@} @defgroup CLPR_Unification Use of unification @ingroup clpr @@ -100,7 +101,7 @@ X = 5.0 ~~~~~ - +@} @defgroup CLPR_NonhYlinear_Constraints Non-Linear Constraints @ingroup clpr @@ -133,3 +134,5 @@ X = tan(Y) @} +@} + diff --git a/docs/doxygen.rc b/docs/doxygen.rc index 3143d7397..1397cf394 100644 --- a/docs/doxygen.rc +++ b/docs/doxygen.rc @@ -58,7 +58,7 @@ PROJECT_LOGO = misc/icons/yap_96x96x32.png # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = /scratch/vitor/doxout +OUTPUT_DIRECTORY = /Users/vsc/Yap/doxout # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -788,10 +788,6 @@ WARN_LOGFILE = INPUT = foreigns.yap \ docs/yap.md \ - docs/chr.md \ - docs/threads.md \ - docs/syntax.md \ - docs/clpqr.md \ pl \ C \ H \ diff --git a/docs/threads.md b/docs/threads.md deleted file mode 100644 index 4f078daa9..000000000 --- a/docs/threads.md +++ /dev/null @@ -1,179 +0,0 @@ - -@defgroup Threads Threads -@ingroup YAPExtensions -@{ - -YAP implements a SWI-Prolog compatible multithreading -library. Like in SWI-Prolog, Prolog threads have their own stacks and -only share the Prolog heap: predicates, records, flags and other -global non-backtrackable data. The package is based on the POSIX thread -standard (Butenhof:1997:PPT) used on most popular systems except -for MS-Windows. - -@defgroup Creating_and_Destroying_Prolog_Threads Creating and Destroying Prolog Threads -@ingroup Threads - -@pred thread_create(: _Goal_, - _Id_, + _Options_) - -Create a new Prolog thread (and underlying C-thread) and start it -by executing _Goal_. If the thread is created successfully, the -thread-identifier of the created thread is unified to _Id_. - _Options_ is a list of options. Currently defined options are: - -+ stack -Set the limit in K-Bytes to which the Prolog stacks of -this thread may grow. If omitted, the limit of the calling thread is -used. See also the commandline `-S` option. - -+ trail -Set the limit in K-Bytes to which the trail stack of this thread may -grow. If omitted, the limit of the calling thread is used. See also the -commandline option `-T`. - -+ alias -Associate an alias-name with the thread. This named may be used to -refer to the thread and remains valid until the thread is joined -(see thread_join/2). - -+ at_exit -Define an exit hook for the thread. This hook is called when the thread -terminates, no matter its exit status. - -+ detached -If `false` (default), the thread can be waited for using -thread_join/2. thread_join/2 must be called on this thread -to reclaim the all resources associated to the thread. If `true`, -the system will reclaim all associated resources automatically after the -thread finishes. Please note that thread identifiers are freed for reuse -after a detached thread finishes or a normal thread has been joined. -See also thread_join/2 and thread_detach/1. - - -The _Goal_ argument is copied to the new Prolog engine. -This implies further instantiation of this term in either thread does -not have consequences for the other thread: Prolog threads do not share -data from their stacks. - - @defgroup Monitoring_Threads Monitoring Threads -@ingroup Threads - - -Normal multi-threaded applications should not need these the predicates -from this section because almost any usage of these predicates is -unsafe. For example checking the existence of a thread before signalling -it is of no use as it may vanish between the two calls. Catching -exceptions using catch/3 is the only safe way to deal with -thread-existence errors. - -These predicates are provided for diagnosis and monitoring tasks. - - - - - - @defgroup Thread_Communication Thread communication -@ingroup Threads - - -Prolog threads can exchange data using dynamic predicates, database -records, and other globally shared data. These provide no suitable means -to wait for data or a condition as they can only be checked in an -expensive polling loop. Message queues provide a means for -threads to wait for data or conditions without using the CPU. - -Each thread has a message-queue attached to it that is identified -by the thread. Additional queues are created using -`message_queue_create/2`. - - - - @pred thread_send_message(+ _Term_) - - -Places _Term_ in the message-queue of the thread running the goal. -Any term can be placed in a message queue, but note that the term is -copied to the receiving thread and variable-bindings are thus lost. -This call returns immediately. - - - - - - @defgroup Signalling_Threads Signalling Threads -@ingroup Threadas - - -These predicates provide a mechanism to make another thread execute some -goal as an interrupt. Signalling threads is safe as these -interrupts are only checked at safe points in the virtual machine. -Nevertheless, signalling in multi-threaded environments should be -handled with care as the receiving thread may hold a mutex -(see with_mutex/2). Signalling probably only makes sense to start -debugging threads and to cancel no-longer-needed threads with throw/1, -where the receiving thread should be designed carefully do handle -exceptions at any point. - - - - - - @defgroup Threads_and_Dynamic_Predicates Threads and Dynamic Predicates -@ingroup Threads - - -Besides queues threads can share and exchange data using dynamic -predicates. The multi-threaded version knows about two types of -dynamic predicates. By default, a predicate declared dynamic -(see dynamic/1) is shared by all threads. Each thread may -assert, retract and run the dynamic predicate. Synchronisation inside -Prolog guarantees the consistency of the predicate. Updates are -logical: visible clauses are not affected by assert/retract -after a query started on the predicate. In many cases primitive from -thread synchronisation should be used to ensure application invariants on -the predicate are maintained. - -Besides shared predicates, dynamic predicates can be declared with the -thread_local/1 directive. Such predicates share their -attributes, but the clause-list is different in each thread. - - - - - -@defgroup Thread_Synchronisation Thread Synchronisation -@ingroup Threads - -All - internal Prolog operations are thread-safe. This implies two Prolog -threads can operate on the same dynamic predicate without corrupting the -consistency of the predicate. This section deals with user-level -mutexes (called monitors in ADA or -critical-sections by Microsoft). A mutex is a -MUTual EXclusive device, which implies at most one thread -can hold a mutex. - -Mutexes are used to realise related updates to the Prolog database. -With `related', we refer to the situation where a `transaction' implies -two or more changes to the Prolog database. For example, we have a -predicate `address/2`, representing the address of a person and we want -to change the address by retracting the old and asserting the new -address. Between these two operations the database is invalid: this -person has either no address or two addresses, depending on the -assert/retract order. - -Here is how to realise a correct update: - -~~~~~ -:- initialization - mutex_create(addressbook). - -change_address(Id, Address) :- - mutex_lock(addressbook), - retractall(address(Id, _)), - asserta(address(Id, Address)), - mutex_unlock(addressbook). -~~~~~ - - - -@} diff --git a/docs/yap.md b/docs/yap.md index 33cfd7ff5..6b6989129 100644 --- a/docs/yap.md +++ b/docs/yap.md @@ -3,20 +3,13 @@ This file documents the YAP Prolog System version 6.3.4, a high-performance Prol + @ref DownloadInstall -+ @ref Run describes how to invoke YAP ++ @ref Run -+ @ref YAPLoading presents the main predicates and - directives available to load files and to control the Prolog - environment. ++ @ref YAPLoading - + @ref YAPConsulting - + @ref YAPModules introduces the YAP module system and meta-predicates. ++ @ref YAPBuiltins -+ @ref YAPBuiltins describes predicates providing core YAP - functionality: - -+ @ref YAPExtensions presents several extensions over standard - Prolog ++ @ref YAPExtensions + @ref YAPProgramming @@ -782,9 +775,11 @@ will be used: + @ref arithmetic ++ @ref YAPChars + + @ref YAP_Terms -+ @ref InputOutput. ++ @ref YAP_InputOutput + @ref YAPOS @@ -816,7 +811,7 @@ being designed to work with the swig (@url(www.swig.org}) interface compiler. @defgroup YAPExtensions Extensions to core Prolog. -+ @ref Rational_Trees ++@ref Rational_Trees + @ref CohYroutining @@ -901,6 +896,8 @@ being designed to work with the swig (@url(www.swig.org}) interface compiler. @defgroup YAPProgramming Programming in YAP +@page Programming Programming in YAP + + @ref Syntax + @ref Indexing @@ -909,18 +906,52 @@ being designed to work with the swig (@url(www.swig.org}) interface compiler. @defgroup SWILibrary SWI-Prolog Libraries and Packages -+ @ref Read_Utilities Read Utilities - -+ @ref shlib SWI-Prolog's shlib library +@page SWICode The SWI-Prolog Libraries and Packages -+ @ref Lambda Lambda Expressions ++ @ref aggregates + ++ @ref date + ++ @ref debug + ++ @ref persistence + ++ @ref pio + ++ @ref predicate_options + ++ @ref prolog_clause + ++ @ref prolog_colour + ++ @ref prolog_main + ++ @ref prolog_source + ++ @ref quasi_quotations + ++ @ref swi_option + ++ @ref read_util + ++ @ref record + ++ @ref settings + ++ @ref shlib + ++ @ref url + ++ @ref Lambda + @ref archive -+ @ref chr ++ @ref CHR + @ref clpr ++ @ref http + + @ref zlib @defgroup YAPPackages The YAP packages @@ -935,7 +966,16 @@ being designed to work with the swig (@url(www.swig.org}) interface compiler. + @ref MYDDAS -@defgroup http The SWI The SWI http packages ++ @ref PFL + ++ @ref ProbLog1 + ++ @ref YAPRaptor + ++ @ref YAP-LBFGS + +@defgroup http The SWI http packages +@ingroup SWILibrary Tthe package HTTP is a series of libraries developed by Jan Wielmaker and the SWI-Prolog community for accessing and serving data on the @@ -945,9 +985,6 @@ data-representation primitives, and more. The port to YAP focussed on the client-side support. The server package has not been as widely tested. - -\toc - @page Compatibility Compatibility with Other Prolog systems YAP has been designed to be as compatible as possible with diff --git a/library/apply.yap b/library/apply.yap index 259864777..ed66d5867 100644 --- a/library/apply.yap +++ b/library/apply.yap @@ -3,9 +3,8 @@ @{ This library provides a SWI-compatible set of utilities for applying a -predicate to all elements of a list. The library just forwards -definitions from the `maplist` library. - +predicate to all elements of a list. In practice, the library just forwards +definitions from the @ref maplist library library. */ diff --git a/library/atts.yap b/library/atts.yap index 57b26003d..bab2b56a6 100644 --- a/library/atts.yap +++ b/library/atts.yap @@ -22,7 +22,8 @@ @ingroup Attributed_Variables @{ -Old style attribute declarations are activated through loading the library atts . The command +Old style attribute declarations are activated through loading the +library atts . The command ~~~~~ | ?- use_module(library(atts)). diff --git a/library/dialect/swi.yap b/library/dialect/swi.yap index c1336cc6b..69a2dc9d0 100644 --- a/library/dialect/swi.yap +++ b/library/dialect/swi.yap @@ -5,16 +5,17 @@ /** -@defgroup system - -@file swi.yap - -@page SWIhYProlog_Emulation SWI-Prolog Emulation +@defgroup System SWI Dialect SupportXS This library provides a number of SWI-Prolog builtins that are not by default in YAP. This support is loaded with the -`expects_dialect(swi)` command. +~~~~~ +expects_dialect(swi) +~~~~~ + command. + +@{ */ @@ -26,14 +27,6 @@ Unify the last modification time of _File_ with elapsed since Jan 1, 1970. -*/ -/** @pred chdir(+ _Dir_) - - - -Compatibility predicate. New code should use working_directory/2. - - */ /** @pred concat_atom(+ _List_,- _Atom_) @@ -46,29 +39,7 @@ allowing for variables in the list. */ -/** @pred concat_atom(? _List_,+ _Separator_,? _Atom_) - -Creates an atom just like concat_atom/2, but inserts _Separator_ -between each pair of atoms. For example: - -~~~~~ -?- concat_atom([gnu, gnat], ', ', A). - -A = 'gnu, gnat' -~~~~~ - -(Unimplemented) This predicate can also be used to split atoms by -instantiating _Separator_ and _Atom_: - -~~~~~ -?- concat_atom(L, -, 'gnu-gnat'). - -L = [gnu, gnat] -~~~~~ - - -*/ :- module(system, [concat_atom/2, concat_atom/3, read_clause/1, @@ -215,7 +186,29 @@ user:file_search_path(foreign, swi(ArchLib)) :- atom_concat('lib/', Arch, ArchLib). user:file_search_path(foreign, swi(lib)). +/** @pred concat_atom(? _List_,+ _Separator_,? _Atom_) + +Creates an atom just like concat_atom/2, but inserts _Separator_ +between each pair of atoms. For example: + +~~~~~ +?- concat_atom([gnu, gnat], ', ', A). + +A = 'gnu, gnat' +~~~~~ + +(Unimplemented) This predicate can also be used to split atoms by +instantiating _Separator_ and _Atom_: + +~~~~~ +?- concat_atom(L, -, 'gnu-gnat'). + +L = [gnu, gnat] +~~~~~ + + +*/ concat_atom([A|List], Separator, New) :- var(List), !, atom_codes(Separator,[C]), atom_codes(New, NewChars), @@ -254,6 +247,10 @@ cvt_bindings([[Name|Value]|L],[AName=Value|Bindings]) :- atom_codes(AName, Name), cvt_bindings(L,Bindings). +/** @pred chdir(+ _Dir_) + +Compatibility predicate. New code should use working_directory/2. +*/ chdir(X) :- cd(X). %% convert_time(+Stamp, -String) @@ -342,4 +339,6 @@ required_predicate(Na/Ar, M) :- autoloader:find_predicate(G, _) ). - +/** +@} +*/ diff --git a/library/lineutils.yap b/library/lineutils.yap index 2264ae679..86aeb4040 100644 --- a/library/lineutils.yap +++ b/library/lineutils.yap @@ -22,8 +22,10 @@ This package provides a set of useful predicates to manipulate sequences of characters codes, usually first read in as a line. It is -available by loading the library `library(lineutils)`. - +available by loading the +~~~~ +:- use_module(library(lineutils)). +~~~~ */ @@ -191,7 +193,19 @@ copy_line(StreamInp, StreamOut) :- For every line _LineIn_ in stream _StreamInp_, execute `call(Goal,LineIn,LineOut)`, and output _LineOut_ to -stream _StreamOut_. +stream _StreamOut_. If `call(Goal,LineIn,LineOut)` fails, +nothing will be output but execution continues with the next +line. As an example, consider a procedure to select the second and +fifth field of a CSV table : +~~~~~{.prolog} +select(Sep, In, Out) :- + fields(In, Sep, [_,F2,_,_,F5|_]), + fields(Out,Sep, [F2,F5]). + +select :- + filter(",", +~~~~~ + */ filter(StreamInp, StreamOut, Command) :- repeat, @@ -206,7 +220,7 @@ filter(StreamInp, StreamOut, Command) :- fail ). -/** @pred process(+ _StreamInp_, + _Goal_) +/** @pred process(+ _StreamInp_, + _Goal_) is meta For every line _LineIn_ in stream _StreamInp_, call `call(Goal,LineIn)`. @@ -224,7 +238,7 @@ process(StreamInp, Command) :- ). -/** @pred file_filter(+ _FileIn_, + _FileOut_, + _Goal_) +/** @pred file_filter(+ _FileIn_, + _FileOut_, + _Goal_) is meta For every line _LineIn_ in file _FileIn_, execute `call(Goal,LineIn,LineOut)`, and output _LineOut_ to file diff --git a/misc/sysgraph b/misc/sysgraph index 6db2e958c..e3a3f438d 100644 --- a/misc/sysgraph +++ b/misc/sysgraph @@ -1399,7 +1399,7 @@ atom_pred(N) --> !, decl(1,N). atom_pred(0) --> - blank, !. + blanks, !. int(I0, I) --> [A], @@ -1419,9 +1419,9 @@ decl(I0, I) --> [_], decl( I0, I). -blank --> " ", !, blank. -blank --> "\t", !, blank. -blank --> []. +blanks --> " ", !, blanks. +blanks --> "\t", !, blanks. +blanks --> []. atom([A|As]) --> [A], @@ -1440,8 +1440,7 @@ atom2([A|As]) --> atom2([]) --> []. add_comments :- - open( commands, write, S ), - findall(File, do_comment( File, Line, C, Type, Dup), Fs0 ), + findall(File, do_comment( File, Line, C, Type, Dup), Fs0 ), ( sort(Fs0, Fs), member( File, Fs ), diff --git a/os/pl-ctype.c b/os/pl-ctype.c index bdea60f85..ce22805b5 100644 --- a/os/pl-ctype.c +++ b/os/pl-ctype.c @@ -1,3 +1,5 @@ + + /* Part of SWI-Prolog Author: Jan Wielemaker @@ -25,6 +27,13 @@ #include #include "pl-ctype.h" +//! @defgroup YAPChars Character Classification and Manipulation +// @ingroup YAPBuiltins +// +// This module defines routines to manipulate individual characters. +// +// @{ + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This module defines: @@ -436,9 +445,23 @@ error: +/** @pred char_type(? _Char_, ? _Type_) + + +Like code_type/2, tests or generates alternative _Types_ or +_Chars_. The character-types are inspired by the standard `C` +`` primitives. + + */ + +/// @memberof code_type/2 static PRED_IMPL("char_type", 2, char_type, PL_FA_NONDETERMINISTIC) -/** @pred char_type(? _Char_, ? _Type_) +{ return do_char_type(A1, A2, PL__ctx, PL_CHAR); +} + + +/** @pred code_type(? _Char_, ? _Type_) Tests or generates alternative _Types_ or _Chars_. The @@ -536,10 +559,7 @@ atom_chars/2 and atom_codes/2. */ -{ return do_char_type(A1, A2, PL__ctx, PL_CHAR); -} - - +/// @memberof code_type/2 static PRED_IMPL("code_type", 2, code_type, PL_FA_NONDETERMINISTIC) { return do_char_type(A1, A2, PL__ctx, PL_CODE); @@ -698,12 +718,31 @@ modify_case_atom(term_t in, term_t out, int down) } +/** @pred downcase_atom(+ _Word_, - _LowerCaseWord_) + +If the first argument is bound to an atom _Word_, the +second argument shoud unify with an atom such that all alphabetic cdes +are lower case, _LowerCaseWord_. Non-alphabetic characers are +preserved. + + */ + +/// @memberof downcase_atom/2 static PRED_IMPL("downcase_atom", 2, downcase_atom, 0) { return modify_case_atom(A1, A2, TRUE); } +/** @pred upcase_atom(+ _Word_, - _UpCaseWord_) +If the first argument is bound to an atom _Word_, the +second argument shoud unify with an atom such that all alphabetic cdes +are up case, _UpCaseWord_. Non-alphabetic characers are +preserved. + + */ + +/// @memberof upcase_atom/2 static PRED_IMPL("upcase_atom", 2, upcase_atom, 0) { return modify_case_atom(A1, A2, FALSE); @@ -748,6 +787,24 @@ write_normalize_space(IOSTREAM *out, term_t in) } +/** @pred normalize_space(- _Out_, + _In_) + +Remove white space at the beginning an end of the word _In_, and replace +sequences of white space in the middle of _In_ by a single white +space. +~~~ + ?- normalize_space(atom(X), ' the white fox jumped '). +X = 'the white fox jumped'. + ?- normalize_space(string(X), ' over the lazy dog '). +X = "over the lazy dog". +~~~ + +Notice that the first argument is bound to a stream descriptor in the +style of format/3. + + */ + +/// @memberof normalize_space/2 static PRED_IMPL("normalize_space", 2, normalize_space, 0) { redir_context ctx; @@ -764,6 +821,9 @@ PRED_IMPL("normalize_space", 2, normalize_space, 0) } +/// @addtogroup SetLocale +// @{ +// /******************************* * LOCALE * @@ -819,7 +879,13 @@ static lccat lccats[] = { 0, NULL } }; +/// @} +/** @pred setlocale( + _In_, - _Old_, -_New_) + + */ + +/// @memberof setlocale/3 static PRED_IMPL("setlocale", 3, setlocale, 0) { PRED_LD @@ -871,7 +937,7 @@ PRED_IMPL("setlocale", 3, setlocale, 0) } #endif - +/// @} /******************************* * PUBLISH PREDICATES * @@ -994,3 +1060,5 @@ initCharTypes(void) { initEncoding(); } +/// @} + diff --git a/os/pl-file.c b/os/pl-file.c index a05ced2a2..402e8019a 100644 --- a/os/pl-file.c +++ b/os/pl-file.c @@ -22,13 +22,9 @@ */ -/** @defgroup Streams_and_Files Handling Streams and Files -@ingroup YAPBuiltins +/** @addtogroup YAP_inputOutput @{ - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -124,11 +120,16 @@ standardStreamIndexFromStream(IOSTREAM *s) return -1; } - +//! @} /******************************* * BOOKKEEPING * *******************************/ +/** + * @defgroup YAP_StreamM Stream Manipulation + * @ingroup YAP_InputOutput + * @{ + */ static void aliasStream(IOSTREAM *s, atom_t alias); static void unaliasStream(IOSTREAM *s, atom_t name); @@ -898,8 +899,14 @@ getBinaryInputStream__LD(term_t t, IOSTREAM **stream ARG_LD) } -/** stream_pairs(+Pair, -Read, -Write) - stream_pairs(-Pair, +Read, +Write) +/** stream_pairs(-Pair, +Read, +Write) + * stream_pairs(+Pair, -Read, -Write) + * + * This SWI Built-in can be used in two ways: if the second argument is an input stream + * and the third sn output stresm, Prolog createes a new _Pair_. A stream pair can be + * used in any operation, with the Prolog chosing the appropriate stream to the operation. + * + * If _Pair_ is bound, the predicate can be used to access the two streams in the pair. */ static @@ -1434,7 +1441,40 @@ discardOutputRedirect(redir_context *ctx) } } +/** @pred with_output_to(+ _Ouput_,: _Goal_) + +This SWI-Prolog predicate runs _Goal_ as once/1, while characters written to the current +output are sent to _Output_. + +This predicate supports creating +difference-lists from character data efficiently. The example below +defines the DCG rule `term/3` to insert a term in the output: + +~~~~~ + term(Term, In, Tail) :- + with_output_to(codes(In, Tail), write(Term)). + +?- phrase(term(hello), X). + +X = [104, 101, 108, 108, 111] +~~~~~ + ++ A Stream handle or alias +Temporary switch current output to the given stream. Redirection using with_output_to/2 guarantees the original output is restored, also if Goal fails or raises an exception. See also call_cleanup/2. ++ atom(- _Atom_) +Create an atom from the emitted characters. Please note that there is a cost in creating atoms. ++ string(- _String_) +Create a string-object. ++ codes(- _Codes_) +Create a list of character codes from the emitted characters, similar to atom_codes/2. ++ codes(- _Codes_, - _Tail_) +Create a list of character codes as a difference-list. ++ chars(- _Chars_) +Create a list of one-character-atoms codes from the emitted characters, similar to atom_chars/2. ++ chars(- _Chars_, - _Tail_) +Create a list of one-character-atoms as a difference-list. + */ static PRED_IMPL("with_output_to", 2, with_output_to, PL_FA_TRANSPARENT) { redir_context outctx; @@ -1638,7 +1678,6 @@ openProtocol(term_t f, int appnd) return FALSE; } - static int noprotocol(void) { GET_LD @@ -1664,12 +1703,20 @@ noprotocol(void) return TRUE; } +/** @pred noprotocol +Stop protocolling user interaction. +*/ static PRED_IMPL("noprotocol", 0, noprotocol, 0) { return noprotocol(); } +//! @} + +// @{ +// + /******************************* * STREAM ATTRIBUTES * @@ -1986,7 +2033,12 @@ static const set_stream_info ss_info[] = SS_INFO((atom_t)0, 0) }; +/** @pred set_stream(+ _S_, + _Prop_) is iso + +Set a property _Prop_ for a stream _S_. + +*/ static PRED_IMPL("set_stream", 2, set_stream, 0) { PRED_LD @@ -2054,6 +2106,11 @@ extern int ftruncate(int fileno, int64_t length); #define HAVE_FTRUNCATE #endif +/** @pred set_end_of_stream(+ _S_ ) is iso + +Set stream position to be the end of stream. + +*/ static PRED_IMPL("set_end_of_stream", 1, set_end_of_stream, 0) { IOSTREAM *s; @@ -2129,6 +2186,14 @@ toldString(void) #ifndef HAVE_SELECT +/** @pred wait_for_input(+ _Streams_, -_Available_, - _Timeout_) is iso + * + * Implement the select operation over a set of stream _Streams, with + * _Available_ unified with all ready streams. The operation can last at most + * _Timeout_ seconds. + * + * +*/ static PRED_IMPL("wait_for_input", 3, wait_for_input, 0) { return notImplemented("wait_for_input", 3); @@ -2369,7 +2434,12 @@ skip_cr(IOSTREAM *s) return FALSE; } - +/** @pred read_pending_input( _Stream_ , _Codes_, _End_ ) + * + * Reads all characters or bytes currently available from _Stream_ to the difference + * list _Codes_ - _End_. This SWI predicate allows cleaning up input from unbuffered + * streams. + */ static PRED_IMPL("read_pending_input", 3, read_pending_input, 0) { PRED_LD @@ -2595,6 +2665,12 @@ PRED_IMPL("read_pending_input", 3, read_pending_input, 0) return FALSE; } +// @} + +//! @defgroup YAPCharsIO Character Input/Output +// @ingroup YAP_InputOutput +// @{ +// static foreign_t put_byte(term_t stream, term_t byte ARG_LD) @@ -2615,8 +2691,6 @@ put_byte(term_t stream, term_t byte ARG_LD) /** @pred put_byte(+ _S_,+ _N_) is iso As `put_byte(N)`, but to binary stream _S_. - - */ static PRED_IMPL("put_byte", 2, put_byte2, 0) @@ -2631,8 +2705,6 @@ PRED_IMPL("put_byte", 2, put_byte2, 0) Outputs to the current output stream the character whose code is _N_. The current output stream must be a binary stream. - - */ static PRED_IMPL("put_byte", 1, put_byte1, 0) @@ -2663,6 +2735,12 @@ put_code(term_t stream, term_t chr ARG_LD) As `put_code(N)`, but to text stream _S_. +*/ +/** @pred put_char(+ _S_,+ _A_) is iso + +As `put_char(A)`, but to text stream _S_. + + */ static PRED_IMPL("put_code", 2, put_code2, 0) @@ -2672,6 +2750,15 @@ PRED_IMPL("put_code", 2, put_code2, 0) } +/** @pred put_char(+ _N_) is iso + + +Outputs to the current output stream the character who is used to build +the representation of atom `A`. The current output stream must be a +text stream. + + +*/ /** @pred put_code(+ _N_) is iso @@ -2830,7 +2917,13 @@ PRED_IMPL("skip", 2, skip2, 0) return skip(A1, A2 PASS_LD); } - +/** @pred get_single_char( +_Stream_ ) + * + * SWI-Prolog predicate that reads the first charcter from `user_input`. + * This operation is unbuffered, + * and it does not have to wait for n newline. Spaces and tabulation characters are + * ignored. + */ static PRED_IMPL("get_single_char", 1, get_single_char, 0) { GET_LD @@ -2909,7 +3002,12 @@ PRED_IMPL("get_byte", 1, get_byte1, 0) return get_byte2(0, A1 PASS_LD); } +/** @pred get0(+ _S_,- _C_) +The same as `get0(C)`, but from stream _S_. + + +*/ static foreign_t get_code2(term_t in, term_t chr ARG_LD) { IOSTREAM *s; @@ -3014,6 +3112,11 @@ PRED_IMPL("get_char", 1, get_char1, 0) } +/** @pred ttyflush + +Flush the current output stream. +*/ + static PRED_IMPL("ttyflush", 0, ttyflush, 0) { PRED_LD @@ -3029,18 +3132,34 @@ PRED_IMPL("ttyflush", 0, ttyflush, 0) } +/** @pred protocol( _File_ ) + * + * Start protocolling user interaction to _File_, closing any previous protocolling + * file and truncating it. + * +*/ static PRED_IMPL("protocol", 1, protocol, 0) { return openProtocol(A1, FALSE); } +/** @pred protocola( _File_ ) + * + * Start protocolling user interaction to _File_, closing any previous protocolling + * file and then appending it. + * +*/ static PRED_IMPL("protocola", 1, protocola, 0) { return openProtocol(A1, TRUE); } - +/** @pred protocolling( -_File_ ) + * + * Report whether we are protocolling and to which _File_. + * +*/ static PRED_IMPL("protocolling", 1, protocolling, 0) { PRED_LD @@ -3061,10 +3180,7 @@ PRED_IMPL("protocolling", 1, protocolling, 0) /** @pred prompt(- _A_,+ _B_) - Changes YAP input prompt from _A_ to _B_. - - */ static PRED_IMPL("prompt", 2, prompt, 0) @@ -3086,7 +3202,10 @@ PRED_IMPL("prompt", 2, prompt, 0) return FALSE; } +/** @pred prompt1(+ _Prompt_) +Set the YAP input prompt for the next line. +*/ void prompt1(atom_t prompt) { GET_LD @@ -3514,8 +3633,6 @@ Opens the file with name _F_ in mode _M_ (`read`, `write` or `append`), returning _S_ unified with the stream name, and following these options: - - + `type(+ _T_)` is iso Specify whether the stream is a `text` stream (default), or a @@ -3618,6 +3735,11 @@ PRED_IMPL("open", 3, open3, PL_FA_ISO) return FALSE; } +/** @defgroup DEC10_IO DEC-10/C-Prolog Compatible File Handling + * + * @ingroup YAP_InputOutput + * @{ + */ /******************************* * EDINBURGH I/O * *******************************/ @@ -3730,9 +3852,6 @@ PRED_IMPL("see", 1, see, 0) Closes the current input stream (see 6.7.). - - - */ static PRED_IMPL("seen", 0, seen, 0) @@ -3872,6 +3991,16 @@ PRED_IMPL("told", 0, told, 0) return symbol_no_stream(ATOM_current_output); } +/** + * @} + */ + +//! @defgroup YAPStream Opening and Closing Streams +// @ingroup YAP_InputOutput +// @{ +// + + /******************************* * NULL-STREAM * *******************************/ @@ -4426,8 +4555,6 @@ typedef struct } prop_enum; -static -PRED_IMPL("stream_property", 2, stream_property, /** @pred stream_property(? _Stream_,? _Prop_) is iso @@ -4508,6 +4635,8 @@ Unify _LineNumber_ with the line number for the current stream. */ +static +PRED_IMPL("stream_property", 2, stream_property, PL_FA_ISO|PL_FA_NONDETERMINISTIC) { PRED_LD IOSTREAM *s; @@ -4714,15 +4843,13 @@ Unify _LineNumber_ with the line number for the current stream. } -static -PRED_IMPL("is_stream", 1, is_stream, 0) /** @pred is_stream( _S_) Succeeds if _S_ is a currently open stream. - - */ +static +PRED_IMPL("is_stream", 1, is_stream, 0) { GET_LD IOSTREAM *s; atom_t a; @@ -4734,11 +4861,17 @@ Succeeds if _S_ is a currently open stream. return FALSE; } - - /******************************* * FLUSH * *******************************/ +/** + * @} + */ + +/** + * @addtogroup YAPStreamM + * @{ + */ static int @@ -4753,8 +4886,6 @@ flush_output(term_t out ARG_LD) return FALSE; } -static -PRED_IMPL("flush_output", 0, flush_output, PL_FA_ISO) /** @pred flush_output is iso @@ -4762,24 +4893,35 @@ Send out all data in the output buffer of the current output stream. */ +static +PRED_IMPL("flush_output", 0, flush_output, PL_FA_ISO) { PRED_LD return flush_output(0 PASS_LD); } -static -PRED_IMPL("flush_output", 1, flush_output1, PL_FA_ISO) /** @pred flush_output(+ _S_) is iso Send all data in the output buffer for stream _S_. */ +static +PRED_IMPL("flush_output", 1, flush_output1, PL_FA_ISO) { PRED_LD return flush_output(A1 PASS_LD); } +/** + * @} + */ + +/** + * @addtogroup YAPStream + * @{ + */ + static int getStreamWithPosition(term_t stream, IOSTREAM **sp) @@ -4826,8 +4968,6 @@ getRepositionableStream(term_t stream, IOSTREAM **sp) } -static -PRED_IMPL("set_stream_position", 2, set_stream_position, PL_FA_ISO) /** @pred set_stream_position(+ _S_, + _POS_) is iso @@ -4836,6 +4976,8 @@ stream position for _S_ to be _POS_. */ +static +PRED_IMPL("set_stream_position", 2, set_stream_position, PL_FA_ISO) { PRED_LD IOSTREAM *s = NULL; /* make compiler happy */ int64_t charno, byteno; @@ -4932,8 +5074,6 @@ PRED_IMPL("seek", 4, seek, 0) } -static -PRED_IMPL("set_input", 1, set_input, PL_FA_ISO) /** @pred set_input(+ _S_) is iso @@ -4942,6 +5082,8 @@ and get/1 will start using stream _S_. */ +static +PRED_IMPL("set_input", 1, set_input, PL_FA_ISO) { PRED_LD IOSTREAM *s; @@ -4955,9 +5097,7 @@ and get/1 will start using stream _S_. } -static -PRED_IMPL("set_output", 1, set_output, PL_FA_ISO) -/** @pred set_output(+ _S_) is iso +/** @pred set_output(+ _S_) is iso Set stream _S_ as the current output stream. Predicates like @@ -4965,6 +5105,8 @@ write/1 and put/1 will start using stream _S_. */ +static +PRED_IMPL("set_output", 1, set_output, PL_FA_ISO) { PRED_LD IOSTREAM *s; @@ -4978,8 +5120,6 @@ write/1 and put/1 will start using stream _S_. } -static -PRED_IMPL("current_input", 1, current_input, PL_FA_ISO) /** @pred current_input(- _S_) is iso @@ -4987,13 +5127,13 @@ Unify _S_ with the current input stream. */ +static +PRED_IMPL("current_input", 1, current_input, PL_FA_ISO) { PRED_LD return PL_unify_stream(A1, Scurin); } -static -PRED_IMPL("current_output", 1, current_output, PL_FA_ISO) /** @pred current_output(- _S_) is iso @@ -5001,11 +5141,21 @@ Unify _S_ with the current output stream. */ +static +PRED_IMPL("current_output", 1, current_output, PL_FA_ISO) { PRED_LD return PL_unify_stream(A1, Scurout); } +/** @pred character_count(+ _Stream_,- _ByteCount_) + + +Unify _CharacterCount_ with the number of bytes written to or +read from _Stream_. + + +*/ static PRED_IMPL("byte_count", 2, byte_count, 0) { PRED_LD @@ -5022,16 +5172,16 @@ PRED_IMPL("byte_count", 2, byte_count, 0) } -static -PRED_IMPL("character_count", 2, character_count, 0) /** @pred character_count(+ _Stream_,- _CharacterCount_) Unify _CharacterCount_ with the number of characters written to or -read to _Stream_. +read from _Stream_. */ +static +PRED_IMPL("character_count", 2, character_count, 0) { PRED_LD IOSTREAM *s; @@ -5046,8 +5196,6 @@ read to _Stream_. } -static -PRED_IMPL("line_count", 2, line_count, 0) /** @pred line_count(+ _Stream_,- _LineNumber_) @@ -5055,6 +5203,8 @@ Unify _LineNumber_ with the line number for the _Stream_. */ +static +PRED_IMPL("line_count", 2, line_count, 0) { GET_LD IOSTREAM *s; @@ -5069,8 +5219,6 @@ Unify _LineNumber_ with the line number for the _Stream_. } -static -PRED_IMPL("line_position", 2, line_position, 0) /** @pred line_position(+ _Stream_,- _LinePosition_) @@ -5079,6 +5227,8 @@ Unify _LinePosition_ with the position on current text stream */ +static +PRED_IMPL("line_position", 2, line_position, 0) { GET_LD IOSTREAM *s; @@ -5129,8 +5279,6 @@ at_end_of_stream(term_t stream ARG_LD) return FALSE; /* exception */ } -static -PRED_IMPL("at_end_of_stream", 1, at_end_of_stream, PL_FA_ISO) /** @pred at_end_of_stream(+ _S_) is iso Succeed if the stream _S_ has stream position end-of-stream or @@ -5138,12 +5286,12 @@ past-end-of-stream. Note that _S_ must be a readable stream. */ +static +PRED_IMPL("at_end_of_stream", 1, at_end_of_stream, PL_FA_ISO) { PRED_LD return at_end_of_stream(A1 PASS_LD); } -static -PRED_IMPL("at_end_of_stream", 0, at_end_of_stream0, PL_FA_ISO) /** @pred at_end_of_stream is iso @@ -5152,6 +5300,8 @@ past-end-of-stream. */ +static +PRED_IMPL("at_end_of_stream", 0, at_end_of_stream0, PL_FA_ISO) { PRED_LD return at_end_of_stream(0 PASS_LD); } @@ -5187,9 +5337,17 @@ peek(term_t stream, term_t chr, int how ARG_LD) return PL_unify_char(chr, c, how); } +/** + * @} + */ + +/** + * @addtogroup YAPCharsIO + * @{ + */ + + -static -PRED_IMPL("peek_byte", 2, peek_byte2, 0) /** @pred peek_byte(+ _S_,- _C_) is iso If _C_ is unbound, or is a character code, and _S_ is a binary @@ -5198,13 +5356,13 @@ with _C_, while leaving the current stream position unaltered. */ +static +PRED_IMPL("peek_byte", 2, peek_byte2, 0) { PRED_LD return peek(A1, A2, PL_BYTE PASS_LD); } -static -PRED_IMPL("peek_byte", 1, peek_byte1, 0) /** @pred peek_byte(- _C_) is iso @@ -5214,13 +5372,13 @@ code with _C_, while leaving the current stream position unaltered. */ +static +PRED_IMPL("peek_byte", 1, peek_byte1, 0) { PRED_LD return peek(0, A1, PL_BYTE PASS_LD); } -static -PRED_IMPL("peek_code", 2, peek_code2, 0) /** @pred peek_code(+ _S_,- _C_) is iso If _C_ is unbound, or is an atom representation of a character, and @@ -5230,30 +5388,29 @@ the current stream position unaltered. */ +static +PRED_IMPL("peek_code", 2, peek_code2, 0) { PRED_LD return peek(A1, A2, PL_CODE PASS_LD); } -static -PRED_IMPL("peek_code", 1, peek_code1, 0) -/** @pred peek_code(- _C_) is iso +/** @pred peek_code(+ _S_,- _C_) is iso - -If _C_ is unbound, or is the code for a character, and -the current stream is a text stream, read the next character from the -current stream and unify its code with _C_, while -leaving the current stream position unaltered. +If _C_ is unbound, or is an atom representation of a character, and +the stream _S_ is a text stream, read the next character from that +stream and unify its representation as an atom with _C_, while leaving +the current stream position unaltered. */ +static +PRED_IMPL("peek_code", 1, peek_code1, 0) { PRED_LD return peek(0, A1, PL_CODE PASS_LD); } -static -PRED_IMPL("peek_char", 2, peek_char2, 0) /** @pred peek_char(+ _S_,- _C_) is iso If _C_ is unbound, or is an atom representation of a character, and @@ -5263,13 +5420,12 @@ the current stream position unaltered. */ +static +PRED_IMPL("peek_char", 2, peek_char2, 0) { PRED_LD return peek(A1, A2, PL_CHAR PASS_LD); } - -static -PRED_IMPL("peek_char", 1, peek_char1, 0) /** @pred peek_char(- _C_) is iso @@ -5280,6 +5436,8 @@ leaving the current stream position unaltered. */ +static +PRED_IMPL("peek_char", 1, peek_char1, 0) { PRED_LD return peek(0, A1, PL_CHAR PASS_LD); } @@ -5500,18 +5658,30 @@ copy_stream_data(term_t in, term_t out, term_t len ARG_LD) return streamStatus(i); } +/** @pred copy_stream_data( +_Source_, +_Output_, +_Len_) + * + * Copy at most _Len_ characters from stream _Source_ to stream _Output_. + */ static PRED_IMPL("copy_stream_data", 3, copy_stream_data3, 0) { PRED_LD return copy_stream_data(A1, A2, A3 PASS_LD); } +/** @pred copy_stream_data( +_Source_, +_Output_) + * + * Copy all the data left in _Source_ to stream _Output_. + */ static PRED_IMPL("copy_stream_data", 2, copy_stream_data2, 0) { PRED_LD return copy_stream_data(A1, A2, 0 PASS_LD); } +/** + * @} + */ + /******************************* * PUBLISH PREDICATES * @@ -5544,22 +5714,7 @@ BeginPredDefs(file) PRED_DEF("put_code", 2, put_code2, PL_FA_ISO) PRED_DEF("put_code", 1, put_code1, PL_FA_ISO) PRED_DEF("put_char", 2, put_code2, PL_FA_ISO) -/** @pred put_char(+ _S_,+ _A_) is iso - -As `put_char(A)`, but to text stream _S_. - - -*/ PRED_DEF("put_char", 1, put_code1, PL_FA_ISO) -/** @pred put_char(+ _N_) is iso - - -Outputs to the current output stream the character who is used to build -the representation of atom `A`. The current output stream must be a -text stream. - - -*/ PRED_DEF("flush_output", 0, flush_output, PL_FA_ISO) PRED_DEF("flush_output", 1, flush_output1, PL_FA_ISO) PRED_DEF("at_end_of_stream", 1, at_end_of_stream, PL_FA_ISO) @@ -5583,23 +5738,7 @@ text stream. PRED_DEF("get", 1, get1, 0) PRED_DEF("get", 2, get2, 0) PRED_DEF("get0", 2, get_code2, 0) -/** @pred get0(+ _S_,- _C_) - -The same as `get0(C)`, but from stream _S_. - - -*/ PRED_DEF("get0", 1, get_code1, 0) -/** @pred get0(- _C_) - - -The next character from the current input stream is consumed, and then -unified with _C_. There are no restrictions on the possible -values of the ASCII code for the character, but the character will be -internally converted by YAP. - - -*/ PRED_DEF("ttyflush", 0, ttyflush, 0) PRED_DEF("prompt", 2, prompt, 0) PRED_DEF("tab", 2, tab2, 0) @@ -5722,148 +5861,19 @@ pl_sleep(term_t time) static const PL_extension foreigns[] = { FRG("nl", 0, pl_nl, ISO), -/** @pred nl is iso - - -Outputs a new line to the current output stream. - - - - - */ FRG("write_canonical", 1, pl_write_canonical, ISO), -/** @pred write_canonical(+ _T_) is iso - - -Displays term _T_ on the current output stream. Atoms are quoted -when necessary, and operators are ignored, that is, the term is written -in standard parenthesized prefix notation. - - -*/ FRG("write_term", 2, pl_write_term, ISO), -/** @pred write_term(+ _T_, + _Opts_) is iso - - -Displays term _T_ on the current output stream, according to the -following options: - -+ quoted(+ _Bool_) is iso -If `true`, quote atoms if this would be necessary for the atom to -be recognized as an atom by YAP's parser. The default value is -`false`. - -+ ignore_ops(+ _Bool_) is iso -If `true`, ignore operator declarations when writing the term. The -default value is `false`. - -+ numbervars(+ _Bool_) is iso -If `true`, output terms of the form -`$VAR(N)`, where _N_ is an integer, as a sequence of capital -letters. The default value is `false`. - -+ portrayed(+ _Bool_) -If `true`, use portray/1 to portray bound terms. The default -value is `false`. - -+ portray(+ _Bool_) -If `true`, use portray/1 to portray bound terms. The default -value is `false`. - -+ max_depth(+ _Depth_) -If `Depth` is a positive integer, use Depth as -the maximum depth to portray a term. The default is `0`, that is, -unlimited depth. - -+ priority(+ _Piority_) -If `Priority` is a positive integer smaller than `1200`, -give the context priority. The default is `1200`. - -+ cycles(+ _Bool_) -Do not loop in rational trees (default). - - - -*/ FRG("write_term", 3, pl_write_term3, ISO), -/** @pred write_term(+ _S_, + _T_, + _Opts_) is iso - -Displays term _T_ on the current output stream, according to the same -options used by `write_term/3`. - - -*/ FRG("write", 1, pl_write, ISO), -/** @pred write( _T_) is iso - - -The term _T_ is written to the current output stream according to -the operator declarations in force. - - -*/ FRG("writeq", 1, pl_writeq, ISO), -/** @pred writeq( _T_) is iso - - -Writes the term _T_, quoting names to make the result acceptable to -the predicate `read` whenever necessary. - - -*/ FRG("print", 1, pl_print, 0), -/** @pred print( _T_) - - -Prints the term _T_ to the current output stream using write/1 -unless T is bound and a call to the user-defined predicate -`portray/1` succeeds. To do pretty printing of terms the user should -define suitable clauses for `portray/1` and use print/1. - - -*/ FRG("nl", 1, pl_nl1, ISO), -/** @pred nl(+ _S_) is iso - -Outputs a new line to stream _S_. - - - - - */ FRG("format", 2, pl_format, META), FRG("write", 2, pl_write2, ISO), -/** @pred write(+ _S_, _T_) is iso - -Writes term _T_ to stream _S_ instead of to the current output -stream. - - -*/ FRG("writeq", 2, pl_writeq2, ISO), -/** @pred writeq(+ _S_, _T_) is iso - -As writeq/1, but the output is sent to the stream _S_. - - -*/ FRG("print", 2, pl_print2, 0), -/** @pred print(+ _S_, _T_) - -Prints term _T_ to the stream _S_ instead of to the current output -stream. - - -*/ FRG("write_canonical", 2, pl_write_canonical2, ISO), -/** @pred write_canonical(+ _S_,+ _T_) is iso - -Displays term _T_ on the stream _S_. Atoms are quoted when -necessary, and operators are ignored. - - -*/ FRG("format", 3, pl_format3, META), FRG("sleep", 1, pl_sleep, 0), FRG("get_time", 1, pl_get_time, 0), diff --git a/os/pl-fmt.c b/os/pl-fmt.c index db42c80ca..dc50a4388 100644 --- a/os/pl-fmt.c +++ b/os/pl-fmt.c @@ -21,6 +21,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/** + * @defgroup YAP_Format Formatted Output + * @ingroup YAP_InputOutput + * @{ + */ + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Formatted output (Prolog predicates format/[1,2,3]). One day, the C source should also use format() to produce error messages, etc. @@ -326,6 +332,12 @@ format_impl(IOSTREAM *out, term_t format, term_t Args, Module m) } +/** @pred format(+ _S_,+ _T_,+ _L_) + +Print formatted output to stream _S_. + + +*/ word pl_format3(term_t out, term_t format, term_t args) { GET_LD @@ -347,7 +359,210 @@ pl_format3(term_t out, term_t format, term_t args) return rc; } +/** @pred format(+ _T_,+ _L_) + +Print formatted output to the current output stream. The arguments in +list _L_ are output according to the string or atom _T_. + +A control sequence is introduced by a `w`. The following control +sequences are available in YAP: + + + ++ `~~` +Print a single tilde. + ++ `~a` +The next argument must be an atom, that will be printed as if by `write`. + ++ `~Nc` +The next argument must be an integer, that will be printed as a +character code. The number _N_ is the number of times to print the +character (default 1). + ++ `~Ne` ++ `~NE` ++ `~Nf` ++ `~Ng` ++ `~NG` +The next argument must be a floating point number. The float _F_, the number + _N_ and the control code `c` will be passed to `printf` as: + +~~~~~{.prolog} + printf("%s.Nc", F) +~~~~~ + +As an example: + +~~~~~{.prolog} +?- format("~8e, ~8E, ~8f, ~8g, ~8G~w", + [3.14,3.14,3.14,3.14,3.14,3.14]). +3.140000e+00, 3.140000E+00, 3.140000, 3.14, 3.143.14 +~~~~~ + ++ `~Nd` +The next argument must be an integer, and _N_ is the number of digits +after the decimal point. If _N_ is `0` no decimal points will be +printed. The default is _N = 0_. + +~~~~~{.prolog} +?- format("~2d, ~d",[15000, 15000]). +150.00, 15000 +~~~~~ + ++ `~ND` +Identical to `~Nd`, except that commas are used to separate groups +of three digits. + +~~~~~{.prolog} +?- format("~2D, ~D",[150000, 150000]). +1,500.00, 150,000 +~~~~~ + ++ `~i` +Ignore the next argument in the list of arguments: + +~~~~~{.prolog} +?- format('The ~i met the boregrove',[mimsy]). +The met the boregrove +~~~~~ + ++ `~k` +Print the next argument with `write_canonical`: + +~~~~~{.prolog} +?- format("Good night ~k",a+[1,2]). +Good night +(a,[1,2]) +~~~~~ + ++ `~Nn` +Print _N_ newlines (where _N_ defaults to 1). + ++ `~NN` +Print _N_ newlines if at the beginning of the line (where _N_ +defaults to 1). + ++ `~Nr` +The next argument must be an integer, and _N_ is interpreted as a +radix, such that `2 <= N <= 36` (the default is 8). + +~~~~~{.prolog} +?- format("~2r, 0x~16r, ~r", + [150000, 150000, 150000]). +100100100111110000, 0x249f0, 444760 +~~~~~ + +Note that the letters `a-z` denote digits larger than 9. + ++ `~NR` +Similar to `~NR`. The next argument must be an integer, and _N_ is +interpreted as a radix, such that `2 <= N <= 36` (the default is 8). + +~~~~~{.prolog} +?- format("~2r, 0x~16r, ~r", + [150000, 150000, 150000]). +100100100111110000, 0x249F0, 444760 +~~~~~ + +The only difference is that letters `A-Z` denote digits larger than 9. + ++ `~p` +Print the next argument with print/1: + +~~~~~{.prolog} +?- format("Good night ~p",a+[1,2]). +Good night a+[1,2] +~~~~~ + ++ `~q` +Print the next argument with writeq/1: + +~~~~~{.prolog} +?- format("Good night ~q",'Hello'+[1,2]). +Good night 'Hello'+[1,2] +~~~~~ + ++ `~Ns` +The next argument must be a list of character codes. The system then +outputs their representation as a string, where _N_ is the maximum +number of characters for the string ( _N_ defaults to the length of the +string). + +~~~~~{.prolog} +?- format("The ~s are ~4s",["woods","lovely"]). +The woods are love +~~~~~ + ++ `~w` +Print the next argument with write/1: + +~~~~~ +?- format("Good night ~w",'Hello'+[1,2]). +Good night Hello+[1,2] +~~~~~ + + +The number of arguments, `N`, may be given as an integer, or it +may be given as an extra argument. The next example shows a small +procedure to write a variable number of `a` characters: + +~~~~~ +write_many_as(N) :- + format("~*c",[N,0'a]). +~~~~~ + +The format/2 built-in also allows for formatted output. One can +specify column boundaries and fill the intermediate space by a padding +character: + ++ `~N|` +Set a column boundary at position _N_, where _N_ defaults to the +current position. + ++ `~N+` +Set a column boundary at _N_ characters past the current position, where + _N_ defaults to `8`. + ++ `~Nt` +Set padding for a column, where _N_ is the fill code (default is +`SPC`). + + + +The next example shows how to align columns and padding. We first show +left-alignment: + +~~~~~ + ?- format("~n*Hello~16+*~n",[]). +*Hello * +~~~~~ + +Note that we reserve 16 characters for the column. + +The following example shows how to do right-alignment: + +~~~~~ + ?- format("*~tHello~16+*~n",[]). +* Hello* + +~~~~~ + +The `~t` escape sequence forces filling before `Hello`. + +We next show how to do centering: + +~~~~~ + ?- format("*~tHello~t~16+*~n",[]). +* Hello * +~~~~~ + +The two `~t` escape sequence force filling both before and after +`Hello`. Space is then evenly divided between the right and the +left sides. + + +*/ word pl_format(term_t fmt, term_t args) { return pl_format3(0, fmt, args); @@ -1489,3 +1704,5 @@ formatFloat(PL_locale *locale, int how, int arg, Number f, Buffer out) return baseBuffer(out, char); } + +//! @} diff --git a/os/pl-locale.c b/os/pl-locale.c index 85b576dd1..469acb745 100644 --- a/os/pl-locale.c +++ b/os/pl-locale.c @@ -20,6 +20,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/** @defgroup SetLocale Localization Support + * @ingroup YAP_InputOutput + * @{ + * + * This code includes support for localization, that is, the ability to support + * different languages and representation formats. + * + * The code was written by Jan Wielemaker for SWI-Prolog. + */ #include "pl-incl.h" #include "pl-locale.h" @@ -475,7 +484,7 @@ get_atom_arg(term_t t, atom_t *a) /** locale_property(?Locale, ?Property) is nondet. */ - +/// @memberof locale_property/2 static PRED_IMPL("locale_property", 2, locale_property, PL_FA_NONDETERMINISTIC) { PRED_LD @@ -681,7 +690,7 @@ set_grouping(term_t t, char **valp) /** locale_create(-Locale, +Default, +Options) is det. */ - +/// @memberof locale_create/3 static PRED_IMPL("locale_create", 3, locale_create, 0) { PRED_LD @@ -760,6 +769,9 @@ PRED_IMPL("locale_create", 3, locale_create, 0) } +/** locale_destroy(+Locale) is det. +*/ +/// @memberof locale_destroy/1 static PRED_IMPL("locale_destroy", 1, locale_destroy, 0) { PL_locale *l; @@ -787,7 +799,7 @@ PRED_IMPL("locale_destroy", 1, locale_destroy, 0) /** set_locale(+Locale) is det. */ - +/// @memberof set_locale/1 static PRED_IMPL("set_locale", 1, set_locale, 0) { PRED_LD @@ -820,7 +832,7 @@ PRED_IMPL("set_locale", 1, set_locale, 0) /** current_locale(-Locale) is det. */ - +/// @memberof current_locale/1 static PRED_IMPL("current_locale", 1, current_locale, 0) { PRED_LD @@ -927,3 +939,5 @@ BeginPredDefs(locale) EndPredDefs #endif /*O_LOCALE*/ + +/// @} diff --git a/os/pl-write.c b/os/pl-write.c index cdf9b3726..79e401db9 100644 --- a/os/pl-write.c +++ b/os/pl-write.c @@ -23,6 +23,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/** @defgroup YAPWrite Outputting a term to a Stream + * @ingroup YAP_InputOutput + * + * @brief Predicates that output a term to a stream. The predicates + * call upon write_term/3 to do the actual work. They differ on the + * parameters being used + * whether they write to user_output or to an user-specified stream. + * + * @{ + */ #include #include "pl-incl.h" #include "pl-dtoa.h" @@ -67,6 +77,11 @@ typedef struct term_t prec_opt; /* term in write options with prec */ } write_options; +/** @pred nl(+ _S_) is iso + +Outputs a new line to stream _S_. + */ +/// @memberof nl/1 word pl_nl1(term_t stream) { GET_LD @@ -80,6 +95,12 @@ pl_nl1(term_t stream) fail; } +/** @pred nl is iso + +Outputs a new line to the current output stream. + + */ +/// @memberof nl/0 word pl_nl(void) { return pl_nl1(0); @@ -517,13 +538,69 @@ out: return (!s || streamStatus(s)) && rc; } +/** @pred write_term(+ _S_, + _T_, + _Opts_) is iso +Displays term _T_ on the current output stream, according to the same +options used by `write_term/3`. + + +*/ +/// @memberof write_term/3 word pl_write_term(term_t term, term_t options) { return pl_write_term3(0, term, options); } +/** @pred write_term(+ _T_, + _Opts_) is iso + +Displays term _T_ on the current output stream, according to the +following options: + ++ quoted(+ _Bool_) is iso + + If `true`, quote atoms if this would be necessary for the atom to +be recognized as an atom by YAP's parser. The default value is +`false`. + ++ ignore_ops(+ _Bool_) is iso + + If `true`, ignore operator declarations when writing the term. The +default value is `false`. + ++ numbervars(+ _Bool_) is iso + + If `true`, output terms of the form +`$VAR(N)`, where _N_ is an integer, as a sequence of capital +letters. The default value is `false`. + ++ portrayed(+ _Bool_) + + If `true`, use portray/1 to portray bound terms. The default +value is `false`. + ++ portray(+ _Bool_) + + If `true`, use portray/1 to portray bound terms. The default +value is `false`. + ++ max_depth(+ _Depth_) + + If `Depth` is a positive integer, use Depth as +the maximum depth to portray a term. The default is `0`, that is, +unlimited depth. + ++ priority(+ _Piority_) + + If `Priority` is a positive integer smaller than `1200`, +give the context priority. The default is `1200`. + ++ cycles(+ _Bool_) + + Do not loop in rational trees (default). + +*/ +/// @memberof write_term/2 int PL_write_term(IOSTREAM *s, term_t term, int precedence, int flags) { write_options options; @@ -572,22 +649,53 @@ do_write2(term_t stream, term_t term, int flags) } +/** @pred write(+ _S_, _T_) is iso + +Writes term _T_ to stream _S_ instead of to the current output +stream. + + +*/ +/// @memberof write/2 word pl_write2(term_t stream, term_t term) { return do_write2(stream, term, PL_WRT_NUMBERVARS); } +/** @pred writeq(+ _S_, _T_) is iso + +As writeq/1, but the output is sent to the stream _S_. + + +*/ +/// @memberof writeq/2 word pl_writeq2(term_t stream, term_t term) { return do_write2(stream, term, PL_WRT_QUOTED|PL_WRT_NUMBERVARS); } +/** @pred print(+ _S_, _T_) + +Prints term _T_ to the stream _S_ instead of to the current output +stream. + + +*/ +/// @memberof print/2 word pl_print2(term_t stream, term_t term) { return do_write2(stream, term, PL_WRT_PORTRAY|PL_WRT_NUMBERVARS); } +/** @pred write_canonical(+ _S_,+ _T_) is iso + +Displays term _T_ on the stream _S_. Atoms are quoted when +necessary, and operators are ignored. + + +*/ +/// @memberof write_canonical/2 word pl_write_canonical2(term_t stream, term_t term) { GET_LD @@ -611,26 +719,69 @@ pl_write_canonical2(term_t stream, term_t term) return rc; } +/** @pred write( _T_) is iso + + +The term _T_ is written to the current output stream according to +the operator declarations in force. +*/ +/// @memberof write/1 word pl_write(term_t term) { return pl_write2(0, term); } word +/** @pred writeq( _T_) is iso + +Writes the term _T_, quoting names to make the result acceptable to +the predicate `read` whenever necessary. +*/ +/// @memberof writeq/1 pl_writeq(term_t term) { return pl_writeq2(0, term); } +/** @pred print( _T_) + + +Prints the term _T_ to the current output stream using write/1 +unless T is bound and a call to the user-defined predicate +`portray/1` succeeds. To do pretty printing of terms the user should +define suitable clauses for `portray/1` and use print/1. + + +*/ +/// @memberof print/1 word pl_print(term_t term) { return pl_print2(0, term); } +/** @pred write_canonical(+ _T_) is iso + + +Displays term _T_ on the current output stream. Atoms are quoted +when necessary, and operators are ignored, that is, the term is written +in standard parenthesized prefix notation. + + +*/ +/// @memberof write_canonical/1 word pl_write_canonical(term_t term) { return pl_write_canonical2(0, term); } +/** @pred writeln( _T_) + + +Prints the term _T_ to the current output stream using write/1, +followed by a newline. + + +*/ +/// @memberof writeln/1 word pl_writeln(term_t term) { return do_write2(0, term, PL_WRT_NUMBERVARS|PL_WRT_NEWLINE); @@ -641,7 +792,9 @@ pl_writeln(term_t term) /******************************* * PUBLISH PREDICATES * *******************************/ +/// @} BeginPredDefs(write) EndPredDefs + diff --git a/packages/CLPBN/pfl.yap b/packages/CLPBN/pfl.yap index 569faa460..12f69c48b 100644 --- a/packages/CLPBN/pfl.yap +++ b/packages/CLPBN/pfl.yap @@ -21,6 +21,332 @@ add_ground_factor/5 %add a new bayesian variable (for now) ]). +/** @defgroup PFL The PrologFactor Language +@ingroup YAPPackagaes + +section{Introduction} +The Prolog Factor Language (PFL) is a language that extends Prolog for providing a syntax to describe first-order probabilistic graphical models. These models can be either directed (bayesian networks) or undirected (markov networks). This language replaces the old one known as CLP(BN). + +The package also includes implementations for a set of well-known inference algorithms for solving probabilistic queries on these models. Both ground and lifted inference methods are support. + +### Installation +PFL is included with the YAP Prolog system. The commands to perform a default installation of YAP in your home directory in a Unix-based environment are shown next. + +1 `$ cd $HOME` +2 `$ git clone git://yap.git.sourceforge.net/gitroot/yap/yap-6.3` +3 `$ cd yap-6.3/` +4 `$ ./configure --enable-clpbn-bp --prefix=$HOME` +5 `$ make depend \& make install` + +In case you want to install YAP somewhere else or with different settings, please consult the YAP documentation. From now on, we will assume that the directory `$HOME/bin` (where the binary is) is in your `$PATH` environment variable. + +Once in a while, we will refer to the PFL examples directory. In a default installation, this directory will be located at `$HOME/share/doc/Yap/packages/examples/CLPBN`. + + + +### Language +A first-order probabilistic graphical model is described using parametric factors, commonly known as parfactors. The PFL syntax for a parfactor is + +_Type F; Phi ; C._ + +Where, ++ _Type_ refers the type of network over which the parfactor is defined. It can be `bayes` for directed networks, or `markov` for undirected ones. + ++ _F_ is a comma-separated sequence of Prolog terms that will define sets of random variables under the constraint _C_. If _Type_ is `bayes`, the first term defines the node while the remaining terms define its parents. + ++ _Phi_ is either a Prolog list of potential values or a Prolog goal that unifies with one. Notice that if _Type_ is `bayes`, this will correspond to the conditional probability table. Domain combinations are implicitly assumed in ascending order, with the first term being the 'most significant' (e.g. _\mathtt{x_0y_0}_, _\mathtt{x_0y_1}_, _\mathtt{x_0y_2}_, _\mathtt{x_1y_0}_, _\mathtt{x_1y_1}_, _\mathtt{x_1y_2}_). + ++ _C_ is a (possibly empty) list of Prolog goals that will instantiate the logical variables that appear in _F_, that is, the successful substitutions for the goals in _C_ will be the valid values for the logical variables. This allows the constraint to be defined as any relation (set of tuples) over the logical variables. + +~~~~ +:- use_module(library(pfl)). + +bayes cloudy ; cloudy_table ; []. + +bayes sprinkler, cloudy ; sprinkler_table ; []. + +bayes rain, cloudy ; rain_table ; []. + +bayes wet_grass, sprinkler, rain ; wet_grass_table ; []. + +cloudy_table( + [ 0.5, + 0.5 ]). + +sprinkler_table( + [ 0.1, 0.5, + 0.9, 0.5 ]). + +rain_table( + [ 0.8, 0.2, + 0.2, 0.8 ]). + +wet_grass_table( + [ 0.99, 0.9, 0.9, 0.0, + 0.01, 0.1, 0.1, 1.0 ]). +~~~~ + +In the example, we started by loading the PFL library, then we have defined one factor for each node, and finally we have specified the probabilities for each conditional probability table. + +Notice that this network is fully grounded, as all constraints are empty. Next we present the PFL representation for a well-known markov logic network - the social network model. For convenience, the two main weighted formulas of this model are shown below. + +~~~~ +1.5 : Smokes(x) => Cancer(x) +1.1 : Smokes(x) ^ Friends(x,y) => Smokes(y) +~~~~ + +Next, we show the PFL representation for this model. + +~~~~ +:- use_module(library(pfl)). + +person(anna). +person(bob). + +markov smokes(X), cancer(X) ; + [4.482, 4.482, 1.0, 4.482] ; + [person(X)]. + +markov friends(X,Y), smokes(X), smokes(Y) ; + [3.004, 3.004, 3.004, 3.004, 3.004, 1.0, 1.0, 3.004] ; + [person(X), person(Y)]. + +%markov smokes(X) ; [1.0, 4.055]; [person(X)]. +%markov cancer(X) ; [1.0, 9.974]; [person(X)]. +%markov friends(X,Y) ; [1.0, 99.484] ; [person(X), person(Y)]. +~~~~ + +Notice that we have defined the world to be consisted of only two persons, `anna` and `bob`. We can easily add as many persons as we want by inserting in the program a fact like `person @ 10.`~. This would automatically create ten persons named `p1`, `p2`, \dots, `p10`. + +Unlike other fist-order probabilistic languages, in PFL the logical variables that appear in the terms are not directly typed, and they will be only constrained by the goals that appears in the constraint of the parfactor. This allows the logical variables to be constrained to any relation (set of tuples), and not only pairwise (in)equalities. For instance, the next example defines a network with three ground factors, each defined respectively over the random variables `p(a,b)`, `p(b,d)` and `p(d,e)`. + +~~~~ +constraint(a,b). +constraint(b,d). +constraint(d,e). + +markov p(A,B); some_table; [constraint(A,B)]. +~~~~ + +We can easily add static evidence to PFL programs by inserting a fact with the same functor and arguments as the random variable, plus one extra argument with the observed state or value. For instance, suppose that we know that `anna` and `bob` are friends. We can add this knowledge to the program with the following fact: `friends(anna,bob,t).`~. + +One last note for the domain of the random variables. By default, all terms instantiate boolean (`t`/`f`) random variables. It is possible to choose a different domain for a term by appending a list of its possible values or states. Next we present a self-explanatory example of how this can be done. + +~~~~ +bayes professor_ability::[high, medium, low] ; [0.5, 0.4, 0.1]. +~~~~ + +More probabilistic models defined using PFL can be found in the examples directory. + + + +### Querying +In this section we demonstrate how to use PFL to solve probabilistic queries. We will use the sprinkler network as example. + +Assuming that the current directory is the one where the examples are located, first we load the model with the following command. + +`$ yap -l sprinkler.pfl` + +Let's suppose that we want to estimate the marginal probability for the $WetGrass$ random variable. To do so, we call the following goal. + +`?- wet\_grass(X).` + +The output of this goal will show the marginal probability for each $WetGrass$ possible state or value, that is, `t` and `f`. Notice that in PFL a random variable is identified by a term with the same functor and arguments plus one extra argument. + +Now let's suppose that we want to estimate the probability for the same random variable, but this time we have evidence that it had rained in the day before. We can estimate this probability without resorting to static evidence with: + +`?- wet\_grass(X), rain(t).` + +PFL also supports calculating joint probability distributions. For instance, we can obtain the joint probability for $Sprinkler$ and $Rain$ with: + +`?- sprinkler(X), rain(Y).` + + + +%------------------------------------------------------------------------------ +%------------------------------------------------------------------------------ +%------------------------------------------------------------------------------ +%------------------------------------------------------------------------------ +### Options +PFL supports both ground and lifted inference methods. The inference algorithm can be chosen by calling `set\_solver/1`. The following are supported: ++ `ve`, variable elimination (written in Prolog) ++ `hve`, variable elimination (written in C++) ++ `jt`, junction tree ++ `bdd`, binary decision diagrams ++ `bp`, belief propagation ++ `cbp`, counting belief propagation ++ `gibbs`, gibbs sampling ++ `lve`, generalized counting first-order variable elimination (GC-FOVE) ++ `lkc`, lifted first-order knowledge compilation ++ `lbp`, lifted first-order belief propagation + +For instance, if we want to use belief propagation to solve some probabilistic query, we need to call first: + +`?- set\_solver(bp).` + +It is possible to tweak some parameters of PFL through `set\_pfl\_flag/2` predicate. The first argument is a option name that identifies the parameter that we want to tweak. The second argument is some possible value for this option. Next we explain the available options in detail. + +\optionsection{verbosity} +This option controls the level of debugging information that will be shown. + ++ Values: a positive integer (default is 0 - no debugging). The higher the number, the more information that will be shown. ++ Affects: `hve`, `bp`, `cbp`, `lve`, `lkc` and `lbp`. + +For instance, we can view some basic debugging information by calling the following goal. + +`?- set\_pfl\_flag(verbosity, 1).` + + +\optionsection{use\_logarithms} +This option controls whether the calculations performed during inference should be done in a logarithm domain or not. ++ Values: `true` (default) or `false`. ++ Affects: `hve`, `bp`, `cbp`, `lve`, `lkc` and `lbp`. + + +\optionsection{hve\_elim\_heuristic} +This option allows to choose which elimination heuristic will be used by the `hve`. ++ Values: `sequential`, `min\_neighbors`, `min\_weight`, `min\_fill` and\\ `weighted\_min\_fill` (default). ++ Affects: `hve`. + +An explanation for each of these heuristics can be found in Daphne Koller's book \textit{Probabilistic Graphical Models}. + + +\optionsection{bp\_max\_iter} +This option establishes a maximum number of iterations. One iteration consists in sending all possible messages. + ++ Values: a positive integer (default is `1000`). ++ Affects: `bp`, `cbp` and `lbp`. + + +\optionsection{bp\_accuracy} +This option allows to control when the message passing should cease. Be the residual of one message the difference (according some metric) between the one sent in the current iteration and the one sent in the previous. If the highest residual is lesser than the given value, the message passing is stopped and the probabilities are calculated using the last messages that were sent. + ++ Values: a float-point number (default is `0.0001`). ++ Affects: `bp`, `cbp` and `lbp`. + + ++ bp\_msg\_schedule +This option allows to control the message sending order. ++ Values: + + `seq\_fixed` (default), at each iteration, all messages are sent with the same order. + + + `seq\_random`, at each iteration, all messages are sent with a random order. + + + `parallel`, at each iteration, all messages are calculated using only the values of the previous iteration. + + + `max\_residual`, the next message to be sent is the one with maximum residual (as explained in the paper \textit{Residual Belief Propagation: Informed Scheduling for Asynchronous Message Passing}). + + + Affects: `bp`, `cbp` and `lbp`. + + ++ export\_libdai +This option allows exporting the current model to the libDAI, http://cs.ru.nl/~jorism/libDAI/doc/fileformats.html, file format. + + Values: `true` or `false` (default). + + Affects: `hve`, `bp`, and `cbp`. + + ++ export\_uai +This option allows exporting the current model to the \href{http://graphmod.ics.uci.edu/uai08/FileFormat}{UAI08} file format. + + Values: `true` or `false` (default). + + Affects: `hve`, `bp`, and `cbp`. + + ++ export\_graphviz +This option allows exporting the factor graph's structure into a format that can be parsed by \href{http://www.graphviz.org/}{Graphviz}. + + Values: `true` or `false` (default). + + Affects: `hve`, `bp`, and `cbp`. + ++ print\_fg +This option allows to print a textual representation of the factor graph. + + Values: `true` or `false` (default). + + Affects: `hve`, `bp`, and `cbp`. + + + +### Learning +PFL is capable to learn the parameters for bayesian networks, through an implementation of the expectation-maximization algorithm. + +Next we show an example of parameter learning for the sprinkler network. + +~~~~ +:- [sprinkler.pfl]. + +:- use_module(library(clpbn/learning/em)). + +data(t, t, t, t). +data(_, t, _, t). +data(t, t, f, f). +data(t, t, f, t). +data(t, _, _, t). +data(t, f, t, t). +data(t, t, f, t). +data(t, _, f, f). +data(t, t, f, f). +data(f, f, t, t). + +main :- + findall(X, scan_data(X), L), + em(L, 0.01, 10, CPTs, LogLik), + writeln(LogLik:CPTs). + +scan_data([cloudy(C), sprinkler(S), rain(R), wet_grass(W)]) :- + data(C, S, R, W). +~~~~ + +Parameter learning is done by calling the `em/5` predicate. Its arguments are the following. + +\begin{center} +`em(+Data, +MaxError, +MaxIters, -CPTs, -LogLik)` +\end{center} + +Where, ++ `Data` is a list of samples for the distribution that we want to estimate. Each sample is a list of either observed random variables or unobserved random variables (denoted when its state or value is not instantiated). ++ `MaxError` is the maximum error allowed before stopping the EM loop. ++ `MaxIters` is the maximum number of iterations for the EM loop. ++ `CPTs` is a list with the estimated conditional probability tables. ++ `LogLik` is the log-likelihood. + + +It is possible to choose the solver that will be used for the inference part during parameter learning with the `set\_em\_solver/1` predicate (defaults to `hve`). At the moment, only the following solvers support parameter learning: `ve`, `hve`, `bdd`, `bp` and `cbp`. + +Inside the `learning` directory from the examples directory, one can find more examples of parameter learning. + + + +### External Interface +This package also includes an external command for perform inference over probabilistic graphical models described in formats other than PFL. Currently two are support, the \href{http://cs.ru.nl/~jorism/libDAI/doc/fileformats.html}{libDAI file format}, and the \href{http://graphmod.ics.uci.edu/uai08/FileFormat}{UAI08 file format}. + +This command's name is `hcli` and its usage is as follows. + +~~~ + $ ./hcli [solver=hve|bp|cbp] [