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