Думаю, что на данном этапе я приостановлю эту работу. Вылизывать можно до безконечности, но вроде сейчас инструмент уже более-менее сносно работает. Идея в том, что можно печатать либо объект (ANY), используя динамическую инфу о его типе, либо модуль (состояние модуля), либо стек выполнения, снятый за счёт вставки особого вызова в код процедуры.

При этом рекурсивно печатается граф объектов, записей и массивов с отслеживанием повторов. Если какой-то адрес один раз напечатался, то при повторной печати вместо рекурсивной печати содержимого по этому адресу выводится просто ^адрес.

Некоторые типы данных не печатаются.

Также можно задать ограничение на глубину рекурсии и на длину массивов. При превышении глубины печатается некий замещающий текст. Идея в целом позаимствована из лиспового print, print-length, print-circle и т.п. См, напр,

http://filonenko-mikhail.github.io/cltl ... 139-188031

Печать выделяет (как я надеюсь) данные только на стеке, поэтому теоретически можно применять её в обработчике TRAPов вместо стандартной.


Пример модуля Proba:
## Код:
```
MODULE Proba; IMPORT Commands, Modules, PodrobnajaPechatq, Streams, Objects (* ,Debugging ,SYSTEM , Heaps, Reflection *);

TYPE myRec1* = POINTER TO RECORD
   txt* : ARRAY 7 OF CHAR END;

TYPE myRecPtrType* = POINTER TO myRecType;
       myRecType* = RECORD 
      text* : ARRAY 4 OF CHAR;
      pointerToArrayOfAny* : POINTER TO ARRAY OF ANY END;
      
TYPE myObjType* = OBJECT 
   VAR mrt* : myRecType;
   END myObjType;
   
PROCEDURE zin() : myRecPtrType;
VAR item : myRec1; res : myRecPtrType;
BEGIN
   NEW(res);
   NEW(res.pointerToArrayOfAny, 2);
   NEW(item);
   item.txt := "ITEM0";
   res.pointerToArrayOfAny[0] := item;
   NEW(item);
   item.txt := "ITEM1";
   res.pointerToArrayOfAny[1] := item;
   RETURN res END zin;
   
VAR ptr0 : POINTER TO ARRAY OF myRecPtrType;
VAR ptr0a : POINTER TO ARRAY OF myRecType;
VAR ptr1 : POINTER TO ARRAY 4 OF POINTER TO ARRAY 3 OF CHAR;
VAR ptr2 : POINTER TO ARRAY OF CHAR; 
VAR ptr3 : POINTER TO ARRAY 4 OF CHAR;
VAR a3 : ARRAY 5 OF CHAR; 
VAR ptr5 : POINTER TO ARRAY 5 OF BOOLEAN;
VAR a5 : ARRAY 5 OF BOOLEAN; 
VAR p6 : POINTER TO ARRAY OF ARRAY 4 OF CHAR; 
VAR p9 : POINTER TO ARRAY OF ANY;
VAR any10 : ANY;
VAR any11 : ANY;


PROCEDURE z*(context : Commands.Context);
VAR m: Modules.Module;
VAR res : LONGINT; msg : ARRAY 4096 OF CHAR; o : Streams.Writer; 
   (* ty : Modules.TypeDesc; *) 
   k : PodrobnajaPechatq.KontekstPechati; 

   LOCALobj7 : myObjType; 
   LOCALany8 : ANY;

BEGIN
   o := context.out;
   PodrobnajaPechatq.ZadajjKontekstPechatiPoUmolch(k);
   k.w := o;
   PrimerStackTraceBack(o);
   o.Ln; o.String("======== TraceBack END =========");
   o.String("Loading the module"); o.Ln;
   m := Modules.ThisModule("Proba", res, msg);
   IF (m = NIL) OR (res # 0) THEN
      o.String("z: Failed to load module:"); o.String(msg); o.Ln;
      RETURN END;
      

   NEW(ptr0, 3);
   NEW(ptr0[0]);
   ptr0[0].text := "LLL";
   NEW(ptr0[2]);
   ptr0[2].text := "SSS";
   o.Ln; o.String("======= PodrobnajaPechatq.PechVKontektse ptr0 ========: "); o.Ln; PodrobnajaPechatq.PechVKontekste(k, ptr0); 
   
   NEW(ptr0a,3);
   ptr0a[0].text := "LLL";
   ptr0a[2].text := "SSS";
   o.Ln; o.String("======= PodrobnajaPechatq.PechVKontektse ptr0a ========: "); o.Ln; PodrobnajaPechatq.PechVKontekste(k, ptr0a); 

   
   NEW(ptr1);
   (* o.String("Address of ptr1 = "); o.Address(SYSTEM.VAL(ADDRESS, ptr1)); o.Ln; *)
   NEW(ptr1[0]); 
   (* o.String("Value of ptr1[0] = "); o.Address(SYSTEM.VAL(ADDRESS, ptr1[0])); o.Ln; *)
   ptr1[0]^ := "AB";   
   NEW(ptr1[2]);
   (* o.String("Value of ptr.1[2] = "); o.Address(SYSTEM.VAL(ADDRESS, ptr1[1])); o.Ln; *)
   ptr1[2]^ := "CD";
   ptr1[3] := ptr1[2];
   o.Ln; o.String("======= PodrobnajaPechatq.PechVKontektse ptr1 ========: "); o.Ln; PodrobnajaPechatq.PechVKontekste(k, ptr1); 

   NEW(ptr2,3);
   ptr2^ := "AB";
   o.Ln; o.String("======= PodrobnajaPechatq.PechVKontektse ptr2 ========: "); o.Ln; PodrobnajaPechatq.PechVKontekste(k, ptr2);  
   
   
   NEW(ptr3); 
   ptr3^ := "DEF";
   o.Ln; o.String("======= PodrobnajaPechatq.PechVKontektse ptr3 ========: "); o.Ln; PodrobnajaPechatq.PechVKontekste(k, ptr3);  
   
   a3 := "ABC";
   
   NEW(ptr5);
   ptr5[0] := TRUE;
   ptr5[4] := TRUE;
   a5[0] := TRUE;
   a5[4] := TRUE;
   (* o.String("========= PodrobnajaPechatq.Report ==========="); o.Ln;
   Reflection.Report(o, m.refs, 0);  *) 
   
   NEW(p6, 2);
   p6[0] := "AAA";
   p6[1] := "BBB";
      
   NEW(LOCALobj7);
   LOCALany8 := LOCALobj7;
   NEW(LOCALobj7);

     NEW(p9, 2);
     p9[0] := LOCALobj7;
     p9[1] := LOCALany8;

   any10 := zin();
   any11 := Objects.ActiveObject();
   
   (* o.Ln; o.String("========= PodrobnajaPechatq.Pech(o, obj) ======="); o.Ln;

   PodrobnajaPechatq.Pech(o, obj); *)
   
   o.Ln; o.String("========= PodrobnajaPechatq.ModuleState ======="); o.Ln;
   
   PodrobnajaPechatq.ModuleState(o, m); 
   
   


   (* o.String("====== Printing individual values =========="); o.Ln;
   ASSERT(SYSTEM.TYPECODE(myPtrToRecordVar) = SYSTEM.TYPECODE(myPtrToRecordType));
   PodrobnajaPechatq.Pech(o, myPtrToRecordVar); 
   (* Alqternativa: 
      PodrobnajaPechatq.PechPoAdr(o, SYSTEM.VAL(ADDRESS,myPtrToRecordVar), SYSTEM.TYPECODE(myPtrToRecordVar)); *)
   PodrobnajaPechatq.PechPoAdr(o, ADDRESS OF myRecordVar, SYSTEM.TYPECODE(myRecordVar)); *)
   END z;


PROCEDURE PrimerStackTraceBack(o : Streams.Writer); 
VAR m : ARRAY 5 OF INTEGER;
BEGIN
   m[0] := 5;
   m[4] := 33; 
   PodrobnajaPechatq.TraceBack(o, 1, 1); 
END PrimerStackTraceBack;

END Proba.


(SystemTools.DoCommands 
   SystemTools.FreeDownTo PodrobnajaPechatq~ 
   Proba.z~
   WMKernelLog.Open~~)
```


