Modula 3.1 is designed to be enough of an extension of Modula-3 to
support Microsoft's .NET runtime type system without having to rebuild
the Microsoft Universe. It should be implementable in M3 by providing
a translation program Modula 3.1 to M3, and ordinary M3 code should be
compilable without modification with the proposed Modula 3.1 compiler.
A Property is a hybrid between an object's methods and its fields: it
is method-like in that it may raise exceptions, and employ procedural
code -- it is field-like in the way clients access it. It serves to
shield the client from implementation details, but the convenience
comes at a cost. I cannot foresee how any re-design would not require
the invalidation until recompilation of each and every client.
The design I came up with to support this is to me uncomfortably far
from the M3 spirit. However, the .NET runtime employs properties
extensively. My favorite benefit I enjoy working with M3 was its
expressiveness on a simple syntax; I hope to preserve that here.
I propose within a type declaration within OBJECT ... END, in
addition to METHODS and OVERRIDES a new section PROPS before the
METHODS section to introduce properties. Properties may be read only,
write only, or both readable and writable. As with an object's
methods, its properties may be declared without detailing the
implementation. Here is a read-only property declaration:
TYPE T1 = OBJECT
pagesize : INTEGER;
PROPS
ix : INTEGER RAISES{ InvalidException } ;
END ;
Here is a write-only property declaration:
TYPE T2 = OBJECT
PROPS
ix : INTEGER RAISES{ UnimplementedException } { := n } ;
METHODS
f( a, b : T1 );
END ;
A property would be readable and writeable by including both sections.
TYPE T3 <: OBJECT
PROPS
ix : INTEGER ;
ix : INTEGER { := n } ;
END ;
In the _T2_ and _T3_ example, the _n_ in _{ := n }_ is simply a
placeholder, exactly as _a_ and _b_ are placeholders in the signature
of _f_ in the methods section. In either case, a property may be
implemented by specifying either a target expression or a target
statement sequence. In the following example, the read section is
implemented by an expression, the write section by a statement
sequence:
CONST pagesize = 31 ;
REVEAL T3 = OBJECT
page : ARRAY OF INTEGER ;
location : INTEGER ;
PROPS
ix : INTEGER ( th ):= th.page[ location MOD pagesize ] ;
ix : INTEGER { := n } ( tn )= BEGIN
tn.location:= n DIV pagesize;
tn.page[ tn.location MOD pagesize ]:= n;
END;
METHODS
END;
The _th_ and _tn_ are the "this object" indicators in the expression
and statement sequence, respectively.
A property should be implementable by simple macro expansion. For
example:
VAR v : T3 = NEW( T3, page := NEW( ARRAY OF INTEGER, pagesize ),
location:= 0 );
BEGIN
v.ix := 12;
END
should translate into:
VAR v : T3 = NEW( T3, page := NEW( ARRAY OF INTEGER, pagesize ),
location:= 0 );
BEGIN
v.location := 12 DIV pagesize;
v.page[ v.location MOD pagesize ]:= 12;
END
As such, it is a static error for the statements or expression
specifying a property to form an infinite macro expansion. --leeo


|