[M3devel] M3CG_Ops.Public vs. M3CG.T
Jay K
jay.krell at cornell.edu
Thu Sep 27 21:00:30 CEST 2012
One thing I missed is that IMPORT M3CG; Give you an M3CG.T that you can only pass around. Add IMPORT M3CG_Ops I think it was and then you can make all the method calls on an M3CG.T. I don't see that the first intermediate step is useful, but oh well. Everyone might as well just IMPORT M3CG_Ops. It is kind of interesting that "private" and "protected" are kind of available in Modula-3, or at least one clump therein, by moving part of the interface into a separate file. I say one clump, because I don't think you can do this: FooRoot.i3: TYPE Foo <: ROOT; Foo1.i3: TYPE Foo <: OBJECT METHODS PROCEDURE F1(); END; Foo2.i3:TYPE Foo <: OBJECT METHODSPROCEDURE F2();END; Foo.m3: REVEAL Foo = OBJECT METHODS PROCEDURE F1(); PROCEDURE F2(); END; I think you can only have just: FooRoot.i3: TYPE Foo <: ROOT; Foo1.i3: TYPE Foo <: OBJECT METHODS PROCEDURE F1(); END; Foo.m3: REVEAL Foo = OBJECT METHODS PROCEDURE F1(); PROCEDURE F2(); END; It'd also be useful if you could do like this: Stream.i3: Reader = OBJECT METHODS PROCEDURE Read(); END; Writer = OBJECT METHODS PROCEDURE Write(); END; TYPE Stream <: Reader; TYPE Stream <: Writer; Stream.m3: REVEAL Stream = OBJECT METHODS PROCEDURE Read(); PROCEDURE Write(); END; i.e. -- multiple inheritance. I realize you can reveal in multiple linear steps though...which I'm not going to give an example of right now.. so it isn't just "one clump", but if you reveal "multiple clumps", they need to form a linear chain, right? You can't "mix" as I showed for read/write. ? - Jay
From: jay.krell at cornell.edu
To: hosking at cs.purdue.edu
Date: Thu, 27 Sep 2012 05:14:27 +0000
CC: m3devel at elegosoft.com
Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T
No. I'm ok with that.
My point is, that basically, there are two really good forms ofinterface that have the right level of revelation and hiding.I don't see much point for in-between.
The two forms..they are kind of canonical C and C++ forms, butthey both map to Modula-3.
One form is a fully opaque type and a bunch of functionsthat take that type as the first parameter.
Like this:
struct Window_t; typedef struct Window_t* Window_t;
Window_t* Window_Create(...); /* create is special -- first parameter isn't Window_t* */ void Window_Close(Window_t*...); void Window_SetTitle(Window_t*...); TEXT Window_GetTitle(Window_t*...);
It maps directly to Modula-3.Though I'm not sure exactly how.
Window.i3:INTERFACE Window;TYPE T <: ROOT;PROCEDURE Close(T);PROCEDURE SetTitle(T, TEXT);PROCEDURE GetTitle(T): TEXT;
The other form is a bunch of pure virtual functions, nodata, no non-virtual functions. This is what COM prescribes.And "Create" is special.
struct Window_t{ virtual void Close() = 0; virtual void SetTitle(TEXT) = 0; virtual TEXT GetTitle() = 0;};
Window_t* Window_Create(...);
This maps well to Modula-3 as well:
Window.i3:T <: OBJECT METHODS PROCEDURE Close(); PROCEDURE SetTitle(TEXT); PROCEDURE GetTitle(): TEXT;END;
The in-between, which I'm not sure is all that worthwhile,is where C++ offers "protected", and "worse", "private".Really "private" doesn't belong in a header.
In the case of M3CG, I don't think we have any need for in-between.I think currently clients either know it is <: ROOT or <: Ops.Public.
I don't see the point in hiding <: Ops.Public.You might as well let every client know that.They just pass them around by value/reference, and not callany methods/member-functions, but I don't see that hidingthem helps anything.
Typical "operating system" interfaces look like what I showed first,except that Window_t* is replaced by "int" or "void*". Which I think ismostly inferior. void* at least allows for basically the same implementationstrategies, including casting it to int and indexing into a table, buthaving different pointer types allows for a little bit of type-safetyin the clients (i.e. avoiding passing a Windows_t* to File_Read).
- Jay
From: hosking at cs.purdue.edu
Date: Wed, 26 Sep 2012 15:53:26 -0400
To: jay.krell at cornell.edu
CC: m3devel at elegosoft.com
Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T
Are you saying that you don’t like importing M3CG as well as M3CG_Ops?
On Sep 26, 2012, at 3:30 PM, Jay <jay.krell at cornell.edu> wrote:Ok but this seems not great..
- Jay (briefly/pocket-sized-computer-aka-phone)
On Sep 26, 2012, at 8:58 AM, Antony Hosking <hosking at cs.purdue.edu> wrote:
Yes, M3CG.T is the most abstract type.Please don’t make this change.
On Sep 26, 2012, at 11:36 AM, Jay K <jay.krell at cornell.edu> wrote:It is not pervasive.It is like one line in about six files. M3CG.T => M3CG_Ops.Publics.
I guess you are saying that M3CG.T is merely the extremely abstract ROOT, where M3CG_Ops.Public has a bunch of methods? Then I might argue that M3CG.T is overly abstract -- it is like void* instead of pointer just with a bunch of methods.
This isn't quite right, doesn't compilte, but rougly:
Index: M3CG_BinRd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinRd.i3--- M3CG_BinRd.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinRd.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinRd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the binary intermediate code M3CG calls from 'rd' and call 'cg' to implement them. *) Index: M3CG_BinRd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,vretrieving revision 1.19diff -u -r1.19 M3CG_BinRd.m3--- M3CG_BinRd.m3 4 Sep 2012 14:29:54 -0000 1.19+++ M3CG_BinRd.m3 26 Sep 2012 15:34:32 -0000@@ -20,7 +20,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; buf : InputBuffer; buf_len: CARDINAL; buf_ptr: CARDINAL;@@ -200,7 +200,7 @@ Cmd {Bop.fetch_and_xor, fetch_and_xor} }; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_BinWr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.i3,vretrieving revision 1.2diff -u -r1.2 M3CG_BinWr.i3--- M3CG_BinWr.i3 12 Feb 2001 15:25:47 -0000 1.2+++ M3CG_BinWr.i3 26 Sep 2012 15:34:32 -0000@@ -3,9 +3,9 @@ INTERFACE M3CG_BinWr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as binary intermediate code on 'wr'. See M3CG_Binary for the binary format. *)Index: M3CG_BinWr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinWr.m3,vretrieving revision 1.23diff -u -r1.23 M3CG_BinWr.m3--- M3CG_BinWr.m3 4 Sep 2012 15:20:09 -0000 1.23+++ M3CG_BinWr.m3 26 Sep 2012 15:34:32 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: M3CG_Check.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Check.i3--- M3CG_Check.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Check.i3 26 Sep 2012 15:34:32 -0000@@ -7,11 +7,11 @@ INTERFACE M3CG_Check; -IMPORT M3CG;+IMPORT M3CG_Ops; -PROCEDURE New (child: M3CG.T;+PROCEDURE New (child: M3CG_Ops.Public; clean_jumps, clean_stores: BOOLEAN;- nested_calls, nested_procs: BOOLEAN): M3CG.T;+ nested_calls, nested_procs: BOOLEAN): M3CG_Ops.Public; (* returns a fresh, initialized code generator that passes its calls to 'child' and checks that the stream obeys the M3CG restrictions. If 'clean_jumps', it also checks that the stack is empty at everyIndex: M3CG_Check.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Check.m3,vretrieving revision 1.17diff -u -r1.17 M3CG_Check.m3--- M3CG_Check.m3 4 Sep 2012 14:47:43 -0000 1.17+++ M3CG_Check.m3 26 Sep 2012 15:34:33 -0000@@ -32,7 +32,7 @@ }; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT clean_stores := FALSE; clean_jumps := FALSE; nested_calls := TRUE;===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Ops.i3,vretrieving revision 1.12diff -u -r1.12 M3CG_Ops.i3--- M3CG_Ops.i3 16 Aug 2012 13:12:35 -0000 1.12+++ M3CG_Ops.i3 26 Sep 2012 15:34:33 -0000@@ -30,7 +30,7 @@ Public = OBJECT (*------------------------------------------------ READONLY configuration ---*) -child: M3CG.T := NIL;+child: Public := NIL; (* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *)Index: M3CG_Rd.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Rd.i3--- M3CG_Rd.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Rd.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Rd; -IMPORT M3CG, Rd;+IMPORT M3CG_Ops, Rd; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T);+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public); (* Parse the M3CG calls from 'rd' and call 'cg' to implement them. *) END M3CG_Rd.Index: M3CG_Rd.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,vretrieving revision 1.15diff -u -r1.15 M3CG_Rd.m3--- M3CG_Rd.m3 4 Sep 2012 14:52:46 -0000 1.15+++ M3CG_Rd.m3 26 Sep 2012 15:34:33 -0000@@ -22,7 +22,7 @@ TYPE State = RECORD rd : Rd.T;- cg : M3CG.T;+ cg : M3CG_Ops.Public; ch : CHAR; (* current scan character *) buf : InputBuffer; buf_len: CARDINAL;@@ -206,7 +206,7 @@ cmds: IntIntTbl.T := NIL; types: IntIntTbl.T := NIL; -PROCEDURE Inhale (rd: Rd.T; cg: M3CG.T) =+PROCEDURE Inhale (rd: Rd.T; cg: M3CG_Ops.Public) = VAR s: State; op: M3CG.Name; cmd: INTEGER; BEGIN s.rd := rd;Index: M3CG_Wr.i3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.i3,vretrieving revision 1.1.1.1diff -u -r1.1.1.1 M3CG_Wr.i3--- M3CG_Wr.i3 14 Jan 2001 13:40:37 -0000 1.1.1.1+++ M3CG_Wr.i3 26 Sep 2012 15:34:33 -0000@@ -7,9 +7,9 @@ INTERFACE M3CG_Wr; -IMPORT M3CG, Wr;+IMPORT M3CG_Ops, Wr; -PROCEDURE New (wr: Wr.T): M3CG.T;+PROCEDURE New (wr: Wr.T): M3CG_Ops.Public; (* returns a fresh, initialized code generator that writes its calls as readable ASCII on 'wr'. *) Index: M3CG_Wr.m3===================================================================RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Wr.m3,vretrieving revision 1.18diff -u -r1.18 M3CG_Wr.m3--- M3CG_Wr.m3 22 Aug 2012 14:15:40 -0000 1.18+++ M3CG_Wr.m3 26 Sep 2012 15:34:33 -0000@@ -27,7 +27,7 @@ END; TYPE- U = M3CG.T OBJECT+ U = M3CG_Ops.Public OBJECT wr : Wr.T := NIL; buf : M3Buf.T := NIL; buf_len : INTEGER := 0;@@ -375,7 +375,7 @@ (*---------------------------------------------------------------------------*) -PROCEDURE New (output: Wr.T): M3CG.T =+PROCEDURE New (output: Wr.T): M3CG_Ops.Public = VAR mbuf := M3Buf.New (); BEGIN M3Buf.AttachDrain (mbuf, output);Index: Target.i3===================================================================
- Jay
From: hosking at cs.purdue.edu
Date: Wed, 26 Sep 2012 10:42:26 -0400
To: jay.krell at cornell.edu
CC: m3devel at elegosoft.com
Subject: Re: [M3devel] M3CG_Ops.Public vs. M3CG.T
I disagree. M3CG.T is more abstract than M3CG_Ops. The revelation of M3CG.T <: M3CG_Ops.Public is in M3CG_Ops. If you want the ops you simply import that interface to get the revelation. Please don’t make pervasive changes in interfaces that some of us are developing against.
On Sep 26, 2012, at 4:11 AM, Jay K <jay.krell at cornell.edu> wrote:M3CG_Ops.i3:
child: M3CG.T := NIL;(* The default methods simply call the corresponding method in 'child', hence a vanilla 'M3CG.T' can be used as a filter where you override only the methods of interest. *)
1)
I am not keen on fixing this, but I feel this was clearly a mistake.
M3CG_Ops.Public should have been "purely abstract" with no defaultimplementation.M3CG_Filter.T or somesuch could have been as described.
2) I am fixing:M3CG.T is overused.Most uses should be M3CG_Ops.Public.It is ok to derive from -- though that was a mistake.But functions that take or return M3CG.T should really betaking and returning M3CG_Ops.Public.
- Jay
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20120927/b0ad5030/attachment-0002.html>
More information about the M3devel
mailing list