[Oberon] FPGA - Simple OOP example
    Tomas Kral 
    thomas.kral at email.cz
       
    Wed Aug 15 14:34:37 CEST 2018
    
    
  
Hi,
I have recoded the example as advised.
> 1) Space.
Every Term based type (class) carries its own copy of methods, some may
be [overriden] overwritten, e.g. Write.
NEW(m); m^ = methods^; m.Write := Write
 
> 2) Consistency.
To keep the same methods for all Term based types, we can leave out
NEW(m), and just assign a pointer.
(*NEW(m)*); m = methods;
QUESTION, can we somehow call base method from the overwritten one?
(* ------- OOP EXAMPLE -------- *)
MODULE Term; (* TK 15.8.2018 revised OOP example *)
  IMPORT Texts, Oberon;
  TYPE
    Term* = POINTER TO TDesc;
    Methods* = POINTER TO MDesc;
    (* Base method suite *)
    MDesc* = RECORD
      Write*: PROCEDURE(t: Term; ch: CHAR);
      Refresh*: PROCEDURE(t: Term)
      (* other methods come here *)
    END ;
    (* Base data suite *)
    TDesc* = RECORD
      do*: Methods;
      (* generic terminal data comes here *)
    END ;
  VAR W: Texts.Writer; methods: Methods;
  (* ------ Initialisation for clients ------ *)
  PROCEDURE Init*(t: Term);
  BEGIN t.do := methods
  END Init;
  PROCEDURE InitMethods*(VAR m: Methods);
  BEGIN m^ := methods^
  END InitMethods;
  (* ------ Term base methods ----- *)
  PROCEDURE Write(t: Term; ch: CHAR);
  BEGIN Texts.Write(W, ch)
  END Write;
  PROCEDURE Refresh(t: Term);
  BEGIN Texts.Append(Oberon.Log, W.buf)
  END Refresh;
    
BEGIN Texts.OpenWriter(W); NEW(methods); methods.Write := Write;
  methods.Refresh := Refresh END Term.
MODULE CapTerm;
  IMPORT Texts, Oberon, Term;
  TYPE
    CapTerm* = POINTER TO CTDesc;
    CTDesc* = RECORD (Term.TDesc)
      (* specific cap terminal data comes here *)
      col: INTEGER 
    END ;
     
  VAR W: Texts.Writer; m: Term.Methods;
  PROCEDURE Init*(t: CapTerm; color: INTEGER (* other data for the
  CapTerm if any *) ); BEGIN t.do := m; t.col := color
  END Init;
  PROCEDURE CAP*(ch: CHAR): CHAR;
    VAR up: CHAR;
  BEGIN
    IF (ch >= "a") OR (ch <= "z") THEN
      up := CHR(ORD(ch) + ORD("A") - ORD("a"))
    ELSE up := ch END
  RETURN up END CAP;
  (* --------- Methods to override from Term base ------- *)
  PROCEDURE Write(t: Term.Term; ch: CHAR);
  (* Write method specific for CapTerm *)
  BEGIN
    ch := CAP(ch); Texts.Write(W, ch); Texts.Append(Oberon.Log, W.buf)
    (* could we call base Write instead of Texts.Write/Append ? *)
  END Write;
  (* Refresh() method not to be overriden *)
BEGIN Texts.OpenWriter(W); NEW(m); Term.InitMethods(m); m.Write := Write
END CapTerm.
MODULE TestTerm;
  IMPORT Texts, Oberon, Term, CapTerm;
  VAR
    W: Texts.Writer; t: Term.Term; c: 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
      t.do.Write(t, S.s[0]); t.do.Refresh(t); 
      c.do.Write(c, S.s[0]); c.do.Refresh(c); (* calls Term.Refresh() *)
      Texts.Scan(S)
    END ;
    Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)
  END Run;
BEGIN Texts.OpenWriter(W);
  NEW(t); Term.Init(t);
  NEW(c); CapTerm.Init(c, 20)
END TestTerm.
TestTerm.Run  a b c ~
-- 
Tomas Kral <thomas.kral at email.cz>
    
    
More information about the Oberon
mailing list