[Oberon] FPGA - Simple OOP example
Jörg
joerg.straube at iaeth.ch
Tue Aug 14 19:05:21 CEST 2018
Tomas
Your example is a very good base.
Please understand the following hints only as a minor refinement of your
example....
Hint1: Try to separate the procedures (methods of your object) from the
object's data. Okay in the example, your Terms had no local data but as a
general design pattern.
MODULE Term;
TYPE
T* = POINTER TO TDesc;
Methods* = POINTER TO MDesc;
MDesc = RECORD
Write*: PROCEDURE (t: Term);
Refresh*: PROCEDURE (t: Term);
(* other methods come here *)
END;
TDesc = RECORD
do*: Methods;
(* generic terminal data comes here *)
END;
VAR methods: Methods;
PROCEDURE InitMethods*(VAR m: Methods); BEGIN m := methods END Methods;
Hint2: Then in every specific module provide an Init() procedure for the
specific terminal, to initialize the DATA for that specific type of Term.
Initialize the METHODS once per module in the module body.
MODULE CapTerm;
IMPORT Term;
TYPE
T* = POINTER TO TermDesc;
TDesc = RECORD (Term.TDesc) col: INTEGER (*or any data you may need for
CapTerm *) END;
VAR m: Term.Methods;
PROCEDURE Init* (t: T; color: INTEGER (* other data for the CapTerm if any
*));
BEGIN t.do := m; t.col := color END Init;
PROCEDURE Write(t: Term.T, ch: CHAR); BEGIN (* Write method specific to
CapTerm *) END Write;
(* let's assume Refresh() has not to be overwritten *)
BEGIN
(* here you allocate the container for all your CapTerm methods once per
module and initialize it with the specific CapTerm methods *)
NEW(m); Term.InitMethods(m); m.Write := Write; (* you have the
possibility to overwrite Write, but leave e.g Refresh as in the base methods
*)
END CapTerm.
Hint3: The parameter t:Term to the procedures is basically only needed to
find the local data of your term not the methods.
As in your specific example term have no local data, you could basically
leave away the parameter, but as a general design add it to the methods.
Then in your Test module you can write something like this
MODULE Test;
IMPORT Term, CapTerm;
VAR t: Term.T; c: CapTerm.T;
BEGIN
NEW(t); Term.Init(t); t.do.Write(t, "Q");
t.do.Refresh(t); (* calls Term.Refresh *)
NEW(c); CapTerm.Init(c, 20); c.do.Write(c, "A"); c.do.Refresh(c) (*
also calls Term.Refresh, as we chose to not overwrite it with
CapTerm.Refresh *)
END Test.
-----Original Message-----
From: Oberon [mailto:oberon-bounces at lists.inf.ethz.ch] On Behalf Of Tomas
Kral
Sent: Tuesday, August 14, 2018 1:52 PM
To: Oberon at lists.inf.ethz.ch
Subject: [Oberon] FPGA - Simple OOP example
Hi,
Just reading Oberon book on OOP by Hanspeter Mosenbok. I would like to set a
reusable code pattern for that, not sure how close I am, my try below. There
is also other way of doing it, using so called `message' handler.
Cheers Tomas
MODULE Term; (* TK 14.8.2018 lower/capital case terminal, simple OOP example
*)
IMPORT Texts, Oberon;
TYPE
Term* = POINTER TO TermDesc;
TermDesc* = RECORD
write*: PROCEDURE(t: Term; ch: CHAR)
END ;
VAR
W: Texts.Writer; t*: Term;
(* Generic output routine accepting any Term based type *)
PROCEDURE Out*(t: Term; ch: CHAR);
BEGIN t.write(t, ch)
END Out;
PROCEDURE Write(t: Term; ch: CHAR);
BEGIN
Texts.Write(W, ch); Texts.Append(Oberon.Log, W.buf)
END Write;
BEGIN Texts.OpenWriter(W); NEW(t); t.write := Write; END Term.
MODULE CapTerm; (* capital terminal *)
IMPORT Term, Texts, Oberon;
TYPE
CapTerm* = POINTER TO CapTermDesc;
CapTermDesc* = RECORD (Term.TermDesc) END ;
VAR
W: Texts.Writer; ct*: CapTerm;
PROCEDURE CAP(ch: CHAR): CHAR;
VAR up: CHAR;
BEGIN
up := CHR(ORD(ch) + ORD("A") - ORD("a"));
RETURN up END CAP;
PROCEDURE Write(t: Term.Term; ch: CHAR);
BEGIN
IF (ch >= "a") OR (ch <= "z") THEN ch := CAP(ch) END ;
Texts.Write(W, ch); Texts.Append(Oberon.Log, W.buf)
END Write;
BEGIN Texts.OpenWriter(W); NEW(ct); ct.write := Write; END CapTerm.
MODULE TestTerm;
IMPORT Term, CapTerm, Texts, Oberon;
VAR
W: Texts.Writer; t: Term.Term; ct: CapTerm.CapTerm;
PROCEDURE Run*;
VAR S: Texts.Scanner;
BEGIN
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
Texts.Scan(S);
WHILE S.class = Texts.Name DO
Term.Out(t, S.s[0]); Term.Out(ct, S.s[0]);
Texts.Scan(S)
END ;
Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
END Run;
BEGIN Texts.OpenWriter(W); t := Term.t; ct := CapTerm.ct; END TestTerm.
TestTerm.Run a b c ~
--
Tomas Kral <thomas.kral at email.cz>
--
Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
https://lists.inf.ethz.ch/mailman/listinfo/oberon
More information about the Oberon
mailing list