Была где-то у Александра Ильина отдельная тема, где он циклы переписывал, на сразу не нашел, а сюда тоже пойдет.

Ковыряюсь в Zlib (который из A2) и не знаю, что думать. Вирта на них не было? Сперли сишную реализацию?## Код:
```
(** close writer **)
   PROCEDURE Close* (VAR w: Writer);
   VAR
      done: BOOLEAN;
      len: INTEGER;
   BEGIN
      ASSERT(w.s.in.avail = 0, 110);
      done := FALSE;
      LOOP
         len := BufSize - w.s.out.avail;
         IF len # 0 THEN
            w.r.file.WriteBytes(w.r, w.out^, 0, len);
            ZlibBuffers.Rewrite(w.s.out)
         END;
         IF done THEN EXIT END;
         ZlibDeflate.Deflate(w.s, ZlibDeflate.Finish);
         IF (len = 0) & (w.s.res = BufError) THEN
            w.res := Ok
         ELSE
            w.res := w.s.res
         END;
         done := (w.s.out.avail # 0) OR (w.res = StreamEnd);
         IF (w.res # Ok) & (w.res # StreamEnd) THEN EXIT END
      END;
      ZlibDeflate.Close(w.s);
      w.res := w.s.res
   END Close;
```

Поковыряешься в таком, и в очередной раз убеждаешься, что пространства для GOTO-like маневров оставлять никак нельзя. Что Вирт и сделал к Оберону-07 (RETURN и цикл Дейкстры).## Код:
```
PROCEDURE Close* (w: Writer);
      VAR   len: INTEGER;
   BEGIN
      ASSERT(w.s.open, 30);
      ASSERT(w.s.res = ZlibDeflate.Ok, 100);
      LOOP IF w.s.out.avail = 0 THEN
         w.rider.WriteBytes(w.out, 0, BufSize);
         ZlibBuffers.Rewrite(w.s.out)
      ELSIF (*~(w.s.out.avail = 0) &*) (w.s.res = ZlibDeflate.Ok) THEN
         ZlibDeflate.Deflate(w.s,  ZlibDeflate.Finish);
         ASSERT((w.s.res = ZlibDeflate.Ok) OR (w.s.res = ZlibDeflate.StreamEnd), 101)
      ELSE EXIT END END;
      ASSERT(w.s.res = ZlibDeflate.StreamEnd);
      len := BufSize - w.s.out.avail;
      IF 0 < len THEN w.rider.WriteBytes(w.out, 0, len) END;
      ZlibDeflate.Close(w.s); ASSERT(~w.s.open & (w.s.res = ZlibDeflate.Ok));
      w.rider := NIL
   END Close;
```
