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