Прошу:
Код:
MODULE назовите-как-хотите;
   IMPORT S := SYSTEM, Kernel, Files;
   TYPE
      Bytes = ARRAY [untagged] 1000000000 OF BYTE;
   PROCEDURE SizeOf* (IN rec: ANYREC): INTEGER;
      VAR type: Kernel.Type;
   BEGIN
      type := S.VAL(Kernel.Type, S.TYP(rec));
      RETURN type.size
   END SizeOf;
   PROCEDURE RecWithoutPtrFields* (IN rec: ANYREC): BOOLEAN;
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      RETURN t.ptroffs[0] < 0
   END RecWithoutPtrFields;
   PROCEDURE RecToBytes* (IN rec: ANYREC; VAR bytes: ARRAY OF BYTE; VAR pos: INTEGER);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      ASSERT(pos + t.size <= LEN(bytes), 21);
      IF Kernel.littleEndian THEN
         S.MOVE(S.ADR(rec), S.ADR(bytes) + pos, t.size);
         INC(pos, t.size)
      ELSE
         HALT(126)
      END
   END RecToBytes;
   PROCEDURE RecFromBytes* (VAR rec: ANYREC; IN bytes: ARRAY OF BYTE; VAR pos: INTEGER);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      ASSERT(pos + t.size <= LEN(bytes), 21);
      IF Kernel.littleEndian THEN
         S.MOVE(S.ADR(bytes) + pos, S.ADR(rec), t.size);
         INC(pos, t.size)
      ELSE
         HALT(126)
      END
   END RecFromBytes;
   PROCEDURE RecToFile* (IN rec: ANYREC; wr: Files.Writer);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      IF Kernel.littleEndian THEN
         wr.WriteBytes(S.VAL(Bytes, rec), 0, t.size)
      ELSE
         HALT(126)
      END
   END RecToFile;
   PROCEDURE RecFromFile* (VAR rec: ANYREC; rd: Files.Reader);
      VAR t: Kernel.Type;
   BEGIN
      t := S.VAL(Kernel.Type, S.TYP(rec));
      ASSERT(t.ptroffs[0] < 0, 20);
      IF Kernel.littleEndian THEN
         rd.ReadBytes(S.VAL(Bytes, rec), 0, t.size)
      ELSE
         HALT(126)
      END
   END RecFromFile;
   PROCEDURE New* (IN sameType: ANYREC): ANYPTR;
   BEGIN
      RETURN S.VAL(ANYPTR, Kernel.NewRec(S.TYP(sameType)))
   END New;
   PROCEDURE CopyBase* (IN src: ANYREC; VAR dest: ANYREC);
(* Берёт "общий знаменатель" двух записей и копирует из src в dest *)
      VAR ts, td: Kernel.Type;
            i: INTEGER;
   BEGIN
      ASSERT(S.ADR(src) # S.ADR(dest), 20);
      ts := S.VAL(Kernel.Type, S.TYP(src));
      td := S.VAL(Kernel.Type, S.TYP(dest));
      i := 0;
      WHILE (ts.base[i] # NIL) & (ts.base[i] = td.base[i]) DO
         INC(i)
      END;
      IF i > 0 THEN
         S.MOVE(S.ADR(src), S.ADR(dest), ts.base[i-1].size)  
      END
   END CopyBase;