В итоге сделал так:
Код:
MODULE TmpM3;
IMPORT SYSTEM, Kernel;
TYPE
Msg* = POINTER TO ABSTRACT RECORD END;
MsgHandler* = POINTER TO ABSTRACT RECORD END;
Table* = POINTER TO ABSTRACT RECORD END;
PROCEDURE (h: MsgHandler) Handle- (msg: Msg), NEW, ABSTRACT;
PROCEDURE (t: Table) Lookup- (id: BYTE; OUT len: BYTE; OUT type: INTEGER; OUT ok: BOOLEAN), NEW, ABSTRACT;
PROCEDURE DataReceived* (id: BYTE; IN a: ARRAY OF BYTE; len: BYTE; h: MsgHandler; table: Table);
VAR type: INTEGER; len1: BYTE; ok: BOOLEAN;
msg: Msg;
BEGIN
table.Lookup(id, len1, type, ok);
IF ok & (len = len1) THEN
Kernel.NewObj( msg, SYSTEM.VAL( Kernel.Type, type) );
SYSTEM.MOVE( SYSTEM.ADR(a), SYSTEM.ADR(msg^), len );
ASSERT(msg # NIL);
h.Handle(msg)
END
END DataReceived;
END TmpM3.
Код:
MODULE TmpM4;
(* этот модуль должен создаваться автоматически *)
IMPORT SYSTEM, TmpM3;
TYPE
MsgA* = POINTER TO MsgADesc;
MsgADesc* = RECORD (TmpM3.Msg)
a-, b-: INTEGER
END;
MsgB* = POINTER TO MsgBDesc;
MsgBDesc* = RECORD (TmpM3.Msg)
x-, y-, z-: SHORTREAL
END;
Table = POINTER TO RECORD (TmpM3.Table) END;
VAR
table-: Table;
PROCEDURE (t: Table) Lookup (id: BYTE; OUT len: BYTE; OUT type: INTEGER; OUT ok: BOOLEAN);
BEGIN
CASE id OF 10H:
len := SIZE(MsgADesc); type := SYSTEM.TYP(MsgADesc);
ok := TRUE
| 11H:
len := SIZE(MsgBDesc); type := SYSTEM.TYP(MsgBDesc);
ok := TRUE
ELSE
ok := FALSE
END
END Lookup;
BEGIN
NEW(table)
END TmpM4.
Код:
MODULE TmpM5;
IMPORT TmpM3, TmpM4, StdLog;
TYPE
MsgHandler = POINTER TO RECORD (TmpM3.MsgHandler) END;
PROCEDURE (h: MsgHandler) Handle (msg: TmpM3.Msg);
BEGIN
WITH msg: TmpM4.MsgA DO
StdLog.String("A:"); StdLog.Int(msg.a); StdLog.Int(msg.b); StdLog.Ln
| msg: TmpM4.MsgB DO
StdLog.String("B:");
StdLog.Real(msg.x); StdLog.Real(msg.y); StdLog.Real(msg.z);
StdLog.Ln
END
END Handle;
PROCEDURE Test*;
VAR h: MsgHandler;
a: ARRAY 12 OF BYTE;
BEGIN
a[0] := 1; a[1] := 1; a[2] := 0; a[3] := 0;
a[4] := 2; a[5] := 1; a[6] := 0; a[7] := 0;
NEW(h);
TmpM3.DataReceived(10H, a, 8, h, TmpM4.table)
END Test;
END TmpM5.
!(Q)TmpM5.Test