Page Numbers: Yes X: 558 pt Y: 0.5"
Margins: Top: 1.25" Bottom: 1.5"
Columns: 1 Edge Margin: 1.0"
Heading:
File: <Mitchell>cedar-style.bravo April 22, 1980
The Cedar Style Sheet
Names
Capitalization
(C1) The first letter of a name is capital if it identifies a
module, procedure, signal, or type, otherwise the first letter is lower-case.
Fugleman, SomeProc, ObjectSupport
(C1b) Not allowed to declare two identifiers that differ only by case shifts, except for foo:Foo
(C2) Each imbedded word of a multi-word name has its first letter capitalized.
field1, anotherFm, aLongName
Qualification
(Q1) Use fully qualified names, with few exceptions:
OPENing the definitions module that a program module implements.
OPENing an interface in a (small) scope within which items from the interface are used a lot.
or, provided that there is a USING clause in the directory section for the interface.
(Q2) It is usually better to use the "OPEN alternateName: xxx" form with a short alternateName than to use the form "OPEN xxx".
(Q3) No opens unless expression is an interface type
(Q4) use the "WITH alternateName: xxx SELECT ..." form with a short alternateName instead of the form "WITH xxx SELECT ...".
Module Naming
(M1) DEFINITIONS modules have no "Defs" suffix on their names; PROGRAM module names have suffix "Impl"; no suffix on CONFIGURATION module names; e.g.,
ObjectSupport.mesa -- DEFINITIONS module
ClassFugleman.mesa -- DEFINITIONS module for object interface
ObjectSupportImpl.mesa -- PROGRAM module
CedarSupport.config -- CONFIGURATION module
(M1a) Impl is only required if definitions file name conflicts
(M1b) Name of a config file should not include "Config" as a suffix, but should use it as an extension; e.g.,
FooConfig.config NO
Foo.config YES
Types
(Claim) It is almost always better to name a type than to define an anonymous one, especially in definitions modules:
DeckIndex: TYPE = [0..52);
CardDeck: TYPE = ARRAY DeckIndex OF Card; -- YES
CardDeck: TYPE = ARRAY [0..52) OF Card; -- NO
Interval Types
[0..upperLimit) -- preferred form
FOR i IN [0..n) DO IF a[i]=a[n] THEN . . . ENDLOOP;
Record types, constructors, and extractors
(P1) Keyword argument lists, constructors, and extractors
single-argument procs - not needed
two- or more-argument procedures - it's a good idea to use keyword constructors for the argument, especially if any two of the parameters have equivalent types
(P2) include keywords on procedure result fields in defs (if more than one)
SIGNALs
(S0) Don't use ENDCASE to handle specific cases; either use it to handle "all other cases" or to generate an ERROR
In DEFINITIONS modules
(S1) Each DEFINITIONS module defines at most one SIGNAL which passes a single argument detailing the reason for the signal. The argument is a value of an enumerated type. E.g.,
HashTableProblem: SIGNAL [reason: ErrorCode];
ErrorCode: TYPE = {damaged, bug, tableFull};
(S1a) May be a small set of signals such as in (S1)
(S1b) Locally defined signals are okay.
(S1d) (Ed's proposal)
(1) declare ERRORs as ERRORs
(2) each resumable signal should get a different name (since these are rare).
(S2) Each procedure in an interface that generates signals or errors should have stylized comments indicating which errors or signals it generates and what RESUME means for the signals. E.g.,
FindItem: PROCEDURE[k: Key] RETURNS [v: Value, found: BOOLEAN];
-- ERRORs: HashTableProblem[damaged]
-- SIGNALs: HashTableProblem[tableFull]
-- tries again if resumed
(S2b) When generating a SIGNAL or ERROR, one must write SIGNAL foo or "ERROR foo", not just "foo".
In PROGRAM modules
(S3) Don't let errors or signals that are "part of" the interfaces of invoked routines pass by: transform them into ones that are part of your interface (i.e., insulate your clients from details of your implementation).
(S4) Avoid using "ERROR;"
Program layout
We need a pretty printer
Mesa 6: SDD will supply one
Cedar: Warren will supply one
Extra information:
(R1) extra info in first line (+ file name) (passed)
(R2) End of file: Change Log for keeping track of what has happened to a module and for learning its history.
(R2a) paragraph of global info about program just in front of edit log
(R3) don't use bravo formatting (must have passed, but nothing in
my notes)
Where to keep things
[Ivy]<Cedar>ProjectName>Release
Example: [Ivy]<Cedar>Database>1.1
[Ivy]<Cedar>Support>Release -- support software everyone will need
-- comes as a configuration: CedarSupport.config (.bcd)
Library: [Ivy]<Cedar>Library>Release -- talk to Warren if you have something to submit. Documentation on [Ivy]<Cedardocs>Library>*
-- FILE: ClassFugleman.mesa
-- Last Edited by Mitchell, March 27, 1980 9:22 AM
ClassFugleman: DEFINITIONS =
BEGIN
NewStdFugleman: PROCEDURE RETURNS [Fugleman];
-- Each implementation of class Fugleman will, in general, have its own
-- New procedure, with parameters specific to that implementation.
-- There is, however, often a "standard" implementation for a class,
-- and it seems reasonable to put the definition of its New procedure
-- here with the definition of the class.
Fugleman: TYPE = POINTER TO POINTER TO READONLY FuglemanProcs;
FuglemanProcs: TYPE = MACHINE DEPENDENT RECORD
[
Release: PROCEDURE [Self: Fugleman] RETURNS [nilFugleman: Fugleman],
Print: PROCEDURE [Self: Fugleman],
Check: PROCEDURE [Self: Fugleman],
SomeProc: PROCEDURE [Self: Fugleman, otherArgument: CARDINAL]
RETURNS [CARDINAL]
];
END.
This is a template for defining the interface for a class, Fugleman, of objects. It provides for multiple, coexisting implementations of the class. The file FuglemanClient.mesa shows how a client program can create instances of the objects of this class, and the file FuglemanImpl.mesa is a template for an implementation of the class.
Change Log
Created by Mitchell: March 17, 1980 11:00 AM
This is a template for interim Cedar object interfaces. It shows what one would write to define the interface for a class FugleMan of objects with operations Release, Print, Check, and SomeProc
Changed by Mitchell: DateTime
DescriptionOfChange
-- FILE: FuglemanClient.mesa
-- Last Edited by Mitchell, March 27, 1980 9:23 AM
DIRECTORY
ClassFugleman: FROM "ClassFugleman";
FuglemanClient: PROGRAM IMPORTS fugles: ClassFugleman =
BEGIN
SillyTest: PUBLIC PROCEDURE =
-- a nonsense program to show how clients invoke operations on objects implemented this way
BEGIN
fm: fugles.Fugleman = fugles.NewFugleman[];
anotherFm: fugles.Fugleman = fugles.NewFugleman[];
x: CARDINAL ← 1;
fm.Check[fm]; -- check the object
IF fm=anotherFm THEN ERROR; -- should get unique objects
IF fm.SomeProc[fm, 1] = anotherFm.SomeProc[anotherFm, 2] THEN x←2;
END;
END. -- FuglemanClient
This is an example intended only to show syntactically how client programs create object instances, invoke operations on them and catch signals that those operations might generate. The files ClassFugleman.mesa and FuglemanImpl.mesa contain the definitions of the object interface used here and a sample implementation of it, respectively.
Change Log
Created by YourName: DateTime
DescriptionOfChange
Changed by YourName: DateTime
DescriptionOfChange
-- FILE: FuglemanImpl.mesa
-- Last Edited by Mitchell, March 17, 1980 11:33 AM
DIRECTORY
ObjectSupport: FROM "ObjectSupport",
ClassFugleman: FROM "ClassFugleman";
FuglemanStdImpl: PROGRAM IMPORTS ObjSupp: ObjectSupport
EXPORTS ClassFugleman =
BEGIN OPEN ClassFugleman;
-- implementation types
CFugleman: TYPE = POINTER TO CFinger; -- concrete form of the object
CFinger: TYPE = MACHINE DEPENDENT RECORD
[procs: POINTER TO FuglemanProcs, data: POINTER TO FuglemanData];
FuglemanData: TYPE = RECORD
[
count: CARDINAL,
flag: BOOLEAN ← TRUE,
mumble: INTEGER
];
Procedures: FuglemanProcs ← -- this is type-checked by the compiler
[Release: Release, Print: Print, Check: Check, SomeProc: SomeProc];
AbstractToRep: PROCEDURE[Self: Fugleman]
RETURNS [POINTER TO FuglemanData] = INLINE
BEGIN RETURN[LOOPHOLE[Self, CFugleman].data] END;
RepToAbstract: PROCEDURE[rep: CFugleman] RETURNS [Fugleman] = INLINE
BEGIN RETURN[LOOPHOLE[rep, Fugleman]] END;
-- a sample New procedure for creating a Fugleman object
NewStdFugleman: PUBLIC PROCEDURE RETURNS [Fugleman] =
BEGIN
cFugleman: CFugleman ← ObjSupp.AllocateObject[
procs: @Procedures, size: SIZE[FuglemanData]];
cFugleman.data↑ ← [count: 5, mumble: -10];
RETURN[RepToAbstract[cFugleman]];
END;
-- Operations on a Fugleman
Release: PROCEDURE [Self: Fugleman] RETURNS [nilFugleman: Fugleman] =
BEGIN
RETURN[ObjSupp.FreeObject[Self]];
END;
Print: PROCEDURE [Self: Fugleman] =
BEGIN
d: CFugleman = AbstractToRep[Self];
-- refer to "Self.count" as "d.count"
END;
Check: PROCEDURE [Self: Fugleman] =
BEGIN
d: CFugleman = AbstractToRep[Self];
IF d.count>100 OR d.mumble<0 AND NOT d.flag THEN ERROR; -- example only
END;
SomeProc: PROCEDURE [Self: Fugleman, otherArgument: CARDINAL]
RETURNS [CARDINAL] =
BEGIN
d: CFugleman = AbstractToRep[Self];
IF otherArgument>100 THEN otherArgument ← 100;
d.count ← otherArgument;
END;
END.
This is a template for an implementation of the class of objects defined by ClassFugleman.mesa. There may be more than one implementation of this same class. This method of providing objects is intended for use until Cedar/Mesa has sufficient language facilities to avoid the LOOPHOLEs needed here. In any case, no client programs will have to change when this occurs. An example of a client program can be found in FuglemanClient.mesa.
Change Log
Created by YourName: DateTime
DescriptionOfChange
Changed by YourName: DateTime
DescriptionOfChange
-- FILE: ClassFugleman.mesa
-- Last Edited by Mitchell, March 27, 1980 9:22 AM
ClassFugleman: DEFINITIONS =
BEGIN
NewStdFugleman: PROCEDURE RETURNS [Fugleman];
-- Each implementation of class Fugleman will, in general, have its own
-- New procedure, with parameters specific to that implementation.
-- There is, however, often a "standard" implementation for a class,
-- and it seems reasonable to put the definition of its New procedure
-- here with the definition of the class.
Fugleman: TYPE = POINTER TO POINTER TO READONLY FuglemanProcs;
FuglemanProcs: TYPE = MACHINE DEPENDENT RECORD
[
Release: PROCEDURE [Self: Fugleman] RETURNS [nilFugleman: Fugleman],
Print: PROCEDURE [Self: Fugleman],
Check: PROCEDURE [Self: Fugleman],
-- ERRORS: Problem[damaged]
SomeProc: PROCEDURE [Self: Fugleman, otherArgument: CARDINAL]
RETURNS [CARDINAL]
-- SIGNALS: Problem[argumentOutOfRange]
-- uses max allowed value for otherArgument if resumed
];
Problem: SIGNAL[reason: ErrorCode];
ErrorCode: TYPE = {damaged,implementationBug, argumentOutOfRange};
END.
This is a template for defining the interface for a class, Fugleman, of objects. It provides for multiple, coexisting implementations of the class. The file FuglemanClient.mesa shows how a client program can create instances of the objects of this class, and the file FuglemanImpl.mesa is a template for an implementation of the class.
Change Log
Created by Mitchell: March 17, 1980 11:00 AM
This is a template for interim Cedar object interfaces. It shows what one would write to define the interface for a class FugleMan of objects with operations Release, Print, Check, and SomeProc
Changed by Mitchell: DateTime
DescriptionOfChange
-- FILE: FuglemanClient.mesa
-- Last Edited by Mitchell, March 27, 1980 9:23 AM
DIRECTORY
ClassFugleman: FROM "ClassFugleman";
FuglemanClient: PROGRAM IMPORTS fugles: ClassFugleman =
BEGIN
SillyTest: PUBLIC PROCEDURE =
-- a nonsense program to show how clients invoke operations on objects implemented this way
BEGIN
fm: fugles.Fugleman = fugles.NewFugleman[];
anotherFm: fugles.Fugleman = fugles.NewFugleman[];
x: CARDINAL ← 1;
fm.Check[fm ! fugles.Problem => ERROR]; -- check the object
IF fm=anotherFm THEN ERROR; -- should get unique objects
IF fm.SomeProc[fm, 1] = anotherFm.SomeProc[anotherFm, 2] THEN x←2;
END;
END. -- FuglemanClient
This is an example intended only to show syntactically how client programs create object instances, invoke operations on them and catch signals that those operations might generate. The files ClassFugleman.mesa and FuglemanImpl.mesa contain the definitions of the object interface used here and a sample implementation of it, respectively.
Change Log
Created by YourName: DateTime
DescriptionOfChange
Changed by YourName: DateTime
DescriptionOfChange
-- FILE: ClassFuglemanImpl.mesa
-- Last Edited by Mitchell, March 27, 1980 11:24 AM
DIRECTORY
ClassFugleman: FROM "ClassFugleman";
ClassFuglemanImpl: PROGRAM EXPORTS ClassFugleman =
BEGIN OPEN ClassFugleman;
Problem: SIGNAL[reason: ErrorCode] = CODE;
END.
This is a template for a class implementation for ClassFugleman.mesa. Its only purpose is to provide a "home" for any SIGNALs defined in ClassFugleman.mesa as one does not want different implementations to provide different actual SIGNALs for them.
Change Log
Created by YourName: DateTime
DescriptionOfChange
Changed by YourName: DateTime
DescriptionOfChange
-- FILE: FuglemanImpl.mesa
-- Last Edited by Mitchell, March 17, 1980 11:33 AM
DIRECTORY
ObjectSupport: FROM "ObjectSupport",
ClassFugleman: FROM "ClassFugleman";
FuglemanStdImpl: PROGRAM IMPORTS ObjSupp: ObjectSupport
EXPORTS ClassFugleman =
BEGIN OPEN ClassFugleman;
-- implementation types
CFugleman: TYPE = POINTER TO CFinger; -- concrete form of the object
CFinger: TYPE = MACHINE DEPENDENT RECORD
[procs: POINTER TO FuglemanProcs, data: POINTER TO FuglemanData];
FuglemanData: TYPE = RECORD
[
count: CARDINAL,
flag: BOOLEAN ← TRUE,
mumble: INTEGER
];
Procedures: FuglemanProcs ← -- this is type-checked by the compiler
[Release: Release, Print: Print, Check: Check, SomeProc: SomeProc];
AbstractToRep: PROCEDURE[Self: Fugleman]
RETURNS [POINTER TO FuglemanData] = INLINE
BEGIN RETURN[LOOPHOLE[Self, CFugleman].data] END;
RepToAbstract: PROCEDURE[rep: CFugleman] RETURNS [Fugleman] = INLINE
BEGIN RETURN[LOOPHOLE[rep, Fugleman]] END;
-- a sample New procedure for creating a Fugleman object
NewStdFugleman: PUBLIC PROCEDURE RETURNS [Fugleman] =
BEGIN
cFugleman: CFugleman ← ObjSupp.AllocateObject[
procs: @Procedures, size: SIZE[FuglemanData]];
cFugleman.data↑ ← [count: 5, mumble: -10];
RETURN[RepToAbstract[cFugleman]];
END;
-- Operations on a Fugleman
Release: PROCEDURE [Self: Fugleman] RETURNS [nilFugleman: Fugleman] =
BEGIN
RETURN[ObjSupp.FreeObject[Self]];
END;
Print: PROCEDURE [Self: Fugleman] =
BEGIN
d: CFugleman = AbstractToRep[Self];
-- refer to "Self.count" as "d.count"
END;
Check: PROCEDURE [Self: Fugleman] =
-- ERRORS: Problem[damaged]
BEGIN
d: CFugleman = AbstractToRep[Self];
IF d.count>100 OR d.mumble<0 AND NOT d.flag THEN
ERROR Problem[damaged]; -- example only
END;
SomeProc: PROCEDURE [Self: Fugleman, otherArgument: CARDINAL]
RETURNS [CARDINAL] =
-- SIGNALS: Problem[argumentOutOfRange]
-- uses max allowed value for otherArgument if resumed
BEGIN
d: CFugleman = AbstractToRep[Self];
IF otherArgument>100 THEN
BEGIN SIGNAL Problem[argumentOutOfRange]; otherArgument ← 100; END;
d.count ← otherArgument;
END;
END.
This is a template for an implementation of the class of objects defined by ClassFugleman.mesa. There may be more than one implementation of this same class. This method of providing objects is intended for use until Cedar/Mesa has sufficient language facilities to avoid the LOOPHOLEs needed here. In any case, no client programs will have to change when this occurs. An example of a client program can be found in FuglemanClient.mesa.
Change Log
Created by YourName: DateTime
DescriptionOfChange
Changed by YourName: DateTime
DescriptionOfChange