🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.modula2
Article #400

The WITH statement

#400
From: Tim Larson
Date: Fri, 17 Nov 1989 20:40
86 lines
3179 bytes
(*
   Good grief!  I was away from my debugger yesterday and I stared at a
   piece of code for almost an hour before I discovered the culprit - a
   WITH statement!  I don't believe I have ever used the statement in the
   offensive way I wrote it, but, on the other hand, I never knew I
   couldn't until now.  The code in question is too large to post here,
   but it was essentially equivalent to:

      WITH A[i] DO REPEAT WrInt(f, -1); INC (i) UNTIL i > 3 END;

   (see the program following this message) which I intended to mean:

      REPEAT WrInt(A[i].f, -1); INC (i) UNTIL i > 3;

   I believe that the WITH statement as defined in Modula-2 is a bad idea.
   Informally, we often think of the WITH statement as a way of reducing
   the size of the source code, and that we may simply replace the field
   names within the WITH block by the name in the WITH designator.  This
   is simply not true.  What is really happening is that the designator is
   bound once when the WITH statement is encountered and the field names
   are then treated as fields of this static object.

   In the test code given below, the mistake is quite obvious.  This is
   not always the case, however, and it IS the responsibility of the
   language designer to provide semantics that correspond in an obvious
   way with the syntax.  The WITH designator is not required to be a static
   object and yet it is treated as if it were static.  This is a mistake!

   In any case, since Modula-2 is a good language in so many respects, and
   assuming that the semantics will not now be changed, the compiler should
   be made to produce a warning at the least, or perhaps even an error
   message if the designator's value changes in the body of a WITH block.

   There is a test program below that illustrates the comments above.  Any
   comments about this?
*)

MODULE TestWITH;

FROM IO IMPORT WrInt, WrLn;

   TYPE
      R = RECORD f: INTEGER END;

   VAR
      A: ARRAY [0..3] OF R;
      p: POINTER TO R;
      i: INTEGER;

BEGIN (* Note that the desired output is 1234. *)
   A[0].f := 0; A[1].f := 1; A[2].f := 2; A[3].f := 3;

(* The following two blocks are essentially equivalent in the way they
   execute. *)
   i := 0;
   WITH A[i] DO REPEAT
      WrInt (f, -1);
      INC (i)
   UNTIL i > 3 END;
   WrLn;

   i := 0;
   p := ADR(A[i]);
   REPEAT
      WrInt (p:.f, -1);
      INC (i)
   UNTIL i > 3;
   WrLn;

(* The informal way of thinking of WITH leads one to believe that the first
   block is equivalent to the following block (which represents the code
   that was intended). *)
   i := 0;
   REPEAT
      WrInt (A[i].f, -1);
      INC (i)
   UNTIL i > 3;
   WrLn;

END TestWITH.

(*
-Tim Larson
odx@psuvm.bitnet
Naturally, these opinions, for what they are worth, are just mine.
*)
Technical Details
Message-ID: <89321.154018ODX@PSUVM.BITNET>
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!aplcen!samsung!brutus.cs.uiuc.edu!psuvax1!psuvm!odx

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!aplcen!samsung!brutus.cs.uiuc.edu!psuvax1!psuvm!odx
From: ODX@PSUVM.BITNET (Tim Larson)
Newsgroups: comp.lang.modula2
Subject: The WITH statement
Message-ID: <89321.154018ODX@PSUVM.BITNET>
Date: 17 Nov 89 20:40:18 GMT
Organization: Penn State University
Lines: 86