[comp.lang.pascal] Pascal User Manual and Report

wsmith@uiucdcsb.cs.uiuc.edu (02/18/88)

I was just looking at Jensen & Wirth's _Pascal User Manual and Report_.  
In the section on the AND and OR operators, it says:

"Assume for example, that x=0.  Then 
	(x>0) and (x<10)
is already known to be false after computation of the first factor, and the
scond need not be evaluated.  The rules of Pascal neither require nor forbid
						  ^^^^^^^^^^^^^^^
the evaluation of the second part in such cases."

Is this still true in the "current definition" of Pascal.  All of the
implementations I've found will evaluate the second part.  In fact, I believe
most people think that it the evaluation of the second part _is_ required.
However, the statement goes on:

"This means that the programmer must assure that the second factor is
well-defined."   (and goes on to give a standard example when the second part
of an AND expression might access an array out of bounds.)

What if the second part of the AND expression has side effects?  If my
reading of Jensen & Wirth is correct, the result of any program with such 
side effects is undefined in Pascal!  Is this conclusion true?  It certainly 
isn't a pleasant one since there is probably plenty of code that depends on 
the evaluation of the second part being required.

Bill Smith
ihnp4!uiucdcs!wsmith
wsmith@a.cs.uiuc.edu

neubauer@bsu-cs.UUCP (Paul Neubauer) (02/18/88)

In article <169900010@uiucdcsb>, wsmith@uiucdcsb.cs.uiuc.edu writes:
> I was just looking at Jensen & Wirth's _Pascal User Manual and Report_.  
> In the section on the AND and OR operators, it says:
> "Assume for example, that x=0.  Then 
> 	(x>0) and (x<10)
> is already known to be false after computation of the first factor, and the
> scond need not be evaluated.  The rules of Pascal neither require nor forbid
> 						  ^^^^^^^^^^^^^^^
> the evaluation of the second part in such cases."
> 
> Is this still true in the "current definition" of Pascal.  All of the
> implementations I've found will evaluate the second part.  

It turns out that this is not quite true.  VAX Pascal does not (necessarily)
evaluate the second part.  I am not completely sure if this behavior depends
on optimization levels or some such, but around here, the local default is
/NOOPTIMIZE and even something like:

	x := 1;
	y := 0;
	IF (x < y) AND (x/y <> 1) THEN
		...

will not crash.

-- 
Paul Neubauer         neubauer@bsu-cs.UUCP
                      <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!neubauer

sarge@con.Berkeley.EDU (Steven Sargent) (02/18/88)