В результате выполнения команды печатается примерно такая простыня.
## Код:
```
(StackTraceBack 1 1
  (KADR 0 PodrobnajaPechatq.TraceBack:28 pc=248280478 [0ECC759EH] = 248280450 + 28 crc=00000000
  )
  (KADR 1 Proba.PrimerStackTraceBack:41 pc=248332873 [0ECD4249H] = 248332832 + 41 crc=00000000
  
  
  v o 
   ( r.STz &0EABE160 Streams.Writer ~(
      f tail 67
      f buf (&0EABE1A0 [128] CHAR : "")
      f res 0
      f send (DELEGATE)
      f sent 394))

  
  v m (&0B8DAED2 [5] INTEGER : (
     0: 5
     1: 0
     2: 0
     3: 0
     4: 33))
)
  (KADR 2 Proba.z:86 pc=248330487 [0ECD38F7H] = 248330401 + 86 crc=00000000
  )
  (KADR 3 Commands.Runner.@Body:718 pc=4430640 [00439B30H] = 4429922 + 718 crc=00000000
  ){ [P 13896 Commands.Runner] 22:38:43}
======== TraceBack END =========Loading the module

======= PodrobnajaPechatq.PechVKontektse ptr0 ========: 
(&0ECD5420 DT[3] : (
 0: (&0ECD5460  :vidObjqekta 6 :type Proba.myRecType (
    f text "LLL"
    f pointerToArrayOfAny NIL))
 1: NIL
 2: (&0ECD54A0  :vidObjqekta 6 :type Proba.myRecType (
    f text "SSS"
    f pointerToArrayOfAny NIL)))
======= PodrobnajaPechatq.PechVKontektse ptr0a ========: 
(IzuchiMassivSUkazateljamiVElemente: vidObjqektaMassivSElementamiIzvestnogoTipa)
(&0ECD54E0  :vidObjqekta 5 :type Proba.myRecType (
  f text ""
  f pointerToArrayOfAny NIL))
======= PodrobnajaPechatq.PechVKontektse ptr1 ========: 
(&0ECD5540 DT[4] : (
 0: (neKhvataetST 0ECD5580)
 1: NIL
 2: (neKhvataetST 0ECD55C0)
 3: (neKhvataetST 0ECD55C0))
======= PodrobnajaPechatq.PechVKontektse ptr2 ========: 
(neKhvataetST 0ECD5600)
======= PodrobnajaPechatq.PechVKontektse ptr3 ========: 
(neKhvataetST 0ECD5640)
========= PodrobnajaPechatq.ModuleState =======

(SOSTOJANIE MODULJA 'Proba'

 
 v ptr0 (&0ECD5420 [3] (POINTER TO DT RECORD)) : (
    0: 
    ( r.STz &0ECD5460 Proba.myRecType ~(
       f text "LLL"
       f pointerToArrayOfAny NIL))
    1: NIL
    2: 
    ( r.STz &0ECD54A0 Proba.myRecType ~(
       f text "SSS"
       f pointerToArrayOfAny NIL))))

 
 v ptr0a (&0ECD54E0 [3] (RECORD Proba.myRecType) : (
    0: Record ((
      f text "LLL"
      f pointerToArrayOfAny NIL))
    1: Record ((
      f text ""
      f pointerToArrayOfAny NIL))
    2: Record ((
      f text "SSS"
      f pointerToArrayOfAny NIL))))

 
 v ptr1 (&0ECD5540 [4] POINTER TOARRAY 3 OF CHAR : (
    0: (&0ECD5580 [3] CHAR : "AB")
    1: NIL
    2: (&0ECD55C0 [3] CHAR : "CD")
    3: (^0ECD55C0)))

 
 v ptr2 (&0ECD5600 [3] CHAR : "AB")

 
 v ptr3 (&0ECD5640 [4] CHAR : "DEF")

 
 v a3 "ABC"

 
 v ptr5 (&0ECD5680 [5] BOOLEAN : (
    0: true
    1: false
    2: false
    3: false
    4: true))

 
 v a5 (&0ECD42B0 [5] BOOLEAN : (
    0: true
    1: false
    2: false
    3: false
    4: true))
)
```
