AMTypes.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Rovner, July 22, 1983 2:39 pm
Russ Atkinson (RRA) February 12, 1985 1:19:31 pm PST
DIRECTORY
Rope USING [ROPE],
SafeStorage USING [Type, nullType],
WorldVM USING [World];
AMTypes: CEDAR DEFINITIONS = BEGIN OPEN Rope, WorldVM;
Notation for procedure comments
domain: classExpr  {class1, class2, ...}
will raise Error[typeFault] if violated
T Y P E S
Type: TYPE = SafeStorage.Type;
nullType: Type = SafeStorage.nullType;
TypedVariable: TYPE = REF ANY;
TV: TYPE = TypedVariable;
A TV (or TypedVariable) represents a CedarMesa variable. That is, the variable has a certain amount storage, the variable has a type, and it holds a value. There can be numerous variables for a given TV. A TV does NOT provide monitored or otherwise atomic access to its variable, so the user must synchronize uses of TVs.
Status: TYPE = {mutable, readOnly, const};
The three kinds of status are:
mutable - the variable can have its value changed through this TV
readOnly - the variable can NOT have its value changed through this TV
const - the variable has constant contents (as for a literal)
Index: TYPE = NAT;
index range for records, enumerations, etc is [1..n], 0 has special case meaning
Class: TYPE = {
definition,
TypeClass[CODE[T]] where T: TYPE = ...
cardinal, longCardinal, integer, longInteger, real, character,
basic types - e.g. TypeClass[CODE[INT]]
atom, rope, list, ref, pointer, longPointer, descriptor, longDescriptor, basePointer, relativePointer,
address types - e.g. TypeClass[CODE[REF INT]]
procedure, signal, error, program, port,
transfer types - e.g. TypeClass[CODE[PROC]]
enumerated,
e.g. TypeClass[CODE[{red, green, blue}]]
subrange,
e.g. TypeClass[CODE[ [0..4) ]]
union, sequence,
the variant parts of record types
record, structure,
e.g. TypeClass[CODE[ RECORD[INT] ]]
note: structure types are unpainted record types
array,
e.g. TypeClass[CODE[ARRAY T1 OF T2]]
countedZone, uncountedZone,
TypeClass[CODE[ZONE]], TypeClass[CODE[UNCOUNTED ZONE]]
nil,
TypeClass[TVType[NIL]]
unspecified,
TypeClass[CODE[UNSPECIFIED]] or TypeClass[CODE[LONG UNSPECIFIED]]
process,
TypeClass[CODE[PROCESS]]
type,
TypeClass[CODE[TYPE]]
opaque,
UnderClass[CODE[T]], where T: TYPE; or T: TYPE[2]
any,
TypeClass[Range[CODE[REF ANY]]]
globalFrame, localFrame
all global frames have the same type and class
all local frames have the same type and class
};
E R R O R S
Error: ERROR[
reason: ErrorReason,
msg: ROPENIL,
type: Type ← nullType, -- used with TypeFault, IncompatibleTypes
otherType: Type ← nullType -- used with IncompatibleTypes
];
ErrorReason: TYPE = {
noSymbols, -- msg has moduleName
notImplemented, -- mostly DefaultInitialValue cases
incompatibleTypes, -- raised by Assign
rangeFault, -- e.g. empty subrange, Apply bounds check
notMutable, -- raised by (e.g.) Assign
internalTV, -- raised by (e.g.) RefFromTV
badName, -- raised by NameToIndex
badIndex, -- raised by (e.g.) IndexToType
typeFault -- general applicability violation
};
P R O C E D U R E S
Access to general Type characteristics.
Size: PROC [type: Type, length: CARDINAL ← 0] RETURNS [words: INT];
... returns the # of words for the given type. For sequences only, the # of elements must be supplied as well. For unions, the max # of words will be returned.
DefaultInitialValue: PROC [type: Type] RETURNS [TV];
... returns the default initialization for the type. This is useless for record components, since the default initialization is usually associated with the component instead of the type, so use IndexToDefaultInitialValue instead in that case. There are a lot of initial values that the compiler can handle but AMTypes cannot handle, especially initialization to variables or procedure calls (can raise Error[notImplemented]).
IndexToDefaultInitialValue: PROC [type: Type, index: Index] RETURNS [TV];
domain: UnderClass[type]  {record, structure}
... returns the initial value associated with the given component of the type.
TypeClass: PROC [type: Type] RETURNS [Class];
Returns the class of the type.
UnderClass: PROC [type: Type] RETURNS [Class];
Equivalent to TypeClass[UnderType[type]].
IsPainted: PROC [type: Type] RETURNS [BOOL];
Enumerated types and records declared in interfaces are painted.
Access to general TV characteristics.
TVType: PROC [tv: TV] RETURNS [Type];
returns the type of the variable represented by the given TV
TVStatus: PROC [tv: TV] RETURNS [Status];
returns the status of the given TV
TVSize: PROC [tv: TV] RETURNS [words: INT];
returns the # of words for the given TV
GetEmptyTV: PROC RETURNS [TV];
returns a predefined, special TV that is used to indicate the "empty" value. The user should only depend on the identity of this TV, NOT the type, status, or size of the returned TV.
The procedures below are applicable to all but the frame types, opaque and any.
New: PROC [type: Type, status: Status ← mutable, world: World ← NIL, tag: TVNIL] RETURNS [TV];
domain: UnderClass[type] {opaque, any, globalFrame, localFrame}
... creates and returns a cleared object of a give type for the given world (if remote, this is a copied remote object). tag has meaning only for union or sequence-containing record types. See DefaultInitialValue. If world = NIL, then WorldVM.LocalWorld[] is used.
Copy: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[type]] {opaque, any, globalFrame, localFrame}
... returns a copy of the TV (in the same world). This generates a new variable. The returned TV will have mutable status.
Assign: PROC [lhs, rhs: TV];
domain: UnderClass[TVType[lhs]] {any, globalFrame, localFrame}
domain: UnderClass[TVType[rhs]] {any, globalFrame, localFrame}
... assigns the value of rhs to lhs; will raise Error[notMutable] if TVStatus[lhs] # mutable
AssignNew: PROC [lhs, rhs: TV];
... assigns the value of rhs to lhs for initialization only; will raise Error[notMutable] if TVStatus[lhs] # mutable
TVEq: PROC [tv1, tv2: TV] RETURNS [BOOL];
TVEqual[tv1, tv2] iff assignment to one is equivalent to assignment to the other; i.e, they address the same bits.
TVEqual: PROC [tv1, tv2: TV] RETURNS [BOOL];
TVEqual[tv1, tv2] iff the values have the same size and same bits. NOTE: no type checking is done.
Procedures with applicability restrictions (based on Class, noted as comments)
NComponents: PROC [type: Type] RETURNS [Index];
domain: UnderClass[type]  {record, structure}
... returns the # of components for the type
VariableType: PROC [type: Type] RETURNS [v: Type, c: Class];
domain: UnderClass[type]  {record, structure}
result: c  {nil, union, sequence}
returns the union or sequence type and its class (nil if type is not a variant type)
IndexToTV: PROC [tv: TV, index: Index] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {record, structure}
range restriction: index IN [1..NComponents[TVType[tv]]]
IndexToType: PROC [type: Type, index: Index] RETURNS [Type];
domain: UnderClass[type]  {record, structure, union}
... returns the specified component of the type (SPECIAL CASE for union types: index = 0 gets you the tag type
NameToIndex: PROC [type: Type, name: ROPE] RETURNS [CARDINAL];
domain: UnderClass[type]  {record, structure, union, enumerated}
... returns the name associated with the given component (raises Error[badName] if no such named component)
IndexToName: PROC [type: Type, index: CARDINAL] RETURNS [ROPE];
domain: UnderClass[type]  {record, structure, union, enumerated}
... returns the name associated with the given component (SPECIAL CASE for union types: index = 0 gets you the tag name)
TVToType: PROC [tv: TV] RETURNS [Type];
domain: UnderClass[TVType[tv]] = type
... returns the type that tv holds (NOT the type of the value that TV holds)
TVToName: PROC [tv: TV] RETURNS [ans: ROPE];
class restriction: UnderClass[TVType[tv]]  {ref, atom, rope, enumerated, program, procedure, signal, error, globalFrame}
Tag: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]] = union
returns the tag for the given union
Variant: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]] = union
returns a TV for the bound variant
IsOverlaid: PROC [type: Type] RETURNS [BOOL];
domain: UnderClass[type] = union
IsMachineDependent: PROC [type: Type] RETURNS [BOOL];
domain: UnderClass[type]  {record, structure, union, enumerated, sequence}
Domain: PROC [type: Type] RETURNS [Type];
domain: UnderClass[type]  {array, sequence, procedure, signal, process, address}
(not atom, rope)
if type = CODE[ARRAY T1 OF T2], Range[type] = CODE[T1]
Range: PROC [type: Type] RETURNS [Type];
domain: UnderClass[type]  {array, sequence, procedure, signal, process}
if type = CODE[ARRAY T1 OF T2], Range[type] = CODE[T2]
IsPacked: PROC [type: Type] RETURNS [BOOL];
domain: UnderClass[type]  {array, sequence}
IsComputed: PROC [type: Type] RETURNS [BOOL];
domain: UnderClass[type]  {union, sequence}
Apply: PROC [mapper: TV, arg: TV] RETURNS [TV];
domain: UnderClass[TVType[mapper]]  {array, sequence, descriptor, longDescriptor}
Length: PROC [tv: TV] RETURNS [INT];
domain: UnderClass[TVType[tv]]  {sequence, rope}
For a rope, Length returns an INT for the number of characters in the given rope. For a sequence, Length returns an INT specifying the (max) number of elements in the sequence. Use Tag[tv] to obtain the actual sequence tag field. Their values may differ if the tag type has a non-zero lower bound.
Fetch: PROC [tv: TV, index: INT] RETURNS [CHAR];
domain: UnderClass[TVType[tv]]  {rope}
For either local or remote ropes, performs the Fetch operation.
Referent: PROC [tv: TV, base: TVNIL] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {ref, list, pointer, longPointer, relativePointer}
note: base # NIL iff UnderClass[TVType[tv]] = relativePointer
returns a TV for the referent of the address (
ConcreteRef: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]] = ref
ConcreteRef returns a TV for the REF <concrete referent type>. NIL -> NIL. ConcreteRef is implemented only for REFs that are really ATOM, LIST or ROPE guys (Error[reason: notImplemented] is raised otherwise)
ReferentStatus: PROC [type: Type--address (not basePointer, atom)--] RETURNS [Status];
domain: UnderClass[type]  {atom, rope, list, ref, pointer, longPointer, descriptor, longDescriptor, basePointer, relativePointer}
IsRefAny: PROC [type: Type] RETURNS [BOOL];
domain: UnderClass[type]  {atom, list, ref, rope}
IsInterface: PROC [type: Type] RETURNS [BOOL];
domain: UnderClass[type]  {record, structure}
IsAtom: PROC [tv: TV] RETURNS [BOOL];
domain: UnderClass[TVType[tv]]  {atom, ref}
IsRope: PROC [tv: TV] RETURNS [BOOL];
domain: UnderClass[TVType[tv]]  {ref, rope}
IsNil: PROC [tv: TV] RETURNS [BOOL];
domain: UnderClass[TVType[tv]]  {atom, rope, list, ref, pointer, longPointer, descriptor, longDescriptor, basePointer, relativePointer}
IsOrdered: PROC [type: Type] RETURNS [BOOL];
domain: UnderClass[type]  {basePointer, relativePointer}
PropertyList: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {atom}
gets the property list for an ATOM
Coerce: PROC [tv: TV, targetType: Type] RETURNS [TV];
use Coerce to Narrow or Widen
TypeToName: PROC [type: Type, moduleName: REF ROPENIL, fileName: REF ROPENIL] RETURNS [ROPE];
IF name exists and REFs to moduleName and/or fileName ROPEs are provided, TypeToName provides that info too.
Ground: PROC [type: Type] RETURNS [Type];
peels off one layer of definition
GroundStar: PROC [type: Type] RETURNS [Type];
peels off all layers of definition and subrange
UnderType: PROC [type: Type] RETURNS [Type];
returns first non-definition type
InRange: PROC [type: Type, groundTV: TV] RETURNS [BOOL];
domain: UnderClass[type]  {subrange}
tests to make sure that the value in groundTV is in the range given by type
First: PROC [type: Type] RETURNS [TV];
domain: UnderClass[type]  {enumerated, subrange, basic}
Last: PROC [type: Type] RETURNS [TV];
domain: UnderClass[type]  {enumerated, subrange, basic}
Next: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {enumerated, subrange, basic}
returns NIL if no next
Prev: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {enumerated, subrange, basic}
returns NIL if no next
NValues: PROC [type: Type] RETURNS [INT];
domain: UnderClass[type]  {enumerated}
Value: PROC [type: Type, index: CARDINAL] RETURNS [TV];
domain: UnderClass[type]  {enumerated}
index range is [1..NValues[type]]
StaticParent: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {procedure}
returns the static parent (enclosing procedure) for the given procedure (will return NIL for an outer-level procedure)
Access to local and global frames
Locals: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {localFrame}
returns the record for the variables in the given local frame (NIL if no such variables)
EnclosingBody: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {localFrame}
returns the enclosing body for the given local frame (NIL if at the outer level)
Argument: PROC [tv: TV, index: Index] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {localFrame}
returns the given argument for the given local frame
Result: PROC [tv: TV, index: Index] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {localFrame}
returns the given result for the given local frame
Procedure: PROC [tv: TV--localFrame--] RETURNS [TV--procedure--];
domain: UnderClass[TVType[tv]]  {localFrame}
returns the procedure for the given local frame (raises Error[typeFault] if the frame is for a catch phrase)
Signal: PROC [tv: TV--catch frame--] RETURNS [TV--signal descriptor--];
domain: UnderClass[TVType[tv]]  {localFrame}
returns the catch phrase for the given local frame (raises Error[typeFault] if the frame is for a procedure)
IsCatch: PROC [tv: TV] RETURNS [BOOL];
domain: UnderClass[TVType[tv]]  {localFrame}
... returns TRUE iff the TV is for a catch frame (and therefore should work if given to Signal). This is useful when trying to print a local frame.
DynamicParent: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {localFrame}
returns the next elder local frame in the call chain (NIL if at the process base)
GlobalParent: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {localFrame, procedure}
returns the global frame for the given local frame
Globals: PROC [tv: TV] RETURNS [TV];
domain: UnderClass[TVType[tv]]  {globalFrame}
returns the global variable record for the given global frame
END.