Опять задачки от балды?
Кому, для чего, куда этот гетерогенный список?
Хорошо, вот не умозрительная, а практическая задача.
Я работаю с древовидными списками аля Рефал-Лисп. У меня есть модуль для их поддержки:
Код:
DEFINITION RocotStructs;
TYPE
Term = POINTER TO ABSTRACT RECORD
next-, prev-: Term;
pos-: INTEGER;
(t: Term) Expr (): Expr, NEW, EXTENSIBLE;
(t: Term) HandleMsg (VAR msg: Message), NEW, EMPTY
END;
Expr = POINTER TO EXTENSIBLE RECORD (Term)
first-, last-: Term;
(e: Expr) Delete (from, to: Term), NEW;
(e: Expr) Insert (t, after: Term), NEW;
(e: Expr) Paste (source: Expr; from, to, after: Term), NEW
END;
Message = ABSTRACT RECORD END;
PROCEDURE LookupTerm (e: Expr; IN type: ARRAY OF CHAR; after: Term): Term;
END RocotStructs.
Естественно, я хочу иметь возможность удобно просматривать свои деревья, когда мне это нужно.
Пусть у меня есть древовидное выражение expr.
Тогда я просто делаю так:
RocotDebug.ShowExpr(expr).
И у меня на экране появляется документ, показывающий узлы дерева в иерархии стандартных складок ББ. Щёлкнув по синему ромбику, я могу увидеть все поля каждого узла дерева.
Вложение:
trees.gif [ 30.36 КБ | Просмотров: 6184 ]
Вас, конечно, интересует реализация моей функции ShowExpr?
Вот она:
Код:
MODULE RocotDebug;
IMPORT Sys := RocotSys, Structs := RocotStructs, Text := RocotText, BCF := RocotBCF, StdFolds, DevDebug, Views, TextModels, TextViews, Log;
PROCEDURE OutTerm (wr: Text.Writer; term: Structs.Term);
VAR type: ARRAY 256 OF CHAR;
adr: Sys.Address;
ref: Views.View;
BEGIN
Sys.GetTypeName(term, type);
adr := Sys.AdrOf(term);
ref := DevDebug.HeapRefView(adr, type);
wr.String(' ' + type + ' '); wr.Core()(TextModels.Writer).WriteView(ref, Views.undefined, Views.undefined)
END OutTerm;
PROCEDURE OutExpr (wr: Text.Writer; expr: Structs.Expr);
VAR type: ARRAY 256 OF CHAR;
t: Structs.Term;
f: StdFolds.Fold;
txt: Text.Model;
wr1: Text.Writer;
BEGIN
ASSERT(expr # NIL, 20);
Sys.GetTypeName(expr, type);
txt := wr.Base().New();
wr1 := txt.NewWriter(NIL); wr1.indent.char := ' ';
OutTerm(wr1, expr); wr1.Ln(wr.indent.level + 1);
t := expr.first;
WHILE t # NIL DO
IF (t IS Structs.Expr) & (t(Structs.Expr).first # NIL) THEN
OutExpr(wr1, t(Structs.Expr))
ELSE
OutTerm(wr1, t)
END;
t := t.next;
IF t # NIL THEN wr1.Ln(0) END
END;
wr1.Ln(-1);
f := StdFolds.dir.New(StdFolds.collapsed, type$, txt.Core()(TextModels.Model));
wr.Core()(TextModels.Writer).WriteView(f, Views.undefined, Views.undefined);
OutTerm(wr, expr);
f := StdFolds.dir.New(StdFolds.collapsed, "", NIL);
wr.Core()(TextModels.Writer).WriteView(f, Views.undefined, Views.undefined)
END OutExpr;
PROCEDURE ShowExpr* (expr: Structs.Expr);
VAR t: Text.Model;
wr: Text.Writer;
BEGIN
t := BCF.WrapText(TextModels.dir.New());
wr := t.NewWriter(NIL);
OutExpr(wr, expr);
Views.OpenAux(TextViews.dir.New(t.Core()(TextModels.Model)), "Rocot Expression")
END ShowExpr;
END RocotDebug.
Очень сложно? Выводится полноценное интерактивное представление, прошу заметить, а не ваши убогие Console.WriteLn.
Вывод значений элементарных типов спрятан в тех самых синих ромбиках - это стандартная вьюшка ББ, из дамп-отладчика.