From 137f69ed22ebe56faa2085dea286d9d604435b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 21 Apr 2014 11:14:18 +0100 Subject: [PATCH 1/4] doc support --- C/arith0.c | 93 ++++++- C/arith1.c | 211 +++++++++++++++- C/arith2.c | 109 ++++++++- C/cmppreds.c | 75 ++++++ C/eval.c | 83 ++++++- H/eval.h | 79 ++++++ Makefile.in | 1 + docs/builtins.tex | 128 ++++++---- docs/doxygen.rc | 34 ++- docs/load.tex | 19 +- docs/swi.tex | 94 ++++--- docs/{conv => }/texi2doxy | 157 ++++++++---- docs/yap.tex | 504 ++++++++++++++++++++------------------ packages/raptor | 2 +- packages/zlib | 2 +- pl/absf.yap | 240 ++++++++++-------- pl/arith.yap | 121 --------- pl/arithpreds.yap | 170 +++++++++++++ pl/init.yap | 1 + 19 files changed, 1476 insertions(+), 647 deletions(-) rename docs/{conv => }/texi2doxy (86%) create mode 100644 pl/arithpreds.yap diff --git a/C/arith0.c b/C/arith0.c index 3beb40cf0..3ce6122cb 100644 --- a/C/arith0.c +++ b/C/arith0.c @@ -18,8 +18,72 @@ static char SccsId[] = "%W% %G%"; #endif -/* - * This file implements arithmetic operations +/** + @file arith0.c + + @defgroup arithmetic_operators Arithmetic Functions + @ingroup arithmetic + + YAP implements several arithmetic functions. Arithmetic expressions + in YAP may use the following operators: + + - pi [ISO]

@anchor pi_0 + + An approximation to the value of pi, that is, the ratio of a circle's circumference to its diameter. + + - e

@anchor e_0 + + Euler's number, the base of the natural logarithms. + + - epsilon

@anchor epsilon_0 + + The difference between the float `1.0` and the next largest floating point number. + + - inf

@anchor inf_0 + + Infinity according to the IEEE Floating-Point standard. Note that evaluating this term will generate a domain error in the `iso` language mode. + + Note also that YAP supports `+inf` and `-inf` + + - nan (not a number)

@anchor nan_0 + + Not-a-number according to the IEEE Floating-Point standard. Note that evaluating this term will generate a domain error in the `iso` language mode. + + - random

@anchor random_0 + + A "random" floating point number between 0 and 1. + + - cputime

@anchor cputime_0 + + CPU time since YAP was invoked, in seconds. + + - heapused

@anchor heapused_0 + + Heap (data-base) space used, in bytes. + + - local

@anchor local_0 + + Local stack in use, in bytes + + - $b

@anchor b_0 + + current choicepoint + + - $env

@anchor env_0 + + Environment + + - $tr

@anchor tr_0 + + Trail in use + + - $free_stack

@anchor free_stack_0 + + Amount of free stack space, that is, free space between global and local stacks. + + - global

@anchor global_0 + + Global stack in use, in bytes. * */ @@ -89,7 +153,7 @@ eval0(Int fi) { } case op_nan: { -#ifdef _MSC_VER /* Microsoft's Visual C++ Compiler */ +#ifdef _MSC_VER /* Microsoft's Visual C++ Compiexp( _X_) [ISO]

@anchor exp_1 + + Natural exponential. + + - log( _X_) [ISO]

@anchor log_1 + + Natural logarithm. + + - log10( _X_)

@anchor log10_1 + + Decimal logarithm. + + - sqrt( _X_) [ISO]

@anchor sqrt_1 + + Square root. + + - sin( _X_) [ISO]

@anchor sin_1 + + Sine. + + - cos( _X_) [ISO]

@anchor cos_1 + + Cosine. + + - tan( _X_) [ISO]

@anchor tan_1 + + Tangent. + + - asin( _X_) [ISO]

@anchor asin_1 + + Arc sine. + + - acos( _X_) [ISO]

@anchor acos_1 + + Arc cosine. + + - atan( _X_) [ISO]

@anchor atan_1 + + Arc tangent. + + - sinh( _X_)

@anchor sinh_1 + + Hyperbolic sine. + + - cosh( _X_)

@anchor cosh_1 + + Hyperbolic cosine. + + - tanh( _X_)

@anchor tanh_1 + + Hyperbolic tangent. + + - asinh( _X_)

@anchor asinh_1 + + Hyperbolic arc sine. + + - acosh( _X_)

@anchor acosh_1 + + Hyperbolic arc cosine. + + - atanh( _X_)

@anchor atanh_1 + + Hyperbolic arc tangent. + + - lgamma( _X_)

@anchor lgamma_1 + + Logarithm of gamma function. + + - erf( _X_)

@anchor erf_1 + + Gaussian error function. + + - erfc( _X_)

@anchor erfc_1 + + Complementary gaussian error function. + + - random( _X_) [ISO]

@anchor random_1_op + + An integer random number between 0 and _X_. + + In `iso` language mode the argument must be a floating + point-number, the result is an integer and it the float is equidistant + it is rounded up, that is, to the least integer greater than _X_. + + - integer( _X_)

@anchor integer_1_op + + If _X_ evaluates to a float, the integer between the value of _X_ and 0 closest to the value of _X_, else if _X_ evaluates to an + integer, the value of _X_. + + - float( _X_) [ISO]

@anchor float_1_op + + If _X_ evaluates to an integer, the corresponding float, else the float itself. + + - float_fractional_part( _X_) [ISO]

@anchor float_fractional_part_1 + + The fractional part of the floating point number _X_, or `0.0` if _X_ is an integer. In the `iso` language mode, _X_ must be an integer. + + - float_integer_part( _X_) [ISO]

@anchor float_integer_part_1 + + The float giving the integer part of the floating point number _X_, or _X_ if _X_ is an integer. In the `iso` language mode, _X_ must be an integer. + + - abs( _X_) [ISO]

@anchor abs_1 + + The absolute value of _X_. + + - ceiling( _X_) [ISO]

@anchor ceiling_1 + + The integer that is the smallest integral value not smaller than _X_. + + In `iso` language mode the argument must be a floating point-number and the result is an integer. + + - floor( _X_) [ISO]

@anchor floor_1 + + The integer that is the greatest integral value not greater than _X_. + + In `iso` language mode the argument must be a floating + point-number and the result is an integer. + + - round( _X_) [ISO]

@anchor round_1 + + The nearest integral value to _X_. If _X_ is equidistant to two integers, it will be rounded to the closest even integral value. + + In `iso` language mode the argument must be a floating point-number, the result is an integer and it the float is equidistant it is rounded up, that is, to the least integer greater than _X_. + + - sign( _X_) [ISO]

@anchor sign_1 + + Return 1 if the _X_ evaluates to a positive integer, 0 it if evaluates to 0, and -1 if it evaluates to a negative integer. If _X_ + evaluates to a floating-point number return 1.0 for a positive _X_, 0.0 for 0.0, and -1.0 otherwise. + + - truncate( _X_) [ISO]

@anchor truncate_1 + + The integral value between _X_ and 0 closest to _X_. + + - rational( _X_)

@anchor rational_1_op + + Convert the expression _X_ to a rational number or integer. The function returns the input on integers and rational numbers. For + floating point numbers, the returned rational number exactly represents + the float. As floats cannot exactly represent all decimal numbers the + results may be surprising. In the examples below, doubles can represent + `0.25` and the result is as expected, in contrast to the result of + `rational(0.1)`. The function `rationalize/1` gives a more + intuitive result. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~prolog +?- A is rational(0.25). + +A is 1 rdiv 4 +?- A is rational(0.1). +A = 3602879701896397 rdiv 36028797018963968 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + - rationalize( _X_)

@anchor rationalize_1 + + Convert the expression _X_ to a rational number or integer. The function is + similar to [rational/1](@ref rational_1), but the result is only accurate within the + rounding error of floating point numbers, generally producing a much + smaller denominator. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~prolog +?- A is rationalize(0.25). + +A = 1 rdiv 4 +?- A is rationalize(0.1). + +A = 1 rdiv 10 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + - \\ _X_ [ISO]

+ + Integer bitwise negation. + + - msb( _X_)

@anchor msb_1 + + The most significant bit of the non-negative integer _X_. + + - lsb( _X_)

@anchor lsb_1 + + The least significant bit of the non-negative integer _X_. + + - popcount( _X_)

@anchor popcount_1 + + The number of bits set to `1` in the binary representation of the non-negative integer _X_. + + - [ _X_]

+ + Evaluates to _X_ for expression _X_. Useful because character +strings in Prolog are lists of character codes. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.prolog} +X is Y*10+C-"0" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +is the same as + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.prolog} +X is Y*10+C-[48]. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +which would be evaluated as: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.prolog} +X is Y*10+C-48. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +*/ #include "Yap.h" #include "Yatom.h" @@ -694,6 +896,7 @@ eval1(Int fi, Term t USES_REGS) { RERROR(); } } + /// end of switch RERROR(); } diff --git a/C/arith2.c b/C/arith2.c index 08d8d075d..c5d76b4bc 100644 --- a/C/arith2.c +++ b/C/arith2.c @@ -18,10 +18,111 @@ static char SccsId[] = "%W% %G%"; #endif -/* - * This file implements unary arithmetic operations in YAP - * - */ +/** + + @file arith2.c + + @addtogroup arithmetic_operators + +These are the binary numeric operators currently supported by YAP. + + - _X_+ _Y_ [ISO]

+ + Sum. + + - _X_- _Y_ [ISO]

+ + Difference. + + - _X_\* _Y_ [ISO]

+ + Product. + + - _X_/ _Y_ [ISO]

+ + Quotient. + + - _X_// _Y_ [ISO]

+ + Integer quotient. + + - _X_ mod _Y_ [ISO]

@anchor mod_2 + + Integer module operator, always positive. + + - _X_ rem _Y_ [ISO]

@anchor rem_2 + + Integer remainder, similar to `mod` but always has the same sign as `X`. + + - _X_ div _Y_ [ISO]

@anchor div_2 + + Integer division, as if defined by `( _X_ - _X_ mod _Y_)// _Y_`. + + - max( _X_, _Y_) [ISO]

@anchor max_2 + + The greater value of _X_ and _Y_. + + - min( _X_, _Y_) [ISO]

@anchor min_2 + + The lesser value of _X_ and _Y_. + + - _X_ ^ _Y_ [ISO]

+ + _X_ raised to the power of _Y_, (from the C-Prolog syntax). + + - exp( _X_, _Y_)

@anchor exp_2 + + _X_ raised to the power of _Y_, (from the Quintus Prolog syntax). + + - _X_ \*\* _Y_ [ISO]

+ + _X_ raised to the power of _Y_ (from ISO). + + - _X_ /\\ _Y_ [ISO]

+ + Integer bitwise conjunction. + + - _X_ \\/ _Y_ [ISO]

+ + Integer bitwise disjunction. + + - _X_ # _Y_

+ + Integer bitwise exclusive disjunction. + + - _X_ \>\< _Y_

+ + Integer bitwise exclusive disjunction. + + - xor( _X_ , _Y_) [ISO]

@anchor xor_2 + + Integer bitwise exclusive disjunction. + + - _X_ \<\< _Y_

+ + Integer bitwise left logical shift of _X_ by _Y_ places. + + - _X_ \>\> _Y_ [ISO]

+ + Integer bitwise right logical shift of _X_ by _Y_ places. + + - gcd( _X_, _Y_)

@anchor gcd_2 + + The greatest common divisor of the two integers _X_ and _Y_. + + - atan( _X_, _Y_)

@anchor atan_2 + + Four-quadrant arc tangent. Also available as `atan2/2`. + + - atan2( _X_, _Y_) [ISO]

@anchor atan2_2 + + Four-quadrant arc tangent. + + - _X_ rdiv _Y_ [ISO]

@anchor rdiv_2 + + Rational division. + +*/ #include "Yap.h" #include "Yatom.h" diff --git a/C/cmppreds.c b/C/cmppreds.c index f48d87c44..0ead85144 100644 --- a/C/cmppreds.c +++ b/C/cmppreds.c @@ -14,6 +14,10 @@ * comments: comparing two prolog terms * * * *************************************************************************/ +/// @file cmppreds.c + + + #ifdef SCCS static char SccsId[] = "%W% %G%"; #endif @@ -647,6 +651,17 @@ 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) { @@ -667,6 +682,15 @@ p_acomp( USES_REGS1 ) return out; } +/** + @class arith_eq_2 + @brief =:=/2: 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_. + */ static Int a_eq(Term t1, Term t2) { @@ -701,6 +725,15 @@ 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 + + + The value of the expression _X_ is different from the value of expression _Y_. + */ static Int a_dif(Term t1, Term t2) { @@ -710,6 +743,16 @@ a_dif(Term t1, Term t2) return out != 0; } +/** + @class arith_gt_2 + @brief \>/2: Greater than arithmetic expressions + + + _X_ \> + _Y_ [ISO]

@anchor qQlg_2 + + + The value of the expression _X_ is less than or equal to the value + of expression _Y_. +*/ static Int a_gt(Term t1, Term t2) { /* A > B */ @@ -719,6 +762,16 @@ a_gt(Term t1, Term t2) return out > 0; } +/** + @class arith_ge_2 + @brief \>=/2: Greater than or equal to arithmetic expressions + + + _X_ \>= + _Y_ [ISO]

@anchor gGqQ_2 + + + The value of the expression _X_ is greater than or equal to the + value of expression _Y_. +*/ static Int a_ge(Term t1, Term t2) { /* A >= B */ @@ -728,6 +781,16 @@ a_ge(Term t1, Term t2) return out >= 0; } +/** + @class arith_lt_2 + @brief \+ _X_ \< + _Y_ [ISO]

@anchor sS_2 + + + The value of the expression _X_ is less than the value of expression + _Y_. +*/ static Int a_lt(Term t1, Term t2) { /* A < B */ @@ -737,6 +800,17 @@ a_lt(Term t1, Term t2) return out < 0; } +/** + * + @class arith_le_2 + @brief =\+ _X_ =\< + _Y_ [ISO]

@anchor qQsS_2 + + + The value of the expression _X_ is less than or equal to the value + of expression _Y_. +*/ static Int a_le(Term t1, Term t2) { /* A <= B */ @@ -746,6 +820,7 @@ a_le(Term t1, Term t2) return out <= 0; } +/// @} static Int a_noteq(Term t1, Term t2) diff --git a/C/eval.c b/C/eval.c index cb1a46143..25b5b24a1 100644 --- a/C/eval.c +++ b/C/eval.c @@ -18,10 +18,16 @@ static char SccsId[] = "%W% %G%"; #endif -/* - * This file implements arithmetic operations - * - */ +/** + @file eval.c + + @defgroup arithmetic_preds Arithmetic Predicates + @ingroup arithmetic + + @{ +*/ + + #include "Yap.h" #include "Yatom.h" #include "YapHeap.h" @@ -184,6 +190,23 @@ BEAM_is(void) #endif +/** + @class is_2 + @anchor is_2 + @brief evaluation of arithmetic expressions + + ? _X_:number is + _Y_:ground is det + + This predicate succeeds iff the result of evaluating the expression + _Y_ unifies with _X_. This is the predicate normally used to + perform evaluation of arithmetic expressions: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +X is 2+3*4 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + succeeds with `X = 14`. + +*/ + static Int p_is( USES_REGS1 ) { /* X is Y */ @@ -204,6 +227,16 @@ p_is( USES_REGS1 ) return Yap_unify_constant(ARG1,out); } +/** + @class isnan_1 + @anchor isnan_1 + @brief True if _X_ is not a number + + isnan(? _X_:float) is det + + Interface to the IEE754 `isnan` test. +*/ + static Int p_isnan( USES_REGS1 ) { /* X is Y */ @@ -232,6 +265,17 @@ p_isnan( USES_REGS1 ) return isnan(FloatOfTerm(out)); } +/** + @class isinf_1 + @anchor isinf_1 + @brief True if _X_ is infinity + + isnan(? _X_:float) is det + + Interface to the IEE754 `isinf` test. +*/ + + static Int p_isinf( USES_REGS1 ) { /* X is Y */ @@ -260,6 +304,18 @@ p_isinf( USES_REGS1 ) return isinf(FloatOfTerm(out)); } +/** + @class logsum_3 + @anchor logsum_3 + @brief sum of two logarithms + + logsum(+ _Log1_, + _Log2_, - _Out_ ) 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. +*/ static Int p_logsum( USES_REGS1 ) { /* X is Y */ @@ -391,6 +447,25 @@ static Int cont_between( USES_REGS1 ) } } +/** + @class between_3 + @anchor between_3 + @brief sequence of numbers + + between(+ _Low_:int, + _High_:int, ? _Value_:int) is nondet + + _Low_ and _High_ are integers, _High_ \>= _Low_. If + _Value_ is an integer, _Low_ =\< _Value_ + =\< _High_. When _Value_ is a variable it is successively + bound to all integers between _Low_ and _High_. If + _High_ is inf or infinite [between/3](@ref between_3) is true iff + _Value_ \>= _Low_, a feature that is particularly interesting + for generating integers from a certain value. + + @} + +*/ + static Int init_between( USES_REGS1 ) { diff --git a/H/eval.h b/H/eval.h index fad52dd3e..fff67560b 100644 --- a/H/eval.h +++ b/H/eval.h @@ -15,6 +15,85 @@ * * *************************************************************************/ +/** + + @defgroup arithmetic Arithmetic in YAP + + @tableofcontents + + YAP supports several different numeric types: +

