## Код:
```
MODULE M;

    IMPORT SYSTEM;

    TYPE
        Msg* = ABSTRACT RECORD END;
        MsgA* = RECORD (Msg)
            a-, b-: INTEGER
        END;
        MsgB* = RECORD (Msg)
            x-, y-, z-: SHORTREAL
        END;

        MsgHandler* = POINTER TO ABSTRACT RECORD
        END;

    PROCEDURE (h: MsgHandler) Handle- (IN msg: Msg), NEW, ABSTRACT;

    PROCEDURE DataToMsg (type: INTEGER; IN a: ARRAY OF BYTE; len: INTEGER; VAR msg: ANYREC);
    BEGIN
        SetType(msg, type); (* как это сделать? *)
        SYSTEM.MOVE( SYSTEM.ADR(a), SYSTEM.ADR(msg), len )
    END DataToMsg;

    PROCEDURE DataReceived* (id: BYTE; IN a: ARRAY OF BYTE; len: INTEGER; h: MsgHandler);
        TYPE
            MsgX = RECORD (Msg) END;
        VAR ok: BOOLEAN; type: INTEGER; msg: MsgX;
    BEGIN
        ok := FALSE;
        CASE id OF 10H:
            IF len = SIZE(MsgA) THEN
                ok := TRUE;
                type := GetType(MsgA) (* как это сделать? *)
            END
        | 11H:
            IF len = SIZE(MsgB) THEN
                ok := TRUE;
                type := GetType(MsgB) (* как это сделать? *)
            END
        ELSE
        END;

        IF ok THEN
            DataToMsg(type, a, len, msg);
            h.Handle(msg)
        END
    END DataReceived;

END M.

MODULE M1;

    IMPORT M, StdLog;

    TYPE
        MsgHandler = POINTER TO RECORD (M.MsgHandler) END;

    PROCEDURE (h: MsgHandler) Handler (IN msg: Msg);
    BEGIN
        WITH msg: M.MsgA DO
            StdLog.String("A:"); StdLog.Int(msg.a); StdLog.Int(msg.b); StdLog.Ln
        | msg: M.MsgB DO
            StdLog.String("B:"); StdLog.Real(msg.x); StdLog.Real(msg.y); StdLog.Real(msg.z); StdLog.Ln
        END
    END Handler;

    PROCEDURE Test*;
        VAR a: ARRAY 8 OF BYTE;
            h: MsgHandler;
    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);
        M.DataReceived(10H, a, 8, h)
    END Test;

END M1.
```


Желательно с помощью Kernel.