What do you mean by the "current definition?"  I know J&W leaves it
open, but who knows about ISO?   (Does anybody care?)  As to
implementations:

	VAX Pascal (on VMS) uses short-circuit evaluation;

	Sun Pascal (descendant of Berkeley pc) uses a compile-time
	flag, -P, to enable short-circuit evaluation (default full
	evaluation);

	SVS Pascal (Silicon Valley Software; makes compilers for
	various 68000, 32000 boxes running UNIX and other stuff)
	uses short-circuiting in conditionals, e.g.,
		if (p <> NIL) AND (p^.key <> key) then {don't explode}
	but full evaluation for assignments, e.g.,
		found := (p <> NIL) AND (p^.key = key);	{oops}

Coming from C-land, short-circuit evaluation seems much more natural
to me, so I don't mind that my compilers tend to use it.  But it is
bothersome that the behavior isn't nailed down more precisely.
For an allegedly portable language, Pascal leaves a lot of important
stuff to the discretion of implementors; this is just one fairly
minor, but insidious, example.

S.

wsmith@b.cs.uiuc.EDU (02/19/88)

>I was just looking at Jensen & Wirth's _Pascal User Manual and Report_.
>In the section on the AND and OR operators, it says:
>
>"Assume for example, that x=0.  Then
>    (x>0) and (x<10)
>is already known to be false after computation of the first factor, and the
>scond need not be evaluated.  The rules of Pascal neither require nor forbid
>                          ^^^^^^^^^^^^^^^
>the evaluation of the second part in such cases."
>
>Is this still true in the "current definition" of Pascal.  All of the
>implementations I've found will evaluate the second part.  In fact, I believe
>most people think that it the evaluation of the second part _is_ required.

I tried this on my system where the second part is in fact NOT evaluated!
I believe it points out quite clearly the problem that you stated.  We are
running VS Pascal under VM.

pas side
The SIDE LISTING and TEXT files will be put on the A minidisk
 INVOKING PASCAL/VS R2.2
 NO COMPILER DETECTED ERRORS

 Source lines:    16;  Total time:   0.05 seconds;  Total rate:  19200 LPM
EXECUTION BEGINS...
     FALSE           2
      TRUE           1
R;
type side pascal

program side;
 var x:integer;
function side_effect:boolean;
begin
   x:=1;
   side_effect:=true
end;
begin
  termout(output);
  x:=2;
  if (x<2) and side_effect
    then writeln(True,x) else writeln(False,x);
  x:=2;
  if (x<3) and side_effect
    then writeln(True,x) else writeln(False,x);
end.


>What if the second part of the AND expression has side effects?  If my
>reading of Jensen & Wirth is correct, the result of any program with such
>side effects is undefined in Pascal!  Is this conclusion true?  It certainly
>isn't a pleasant one since there is probably plenty of code that depends on
>the evaluation of the second part being required.

I suppose that this program would have different results via your compiler.
---------------------------------------------------------------------
Tim Margush                                    R1TMARG@AKRONVM.BITNET
(216) 375-7109
Department of Mathematical Sciences
University of Akron
Akron, OH 44325

scl@virginia.acc.virginia.edu (Steve Losen) (02/20/88)

Side effects should be avoided at all costs!

In article <11899@brl-adm.ARPA> wsmith@b.cs.uiuc.EDU writes:
>program side;
> var x:integer;
>function side_effect:boolean;
>begin
>   x:=1;
>   side_effect:=true
>end;
>begin
>  termout(output);
>  x:=2;
>  if (x<2) and side_effect
>    then writeln(True,x) else writeln(False,x);
>  x:=2;
>  if (x<3) and side_effect
>    then writeln(True,x) else writeln(False,x);
>end.
>
>
>>What if the second part of the AND expression has side effects?  If my
>>reading of Jensen & Wirth is correct, the result of any program with such
>>side effects is undefined in Pascal!  Is this conclusion true?  It certainly
>>isn't a pleasant one since there is probably plenty of code that depends on
>>the evaluation of the second part being required.
>
>I suppose that this program would have different results via your compiler.

There are lots of little gotchas waiting for the unsuspecting programmer
who uses side effects.  

CAVEAT 1:  The order of evaluation of procedure and function parameters
	is implementation depended in pascal.  Consider the following:

	x:=5;
	foo(x, side_effect);

	Some pascal compilers may evaluate x first, some may evaluate
	side_effect first, so depending on the compiler you could be
	doing foo(5,true) or foo(1,true).

CAVEAT 2: The order of the evaluation of the operands of a dyadic operator
    is implementation dependent in pascal.  Suppose side_effect returns
	an integer:

	function side_effect: integer
	begin
		x := 1;
		side_effect := 3;
	end;
	
	x := 5;
	y := x + side_effect;
	
	Some pascal compilers will evaluate x first and some will evaluate
	side_effect first, so y could be either 8 or 4.

	Note also that "and" and "or" are also dyadic operators.  Furthermore,
	pascal does not require that both operands to "and" and "or" be
	evaluated.  Thus,

	booleexpr1 and booleexpr2

	could be evaluated left to right, right to left, left side only, or
	right side only, depending on the compiler and the values of the
	expressions.

These sorts of traps are much easier for C programmers like myself
to fall into because side effects are much easier to generate. 
In this C example, z could be 10 or 15 depending on the compiler.

x = 10;
z = (x = 5) + x;
-- 
Steve Losen     scl@virginia.edu
University of Virginia Academic Computing Center

4526P%NAVPGS.BITNET@CUNYVM.CUNY.EDU (LT Scott A. Norton, USN) (02/20/88)

I don't have the actual ISO Pascal standard, but the ISO/DIS 7185 draft
standard has this to say:
-----------------------------------------------------------------------
  6.7.2 Operators
   6.7.2.1 General

      multiplying-operator = "*" | "/" | "div" | "mod" | "and" .
      adding-operator = "+" | "-" | "or" .
      relational-operator = "=" | "<>" | "<" | ">" | "<=" | ">=" | "in".

A factor, or a term, or a simple-expression shall be deignated an operand.
The order of evaluation of the operand of a dyadic operator shall be
implementation-dependent.
NOTE: This means, for example, that the operands may be evaluated in
textual order, or in reverse order, or in parallel or they may not
both be evaluated.
-------------------------------------------------------------------------
I was surprised to read this, because it does not apply to just "and"
and "or".  It would be legal to handle the expression

  a := b * SideEffect(c);

so that SideEffect(c) is not evaluated if b is zero.

It should be noted that Ada has very explicit rules about the order of
evaluation and what optimizations can be made.  In particular, Ada has
two constructs for each of "and" and "or":

"and" will evaluate both operands, "and also" will evaluate the second
only if the first is true.  Similarly, "or" evaluates both, but "or else"
evaluate the second only if the first is false.  So you can use the
construct

   if ( p<>nil ) and also ( p@.data = target ) then ...

LT Scott A. Norton, USN
Naval Postgraduate School
Monterey, CA 93943-5018
4526P@NavPGS.BITNET   4526P@NPS.ARPA