+ +Arithmetic functions that require integer arguments accept, in addition +to integers, rational numbers with denominator `1' and floating point +numbers that can be accurately converted to integers. If the required +argument is a float the argument is converted to float. Note that +conversion of integers to floating point numbers may raise an overflow +exception. In all other cases, arguments are converted to the same type +using the order integer to rational number to floating point number. + +Evaluation generates the following _Call_ +exceptions: + + @exception "error(instantiation_error, Call )" if not ground + + @exception "type_error(evaluable( V ), Call)" if not evaluable term + @exception "type_error(integer( V ), Call)" if must be integer + @exception "type_error(float( V ), Call)" if must be float + + @exception "domain_error(out_of_range( V ), Call)" if argument invalid + @exception "domain_error(not_less_than_zero( V ), Call)" if argument must be positive or zero + + @exception "evaluation_error(undefined( V ), Call)" result is not defined (nan) + @exception "evaluation_error(overflow( V ), Call)" result is arithmetic overflow + +@secreflist +@refitem is_2 +@refitem isnan_1 +@endsecreflist + + + **/ + #include /* C library used to implement floating point functions */ diff --git a/Makefile.in b/Makefile.in index fa838f274..ce93d8e7d 100755 --- a/Makefile.in +++ b/Makefile.in @@ -298,6 +298,7 @@ PLCONS_SOURCES = \ PL_SOURCES= \ pl/arith.yap \ + pl/arithpreds.yap \ pl/arrays.yap \ pl/attributes.yap \ pl/atoms.yap \ diff --git a/docs/builtins.tex b/docs/builtins.tex index b9b6d46b1..1ad112d5b 100644 --- a/docs/builtins.tex +++ b/docs/builtins.tex @@ -2,6 +2,8 @@ @node Built-ins, Library, Modules, Top +@chapter Built-In Predicates Library + @menu Built-ins, Debugging, Syntax, Top @@ -13,7 +15,7 @@ Built-ins, Debugging, Syntax, Top * Predicates on Characters:: Manipulating Characters * Comparing Terms:: Comparison of Terms * Arithmetic:: Arithmetic in YAP -* I/O:: Input/Output with YAP +* Input/Output:: Input/Output with YAP * Database:: Modifying Prolog's Database * Sets:: Finding All Possible Solutions * Grammars:: Grammar Rules @@ -30,7 +32,7 @@ Built-ins, Debugging, Syntax, Top @end menu @node Control, Undefined Procedures, , Top -@chapter Control Predicates +@section Control Predicates This chapter describes the predicates for controlling the execution of @@ -696,7 +698,7 @@ Translates a message-term into a string object. Primarily intended for SWI-Prolo @end table @node Testing Terms, Predicates on Atoms, Messages, Top -@chapter Predicates on terms +@section Predicates on terms @table @code @@ -1194,8 +1196,7 @@ the call. @item digit(@var{Weight}) @var{Char} is a digit with value - @var{Weight}. I.e. @code{char_type(X, digit(6))} yields @code{X = - '6'}. Useful for parsing numbers. + @var{Weight}. I.e. @code{char_type(X, digit(6))} yields @code{X = '6'}. Useful for parsing numbers. @item xdigit(@var{Weight}) @var{Char} is a hexa-decimal digit with value @var{Weight}. I.e. char_type(a, xdigit(X) yields X = '10'. Useful for parsing numbers. @@ -1412,9 +1413,21 @@ of length @var{S}. @end table -@node Arithmetic, I/O, Comparing Terms, Top +@node Arithmetic, Input/Output, Comparing Terms, Top @section Arithmetic +@ifplaintext +@copydoc arithmetic + +See @ref arithmetic_preds for the predicates that implement arithment + +See @ref arithmetic_cmps for the arithmetic comparisons supported in YAP + +See @ref arithmetic_operators for how to call arithmetic operations in YAP + +@end ifplaintext + +@texinfo YAP now supports several different numeric types: @table @code @@ -1440,7 +1453,8 @@ YAP now supports several different numeric types: numbers that are returned from is/2 are canonical, which means M is positive and N and M have no common divisors. Rational numbers are introduced in the computation using the rational/1, - rationalize/1 or the rdiv/2 (rational division) function. + rationalize/1 or the +rdiv/2 (rational division) function. @item float Floating point numbers are represented using the C-type double. On most today platforms these are 64-bit IEEE floating point numbers. @@ -1491,8 +1505,7 @@ Integer remainder, similar to @code{mod} but always has the same sign @code{X}. @item @var{X} div @var{Y} [ISO] -Integer division, as if defined by @code{(@var{X} - @var{X} mod @var{Y}) -// @var{Y}}. +Integer division, as if defined by @code{(@var{X} - @var{X} mod @var{Y})// @var{Y}}. @item exp(@var{X}) [ISO] Natural exponential. @@ -1767,6 +1780,7 @@ The primitive YAP predicates involving arithmetic expressions are: @table @code +@itemize @item @var{X} is +@var{Y} [2] @findex is/2 @syindex is/2 @@ -1780,6 +1794,7 @@ X is 2+3*4 @end example @noindent succeeds with @code{X = 14}. +@end itemize @item +@var{X} < +@var{Y} [ISO] @findex trace ; true ), assert_static( source( Inp, Lines, Line0 ) ), ( Line0 == end_of_file -> !, @@ -131,7 +130,9 @@ out( _S ) :- nb_setval( min, 0 ), fail. out( S ) :- - line( F, Pos, Line), + line( F, Pos, Line0), +%( Pos = 5770 -> trace ; true ), + jmp_blanks( Line0, Line), b_setval( line, F:Pos:Line ), process( Line , NewLine, F:Pos), offset( N ), @@ -141,8 +142,8 @@ out( S ) :- ; NewLine == "" -> -% nb_getval( old_line, OldLine ), -% OldLine \= "", + nb_getval( old_line, OldLine ), + OldLine \= "", format(string(SN), '~n', []) ; NewLine == force @@ -185,6 +186,9 @@ singleton_line(L) :- string_concat("@itemize",_R,L), !. singleton_line(L) :- string_concat("@enumerate",_R,L), !. singleton_line(L) :- string_concat("@table",_R,L), !. singleton_line(L) :- string_concat("@example",_R,L), !, assert( singletons ). +singleton_line(L) :- string_concat("@ifplaintext",_R,L), !, assert( singletons ). +singleton_line(L) :- string_concat("@pl_example",_R,L), !, assert( singletons ). +singleton_line(L) :- string_concat("@c_example",_R,L), !, assert( singletons ). singleton_line(L) :- string_concat("@simpleexample",_R,L), !, assert( singletons ). singleton_line(L) :- string_concat("@end",R,L), !, ( sub_string(R, _, _, _, "example") -> retract( singletons ) ; true ). @@ -200,16 +204,20 @@ process( Line , S, F:Pos ) :- ( first_word(Line, "@end", Rest) -> - first_word(Rest, Env1, _Rest2), ( - ( Env1 == "example" ; Env1 == "smallexample" ) + first_word(Rest, Env1, _Rest2), + sub_string( Env1, _, _, 0, "example" ) -> ( S = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" ; pop( skip, verbatim ), fail ) -% fail in other ends -% ; -% Env1 = "cartouche" + ; + first_word(Rest, Env1, _Rest2), + sub_string( Env1, _, _, 0, "plaintext" ) + -> + ( S = "" ; + pop( skip, verbatim ), fail + ) ) ; first_word(Line, "@cartouche", Rest) @@ -224,8 +232,12 @@ process( Line , "", _Pos ) :- first_word(Line, Word, Rest), Word == "@end", first_word(Rest, Word2, _Rest), - W2 = Word2, - pop( skip, W2 ). + ( W2 = Word2 + -> + pop( skip, W2 ) + ; + true + ). % command: flush and continue process( Command , NewLine , Pos) :- do_buffer(Command, NewLine, Pos ). @@ -254,36 +266,49 @@ command( Line, Word, Rest ) :- clause( process( Word, _, _, _, _ ), _), !. +process("@item", _Line, _Rest, NewLine , _FilePos) :- + speek( list, it(_Env, _Item, _Pos, Numb)), + Numb > 1, + NewLine = "". process("@item", Line, Rest, NewLine , FilePos) :- pop( list, it(Env, Item, Pos, Numb)), !, NNumb is Numb+1, run( Text, Rest ), - jmp_blanks( Rest, First ), - item_type(Item, Numb, Marker ), + jmp_blanks( Text, First ), + Pos1 is Pos, +% item_type(Item, Numb, Marker ), + Marker = "", ( - Env = "table", + Env = "@table", atom_string( A, Line ), pred( _Pred, Key, A, FilePos ) -> push( list, it(Env, Item, Pos, NNumb) ), ( % sendout the comand - format(string(NewLine), '~t~s ~*|~s @anchor ~a', [Marker, Pos, First, Key]), + format(string(NewLine), '~t~s ~*+
  • ~s @anchor ~a', [Marker, Pos1, First, Key]), push( indent, done ) ; NewLine = force ) ; - format(string(NewLine), '~t~s ~*|~s', [ Marker, Pos, First]), + format(string(NewLine), '~t~s ~*+
  • ~s', [ Marker, Pos, First]), push( list, it(Env, Item, Pos, NNumb) ), push( indent, done ) - ). + ). %, writeln(+FilePos:Line), listing(stack). +process("@end", _Line, _Rest, "
  • " , _Pos) :- + once( speek(list,it(_Env,_,_LL,_)) ). process("@end", _Line, Rest, NewLine , _Pos) :- speek(list,it(Env,_,_LL,_)), + ( Env = "@enumerate" -> + NewLine = "" + ; + NewLine = "" + ), sub_string( Env, 1, _, 0, Env1 ), sub_string( Rest, _, _, _, Env1), !, % check - pop( list, it(Env, _, _, _) ), - NewLine = "". +% writeln(_Pos:_Line), listing(stack), + pop( list, it(Env, _, _, _) ). process("@end", Line, _Rest, NewLine , _Pos) :- sub_string(Line, _, _, 0, "ifnottex"), !, % check NewLine = "\\endhtmlonly". @@ -304,7 +329,11 @@ process("@end", Line, _Rest, NewLine , _Pos) :- process("@author", _Line, Rest, NewLine , _Pos) :- !, jmp_blanks( Rest, Firs ), format( string( NewLine), '\\author ~s', [ Firs ] ). -process("@*", _Line, _Rest, ¨¨ , _Pos) :- !. +process("@*", _Line, _Rest, "" , _Pos). +process("@*", _Line, Rest, Line , _Pos) :- + !, + jmp_blanks( Rest, Firs ), + run( Line, Firs ). process("@c", _Line, Rest, NewLine , _Pos) :- !, gen_comment( Rest, NewLine ). process("@comment", _Line, Rest, NewLine , _Pos) :- !, @@ -320,7 +349,8 @@ process("@chapter", _Line, Rest, NewLine, _Pos ) :- !, run( Title, Firs ), nb_setval( level, 1 ), title_from_words(Firs, Id, _Pos), - format(string(NewLine), '@section ~s ~s', [Id,Title]). + title( '@chapter', _, TitleDox ), + format(string(NewLine), '~a ~s ~s', [TitleDox, Id,Title]). % ( format( string(NewLine), '~s', [Title] ) ; NewLine = "======" ). process("@cindex", _Line, _Rest, no , _Pos) :- !. process("@caindex", _Line, _Rest, no, _Pos ) :- !. @@ -329,6 +359,9 @@ process("@defindex", Line, _Rest, NewLine , _Pos) :- !, process("@direntry", Line, _Rest, NewLine, _Pos ) :- !, gen_comment( Line, NewLine ), push(skip, "direntry" ). +process("@texinfo", Line, _Rest, NewLine, _Pos ) :- !, + gen_comment( Line, NewLine ), + push(skip, "texinfo" ). process("@documentencoding", _Line, _Rest, "" , _Pos) :- !. % jmp_blanks( Rest, NewString ), % format( string( NewLine), '', [ NewString ] ). @@ -340,7 +373,16 @@ process("@enumerate", _Line, _Rest, NewLine , _Pos) :- process("@example", _Line, _Rest, "" , _Pos). process("@example", _Line, _Rest, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" , _Pos) :- !, push( skip, verbatim). +process("@ifplaintext", _Line, _Rest, "" , _Pos) :- !, + push( skip, verbatim). +process("@pl_example", _Line, _Rest, "" , _Pos). +process("@pl_example", _Line, _Rest, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.prolog}" , _Pos) :- !, + push( skip, verbatim). +process("@c_example", _Line, _Rest, "" , _Pos). +process("@c_example", _Line, _Rest, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}" , _Pos) :- !, + push( skip, verbatim). process("@format", _Line, _Rest, "", _Pos ) :- !. +process("@alias", _Line, _Rest, "", _Pos ) :- !. process("@dircategory", _Line, _Rest, "", _Pos ) :- !. process("@smallexample", _Line, _Rest, "" , _Pos). process("@smallexample", _Line, _Rest, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" , _Pos) :- !, @@ -373,8 +415,9 @@ process("@section", _Line, Rest, NewLine, Pos ) :- !, run( NewTitle, Title ), nb_setval( level, 2 ), % format(string(NewLine), '# ~s #', [NewTitle]). + title( '@section', _, TitleDox ), title_from_words(NewTitle, Id, Pos), - format(string(NewLine), '@subsection ~s ~s', [Id,NewTitle]). + format(string(NewLine), '~a ~s ~s', [TitleDox,Id,NewTitle]). % format(string(NewLine), '# ~s #', [NewTitle]). process("@appendix", _Line, Rest, NewLine, _Pos ) :- !, jmp_blanks( Rest, Title ), @@ -384,8 +427,9 @@ process("@subsection", _Line, Rest, NewLine, _Pos ) :- !, jmp_blanks( Rest, Title ), run( NewTitle, Title ), nb_setval( level, 3 ), + title( '@subsection', _, TitleDox ), title_from_words(NewTitle, Id, _Pos), - format(string(NewLine), '@subsubsection ~s ~s', [Id,NewTitle]). + format(string(NewLine), '~a ~s ~s', [TitleDox,Id,NewTitle]). % format(string(NewLine), '## ~s ##', [NewTitle]). process("@unnumberedsubsubsec", _Line, Rest, NewLine, _Pos ) :- !, nb_setval( level, 4 ), @@ -394,8 +438,9 @@ process("@subsubsection", _Line, Rest, NewLine, _Pos ) :- !, nb_setval( level, 4 ), jmp_blanks( Rest, Title ), run( NewTitle, Title ), + title( '@subsubsection', _, TitleDox ), title_from_words(NewTitle, Id, _Pos), - format(string(NewLine), '@paragraph ~s ~s', [Id,NewTitle]). + format(string(NewLine), '~a ~s', [TitleDox,Id,NewTitle]). % format(string(NewLine), '### ~s ###', [NewTitle]). process("@set", _Line, Rest, NewLine , _Pos) :- !, first_word( Rest, V, SecC), @@ -416,16 +461,7 @@ process("@setchapternewpage", Line, _Rest, NewLine, _Pos ) :- !, gen_comment( Line, NewLine ). process("@setfilename", Line, _Rest, NewLine, _Pos ) :- !, gen_comment( Line, NewLine ). -process("@settitle", _Line, Rest, NewLine , _Pos) :- !, - jmp_blanks( Rest, Title ), - ( format(string(NewLine), '~s {#mainpage}', [Title]) ; NewLine = "=================="; NewLine = "" ; - NewLine = ""; - NewLine = "[TOC]"; - NewLine = ""; -NewLine = "@secreflist" ; - NewLine = ""; -NewLine = "@endsecreflist" -). +process("@settitle", _Line, _Rest, "" , _Pos) :- !. process("@subtitle", _Line, _Rest, "", _Pos ) :- !. process("@include", _Line, _Rest, "", _Pos ) :- !. process("@table", _Line, Rest, NewLine , _Pos) :- !, @@ -461,21 +497,25 @@ get_second( Rest, Title ) :- % clear the buffer first. % list( Env, Line, New, _Pos) :- - writeln(_Pos), first_word( Line, V, Rest), jmp_blanks( Rest, End ), ( - speek( list, it(_, _,Pos, _) ) -> - Pos1 is Pos + 6 + speek( list, it(_, _, _Pos, _) ) -> + Pos1 is 0 % Pos + 4 ; - Pos1 = 6 + Pos1 = 0 %4 ), push( list, it( Env, V, Pos1, 1 ) ), % b_getval( pos, _Pos ), % writeln(add:_Pos:Env:Pos1:End), % listing(stack), run( New, End). - +list( Env, _Line, NewLine, _Pos) :- + ( Env = "@enumerate" -> + NewLine = "
      " + ; + NewLine = "
        " + ). item_type("@bullet", _, "-" ). item_type("@code", _, "-" ). @@ -521,9 +561,11 @@ from_word( Line, Id ) :- simplify( C1, C0, []), string_codes( Id, C1 ). -simplify( [0'_|L]) --> " ", !, +simplify( [0'_|L]) --> " ", !, %' simplify(L). -simplify( [0'a,0'A|L]) --> "@", !, +simplify( [0's,0'T|L]) --> "*", !, %' + simplify(L). +simplify( [0'a,0'A|L]) --> "@", !, simplify(L). simplify( [0'b,0'A|L]) --> "'", !, simplify(L). @@ -637,7 +679,7 @@ pop(Type, Val) :- stack(T, V), !, T = Type, V = Val, - retract(stack(T,V)). + once( retract(stack(T,V)) ). push(Type, Val) :- asserta(stack(Type,Val)). @@ -706,11 +748,17 @@ run( L) --> "@value{", !, run(R). run( L) --> "@pxref{", !, argument(AL, 0'{, 0'}), - { format(codes(L, R), '`see ~s`', [AL] ) }, %' + { + string_codes(S, AL), + from_word(S, Id), + format(codes(L, R), ' (see [~s](@ref ~s))', [AL,Id] ) }, %' % run(R). run( L) --> "@ref{", !, argument(AL, 0'{, 0'}), - { format(codes(L, R), '[~s](@ref ~s)', [AL,AL] ) }, %' + { + string_codes(S, AL), + from_word(S, Id), + format(codes(L, R), '[~s](@ref ~s)', [AL,Id] ) }, %' run(R). run( L) --> "@strong{", !, argument(AL, 0'{, 0'}), @@ -808,11 +856,9 @@ argument(L, _C0, _C, L, []) :- format(user_error, 'Line ~w :-~n argument ~c~s~c does not close in same line.~n', [Line, _C0, L, _C]). argument0([], 0, _, C ) --> [C], !. -%:- start_low_level_trace. argument0([C|L], I0, C0, C ) --> [C], !, { I0 > 0, I is I0-1 }, argument0( L, I, C0, C). -%:- stop_low_level_trace. argument0([C0|L], I0, C0, C ) --> [C0], !, { I is I0+1 }, argument0( L, I, C0, C). @@ -854,11 +900,18 @@ id(X) :- X1 is X+100, assert(i(X1)). -title(1, page). -title(2, section). -title(3, subsection). -title(4, subsubsection). -title(5, paragraph). -title(6, paragraph). +title(TexTitle, Level, DoxTitle) :- + title( Level, TexTitle), +% Level1 is Level + 1, + title( Level, DoxTitle ), !. + +title(1, '@page' ). +title(1, '@chapter' ). +title(2, '@section' ). +title(3, '@subsection' ). +title(4, '@subsubsection' ). +title(5, '@paragraph' ). +title(6, '@paragraph' ). %:- spy title_from_words. + diff --git a/docs/yap.tex b/docs/yap.tex index 13c94952c..e9022daa9 100644 --- a/docs/yap.tex +++ b/docs/yap.tex @@ -28,6 +28,8 @@ @c Index for predicates sort of (almost) in SICStus Prolog @defindex sa +@alias pl_example=example +@alias c_example=example @setchapternewpage odd @c @smallbook @@ -79,6 +81,55 @@ Machine), with several optimizations for better performance. YAP follows the Edinburgh tradition, and is largely compatible with DEC-10 Prolog, Quintus Prolog, and especially with C-Prolog. + +@ifplaintext + +
          +
        • @subpage Install discusses how to download, compile and install + YAP for your platform. +
        • +
        • @subpage Syntax describes the syntax of YAP. +
        • +
        • @subpage Run describes how to invoke YAP +
        • +
        • @subpage Syntax describe the syntax of YAP. +
        • + +
        • @subpage Loading_Programs presents the main predicates and +directives available to load files and to control the Prolog +environment. + +
          • @subpage abs_file_name explains how to find a file full path. +
          • +
          + +
        • Built-Ins +
            @subpage page_arithmetic describes how arithmetic works in YAP. + +
          • @subpage Control describes the predicates for controlling the execution of Prolog programs. +
          • + +
          • @subpage Testing_Terms describes the main predicates on terms +
          • + +
          • @subpage Input_Output goes into Input/Ouput. +
          • + +
          • @subpage Database discusses the clausal data-base +
          • +
          + +
        • @subpage Grammars presents Grammar rules in Prolog + that are both a convenient way to express definite clause grammars + and an extension + of the well known context-free grammars. +
        • + +
        • @subpage OS discusses access to Operating System functionality +
        • +@end ifplaintext + + This file contains extracts of the SWI-Prolog manual, as written by Jan Wielemaker. Our thanks to the author for his kind permission in allowing us to include his text in this document. @@ -124,7 +175,7 @@ Built In Predicates * Predicates on Characters:: Manipulating Characters * Comparing Terms:: Comparison of Terms * Arithmetic:: Arithmetic in YAP -* I/O:: Input/Output with YAP +* Input/Output:: Input/Output with YAP * Database:: Modifying Prolog's Database * Sets:: Finding All Possible Solutions * Grammars:: Grammar Rules @@ -180,11 +231,11 @@ Subnodes of Modules Subnodes of Input/Output * Streams and Files:: Handling Streams and Files * C-Prolog File Handling:: C-Prolog Compatible File Handling -* I/O of Terms:: Input/Output of terms -* I/O of Characters:: Input/Output of Characters -* I/O for Streams:: Input/Output using Streams -* C-Prolog to Terminal:: C-Prolog compatible Character I/O to terminal -* I/O Control:: Controlling your Input/Output +* Input/Output of Terms:: Input/Output of terms +* Input/Output of Characters:: Input/Output of Characters +* Input/Output for Streams:: Input/Output using Streams +* C-Prolog to Terminal:: C-Prolog compatible Character Input/Output to terminal +* Input/Output Control:: Controlling your Input/Output * Sockets:: Using Sockets from YAP Subnodes of Database @@ -222,7 +273,7 @@ Subnodes of Library * RegExp:: Regular Expression Manipulation * shlib:: SWI Prolog shlib library * Splay Trees:: Splay Trees -* String I/O:: Writing To and Reading From Strings +* String Input/Output:: Writing To and Reading From Strings * System:: System Utilities * Terms:: Utilities on Terms * Cleanup:: Call With registered Cleanup Calls @@ -343,9 +394,8 @@ Tables @end ifnottex - @node Intro, Install, , Top -@unnumbered Introduction +@section Introduction This document provides User information on version @value{VERSION} of YAP (@emph{Yet Another Prolog}). The YAP Prolog System is a @@ -356,7 +406,7 @@ Porto. YAP provides several important features: @item Speed: YAP is widely considered one of the fastest available Prolog systems. - @item Functionality: it supports stream I/O, sockets, modules, + @item Functionality: it supports stream Input/Output, sockets, modules, exceptions, Prolog debugger, C-interface, dynamic code, internal database, DCGs, saved states, co-routining, arrays, threads. @@ -503,7 +553,7 @@ Library, Extensions, Built-ins, Top * RegExp:: Regular Expression Manipulation * shlib:: SWI Prolog shlib library * Splay Trees:: Splay Trees -* String I/O:: Writing To and Reading From Strings +* String Input/Output:: Writing To and Reading From Strings * System:: System Utilities * Terms:: Utilities on Terms * Timeout:: Call With Timeout @@ -532,10 +582,10 @@ aggregation operations are counting, computing the sum, minimum, maximum, a bag of solutions and a set of solutions. We first give a simple example, computing the country with the smallest area: -@example +@pl_example smallest_country(Name, Area) :- aggregate(min(A, N), country(N, A), min(Area, Name)). -@end example +@end pl_example There are four aggregation predicates, distinguished on two properties. @@ -557,9 +607,9 @@ There are four aggregation predicates, distinguished on two properties. all countries we do not want to lose results because two countries have the same population. Therefore we use: -@example +@pl_example aggregate(sum(P), Name, country(Name, P), Total) -@end example +@end pl_example @end table @@ -636,12 +686,12 @@ The predicates are: any variables that are not shared with Generator. Here is an example: -@example +@pl_example ?- foreach(between(1,4,X), dif(X,Y)), Y = 5. Y = 5 ?- foreach(between(1,4,X), dif(X,Y)), Y = 3. No -@end example +@end pl_example Notice that @var{Goal} is copied repeatedly, which may cause problems if attributed variables are involved. @@ -877,19 +927,19 @@ integers. The package is activated by @code{udi} declarations that state what is the argument of interest: -@example +@pl_example :- udi(diagnoses(exo_interval,?,?)). :- load_files(db, [consult(exo)]). -@end example +@end pl_example It is designed to optimise the following type of queries: -@example +@pl_example ?- max(X, diagnoses(X, 9, Y), X). ?- min(X, diagnoses(X, 9, 36211117), X). ?- X #< Y, min(X, diagnoses(X, 9, 36211117), X ), diagnoses(Y, 9, _). -@end example +@end pl_example The first argument gives the time, the second the patient, and the third the condition code. The first query should find the last time the patient 9 had any code reported, the second looks for the first @@ -913,18 +963,18 @@ of gecode and to have an higher level interface, @subsection The Gecode Interface This text is due to Denys Duchier. The gecode interface requires -@example +@pl_example :- use_module(library(gecode)). -@end example +@end pl_example Several example programs are available with the distribution. @table @code @item CREATING A SPACE A space is gecodes data representation for a store of constraints: -@example +@pl_example Space := space -@end example +@end pl_example @item CREATING VARIABLES @@ -933,27 +983,27 @@ Unlike in Gecode, variable objects are not bound to a specific Space. Each one actually contains an index with which it is possible to access a Space-bound Gecode variable. Variables can be created using the following expressions: -@example +@pl_example IVar := intvar(Space,SPEC...) BVar := boolvar(Space) SVar := setvar(Space,SPEC...) -@end example +@end pl_example where SPEC... is the same as in Gecode. For creating lists of variables use the following variants: -@example +@pl_example IVars := intvars(Space,N,SPEC...) BVars := boolvars(Space,N,SPEC...) SVars := setvars(Space,N,SPEC...) -@end example +@end pl_example where N is the number of variables to create (just like for XXXVarArray in Gecode). Sometimes an IntSet is necessary: -@example +@pl_example ISet := intset([SPEC...]) -@end example +@end pl_example where each SPEC is either an integer or a pair (I,J) of integers. An IntSet describes a set of ints by providing either intervals, or integers (which stand @@ -961,10 +1011,10 @@ for an interval of themselves). It might be tempting to simply represent an IntSet as a list of specs, but this would be ambiguous with IntArgs which, here, are represented as lists of ints. -@example +@pl_example Space += keep(Var) Space += keep(Vars) -@end example +@end pl_example Variables can be marked as "kept". In this case, only such variables will be explicitly copied during search. This could bring substantial benefits in @@ -980,16 +1030,16 @@ Gecode. Wherever a XXXArgs or YYYSharedArray is expected, simply use a list. At present, there is no support for minimodel-like constraint posting. Constraints and branchings are added to a space using: -@example +@pl_example Space += CONSTRAINT Space += BRANCHING -@end example +@end pl_example For example: -@example +@pl_example Space += rel(X,'IRT_EQ',Y) -@end example +@end pl_example arrays of variables are represented by lists of variables, and constants are @@ -998,17 +1048,17 @@ represented by atoms with the same name as the Gecode constant @item SEARCHING FOR SOLUTIONS -@example +@pl_example SolSpace := search(Space) -@end example +@end pl_example This is a backtrackable predicate that enumerates all solution spaces (SolSpace). It may also take options: -@example +@pl_example SolSpace := search(Space,Options) -@end example +@end pl_example Options is a list whose elements maybe: @@ -1034,7 +1084,7 @@ solutions. Below are methods for looking up information about variables. Each of these methods can either take a variable as argument, or a list of variables, and returns resp. either a value, or a list of values: -@example +@pl_example Val := assigned(Space,X) Val := min(Space,X) @@ -1061,7 +1111,7 @@ variables, and returns resp. either a value, or a list of values: Val := glb_values(Space,V) Val := lub_values(Space,V) Val := unknown_values(Space,V) - @end example + @end pl_example @item DISJUNCTORS @@ -1069,9 +1119,9 @@ variables, and returns resp. either a value, or a list of values: Disjunctors provide support for disjunctions of clauses, where each clause is a conjunction of constraints: -@example +@pl_example C1 or C2 or ... or Cn -@end example +@end pl_example Each clause is executed "speculatively": this means it does not affect the main @@ -1083,70 +1133,70 @@ Example: Consider the problem where either X=Y=0 or X=Y+(1 or 2) for variable X and Y that take values in 0..3. -@example +@pl_example Space := space, [X,Y] := intvars(Space,2,0,3), -@end example +@end pl_example First, we must create a disjunctor as a manager for our 2 clauses: -@example +@pl_example Disj := disjunctor(Space), -@end example +@end pl_example We can now create our first clause: -@example +@pl_example C1 := clause(Disj), -@end example +@end pl_example This clause wants to constrain X and Y to 0. However, since it must be executed "speculatively", it must operate on new variables X1 and Y1 that shadow X and Y: -@example +@pl_example [X1,Y1] := intvars(C1,2,0,3), C1 += forward([X,Y],[X1,Y1]), -@end example +@end pl_example The forward(...) stipulation indicates which global variable is shadowed by which clause-local variable. Now we can post the speculative clause-local constraints for X=Y=0: -@example +@pl_example C1 += rel(X1,'IRT_EQ',0), C1 += rel(Y1,'IRT_EQ',0), -@end example +@end pl_example We now create the second clause which uses X2 and Y2 to shadow X and Y: -@example +@pl_example C2 := clause(Disj), [X2,Y2] := intvars(C2,2,0,3), C2 += forward([X,Y],[X2,Y2]), -@end example +@end pl_example However, this clause also needs a clause-local variable Z2 taking values 1 or 2 in order to post the clause-local constraint X2=Y2+Z2: -@example +@pl_example Z2 := intvar(C2,1,2), C2 += linear([-1,1,1],[X2,Y2,Z2],'IRT_EQ',0), -@end example +@end pl_example Finally, we can branch and search: -@example +@pl_example Space += branch([X,Y],'INT_VAR_SIZE_MIN','INT_VAL_MIN'), SolSpace := search(Space), -@end example +@end pl_example and lookup values of variables in each solution: -@example +@pl_example [X_,Y_] := val(SolSpace,[X,Y]). -@end example +@end pl_example @end table @@ -1155,9 +1205,9 @@ and lookup values of variables in each solution: The gecode/clp(fd) interface is designed to use the GECODE functionality in a more CLP like style. It requires -@example +@pl_example :- use_module(library(gecode/clpfd)). -@end example +@end pl_example Several example programs are available with the distribution. Integer variables are declared as: @@ -1196,17 +1246,17 @@ implication (=>), equivalence (<=>), and xor. The @t{sum} constraint allows a t @code{where} conditional, in Zinc style. The send more money equation may be written as: -@example +@pl_example 1000*S + 100*E + 10*N + D + 1000*M + 100*O + 10*R + E #= 10000*M + 1000*O + 100*N + 10*E + Y, -@end example +@end pl_example This example uses @code{where} to select from column @var{I} the elements that have value under @var{M}: -@example +@pl_example OutFlow[I] #= sum(J in 1..N where D[J,I] B. -@end example +@end pl_example Note that not all constraints may be reifiable. @item element(@var{X}, @var{Vs} ) @@ -1296,11 +1346,11 @@ first to the last argument emitting the middle argument, and a final state. The swedish-drinkers protocol is represented as follows: -@example +@pl_example A = [X,Y,Z], dfa( 0, [t(0,0,0),t(0,1,1),t(1,0,0),t(-1,0,0)], [0], C), in_dfa( A, C ), -@end example +@end pl_example This code will enumeratae the valid tuples of three emissions. @item extensional constraints @@ -1308,10 +1358,10 @@ Constraints can also be represented as lists of tuples. The previous example would be written as: -@example +@pl_example extensional_constraint([[0,0,0],[0,1,0],[1,0,0]], C), in_relation( A, C ), -@end example +@end pl_example @item minimum(@var{X}, @var{Vs}) @item min(@var{X}, @var{Vs}) @@ -1486,13 +1536,13 @@ identical to @var{Element} deleted. Flatten a list of lists @var{List} into a single list @var{FlattenedList}. -@example +@pl_example ?- flatten([[1],[2,3],[4,[5,6],7,8]],L). L = [1,2,3,4,5,6,7,8] ? ; no -@end example +@end pl_example @item last(+@var{List},?@var{Last}) @findex last/2 @@ -1565,8 +1615,7 @@ Unifies @var{Elem} with the Nth element of @var{List}, counting from 1, and @var{Rest} with the other elements. It can be used to select the Nth element of @var{List} (yielding @var{Elem} and @var{Rest}), or to insert @var{Elem} before the Nth (counting from 1) element of -@var{Rest}, when it yields @var{List}, e.g. @code{nth(3, List, c, -[a,b,d,e])} unifies List with @code{[a,b,c,d,e]}. @code{nth/4} +@var{Rest}, when it yields @var{List}, e.g. @code{nth(3, List, c, [a,b,d,e])} unifies List with @code{[a,b,c,d,e]}. @code{nth/4} can be used to insert @var{Elem} after the Nth element of @var{Rest}. @item nth(?@var{N}, ?@var{List}, ?@var{Elem}, ?@var{Rest}) @@ -1620,11 +1669,11 @@ stay in the same order). @cnindex selectchk/3 Semi-deterministic selection from a list. Steadfast: defines as -@example +@pl_example selectchk(Elem, List, Residue) :- select(Elem, List, Rest0), !, Rest = Rest0. -@end example +@end pl_example @item sublist(?@var{Sublist}, ?@var{List}) @@ -1750,13 +1799,13 @@ the remainder of the line. Unify @var{Words} with a set of strings obtained from @var{Line} by using the character codes in @var{Separators} as separators. As an example, consider: -@example +@pl_example ?- split("Hello * I am free"," *",S). S = ["Hello","I","am","free"] ? no -@end example +@end pl_example @item split(+@var{Line},-@var{Split}) @findex split/2 @@ -1775,11 +1824,11 @@ Unify @var{Words} with a set of strings obtained from @var{Line} by using the character codes in @var{Separators} as separators for fields. If two separators occur in a row, the field is considered empty. As an example, consider: -@example +@pl_example ?- fields("Hello I am free"," *",S). S = ["Hello","","I","am","","free"] ? -@end example +@end pl_example @item fields(+@var{Line},-@var{Split}) @findex fields/2 @@ -2086,12 +2135,12 @@ result in @var{X}, @var{Y}, @var{Z} and @var{W}. Left scan of list. The scanl family of higher order list operations is defined by: -@example +@pl_example scanl(P, [X11,...,X1n], ..., [Xm1,...,Xmn], V0, [V0,V1,...,Vn]) :- P(X11, ..., Xm1, V0, V1), ... P(X1n, ..., Xmn, Vn-1, Vn). -@end example +@end pl_example @item scanl(:@var{Pred}, +@var{List1}, +@var{List2}, ?@var{V0}, ?@var{Vs}) @@ -2168,7 +2217,7 @@ of @code{<}, @code{=} or @code{>}. @code{Pred} must be deterministic. Examples: -@example +@pl_example %given plus(X,Y,Z) :- Z is X + Y. plus_if_pos(X,Y,Z) :- Y > 0, Z is X + Y. @@ -2194,7 +2243,7 @@ checknodes(\==(T), p(X,p(Y,X),Z)). sumnodes(vars, [c(X), p(X,Y), q(Y)], [], [Y,Y,X,X]). % another one maplist(mapargs(number_atom),[c(1),s(1,2,3)],[c('1'),s('1','2','3')]). -@end example +@end pl_example @node matrix, MATLAB, MapList, Library @section Matrix Library @@ -2359,9 +2408,9 @@ Variables in the goal are assumed to be global, ie, share a single value in the execution. The exceptions are the iteration indices. Moreover, if the goal is of the form @code{@var{Locals}^@var{G}} all variables occurring in @var{Locals} are marked as local. As an example: -@example +@pl_example foreach([I,J] ins 1..N, A^(A <==M[I,J], N[I] <== N[I] + A*A) ) -@end example +@end pl_example the variables @var{I}, @var{J} and @var{A} are duplicated for every call (local), whereas the matrices @var{M} and @var{N} are shared throughout the execution (global). @@ -2794,16 +2843,16 @@ Read or set MATLAB @var{MatVar}(@var{X},@var{Y}) from/to @var{Val}. Use @code{C} notation for matrix access (ie, starting from 0). @item matlab_item1(+@var{MatVar}, +@var{X}, ?@var{Val}) -@findex matlab_item/3 -@snindex matlab_item/3 -@cnindex matlab_item/3 +@findex matlab_item1/3 +@snindex matlab_item1/3 +@cnindex matlab_item1/3 Read or set MATLAB @var{MatVar}(@var{X}) from/to @var{Val}. Use MATLAB notation for matrix access (ie, starting from 1). @item matlab_item1(+@var{MatVar}, +@var{X}, +@var{Y}, ?@var{Val}) -@findex matlab_item/4 -@snindex matlab_item/4 -@cnindex matlab_item/4 +@findex matlab_item1/4 +@snindex matlab_item1/4 +@cnindex matlab_item1/4 Read or set MATLAB @var{MatVar}(@var{X},@var{Y}) from/to @var{Val}. Use MATLAB notation for matrix access (ie, starting from 1). @@ -3375,9 +3424,9 @@ read_header_data(_, Stream, Tail) :- @end example @item read_stream_to_codes(+@var{Stream}, -@var{Codes}) -@findex read_stream_to_codes/3 -@snindex read_stream_to_codes/3 -@cnindex read_stream_to_codes/3 +@findex read_stream_to_codes/2 +@snindex read_stream_to_codes/2 +@cnindex read_stream_to_codes/2 Read all input until end-of-file and unify the result to @var{Codes}. @item read_stream_to_codes(+@var{Stream}, -@var{Codes}, ?@var{Tail}) @@ -3614,12 +3663,6 @@ associated with @var{Val}. @var{Previous} is the previous element after @var{Key} in @var{T}, and is associated with @var{Val}. -@item list_to_rbtree(+@var{L}, -@var{T}) -@findex list_to_rbtree/2 -@snindex list_to_rbtree/2 -@cnindex list_to_rbtree/2 -@var{T} is the red-black tree corresponding to the mapping in list @var{L}. - @item ord_list_to_rbtree(+@var{L}, -@var{T}) @findex list_to_rbtree/2 @snindex list_to_rbtree/2 @@ -3771,7 +3814,7 @@ One of the files provides a global function @code{install_mylib()} that initialises the module using calls to @code{PL_register_foreign()}. Here is a simple example file @code{mylib.c}, which creates a Windows MessageBox: -@example +@c_example #include #include @@ -3792,7 +3835,7 @@ install_t install_mylib() @{ PL_register_foreign("say_hello", 1, pl_say_hello, 0); @} -@end example +@end c_example Now write a file mylib.pl: @@ -3888,7 +3931,7 @@ loaded shared libraries. @c @code{qsave_program/2}). @end table -@node Splay Trees, String I/O, shlib, Library +@node Splay Trees, String Input/Output, shlib, Library @section Splay Trees @cindex splay trees @@ -3956,12 +3999,12 @@ greater than @var{Key}. This operations destroys @var{Tree}. @end table -@node String I/O, System, Splay Trees, Library +@node String Input/Output, System, Splay Trees, Library @section Reading From and Writing To Strings -@cindex string I/O +@cindex string Input/Output From Version 4.3.2 onwards YAP implements SICStus Prolog compatible -String I/O. The library allows users to read from and write to a memory +String Input/Output. The library allows users to read from and write to a memory buffer as if it was a file. The memory buffer is built from or converted to a string of character codes by the routines in library. Therefore, if one wants to read from a string the string must be fully instantiated @@ -4127,7 +4170,7 @@ importing these built-ins. YAP does not currently support opening a @code{charsio} stream in @code{append} mode, or seeking in such a stream. -@node System, Terms, String I/O, Library +@node System, Terms, String Input/Output, Library @section Calling The Operating System from YAP @cindex Operating System Utilities @@ -4179,8 +4222,7 @@ X = 991081786 ? ; @syindex delete_file/1 @cnindex delete_file/1 The @code{delete_file/1} procedure removes file @var{File}. If -@var{File} is a directory, remove the directory @emph{and all its -subdirectories}. +@var{File} is a directory, remove the directory @emph{and all its subdirectories}. @example ?- delete_file(x). @@ -4271,9 +4313,9 @@ Create file @var{OldFile} to @var{NewFile}. This predicate uses the @item environ(?@var{EnvVar},+@var{EnvValue}) -@findex environ/2 -@syindex environ/2 -@cnindex environ/2 +@findex sys_environ/2 +@syindex sys_environ/2 +@cnindex sys_environ/2 Unify environment variable @var{EnvVar} with its value @var{EnvValue}, if there is one. This predicate is backtrackable in Unix systems, but not currently in Win32 configurations. @@ -4380,11 +4422,11 @@ command. The following example demonstrates the use of @code{popen/3} to process the output of a command, as @code{exec/3} would do: -@example +@pl_example ?- popen(ls,read,X),repeat, get0(X,C), (C = -1, ! ; put(C)). X = 'C:\\cygwin\\home\\administrator' ? -@end example +@end pl_example The WIN32 implementation of @code{popen/3} relies on @code{exec/3}. @@ -4409,9 +4451,9 @@ the shell given by the environment variable @code{SHELL} with the option @code{SHELL} is undefined, in this case with the option @code{" /c "}. @item shell(+@var{Command},-@var{Status}) -@findex shell/1 -@syindex shell/1 -@cnindex shell/1 +@findex shell/2 +@syindex shell/2 +@cnindex shell/2 Execute command @var{Command} under a new shell and unify @var{Status} with the exit for the command. YAP will be in background until the command completes. In Unix environments YAP uses the shell given by the @@ -4696,9 +4738,9 @@ Declares the predicate @var{P}=@t{[module:]name/arity} as a fragile predicate, module is optional, default is the current typein_module. Whenever such a fragile predicate is used in a query it will be called through call_cleanup/1. -@example +@pl_example :- fragile foo/1,bar:baz/2. -@end example +@end pl_example @item call_cleanup(:@var{Goal}) @findex call_cleanup/1 @@ -4738,7 +4780,7 @@ required to execute @var{Goal}, close file-descriptors, etc. The example below provides a non-deterministic search for a term in a file, closing the stream as needed. -@example +@pl_example term_in_file(Term, File) :- setup_call_cleanup(open(File, read, In), term_in_stream(Term, In), @@ -4751,7 +4793,7 @@ term_in_stream(Term, In) :- -> !, fail ; T = Term ). -@end example +@end pl_example Note that it is impossible to implement this predicate in Prolog other than by reading all terms into a list, close the file and call @code{member/2}. @@ -4932,20 +4974,20 @@ Given a graph with a set of vertices @var{Vertices} and a set of edges s-representation. Note that the vertices without edges will appear in @var{Vertices} but not in @var{Edges}. Moreover, it is sufficient for a vertex to appear in @var{Edges}. -@example +@pl_example ?- vertices_edges_to_ugraph([],[1-3,2-4,4-5,1-5],L). L = [1-[3,5],2-[4],3-[],4-[5],5-[]] ? -@end example +@end pl_example In this case all edges are defined implicitly. The next example shows three unconnected edges: -@example +@pl_example ?- vertices_edges_to_ugraph([6,7,8],[1-3,2-4,4-5,1-5],L). L = [1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]] ? -@end example +@end pl_example @item vertices(+@var{Graph}, -@var{Vertices}) @findex vertices/2 @@ -4953,11 +4995,11 @@ L = [1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]] ? @cnindex vertices/2 Unify @var{Vertices} with all vertices appearing in graph @var{Graph}. In the next example: -@example +@pl_example ?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], V). L = [1,2,3,4,5] -@end example +@end pl_example @item edges(+@var{Graph}, -@var{Edges}) @findex edges/2 @@ -4965,11 +5007,11 @@ L = [1,2,3,4,5] @cnindex edges/2 Unify @var{Edges} with all edges appearing in graph @var{Graph}. In the next example: -@example +@pl_example ?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], V). L = [1,2,3,4,5] -@end example +@end pl_example @item add_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph}) @findex add_vertices/3 @@ -4977,7 +5019,7 @@ L = [1,2,3,4,5] @cnindex add_vertices/3 Unify @var{NewGraph} with a new graph obtained by adding the list of vertices @var{Vertices} to the graph @var{Graph}. In the next example: -@example +@pl_example ?- add_vertices([1-[3,5],2-[4],3-[],4-[5], 5-[],6-[],7-[],8-[]], [0,2,9,10,11], @@ -4985,7 +5027,7 @@ vertices @var{Vertices} to the graph @var{Graph}. In the next example: NG = [0-[],1-[3,5],2-[4],3-[],4-[5],5-[], 6-[],7-[],8-[],9-[],10-[],11-[]] -@end example +@end pl_example @item del_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph}) @findex del_vertices/3 @@ -4994,12 +5036,12 @@ NG = [0-[],1-[3,5],2-[4],3-[],4-[5],5-[], Unify @var{NewGraph} with a new graph obtained by deleting the list of vertices @var{Vertices} and all the edges that start from or go to a vertex in @var{Vertices} to the graph @var{Graph}. In the next example: -@example +@pl_example ?- del_vertices([2,1],[1-[3,5],2-[4],3-[], 4-[5],5-[],6-[],7-[2,6],8-[]],NL). NL = [3-[],4-[5],5-[],6-[],7-[6],8-[]] -@end example +@end pl_example @item add_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph}) @findex add_edges/3 @@ -5007,12 +5049,12 @@ NL = [3-[],4-[5],5-[],6-[],7-[6],8-[]] @cnindex add_edges/3 Unify @var{NewGraph} with a new graph obtained by adding the list of edges @var{Edges} to the graph @var{Graph}. In the next example: -@example +@pl_example ?- add_edges([1-[3,5],2-[4],3-[],4-[5],5-[],6-[], 7-[],8-[]],[1-6,2-3,3-2,5-7,3-2,4-5],NL). NL = [1-[3,5,6],2-[3,4],3-[2],4-[5],5-[7],6-[],7-[],8-[]] -@end example +@end pl_example @item del_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph}) @findex del_edges/3 @@ -5021,13 +5063,13 @@ NL = [1-[3,5,6],2-[3,4],3-[2],4-[5],5-[7],6-[],7-[],8-[]] Unify @var{NewGraph} with a new graph obtained by removing the list of edges @var{Edges} from the graph @var{Graph}. Notice that no vertices are deleted. In the next example: -@example +@pl_example ?- del_edges([1-[3,5],2-[4],3-[],4-[5],5-[], 6-[],7-[],8-[]], [1-6,2-3,3-2,5-7,3-2,4-5,1-3],NL). NL = [1-[5],2-[4],3-[],4-[],5-[],6-[],7-[],8-[]] -@end example +@end pl_example @item transpose(+@var{Graph}, -@var{NewGraph}) @findex transpose/3 @@ -5036,12 +5078,12 @@ NL = [1-[5],2-[4],3-[],4-[],5-[],6-[],7-[],8-[]] Unify @var{NewGraph} with a new graph obtained from @var{Graph} by replacing all edges of the form @var{V1-V2} by edges of the form @var{V2-V1}. The cost is @code{O(|V|^2)}. In the next example: -@example +@pl_example ?- transpose([1-[3,5],2-[4],3-[], 4-[5],5-[],6-[],7-[],8-[]], NL). NL = [1-[],2-[],3-[1],4-[2],5-[1,4],6-[],7-[],8-[]] -@end example +@end pl_example Notice that an undirected graph is its own transpose. @item neighbors(+@var{Vertex}, +@var{Graph}, -@var{Vertices}) @@ -5051,13 +5093,13 @@ Notice that an undirected graph is its own transpose. Unify @var{Vertices} with the list of neighbors of vertex @var{Vertex} in @var{Graph}. If the vertice is not in the graph fail. In the next example: -@example +@pl_example ?- neighbors(4,[1-[3,5],2-[4],3-[], 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL). NL = [1,2,7,5] -@end example +@end pl_example @item neighbours(+@var{Vertex}, +@var{Graph}, -@var{Vertices}) @findex neighbours/3 @@ -5065,12 +5107,12 @@ NL = [1,2,7,5] @cnindex neighbours/3 Unify @var{Vertices} with the list of neighbours of vertex @var{Vertex} in @var{Graph}. In the next example: -@example +@pl_example ?- neighbours(4,[1-[3,5],2-[4],3-[], 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL). NL = [1,2,7,5] -@end example +@end pl_example @item complement(+@var{Graph}, -@var{NewGraph}) @findex complement/2 @@ -5078,14 +5120,14 @@ NL = [1,2,7,5] @cnindex complement/2 Unify @var{NewGraph} with the graph complementary to @var{Graph}. In the next example: -@example +@pl_example ?- complement([1-[3,5],2-[4],3-[], 4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL). NL = [1-[2,4,6,7,8],2-[1,3,5,6,7,8],3-[1,2,4,5,6,7,8], 4-[3,5,6,8],5-[1,2,3,4,6,7,8],6-[1,2,3,4,5,7,8], 7-[1,2,3,4,5,6,8],8-[1,2,3,4,5,6,7]] -@end example +@end pl_example @item compose(+@var{LeftGraph}, +@var{RightGraph}, -@var{NewGraph}) @findex compose/3 @@ -5093,11 +5135,11 @@ NL = [1-[2,4,6,7,8],2-[1,3,5,6,7,8],3-[1,2,4,5,6,7,8], @cnindex compose/3 Compose the graphs @var{LeftGraph} and @var{RightGraph} to form @var{NewGraph}. In the next example: -@example +@pl_example ?- compose([1-[2],2-[3]],[2-[4],3-[1,2,4]],L). L = [1-[4],2-[1,2,4],3-[]] -@end example +@end pl_example @item top_sort(+@var{Graph}, -@var{Sort}) @findex top_sort/2 @@ -5106,11 +5148,11 @@ L = [1-[4],2-[1,2,4],3-[]] Generate the set of nodes @var{Sort} as a topological sorting of graph @var{Graph}, if one is possible. In the next example we show how topological sorting works for a linear graph: -@example +@pl_example ?- top_sort([_138-[_219],_219-[_139], _139-[]],L). L = [_138,_219,_139] -@end example +@end pl_example @item top_sort(+@var{Graph}, -@var{Sort0}, -@var{Sort}) @findex top_sort/3 @@ -5126,11 +5168,11 @@ sorting of graph @var{Graph}, if one is possible. Generate the graph @var{Closure} as the transitive closure of graph @var{Graph}. In the next example: -@example +@pl_example ?- transitive_closure([1-[2,3],2-[4,5],4-[6]],L). L = [1-[2,3,4,5,6],2-[4,5,6],4-[6]] -@end example +@end pl_example @item reachable(+@var{Node}, +@var{Graph}, -@var{Vertices}) @findex reachable/3 @@ -5138,11 +5180,11 @@ L = [1-[2,3,4,5,6],2-[4,5,6],4-[6]] @cnindex reachable/3 Unify @var{Vertices} with the set of all vertices in graph @var{Graph} that are reachable from @var{Node}. In the next example: -@example +@pl_example ?- reachable(1,[1-[3,5],2-[4],3-[],4-[5],5-[]],V). V = [1,3,5] -@end example +@end pl_example @end table @@ -5364,16 +5406,16 @@ The path @var{Path} is a path starting at vertex @var{Vertex} in graph @var{Graph}. @item dgraph_path(+@var{Vertex}, +@var{Vertex1}, +@var{Graph}, ?@var{Path}) -@findex dgraph_path/3 -@snindex dgraph_path/3 -@cnindex dgraph_path/3 +@findex dgraph_path/4 +@snindex dgraph_path/4 +@cnindex dgraph_path/4 The path @var{Path} is a path starting at vertex @var{Vertex} in graph @var{Graph} and ending at path @var{Vertex2}. @item dgraph_reachable(+@var{Vertex}, +@var{Graph}, ?@var{Edges}) -@findex dgraph_path/3 -@snindex dgraph_path/3 -@cnindex dgraph_path/3 +@findex dgraph_reachable/3 +@snindex dgraph_reachable/3 +@cnindex dgraph_reachable/3 The path @var{Path} is a path starting at vertex @var{Vertex} in graph @var{Graph}. @@ -5504,9 +5546,9 @@ Give general overview of data-base usage in the system. List memory usage for every static predicate. @item db_static(+@var{Threshold}) -@findex db_static/0 -@snindex db_static/0 -@cnindex db_static/0 +@findex db_static/1 +@snindex db_static/1 +@cnindex db_static/1 List memory usage for every static predicate. Predicate must use more than @var{Threshold} bytes. @@ -5517,9 +5559,9 @@ than @var{Threshold} bytes. List memory usage for every dynamic predicate. @item db_dynamic(+@var{Threshold}) -@findex db_dynamic/0 -@snindex db_dynamic/0 -@cnindex db_dynamic/0 +@findex db_dynamic/1 +@snindex db_dynamic/1 +@cnindex db_dynamic/1 List memory usage for every dynamic predicate. Predicate must use more than @var{Threshold} bytes. @@ -5536,11 +5578,11 @@ lambda expressions to simplify higher order programming based on @code{call/N}. Lambda expressions are represented by ordinary Prolog terms. There are two kinds of lambda expressions: -@example +@pl_example Free+\X1^X2^ ..^XN^Goal \X1^X2^ ..^XN^Goal -@end example +@end pl_example The second is a shorthand for@code{ t+\X1^X2^..^XN^Goal}, where @code{Xi} are the parameters. @@ -5556,20 +5598,20 @@ currently not checked. Violations may lead to unexpected bindings. In the following example the parentheses around @code{X>3} are necessary. -@example +@pl_example ?- use_module(library(lambda)). ?- use_module(library(apply)). ?- maplist(\X^(X>3),[4,5,9]). true. -@end example +@end pl_example In the following @var{X} is a variable that is shared by both instances of the lambda expression. The second query illustrates the cooperation of continuations and lambdas. The lambda expression is in this case a continuation expecting a further argument. -@example +@pl_example ?- Xs = [A,B], maplist(X+\Y^dif(X,Y), Xs). Xs = [A, B], dif(X, A), @@ -5580,25 +5622,25 @@ Xs = [A, B], dif(X, A), dif(X, B). -@end example +@end pl_example The following queries are all equivalent. To see this, use the fact @code{f(x,y)}. -@example +@pl_example ?- call(f,A1,A2). ?- call(\X^f(X),A1,A2). -?- call(\X^Y^f(X,Y), A1,A2). +?- call(\X^Y^f(X,Y), A1,A2). ?- call(\X^(X+\Y^f(X,Y)), A1,A2). ?- call(call(f, A1),A2). ?- call(f(A1),A2). ?- f(A1,A2). A1 = x, A2 = y. -@end example +@end pl_example Further discussions -at @url{http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord}. +at Ulrich Neumerker's page in @url{http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord}. @node LAM, BDDs, Lambda, Library @@ -5761,9 +5803,9 @@ Broadcasts the message @var{Data} with tag @var{Tag} from the process with rank to all other processes. @item mpi_ibcast(+@var{Root}, +@var{Data}, +@var{Tag}) -@findex mpi_bcast/3 -@snindex mpi_bcast/3 -@cnindex mpi_bcast/3 +@findex mpi_ibcast/3 +@snindex mpi_ibcast/3 +@cnindex mpi_ibcast/3 Non-blocking operation. Broadcasts the message @var{Data} with tag @var{Tag} from the process with rank @var{Root} to all other processes. @@ -5861,8 +5903,7 @@ logical or @item bdd_tree(+@var{BDDHandle}, @var{Term}) @findex bdd_tree/2 Convert the BDD or ADD represented by @var{BDDHandle} to a Prolog term -of the form @code{bdd(@var{Dir}, @var{Nodes}, @var{Vars})} or @code{ -mtbdd(@var{Nodes}, @var{Vars})}, respectively. The arguments are: +of the form @code{bdd(@var{Dir}, @var{Nodes}, @var{Vars})} or @code{mtbdd(@var{Nodes}, @var{Vars})}, respectively. The arguments are: @itemize @item @var{Dir} direction of the BDD, usually 1 @@ -5971,9 +6012,9 @@ The result will be a file in dot format. You can make a pdf at the shell by asking @code{dot -Tpdf filename > output.pdf}. @item make_diagram(+inputfilename, +ouputfilename, +predicate, +depth, +extension) -@findex make_diagram/2 -@snindex make_diagram/2 -@cnindex make_diagram/2 +@findex make_diagram/5 +@snindex make_diagram/5 +@cnindex make_diagram/5 The same as @code{make_diagram/2} but you can define how many of the imported/exporeted predicates will be shown with predicate, and how deep the crawler is allowed to go with depth. The extension is used if the file use module directives do not include a file extension. @@ -6159,7 +6200,7 @@ no @end table @node Attributed Variables, CLPR, Co-routining, Extensions -@chapter Attributed Variables +@section Attributed Variables @cindex attributed variables @menu @@ -6242,6 +6283,7 @@ attribute_goals(X) --> Before explaining the code we give some example queries: +@texinfo @multitable @columnfractions .70 .30 @item @code{?- domain(X, [a,b]), X = c} @tab @code{fail} @@ -6250,6 +6292,8 @@ Before explaining the code we give some example queries: @item @code{domain(X, [a,b,c]), domain(X, [a,c]).} @tab @code{domain(X, [a,c]).} @end multitable +@end texinfo + The predicate @code{domain/2} fetches (first clause) or assigns (second clause) the variable a @emph{domain}, a set of values it can @@ -6269,15 +6313,6 @@ these attributes. @table @code -@item attvar(?@var{Term}) -@findex attvar/1 -@snindex attvar/1 -@cnindex attvar/1 - -Succeeds if @code{Term} is an attributed variable. Note that @code{var/1} also -succeeds on attributed variables. Attributed variables are created with -@code{put_attr/3}. - @item put_attr(+@var{Var},+@var{Module},+@var{Value}) @findex put_attr/3 @snindex put_attr/3 @@ -6555,7 +6590,7 @@ It is up to the user to define which actions may be performed by unified with @var{Value}. If @t{verify_attributes/3} fails, the unification will fail. -Notice that the @t{verify_attributes/3} may be called even if @var{Var} +Notice that the @t{verify_attributes/3} may be called even if @var{Var}< has no attributes in module @t{Module}. In this case the routine should simply succeed with @var{Goals} unified with the empty list. @@ -6583,14 +6618,6 @@ Prolog top-level to display attributes: User-defined procedure, called to convert the attributes in @var{Var} to a @var{Goal}. Should fail when no interpretation is available. -@item @var{Module}:project_attributes(@var{-QueryVars}, @var{+AttrVars}) -@findex project_attributes/2 -@syindex project_attributes/2 -@cnindex project_attributes/2 -User-defined procedure, called to project the attributes in the query, -@var{AttrVars}, given that the set of variables in the query is -@var{QueryVars}. - @end table @node Projecting Attributes, Attribute Examples, Displaying Attributes, Old Style Attribute Declarations @@ -6820,7 +6847,7 @@ attributes from other known solvers/modules via the module prefix in @include chr.tex @node Logtalk, MYDDAS, CHR, Extensions -@chapter Logtalk +@section Logtalk @cindex Logtalk The Logtalk object-oriented extension is available after running its @@ -6830,7 +6857,7 @@ program group in the Start Menu on Windows systems. For more information please see the URL @url{http://logtalk.org/}. @node MYDDAS, Threads, Logtalk, Extensions -@chapter MYDDAS +@section MYDDAS @cindex MYDDAS The MYDDAS database project was developed within a FCT project aiming at @@ -7582,7 +7609,7 @@ You can see the available SQL Modes at the MySQL homepage at @url{http://www.mysql.org}. @node Threads, Parallelism, MYDDAS, Extensions -@chapter Threads +@section Threads YAP implements a SWI-Prolog compatible multithreading library. Like in SWI-Prolog, Prolog threads have their own stacks and @@ -8257,7 +8284,7 @@ Enumerates all existing mutexes. If the mutex is held by some thread, @node Parallelism, Tabling, Threads, Extensions -@chapter Parallelism +@section Parallelism @cindex parallelism @cindex or-parallelism @@ -8296,7 +8323,7 @@ We expect that some of these restrictions will be removed in future releases. @node Tabling, Low Level Tracing, Parallelism , Extensions -@chapter Tabling +@section Tabling @cindex tabling @strong{YAPTab} is the tabling engine that extends YAP's execution @@ -8449,7 +8476,7 @@ Prints statistics on space used by all tables. @node Low Level Tracing, Low Level Profiling, Tabling, Extensions -@chapter Tracing at Low Level +@section Tracing at Low Level It is possible to follow the flow at abstract machine level if YAP is compiled with the flag @code{LOW_LEVEL_TRACER}. Note @@ -8468,16 +8495,16 @@ deactivate low level tracing: Begin display of messages at procedure entry and retry. @item stop_low_level_trace -@findex start_low_level_trace/0 -@snindex start_low_level_trace/0 -@cnindex start_low_level_trace/0 +@findex stop_low_level_trace/0 +@snindex stop_low_level_trace/0 +@cnindex stop_low_level_trace/0 Stop display of messages at procedure entry and retry. @end table Note that this compile-time option will slow down execution. @node Low Level Profiling, , Low Level Tracing, Extensions -@chapter Profiling the Abstract Machine +@section Profiling the Abstract Machine Implementors may be interested in detecting on which abstract machine instructions are executed by a program. The @code{ANALYST} flag can give @@ -8509,7 +8536,7 @@ label @var{A}. The label must be an atom. @end table @node Debugging,Efficiency,Extensions,Top -@chapter Debugging +@section Debugging @menu * Deb Preds:: Debugging Predicates @@ -8792,10 +8819,10 @@ shows the active goal using display/1 @item + true ; atom(TrueFileName), TrueFileName \= [] ), !, + absolute_file_name(File,Opts,TrueFileName). + absolute_file_name(File,Opts,TrueFileName) :- + '$absolute_file_name'(File,Opts,TrueFileName,absolute_file_name(File,Opts,TrueFileName)). /** - @brief absolute_file_name(+Name:atom,+Options:list) is nondet + absolute_file_name(+Name:atom,+Path:atom) is nondet Converts the given file specification into an absolute path, using default options. See absolute_file_name/3 for details on the options. */ @@ -58,79 +136,7 @@ absolute_file_name(File0,File) :- '$absolute_file_name'(F0,[access(read),file_type(source),file_errors(fail),solutions(first),expand(true)],F,G). -/** - @brief absolute_file_name(+File:atom, +Options:list, +Path:atom) is nondet - @brief absolute_file_name(-File:atom, +Path:atom, +Options:list) is nondet - Option is a list of options to guide the conversion: - - - extensions(+ListOfExtensions) - - List of file-extensions to try. Default is `''`. For each - extension, absolute_file_name/3 will first add the extension and then - verify the conditions imposed by the other options. If the condition - fails, the next extension of the list is tried. Extensions may be - specified both as `.ext` or plain `ext`. - - - relative_to(+FileOrDir) - - Resolve the path relative to the given directory or directory the - holding the given file. Without this option, paths are resolved - relative to the working directory (see [working_directory/2](@ref working_directory/2)) or, - if Spec is atomic and `absolute_file_name/[2,3]` is executed - in a directive, it uses the current source-file as reference. - - - access(+Mode) - - Imposes the condition access_file(File, Mode). Mode is one of `read`, `write`, `append`, `exist` or - `none` (default). - - See also `access_file/2`. - - - file_type(+Type) - - Defines extensions. Current mapping: `txt` implies `['']`, - `prolog` implies `['.yap', '.pl', '.prolog', '']`, `executable` - implies `['.so', '']`, `qlf` implies `['.qlf', '']` and - `directory` implies `['']`. The file-type `source` - is an alias for `prolog` for compatibility to SICStus Prolog. - See also `prolog_file_type/2`. - - Notice also that this predicate only - returns non-directories, unless the option `file_type(directory)` is - specified, or unless `access(none)`. - - - file_errors(`fail`/`error`) - - If `error` (default), throw and `existence_error` exception - if the file cannot be found. If `fail`, stay silent. - - - solutions(`first`/`all`) - - If `first` (default), the predicates leaves no choice-point. - Otherwise a choice-point will be left and backtracking may yield - more solutions. - - - expand(`true`/`false`) - - If `true` (default is `false`) and Spec is atomic, - call [expand_file_name/2](@ref expand_file_name2) followed by [member/2](@ref member2) on Spec before - proceeding. This is originally a SWI-Prolog extension. - -Compatibility considerations to common argument-order in ISO as well -as SICStus absolute_file_name/3 forced us to be flexible here. -If the last argument is a list and the 2nd not, the arguments are -swapped, making the call `absolute_file_name`(+Spec, -Path, -+Options) valid as well. -*/ - -absolute_file_name(File,TrueFileName,Opts) :- - ( var(TrueFileName) -> true ; atom(TrueFileName), TrueFileName \= [] ), - !, - absolute_file_name(File,Opts,TrueFileName). -absolute_file_name(File,Opts,TrueFileName) :- - '$absolute_file_name'(File,Opts,TrueFileName,absolute_file_name(File,Opts,TrueFileName)). - '$absolute_file_name'(File, _Opts, _TrueFileName, G) :- var(File), !, '$do_error'(instantiation_error, G). '$absolute_file_name'(File,Opts,TrueFileName, G) :- @@ -219,7 +225,7 @@ absolute_file_name(File,Opts,TrueFileName) :- '$do_error'(domain_error(file_errors,T),G). '$check_fn_errors'(T,G) :- !, '$do_error'(type_error(atom,T),G). - + '$check_fn_solutions'(V,G) :- var(V), !, '$do_error'(instantiation_error, G). '$check_fn_solutions'(first,_) :- !. @@ -455,7 +461,8 @@ absolute_file_name(File,Opts,TrueFileName) :- '$add_file_to_dir'(P0,A,Atoms,NFile) :- atom_concat([P0,A,Atoms],NFile). -/** @brief path(-Directories:list) is det [DEPRECATED] +/** + path(-Directories:list) is det,deprecated YAP specific procedure that returns a list of user-defined directories in the library search-path. @@ -467,11 +474,18 @@ path(Path) :- findall(X,'$in_path'(X),Path). ( S = "" -> X = '.' ; atom_codes(X,S) ). -/** @brief add_to_path(+Directory:atom) is det [DEPRECATED] +/** + add_to_path(+Directory:atom) is det,deprecated + YAP-specific predicate to include directory in library search path. */ add_to_path(New) :- add_to_path(New,last). +/** + add_to_path(+Directory:atom, +Position:atom) is det,deprecated + + YAP-specific predicate to include directory in front or back of library search path. +*/ add_to_path(New,Pos) :- atom(New), !, '$check_path'(New,Str), @@ -482,7 +496,7 @@ add_to_path(New,Pos) :- '$add_to_path'(New,last) :- !, recordz('$path',New,_). '$add_to_path'(New,first) :- recorda('$path',New,_). -/** @brief remove_from_path(+Directory:atom) is det [DEPRECATED] +/** remove_from_path(+Directory:atom) is det,deprecated */ remove_from_path(New) :- '$check_path'(New,Path), @@ -494,7 +508,15 @@ remove_from_path(New) :- '$check_path'(New,Path), '$check_path'([Ch],[Ch,A]) :- !, integer(Ch), '$dir_separator'(A). '$check_path'([N|S],[N|SN]) :- integer(N), '$check_path'(S,SN). -/** @brief user:library_directory(Directory:atom) +/** + user:library_directory(?Directory:atom) is nondet, dynamic + + Dynamic, multi-file predicate that succeeds when _Directory_ is a + current library directory name. Asserted in the user module. + + Library directories are the places where files specified in the form + `library( _File_)` are searched by the predicates consult/1, + reconsult/1, use_module/1, ensure_loaded/1, and load_files/2. */ @@ -502,7 +524,8 @@ remove_from_path(New) :- '$check_path'(New,Path), :- dynamic user:library_directory/1. -/** @brief user:commons_directory(Directory:atom) +/** + user:commons_directory(?Directory:atom) is nondet, dynamic */ @@ -510,7 +533,8 @@ remove_from_path(New) :- '$check_path'(New,Path), :- dynamic user:commons_directory/1. -/** @brief user:prolog_file_type(Suffix:atom, Handler:atom) +/** + user:prolog_file_type(?Suffix:atom, ?Handler:atom) is nondet, dynamic */ @@ -531,7 +555,25 @@ user:prolog_file_type(A, prolog) :- user:prolog_file_type(A, executable) :- current_prolog_flag(shared_object_extension, A). -/** @brief user:file_search_path(+Type:atom, -Directory:atom) +/** + user:file_search_path(+Name:atom, -Directory:atom) is nondet + + Allows writing file names as compound terms. The _Name_ and + _DIRECTORY_ must be atoms. The predicate may generate multiple + solutions. The predicate is originally defined as follows: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~prolog +file_search_path(library,A) :- + library_directory(A). +file_search_path(system,A) :- + prolog_flag(host_type,A). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Thus, `compile(library(A))` will search for a file using + library_directory/1 to obtain the prefix, + whereas 'compile(system(A))` would look at the `host_type` flag. + +@} */ diff --git a/pl/arith.yap b/pl/arith.yap index ccf3f5e1d..77ec97cee 100644 --- a/pl/arith.yap +++ b/pl/arith.yap @@ -298,125 +298,4 @@ expand_expr(Op, X, Y, O, Q, P) :- '$preprocess_args_for_non_commutative'(X, Y, Z, W, E) :- '$do_and'(Z = X, Y = W, E). -/* Arithmetics */ - - - -% M and N nonnegative integers, N is the successor of M -succ(M,N) :- - ( - var(M) - -> - ( - integer(N), - N > 0 - -> - '$plus'(N,-1,M) - ; - '$succ_error'(M,N) - ) - ; - integer(M), - M >= 0 - -> - ( - var(N) - -> - '$plus'(M,1,N) - ; - integer(N), - N > 0 - -> - '$plus'(M,1,N) - ; - '$succ_error'(M,N) - ) - ; - '$succ_error'(M,N) - ). - -'$succ_error'(M,N) :- - var(M), - var(N), !, - '$do_error'(instantiation_error,succ(M,N)). -'$succ_error'(M,N) :- - nonvar(M), - \+ integer(M), - '$do_error'(type_error(integer, M),succ(M,N)). -'$succ_error'(M,N) :- - nonvar(M), - M < 0, - '$do_error'(domain_error(not_less_than_zero, M),succ(M,N)). -'$succ_error'(M,N) :- - nonvar(N), - \+ integer(N), - '$do_error'(type_error(integer, N),succ(M,N)). -'$succ_error'(M,N) :- - nonvar(N), - N < 0, - '$do_error'(domain_error(not_less_than_zero, N),succ(M,N)). - - - -plus(X, Y, Z) :- - ( - var(X) - -> - ( - integer(Y), integer(Z) - -> - '$minus'(Z,Y,X) - ; - '$plus_error'(X,Y,Z) - ) - ; - integer(X) - -> - ( - var(Y) - -> - ( - integer(Z) - -> - '$minus'(Z,X,Y) - ; - '$plus_error'(X,Y,Z) - ) - ; - integer(Y) - -> - ( - integer(Z) - -> - '$minus'(Z,Y,X) - ; - var(Z) - -> - '$plus'(X,Y,Z) - ; - '$plus_error'(X,Y,Z) - ) - ; - '$plus_error'(X,Y,Z) - ) - ; - '$plus_error'(X,Y,Z) - ). - -'$plus_error'(X,Y,Z) :- - nonvar(X), - \+ integer(X), - '$do_error'(type_error(integer, X),plus(X,Y,Z)). -'$plus_error'(X,Y,Z) :- - nonvar(Y), - \+ integer(Y), - '$do_error'(type_error(integer, Y),plus(X,Y,Z)). -'$plus_error'(X,Y,Z) :- - nonvar(Z), - \+ integer(Z), - '$do_error'(type_error(integer, Z),plus(X,Y,Z)). -'$plus_error'(X,Y,Z) :- - '$do_error'(instantiation_error,plus(X,Y,Z)). - - diff --git a/pl/arithpreds.yap b/pl/arithpreds.yap new file mode 100644 index 000000000..51944851f --- /dev/null +++ b/pl/arithpreds.yap @@ -0,0 +1,170 @@ +/************************************************************************* +* * +* YAP Prolog * +* * +* Yap Prolog was developed at NCCUP - Universidade do Porto * +* * +* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * +* * +************************************************************************** +* * +* File: arithpreds.yap * +* Last rev: * +* mods: * +* comments: arithmetical predicates * +* * +*************************************************************************/ + +/** + @file arithpreds.yap + + @addtogroup arithmetic_preds + + + @{ +*/ + +:- system_module(arithmetic_predicates, [ + plus/3, + succ/2], []). + +:- use_system_module( '$_errors', ['$do_error'/2]). + + +/** succ(? _Int1_:int, ? _Int2_:int) is det + * + + True if _Int2_ = _Int1_ + 1 and _Int1_ \>= 0. At least + one of the arguments must be instantiated to a natural number. This + predicate raises the domain-error not_less_than_zero if called with + a negative integer. E.g. `succ(X, 0)` fails silently and `succ(X, -1)` + raises a domain-error. The behaviour to deal with natural numbers + only was defined by Richard O'Keefe to support the common + count-down-to-zero in a natural way. + + */ + +% M and N nonnegative integers, N is the successor of M +succ(M,N) :- + ( + var(M) + -> + ( + integer(N), + N > 0 + -> + '$plus'(N,-1,M) + ; + '$succ_error'(M,N) + ) + ; + integer(M), + M >= 0 + -> + ( + var(N) + -> + '$plus'(M,1,N) + ; + integer(N), + N > 0 + -> + '$plus'(M,1,N) + ; + '$succ_error'(M,N) + ) + ; + '$succ_error'(M,N) + ). + +'$succ_error'(M,N) :- + var(M), + var(N), !, + '$do_error'(instantiation_error,succ(M,N)). +'$succ_error'(M,N) :- + nonvar(M), + \+ integer(M), + '$do_error'(type_error(integer, M),succ(M,N)). +'$succ_error'(M,N) :- + nonvar(M), + M < 0, + '$do_error'(domain_error(not_less_than_zero, M),succ(M,N)). +'$succ_error'(M,N) :- + nonvar(N), + \+ integer(N), + '$do_error'(type_error(integer, N),succ(M,N)). +'$succ_error'(M,N) :- + nonvar(N), + N < 0, + '$do_error'(domain_error(not_less_than_zero, N),succ(M,N)). + +/** plus(? _Int1_:int, ? _Int2_:int, ? _Int3_:int) is det + + True if _Int3_ = _Int1_ + _Int2_. At least two of the + three arguments must be instantiated to integers. + + @} + + */ + +plus(X, Y, Z) :- + ( + var(X) + -> + ( + integer(Y), integer(Z) + -> + '$minus'(Z,Y,X) + ; + '$plus_error'(X,Y,Z) + ) + ; + integer(X) + -> + ( + var(Y) + -> + ( + integer(Z) + -> + '$minus'(Z,X,Y) + ; + '$plus_error'(X,Y,Z) + ) + ; + integer(Y) + -> + ( + integer(Z) + -> + '$minus'(Z,Y,X) + ; + var(Z) + -> + '$plus'(X,Y,Z) + ; + '$plus_error'(X,Y,Z) + ) + ; + '$plus_error'(X,Y,Z) + ) + ; + '$plus_error'(X,Y,Z) + ). + +'$plus_error'(X,Y,Z) :- + nonvar(X), + \+ integer(X), + '$do_error'(type_error(integer, X),plus(X,Y,Z)). +'$plus_error'(X,Y,Z) :- + nonvar(Y), + \+ integer(Y), + '$do_error'(type_error(integer, Y),plus(X,Y,Z)). +'$plus_error'(X,Y,Z) :- + nonvar(Z), + \+ integer(Z), + '$do_error'(type_error(integer, Z),plus(X,Y,Z)). +'$plus_error'(X,Y,Z) :- + '$do_error'(instantiation_error,plus(X,Y,Z)). + + diff --git a/pl/init.yap b/pl/init.yap index 18aa4c8a0..38860349a 100755 --- a/pl/init.yap +++ b/pl/init.yap @@ -114,6 +114,7 @@ otherwise. 'ground.yap', 'listing.yap', 'preds.yap', + 'arithpreds,yap', % modules must be after preds, otherwise we will have trouble % with meta-predicate expansion being invoked 'modules.yap', From 0625f1d7ad09ca565525dbf65937d634430c57c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 21 Apr 2014 11:20:00 +0100 Subject: [PATCH 2/4] doc support --- pl/init.yap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pl/init.yap b/pl/init.yap index 38860349a..7eff9c3e9 100755 --- a/pl/init.yap +++ b/pl/init.yap @@ -114,7 +114,7 @@ otherwise. 'ground.yap', 'listing.yap', 'preds.yap', - 'arithpreds,yap', + 'arithpreds.yap', % modules must be after preds, otherwise we will have trouble % with meta-predicate expansion being invoked 'modules.yap', From 605e68c80dac003424036b4015cb4b1add1f0977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Mon, 21 Apr 2014 11:29:05 +0100 Subject: [PATCH 3/4] fix prolog:messages --- pl/messages.yap | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pl/messages.yap b/pl/messages.yap index b5384e67e..bcc05f818 100644 --- a/pl/messages.yap +++ b/pl/messages.yap @@ -20,12 +20,11 @@ [system_message/4, prefix/6, prefix/5, - file_location/3, - message/3]). + file_location/3]). :- use_system_module( user, [generate_message_hook/3]). -:- multifile message/3. +:- multifile prolog:message/3. :- multifile user:generate_message_hook/3. From f1951777b7da271f3e2ad21517c840af796cf53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADtor=20Santos=20Costa?= Date: Wed, 23 Apr 2014 21:39:32 +0100 Subject: [PATCH 4/4] fix checker to use read for singleton variables, instead of always computing them. --- C/cdmgr.c | 2 - C/iopreds.c | 74 ++++++++++++++++++++++-- C/modules.c | 3 +- C/tracer.c | 2 +- H/iatoms.h | 6 ++ H/pl-incl.h | 7 +-- H/pl-shared.h | 16 ++++++ H/ratoms.h | 6 ++ H/tatoms.h | 12 ++++ misc/ATOMS | 6 ++ os/pl-read.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++-- pl/boot.yap | 12 +--- pl/checker.yap | 123 ++++++++++++++++++++++++---------------- pl/messages.yap | 25 +++++++-- 14 files changed, 358 insertions(+), 82 deletions(-) diff --git a/C/cdmgr.c b/C/cdmgr.c index 5a1e0de03..e23c8ade7 100644 --- a/C/cdmgr.c +++ b/C/cdmgr.c @@ -1998,7 +1998,6 @@ static void expand_consult( void ) LOCAL_ConsultLow = new_cl; } -/* p was already locked */ static int not_was_reconsulted(PredEntry *p, Term t, int mode) { @@ -6458,7 +6457,6 @@ p_nth_instance( USES_REGS1 ) } - void Yap_InitCdMgr(void) { diff --git a/C/iopreds.c b/C/iopreds.c index 305ace4a8..fdd148fe7 100755 --- a/C/iopreds.c +++ b/C/iopreds.c @@ -553,6 +553,7 @@ Yap_read_term(term_t t0, IOSTREAM *inp_stream, struct read_data_t *rd) } else { Yap_clean_tokenizer(tokstart, LOCAL_VarTable, LOCAL_AnonVarTable, LOCAL_Comments); rd->varnames = 0; + rd->singles = 0; return Yap_unify_constant( Yap_GetFromSlot( t0 PASS_REGS), MkAtomTerm (AtomEof)); } } @@ -636,7 +637,6 @@ Yap_read_term(term_t t0, IOSTREAM *inp_stream, struct read_data_t *rd) return FALSE; } - if (rd->variables) { while (TRUE) { CELL *old_H = HR; @@ -680,8 +680,15 @@ Yap_read_term(term_t t0, IOSTREAM *inp_stream, struct read_data_t *rd) TR = old_TR; } } - if (!Yap_unify(v, Yap_GetFromSlot( rd->singles PASS_REGS))) - return FALSE; + if (rd->singles == 1) { + if (IsPairTerm(v)) + rd->singles = Yap_InitSlot( v PASS_REGS); + else + rd->singles = FALSE; + } else if (rd->singles) { + if (!Yap_unify( rd->singles, Yap_GetFromSlot( v PASS_REGS ))) + return FALSE; + } } Yap_clean_tokenizer(tokstart, LOCAL_VarTable, LOCAL_AnonVarTable, LOCAL_Comments); return TRUE; @@ -871,6 +878,65 @@ p_float_format( USES_REGS1 ) return TRUE; } + +static Int +p_style_checker( USES_REGS1 ) +{ + Term t = Deref( ARG1 ); + LD_FROM_REGS + + if (IsVarTerm(t)) { + Term t = TermNil; + if ( debugstatus.styleCheck & LONGATOM_CHECK) { + t = MkPairTerm( MkAtomTerm(AtomAtom), t ); + } + if ( debugstatus.styleCheck & SINGLETON_CHECK) { + t = MkPairTerm( MkAtomTerm(AtomSingleton), t ); + } + if ( debugstatus.styleCheck & MULTITON_CHECK) { + t = MkPairTerm( MkAtomTerm(AtomVarBranches), t ); + } + if ( debugstatus.styleCheck & DISCONTIGUOUS_STYLE) { + t = MkPairTerm( MkAtomTerm(AtomDiscontiguous), t ); + } + if ( debugstatus.styleCheck & NOEFFECT_CHECK) { + t = MkPairTerm( MkAtomTerm(AtomNoEffect), t ); + } + if ( debugstatus.styleCheck & CHARSET_CHECK) { + t = MkPairTerm( MkAtomTerm(AtomCharset), t ); + } + if ( debugstatus.styleCheck & MULTIPLE_CHECK) { + t = MkPairTerm( MkAtomTerm(AtomMultiple), t ); + } + } else { + while (IsPairTerm(t)) { + Term h = HeadOfTerm( t ); + t = TailOfTerm( t ); + + if (IsAtomTerm(h)) { + Atom at = AtomOfTerm( h ); + if (at == AtomAtom) debugstatus.styleCheck |= LONGATOM_CHECK; + else if (at == AtomSingleton) debugstatus.styleCheck |= SINGLETON_CHECK; + else if (at == AtomVarBranches) debugstatus.styleCheck |= MULTITON_CHECK; + else if (at == AtomDiscontiguous) debugstatus.styleCheck |= DISCONTIGUOUS_STYLE; + else if (at == AtomNoEffect) debugstatus.styleCheck |= NOEFFECT_CHECK; + else if (at == AtomCharset) debugstatus.styleCheck |= CHARSET_CHECK; + else if (at == AtomMultiple) debugstatus.styleCheck |= MULTIPLE_CHECK; + } else { + Atom at = AtomOfTerm( ArgOfTerm( 1, h ) ); + if (at == AtomAtom) debugstatus.styleCheck |= LONGATOM_CHECK; + else if (at == AtomSingleton) debugstatus.styleCheck &= ~SINGLETON_CHECK; + else if (at == AtomVarBranches) debugstatus.styleCheck &= ~MULTITON_CHECK; + else if (at == AtomDiscontiguous) debugstatus.styleCheck &= ~DISCONTIGUOUS_STYLE; + else if (at == AtomNoEffect) debugstatus.styleCheck &= ~NOEFFECT_CHECK; + else if (at == AtomMultiple) debugstatus.styleCheck &= ~MULTIPLE_CHECK; + } + } + } + return TRUE; +} + + void Yap_InitBackIO (void) { @@ -915,5 +981,5 @@ Yap_InitIOPreds(void) // Yap_InitCPred ("stream_select", 3, p_stream_select, SafePredFlag|SyncPredFlag); #endif Yap_InitCPred ("$float_format", 1, p_float_format, SafePredFlag|SyncPredFlag); - + Yap_InitCPred ("$style_checker", 1, p_style_checker, SyncPredFlag); } diff --git a/C/modules.c b/C/modules.c index 7a441c7f8..27d16502e 100644 --- a/C/modules.c +++ b/C/modules.c @@ -120,8 +120,9 @@ LookupModule(Term a ) ModEntry *me; /* prolog module */ - if (a == 0) + if (a == 0) { return GetModuleEntry(AtomProlog); + } at = AtomOfTerm(a); me = GetModuleEntry(at); return me; diff --git a/C/tracer.c b/C/tracer.c index f0ff4ecf3..13dcf2eeb 100755 --- a/C/tracer.c +++ b/C/tracer.c @@ -146,7 +146,7 @@ low_level_trace(yap_low_level_port port, PredEntry *pred, CELL *args) // if (!worker_id) return; LOCK(Yap_heap_regs->low_level_trace_lock); sc = Yap_heap_regs; - //if (vsc_count == 54) jmp_deb(1); + if (vsc_count == 161862) jmp_deb(1); // Sfprintf(stderr,"B=%p ", B); #ifdef THREADS LOCAL_ThreadHandle.thread_inst_count++; diff --git a/H/iatoms.h b/H/iatoms.h index 6102b7d8a..8a4dcde66 100644 --- a/H/iatoms.h +++ b/H/iatoms.h @@ -50,6 +50,7 @@ AtomCharsio = Yap_LookupAtom("charsio"); AtomCharacter = Yap_LookupAtom("character"); AtomCharacterCode = Yap_LookupAtom("character_code"); + AtomCharset = Yap_LookupAtom("charset"); AtomCleanCall = Yap_FullLookupAtom("$clean_call"); AtomColomn = Yap_LookupAtom(":"); AtomCodeSpace = Yap_LookupAtom("code_space"); @@ -81,6 +82,7 @@ AtomDefault = Yap_LookupAtom("default"); AtomDevNull = Yap_LookupAtom("/dev/null"); AtomDiff = Yap_LookupAtom("\\="); + AtomDiscontiguous = Yap_LookupAtom("discontiguous"); AtomDollar = Yap_FullLookupAtom("$"); AtomDoLogUpdClause = Yap_FullLookupAtom("$do_log_upd_clause"); AtomDoLogUpdClause0 = Yap_FullLookupAtom("$do_log_upd_clause0"); @@ -183,6 +185,7 @@ AtomModify = Yap_LookupAtom("modify"); AtomMost = Yap_LookupAtom("most"); AtomMultiFile = Yap_FullLookupAtom("$mf"); + AtomMultiple = Yap_FullLookupAtom("multiple"); AtomMutable = Yap_LookupAtom("mutable"); AtomMutableVariable = Yap_FullLookupAtom("$mutable_variable"); AtomMyddasDB = Yap_FullLookupAtom("$myddas_db"); @@ -195,6 +198,7 @@ AtomNb = Yap_LookupAtom("nb"); AtomNbTerm = Yap_LookupAtom("nb_term"); AtomNew = Yap_LookupAtom("new"); + AtomNoEffect = Yap_LookupAtom("no_effect"); AtomNoMemory = Yap_LookupAtom("no_memory"); AtomNone = Yap_LookupAtom("none"); AtomNonEmptyList = Yap_LookupAtom("non_empty_list"); @@ -282,6 +286,7 @@ AtomSigUsr2 = Yap_LookupAtom("sig_usr2"); AtomSigVTAlarm = Yap_LookupAtom("sig_vtalarm"); AtomSigWakeUp = Yap_LookupAtom("sig_wake_up"); + AtomSingleton = Yap_LookupAtom("singleton"); AtomSlash = Yap_LookupAtom("/"); AtomSocket = Yap_LookupAtom("socket"); AtomSourceSink = Yap_LookupAtom("source_sink"); @@ -335,6 +340,7 @@ AtomUserOut = Yap_LookupAtom("user_output"); AtomVBar = Yap_LookupAtom("|"); AtomVar = Yap_FullLookupAtom("$VAR"); + AtomVarBranches = Yap_LookupAtom("var_branches"); AtomHiddenVar = Yap_FullLookupAtom("$V"); AtomVariable = Yap_LookupAtom("variable"); AtomVersionNumber = Yap_FullLookupAtom("$version_name"); diff --git a/H/pl-incl.h b/H/pl-incl.h index 55a44a7db..81e05be18 100755 --- a/H/pl-incl.h +++ b/H/pl-incl.h @@ -127,8 +127,6 @@ typedef int Char; /* char that can pass EOF */ #define source_char_no (LD->read_source.position.charno) #define source_byte_no (LD->read_source.position.byteno) -#define debugstatus (LD->_debugstatus) - #if SIZE_DOUBLE==SIZEOF_INT_P #define WORDS_PER_DOUBLE 1 #else @@ -319,10 +317,6 @@ typedef struct word culprit; /* for CVT_nocode/CVT_nochar */ } CVT_result; -#define MAXNEWLINES 5 /* maximum # of newlines in atom */ - -#define LONGATOM_CHECK 0x01 /* read/1: error on intptr_t atoms */ - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Operator types. NOTE: if you change OP_*, check operatorTypeToAtom()! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ @@ -467,6 +461,7 @@ extern int fileerrors; extern int ttymode; + #define CHARESCAPE_FEATURE 0x00001 /* handle \ in atoms */ #define GC_FEATURE 0x00002 /* do GC */ #define TRACE_GC_FEATURE 0x00004 /* verbose gc */ diff --git a/H/pl-shared.h b/H/pl-shared.h index 83c02b726..e156199cd 100755 --- a/H/pl-shared.h +++ b/H/pl-shared.h @@ -258,6 +258,22 @@ typedef struct initialise_handle * InitialiseHandle; extern unsigned int getUnknownModule(module_t m); +/* keep in sync with style_name/1 in boot/prims.pl */ + +#define LONGATOM_CHECK 0x0001 /* read/1: error on intptr_t atoms */ +#define SINGLETON_CHECK 0x0002 /* read/1: check singleton vars */ +#define MULTITON_CHECK 0x0004 /* read/1: check multiton vars */ +#define DISCONTIGUOUS_STYLE 0x0008 /* warn on discontiguous predicates */ +#define DYNAMIC_STYLE 0x0010 /* warn on assert/retract active */ +#define CHARSET_CHECK 0x0020 /* warn on unquoted characters */ +#define SEMSINGLETON_CHECK 0x0040 /* Semantic singleton checking */ +#define NOEFFECT_CHECK 0x0080 /* Check for meaningless statements */ +#define VARBRANCH_CHECK 0x0100 /* warn on unbalanced variables */ +#define MULTIPLE_CHECK 0x0100 /* warn on multiple file definitions for a predicate */ +#define MAXNEWLINES 5 /* maximum # of newlines in atom */ + +#define debugstatus (LD->_debugstatus) + #define truePrologFlag(flag) true(&LD->prolog_flag.mask, flag) #define setPrologFlagMask(flag) set(&LD->prolog_flag.mask, flag) #define clearPrologFlagMask(flag) clear(&LD->prolog_flag.mask, flag) diff --git a/H/ratoms.h b/H/ratoms.h index 216126cc0..b6d236910 100644 --- a/H/ratoms.h +++ b/H/ratoms.h @@ -50,6 +50,7 @@ AtomCharsio = AtomAdjust(AtomCharsio); AtomCharacter = AtomAdjust(AtomCharacter); AtomCharacterCode = AtomAdjust(AtomCharacterCode); + AtomCharset = AtomAdjust(AtomCharset); AtomCleanCall = AtomAdjust(AtomCleanCall); AtomColomn = AtomAdjust(AtomColomn); AtomCodeSpace = AtomAdjust(AtomCodeSpace); @@ -81,6 +82,7 @@ AtomDefault = AtomAdjust(AtomDefault); AtomDevNull = AtomAdjust(AtomDevNull); AtomDiff = AtomAdjust(AtomDiff); + AtomDiscontiguous = AtomAdjust(AtomDiscontiguous); AtomDollar = AtomAdjust(AtomDollar); AtomDoLogUpdClause = AtomAdjust(AtomDoLogUpdClause); AtomDoLogUpdClause0 = AtomAdjust(AtomDoLogUpdClause0); @@ -183,6 +185,7 @@ AtomModify = AtomAdjust(AtomModify); AtomMost = AtomAdjust(AtomMost); AtomMultiFile = AtomAdjust(AtomMultiFile); + AtomMultiple = AtomAdjust(AtomMultiple); AtomMutable = AtomAdjust(AtomMutable); AtomMutableVariable = AtomAdjust(AtomMutableVariable); AtomMyddasDB = AtomAdjust(AtomMyddasDB); @@ -195,6 +198,7 @@ AtomNb = AtomAdjust(AtomNb); AtomNbTerm = AtomAdjust(AtomNbTerm); AtomNew = AtomAdjust(AtomNew); + AtomNoEffect = AtomAdjust(AtomNoEffect); AtomNoMemory = AtomAdjust(AtomNoMemory); AtomNone = AtomAdjust(AtomNone); AtomNonEmptyList = AtomAdjust(AtomNonEmptyList); @@ -282,6 +286,7 @@ AtomSigUsr2 = AtomAdjust(AtomSigUsr2); AtomSigVTAlarm = AtomAdjust(AtomSigVTAlarm); AtomSigWakeUp = AtomAdjust(AtomSigWakeUp); + AtomSingleton = AtomAdjust(AtomSingleton); AtomSlash = AtomAdjust(AtomSlash); AtomSocket = AtomAdjust(AtomSocket); AtomSourceSink = AtomAdjust(AtomSourceSink); @@ -335,6 +340,7 @@ AtomUserOut = AtomAdjust(AtomUserOut); AtomVBar = AtomAdjust(AtomVBar); AtomVar = AtomAdjust(AtomVar); + AtomVarBranches = AtomAdjust(AtomVarBranches); AtomHiddenVar = AtomAdjust(AtomHiddenVar); AtomVariable = AtomAdjust(AtomVariable); AtomVersionNumber = AtomAdjust(AtomVersionNumber); diff --git a/H/tatoms.h b/H/tatoms.h index 2c400fffd..7c7b3f06d 100644 --- a/H/tatoms.h +++ b/H/tatoms.h @@ -98,6 +98,8 @@ #define AtomCharacter Yap_heap_regs->AtomCharacter_ Atom AtomCharacterCode_; #define AtomCharacterCode Yap_heap_regs->AtomCharacterCode_ + Atom AtomCharset_; +#define AtomCharset Yap_heap_regs->AtomCharset_ Atom AtomCleanCall_; #define AtomCleanCall Yap_heap_regs->AtomCleanCall_ Atom AtomColomn_; @@ -160,6 +162,8 @@ #define AtomDevNull Yap_heap_regs->AtomDevNull_ Atom AtomDiff_; #define AtomDiff Yap_heap_regs->AtomDiff_ + Atom AtomDiscontiguous_; +#define AtomDiscontiguous Yap_heap_regs->AtomDiscontiguous_ Atom AtomDollar_; #define AtomDollar Yap_heap_regs->AtomDollar_ Atom AtomDoLogUpdClause_; @@ -364,6 +368,8 @@ #define AtomMost Yap_heap_regs->AtomMost_ Atom AtomMultiFile_; #define AtomMultiFile Yap_heap_regs->AtomMultiFile_ + Atom AtomMultiple_; +#define AtomMultiple Yap_heap_regs->AtomMultiple_ Atom AtomMutable_; #define AtomMutable Yap_heap_regs->AtomMutable_ Atom AtomMutableVariable_; @@ -388,6 +394,8 @@ #define AtomNbTerm Yap_heap_regs->AtomNbTerm_ Atom AtomNew_; #define AtomNew Yap_heap_regs->AtomNew_ + Atom AtomNoEffect_; +#define AtomNoEffect Yap_heap_regs->AtomNoEffect_ Atom AtomNoMemory_; #define AtomNoMemory Yap_heap_regs->AtomNoMemory_ Atom AtomNone_; @@ -562,6 +570,8 @@ #define AtomSigVTAlarm Yap_heap_regs->AtomSigVTAlarm_ Atom AtomSigWakeUp_; #define AtomSigWakeUp Yap_heap_regs->AtomSigWakeUp_ + Atom AtomSingleton_; +#define AtomSingleton Yap_heap_regs->AtomSingleton_ Atom AtomSlash_; #define AtomSlash Yap_heap_regs->AtomSlash_ Atom AtomSocket_; @@ -668,6 +678,8 @@ #define AtomVBar Yap_heap_regs->AtomVBar_ Atom AtomVar_; #define AtomVar Yap_heap_regs->AtomVar_ + Atom AtomVarBranches_; +#define AtomVarBranches Yap_heap_regs->AtomVarBranches_ Atom AtomHiddenVar_; #define AtomHiddenVar Yap_heap_regs->AtomHiddenVar_ Atom AtomVariable_; diff --git a/misc/ATOMS b/misc/ATOMS index 98feea28c..f7719f8bf 100644 --- a/misc/ATOMS +++ b/misc/ATOMS @@ -55,6 +55,7 @@ A Char N "char" A Charsio N "charsio" A Character N "character" A CharacterCode N "character_code" +A Charset N "charset" A CleanCall F "$clean_call" A Colomn N ":" A CodeSpace N "code_space" @@ -86,6 +87,7 @@ A Dec10 N "dec10" A Default N "default" A DevNull N "/dev/null" A Diff N "\\=" +A Discontiguous N "discontiguous" A Dollar F "$" A DoLogUpdClause F "$do_log_upd_clause" A DoLogUpdClause0 F "$do_log_upd_clause0" @@ -188,6 +190,7 @@ A Minus N "-" A Modify N "modify" A Most N "most" A MultiFile F "$mf" +A Multiple F "multiple" A Mutable N "mutable" A MutableVariable F "$mutable_variable" A MyddasDB F "$myddas_db" @@ -200,6 +203,7 @@ A Nan N "nan" A Nb N "nb" A NbTerm N "nb_term" A New N "new" +A NoEffect N "no_effect" A NoMemory N "no_memory" A None N "none" A NonEmptyList N "non_empty_list" @@ -287,6 +291,7 @@ A SigUsr1 N "sig_usr1" A SigUsr2 N "sig_usr2" A SigVTAlarm N "sig_vtalarm" A SigWakeUp N "sig_wake_up" +A Singleton N "singleton" A Slash N "/" A Socket N "socket" A SourceSink N "source_sink" @@ -340,6 +345,7 @@ A UserIn N "user_input" A UserOut N "user_output" A VBar N "|" A Var F "$VAR" +A VarBranches N "var_branches" A HiddenVar F "$V" A Variable N "variable" A VersionNumber F "$version_name" diff --git a/os/pl-read.c b/os/pl-read.c index 648b0c123..3ad3a776c 100644 --- a/os/pl-read.c +++ b/os/pl-read.c @@ -126,6 +126,21 @@ reportReadError(ReadData rd) } +/* static int */ +/* reportSingletons(ReadData rd, singletons, Atom amod, Atom aname, UInt arity) */ +/* { */ +/* printMessage(ATOM_warning, PL_FUNCTOR_CHARS, */ +/* "singletons", 2, */ +/* PL_TERM, singletons, */ +/* PL_TERM, mod, */ +/* PL_FUNCTOR_divide2, */ +/* PL_ATOM, name, */ +/* PL_INT, arity); */ + +/* return FALSE; */ +/* } */ + + /******************************** * RAW READING * *********************************/ @@ -945,15 +960,14 @@ callCommentHook(term_t comments, term_t tpos, term_t term) PL_put_term(av+2, term); if ( (qid = PL_open_query(NULL, PL_Q_NODEBUG|PL_Q_CATCH_EXCEPTION, - (predicate_t)PredCommentHook, av)) ) + (predicate_t)PredCommentHook, av)) ) { term_t ex; if ( !PL_next_solution(qid) && (ex=PL_exception(qid)) ) - printMessage(ATOM_error, PL_TERM, ex); + printMessage(ATOM_error, PL_TERM, ex); PL_close_query(qid); } - PL_discard_foreign_frame(fid); } } @@ -1075,6 +1089,126 @@ unify_read_term_position(term_t tpos ARG_LD) } } +/** read_clause(+Stream:stream, -Clause:clause, +Options:list) + +Options: + * variable_names(-Names) + * process_comment(+Boolean) + * comments(-List) + * syntax_errors(+Atom) + * term_position(-Position) + * subterm_positions(-Layout) +*/ + +static const opt_spec read_clause_options[] = +{ { ATOM_variable_names, OPT_TERM }, + { ATOM_term_position, OPT_TERM }, + { ATOM_subterm_positions, OPT_TERM }, + { ATOM_process_comment, OPT_BOOL }, + { ATOM_comments, OPT_TERM }, + { ATOM_syntax_errors, OPT_ATOM }, + { NULL_ATOM, 0 } +}; + + +static int +read_clause(IOSTREAM *s, term_t term, term_t options ARG_LD) +{ read_data rd; + int rval; + fid_t fid; + term_t tpos = 0; + term_t comments = 0; + term_t opt_comments = 0; + int process_comment; + atom_t syntax_errors = ATOM_dec10; + + { + OPCODE ophook = PredCommentHook->OpcodeOfPred; + if (ophook == UNDEF_OPCODE || ophook == FAIL_OPCODE) + process_comment = FALSE; + else + process_comment = TRUE; + } + if ( !(fid=PL_open_foreign_frame()) ) + return FALSE; + +retry: + init_read_data(&rd, s PASS_LD); + + if ( options && + !scan_options(options, 0, ATOM_read_option, read_clause_options, + &rd.varnames, + &tpos, + &rd.subtpos, + &process_comment, + &opt_comments, + &syntax_errors) ) + { PL_close_foreign_frame(fid); + return FALSE; + } + + if ( opt_comments ) + { comments = PL_new_term_ref(); + } else if ( process_comment ) + { if ( !tpos ) + tpos = PL_new_term_ref(); + comments = PL_new_term_ref(); + } + + REGS_FROM_LD + rd.module = Yap_GetModuleEntry( LOCAL_SourceModule ); + if ( comments ) + rd.comments = PL_copy_term_ref(comments); + rd.on_error = syntax_errors; + rd.singles = rd.styleCheck & SINGLETON_CHECK ? 1 : 0; + if ( (rval=read_term(term, &rd PASS_LD)) && + (!tpos || (rval=unify_read_term_position(tpos PASS_LD))) ) + { + if (rd.singles) { + // warning, singletons([X=_A],f(X,Y,Z), pos). + printMessage(ATOM_warning, + PL_FUNCTOR_CHARS, "singletons", 3, + PL_TERM, rd.singles, + PL_TERM, term, + PL_TERM, tpos ); + } + if ( rd.comments && + (rval = PL_unify_nil(rd.comments)) ) + { if ( opt_comments ) + rval = PL_unify(opt_comments, comments); + else if ( !PL_get_nil(comments) ) + callCommentHook(comments, tpos, term); + } else + { if ( rd.has_exception && reportReadError(&rd) ) + { PL_rewind_foreign_frame(fid); + free_read_data(&rd); + goto retry; + } + } + } + free_read_data(&rd); + + return rval; +} + + +static +PRED_IMPL("read_clause", 3, read_clause, 0) +{ PRED_LD + int rc; + IOSTREAM *s; + + if ( !getTextInputStream(A1, &s) ) + return FALSE; + rc = read_clause(s, A2, A3 PASS_LD); + if ( Sferror(s) ) + return streamStatus(s); + else + PL_release_stream(s); + + return rc; +} + word pl_raw_read(term_t term) @@ -1174,8 +1308,9 @@ retry: { if ( !setDoubleQuotes(dq, &rd.flags) ) return FALSE; } - if ( rd.singles && PL_get_atom(rd.singles, &w) && w == ATOM_warning ) - rd.singles = TRUE; + if ( rd.singles && PL_get_atom(rd.singles, &w) && w == ATOM_warning) + rd.singles = 1; + if ( comments ) rd.comments = PL_copy_term_ref(comments); @@ -1355,6 +1490,7 @@ PL_chars_to_term(const char *s, term_t t) BeginPredDefs(read) PRED_DEF("read_term", 3, read_term, PL_FA_ISO) PRED_DEF("read_term", 2, read_term, PL_FA_ISO) + PRED_DEF("read_clause", 3, read_clause, 0) PRED_DEF("atom_to_term", 3, atom_to_term, 0) PRED_DEF("term_to_atom", 2, term_to_atom, 0) #ifdef O_QUASIQUOTATIONS diff --git a/pl/boot.yap b/pl/boot.yap index a3e28d8a1..fdedd5502 100755 --- a/pl/boot.yap +++ b/pl/boot.yap @@ -1187,17 +1187,7 @@ bootstrap(F) :- !. '$enter_command'(Stream,Mod,Status) :- - read_term(Stream, Command, [module(Mod), variable_names(Vars), term_position(Pos), syntax_errors(dec10), process_comment(true), singletons( Singletons ) ]), - ( Singletons == [] - -> - true - ; - get_value('$syntaxchecksinglevar',on) - -> - '$sv_warning'(Singletons, Command ) - ; - true - ), + read_clause(Stream, Command, [variable_names(Vars), term_position(Pos), syntax_errors(dec10) ]), '$command'(Command,Vars,Pos,Status). '$abort_loop'(Stream) :- diff --git a/pl/checker.yap b/pl/checker.yap index de1df3232..3ac5db55b 100644 --- a/pl/checker.yap +++ b/pl/checker.yap @@ -62,7 +62,7 @@ * * *************************************************************************/ -:- system_module( '$_checker', [no_style_check/1, +:- system_module( style_checker, [no_style_check/1, style_check/1], ['$check_term'/5, '$init_style_check'/1, '$sv_warning'/2, @@ -76,40 +76,84 @@ :- op(1150, fx, multifile). style_check(V) :- var(V), !, fail. -style_check(all) :- - '$syntax_check_single_var'(_,on), - '$syntax_check_discontiguous'(_,on), - '$syntax_check_multiple'(_,on). -style_check(single_var) :- - '$syntax_check_single_var'(_,on). -style_check(singleton) :- - style_check(single_var). -style_check(-single_var) :- - no_style_check(single_var). -style_check(-singleton) :- - no_style_check(single_var). -style_check(discontiguous) :- - '$syntax_check_discontiguous'(_,on). -style_check(-discontiguous) :- - no_style_check(discontiguous). -style_check(multiple) :- - '$syntax_check_multiple'(_,on). -style_check(-multiple) :- - no_style_check(multiple). -style_check([]). -style_check([H|T]) :- style_check(H), style_check(T). +style_check(V) :- + style_check_(V), !. +style_check(V) :- + \+atom(V), \+ list(V), V \= + _, V \= + _, !, + '$do_error'( type_error('+|-|?(Flag)', V), style_check(V) ). +style_check(V) :- + \+atom(V), \+ list(V), V \= + _, V \= + _, !, + '$do_error'( domain_error(style_name(Flag), V), style_check(V) ). + + +style_check_(all) :- + '$style_checker'( [ singleton, discontiguous, multiple ] ). +style_check_(single_var) :- + '$style_checker'( [ singleton ] ). +style_check_(singleton) :- + '$style_checker'( [ singleton ] ). +style_check_(+single_var) :- + '$style_checker'( [ singleton ] ). +style_check_(+singleton) :- + '$style_checker'( [ singleton ] ). +style_check_(-single_var) :- + '$style_checker'( [ -singleton ] ). +style_check_(-singleton) :- + '$style_checker'( [ -singleton ] ). +style_check_(discontiguous) :- + '$style_checker'( [ discontiguous ] ). +style_check_(+discontiguous) :- + '$style_checker'( [ discontiguous ] ). +style_check_(-discontiguous) :- + '$style_checker'( [ -discontiguous ] ). +style_check_(multiple) :- + '$style_checker'( [ multiple ] ). +style_check_(+multiple) :- + '$style_checker'( [ multiple ] ). +style_check_(-multiple) :- + '$style_checker'( [ -multiple ] ). +style_check_(no_effect) :- + '$style_checker'( [ no_effect ] ). +style_check_(+no_effect) :- + '$style_checker'( [ no_effect ] ). +style_check_(-no_effect) :- + '$style_checker'( [ -no_effect ] ). +style_check_(var_branches) :- + '$style_checker'( [ var_branches ] ). +style_check_(+var_branches) :- + '$style_checker'( [ var_branches ] ). +style_check_(-var_branches) :- + '$style_checker'( [ -var_branches ] ). +style_check_(atom) :- + '$style_checker'( [ atom ] ). +style_check_(+atom) :- + '$style_checker'( [ atom ] ). +style_check_(-atom) :- + '$style_checker'( [ -atom ] ). +style_check_(charset) :- + '$style_checker'( [ charset ] ). +style_check_(+charset) :- + '$style_checker'( [ charset ] ). +style_check_(-charset) :- + '$style_checker'( [ -charset ] ). +style_check_('?'(Info) ) :- + '$style_checker '( [ L ] ), + lists:member( Style, [ singleton, discontiguous, multiple ] ), + ( lists:member(Style, L ) -> Info = +Style ; Info = -Style ). +style_check_([]). +style_check_([H|T]) :- style_check(H), style_check(T). no_style_check(V) :- var(V), !, fail. no_style_check(all) :- - '$syntax_check_single_var'(_,off), - '$syntax_check_discontiguous'(_,off), - '$syntax_check_multiple'(_,off). -no_style_check(single_var) :- - '$syntax_check_single_var'(_,off). -no_style_check(discontiguous) :- - '$syntax_check_discontiguous'(_,off). -no_style_check(multiple) :- - '$syntax_check_multiple'(_,off). + '$style_checker'( [ -singleton, -discontiguous, -multiple ] ). +no_style_check(-single_var) :- + '$style_checker'( [ -singleton ] ). +no_style_check(-singleton) :- + '$style_checker'( [ -singleton ] ). +no_style_check(-discontiguous) :- + '$stylechecker'( [ -discontiguous ] ). +no_style_check(-multiple) :- + '$style_checker'( [ -multiple ] ). no_style_check([]). no_style_check([H|T]) :- no_style_check(H), no_style_check(T). @@ -183,21 +227,6 @@ no_style_check([H|T]) :- no_style_check(H), no_style_check(T). fail. '$check_term'(_,_,_,_,_). -'$sv_warning'([], _) :- !. -'$sv_warning'(SVs, T) :- - strip_module(T, M, T1), - '$pred_arity'( T1, Name, Arity ), - print_message(warning,singletons(SVs,(M:Name/Arity))). - -'$pred_arity'(V,M,M,V,call,1) :- var(V), !. -'$pred_arity'((H:-_),Name,Arity) :- !, - functor(H,Name,Arity). -'$pred_arity'((H-->_),Name,Arity) :- !, - functor(HL,Name,1), - Arity is A1+2. -'$pred_arity'(H,Name,Arity) :- - functor(H,Name,Arity). - % check if a predicate is discontiguous. '$handle_discontiguous'(F,A,M) :- recorded('$discontiguous_defs','$df'(F,A,M),_), !, diff --git a/pl/messages.yap b/pl/messages.yap index bcc05f818..a533568f8 100644 --- a/pl/messages.yap +++ b/pl/messages.yap @@ -155,11 +155,13 @@ system_message(no_match(P)) --> [ 'No matching predicate for ~w.' - [P] ]. system_message(leash([A|B])) --> [ 'Leashing set to ~w.' - [[A|B]] ]. -system_message(singletons([SV=_],P)) --> - [ 'Singleton variable ~s in ~q.' - [SV,P] ]. -system_message(singletons(SVs,P)) --> - [ 'Singleton variables ~s in ~q.' - [SVsL, P] ], - { svs(SVs,SVsL,[]) }. +system_message(singletons(SVs,P,W)) --> + [ 'Singleton variable~*c ~s in ~q, starting at line ~d' - [NVs, 0's, SVsL, I, L] ], % ' + { svs(SVs,SVsL,[]), + ( SVs = [_] -> NVs = 0 ; NVs = 1 ), + clause_to_indicator(P, I), + stream_position_data( line_count, W, L) + }. system_message(trace_command(-1)) --> [ 'EOF is not a valid debugger command.' ]. system_message(trace_command(C)) --> @@ -581,3 +583,16 @@ prefix(debug(_), '% ', user_error). prefix(information, '% ', user_error). +clause_to_indicator(T, M:Name/Arity) :- + strip_module(T, M, T1), + pred_arity( T1, Name, Arity ). + +pred_arity(V,M,M,V,call,1) :- var(V), !. +pred_arity((H:-_),Name,Arity) :- !, + functor(H,Name,Arity). +pred_arity((H-->_),Name,Arity) :- !, + functor(HL,Name,1), + Arity is A1+2. +pred_arity(H,Name,Arity) :- + functor(H,Name,Arity). +