Вторая итерация, научился искать метод (по всему дереву наследования типа), проверять его имя и набор параметров. Теперь перекидываю адрес метода в локальную переменную и пытаюсь вызвать. Получаю упавший ББ без трэпов и всего такого - просто падает.
Код:
MODULE PrivMethods;
IMPORT SYSTEM, Kernel, Log, Strings; (* PrivMethodAbstract; *)
TYPE
T = POINTER TO ABSTRACT RECORD (* PrivMethodAbstract.T *) END;
T0 = POINTER TO RECORD (T) END;
TDesc = RECORD END;
Msg = RECORD END;
PROCEDURE (t: T) Do, NEW, ABSTRACT;
PROCEDURE (t: T0) Do;
BEGIN
END Do;
PROCEDURE (t: T) HANDLE(VAR msg: ANYREC), NEW, ABSTRACT;
PROCEDURE (t: T0) HANDLE(VAR msg: ANYREC);
BEGIN
WITH msg: Msg DO Log.String('success')
ELSE HALT(100) END;
END HANDLE;
PROCEDURE (t: T0) FINALIZE;
BEGIN END FINALIZE;
PROCEDURE (VAR t: TDesc) HANDLE(VAR msg: ANYREC), NEW;
BEGIN
END HANDLE;
PROCEDURE Do*;
CONST
recPrint = 03X+0BX+03X+11X+0X;
ptrPrint = 03X+0BX+01X+13X+0X;
VAR t: T0; td: TDesc;
VAR type: Kernel.Type; i, len: INTEGER; typ, adr, ref: INTEGER; name: Kernel.Name;
VAR mode, form: SHORTCHAR; d: Kernel.Type; x: INTEGER;
VAR fprint: ARRAY 256 OF SHORTCHAR; ptrM: PROCEDURE (m: ANYPTR; this: T0); recM: PROCEDURE (VAR t: ANYREC; VAR msg: ANYREC);
VAR msg: Msg;
PROCEDURE NofMethods(typ: INTEGER): INTEGER;
VAR a, i: INTEGER;
BEGIN
a:=0; i:=0;
REPEAT
SYSTEM.GET(typ - 4*i, a);
INC(i);
UNTIL a=-1;
DEC(i);
RETURN i
END NofMethods;
PROCEDURE ThisMethod(typ: INTEGER; idx: INTEGER; OUT adr: INTEGER);
BEGIN
ASSERT(idx>0, 20); ASSERT(idx<len, 21);
SYSTEM.GET(typ - 4*idx, adr);
END ThisMethod;
PROCEDURE ThisName(mod: Kernel.Module; madr: INTEGER; OUT name: Kernel.Name; OUT ref: INTEGER);
VAR adr: INTEGER; n: Kernel.Name;
BEGIN
ref:=mod.refs; adr:=0; n:=''; name:='';
REPEAT
IF (madr - mod.procBase) # adr THEN
Kernel.GetRefProc(ref, adr, n); (* каждый раз adrна выходе содержит адрес следующего элемента *)
ELSE Kernel.GetRefProc(ref, adr, name); END;
UNTIL (adr=0) OR (name#'');
END ThisName;
PROCEDURE Find(t: Kernel.Type; adr: INTEGER; OUT name: Kernel.Name; OUT ref: INTEGER);
VAR tn: Kernel.Name; vs: ARRAY 256 OF CHAR; pos: INTEGER;
BEGIN
ThisName(t.mod, adr, name, ref);
IF name$#'' THEN
Kernel.GetTypeName(t, tn);
IF tn[LEN(tn$)-1]='^' THEN tn[LEN(tn$)-1]:='.' ELSE tn:=tn+'.'; END; (* ^ означает разыменованый указатель, у рекордов ^ не бывает *)
Strings.Find(name$, tn$, 0, pos);
ASSERT(pos=0, 40);
Strings.Extract(name$, LEN(tn$), LEN(name$), vs);
name:=SHORT(vs$);
ELSIF Kernel.LevelOf(t)>0 THEN Find(t.base[Kernel.LevelOf(t)-1], adr, name, ref) END;
END Find;
BEGIN
NEW(t);
type:=Kernel.TypeOf(t);
typ:=SYSTEM.TYP(t);
i:=1; len:=NofMethods(typ);
WHILE (i<len) & (name$#'HANDLE') DO
ThisMethod(typ, i, adr);
Find(type, adr, name, ref);
INC(i);
END;
IF name$='HANDLE' THEN
fprint:=''; i:=0;
REPEAT
Kernel.GetRefVar(ref, mode, form, d, x, name);
fprint[i]:=mode; fprint[i+1]:=form; fprint[i+2]:=0X; INC(i, 2);
UNTIL mode=0X;
IF fprint=ptrPrint THEN
SYSTEM.GET(adr, ptrM);
IF (ptrM#NIL) THEN ptrM(t, t); END;
ELSIF fprint = recPrint THEN
SYSTEM.GET(adr, recM);
IF (recM#NIL) THEN recM(msg, td) END;
ELSE HALT(0) END;
END;
END Do;
END PrivMethods.
PrivMethods.Do
В документации сказано про ссылки на процедуры. Я посмотрел, как вызывают финализатор в ядре, и повторил схему. Они просто берут значение в процедурную переменную из адреса метода. А оно падает.