Sather Home Page

Examples 8.11.2.2:
TRI_STATE

The features of the required library class TRI_STATE, an enumeration, are used in individual examples. None of the examples given is a complete class nor necessarily a 'complete' method.

In all of the examples it will be assumed that the code shown is in a class called, say, EXAMPLE.

create

This first variant of enumeration creation takes an argument which is a cardinal number and returns a valid value. Note carefully the pre-condition that the value must lie between offset and (offset + cardinality - 1) - pre-condition failure will occur with any other value, thus -

res : TRI_STATE := TRI_STATE::create(2)

yields the value TRI_STATE::Yes, since

res.card

has the value 2! Remember that res.enum may not have that value!!!!

create

The second form of creation is culture-dependent in the sense that the valid text strings used in testing are defined by the language and culture in which the program is running. For English these strings could indeed be "No", "Yes" and "Unknown" - while for French it could be "Non", "Oui" and "Riens" and so on for other cultures/languages!

It is important to remember that the creation operation will succeed with any prefix of the values which is unique - thus for English only single letters 'N', 'Y' and 'U' will be quite sufficient, thus with a string "Unk"

res : TRI_STATE := TRI_STATE::create(str)

the Unknown value will be created.

is_enum

The specification of that second create operation had a pre-condition - which in the example above was satisfied. However, to be really safe either the pre-condition exception has to be captured or, alternatively, a pre-conversion test satisfied. This could be written something like -

res : TRI_STATE ;

if TRI_STATE::is_enum(str_val) = CONVERSION_RESULTS::All_Right then
res := TRI_STATE::create(str_val)
else
res := TRI_STATE::Unknown
end

in which the 'error handling' is merely suggested and must, in practice, depend on the execution context. Note that the local variable res had to be declared outside of the condition if it is to be used in following code.

build

The build creation operations are provided for use when some form of cursor (binary or text) is in use for handling 'input' (say from a file). This first variant is suitable for use where, say, some external response has been provided, thus -

res : TRI_STATE := TRI_STATE::build(str_cursor)

gives a value to res. Note from the specification of the build operation that void could be returned! This is only done if the string at the starting cursor position did not represent a value of the enumeration type.

build

The first of the two examples below is identical to the one above if the string has been built in the default repertoire and encoding. The second is different. It indicates that the testing has to be done in the indicated culture, any conversion from that of the string argument being done as necessary.

res : TRI_STATE := TRI_STATE::build(str_cursor,LIBCHARS::default) ;
res : TRI_STATE := TRI_STATE::build(str_cursor,other_lib)

build

This final build operation takes a binary cursor rather than a text one. It does, however, function in the same general way in that if the next octets in the cursor buffer are not a valid value of this enumeration then void is returned too. The following build operation will hopefully return a non-void value!
res : TRI_STATE := TRI_STATE::build(bin_cursor)

create

This third form of creation takes a binary string containing one or more octets, depending on the cardinality of the enumeration involved, and creates an enumeration value. This form of creation cannot have a pre-condition other than 'true' so it may return void if the octets are not a valid value. However, practically, if the value concerned is immutable then 'zero' and 'void' are indistinguishable according to the present definition of the language! Thus -

res : TRI_STATE := TRI_STATE::create(binary_string)

could produce a valid value - or void - which in this case, fortunately is never valid. This was the design reason behind making an all clear bit-pattern an invalid enumeration type, so that the many uses of enumerations when creating binary files would never have a 'zero' on the file!

read

Reading is an optional read from a binary string. The next octet is interpreted as a truth value (if possible). If it is either not a truth value or is a truth value, but is false, then void is returned, otherwise an enumeration value (if the octets in the buffer make a valid value of this type).

Disambiguation of the result is possible by testing the state of the cursor. If it is the same as at entry then the next octet wasn't a representation of a truth value, if it has been moved by the size of a truth value representation only, then if void is returned then the truth value was false. If the enumeration value in the buffer was not a valid one then void is also returned and the cursor has been moved by the number of octets forming a valid value. The following code fragment illustrates the various disambiguation tests which could be written.

posn : CARD := buffer_cursor.index ;
loc_res : TRI_STATE := TRI_STATE::read(buffer_cursor) ;
if void(loc_res) then
loc_posn : CARD := buffer_cursor.index ;

if loc_posn = posn then

-- There wasn't even a valid truth value!
elsif (loc_posn - posn) = true.binstr.size then
-- The truth value false
else
-- The value was a bad one!
end
else
-- do something??
end

is_eq

The name of this operation, it will be remembered, permits it to be used in infix syntax. Therefore the following two statements are equivalent.

answer : BOOL := res = loc_res ;
answer := res.is_eq(loc_res)

offset

This feature is a visible constant usable when coding values for use in setting registers, device ports, etc. The default value is always

answer := TRI_STATE::offset = 1

so that answer will be true!

card

This routine returns the numeric value corresponding to the enumeration for external purposes, thus -

answer := TRI_STATE::No = 1

again results in answer being true!

cardinality

This feature is another constant determined when the number of values required is known. Thus, for example, the highest value yielded by the card operation above could be used as -

if TRI_STATE::cardinality = (TRI_STATE::Unknown - loc_res.offset + 1) then ...

is the same things as stating -

if true then ...

which is a bit of useless coding!

enum

The cardinal value returned by this routine need bear no obvious relation to the value returned by card. It is, however, potentially useful if it is desired to write some file, say, for purely local use (any other implementation may have a different value!), thus -

answer : BOOL := res.card = res.enum

is quite as likely to yield false as true.

hash

Since the purpose of a hash value is to 'smear' values across the whole cardinal number domain as evenly as possible, it is most unlikely that the value returned by this routine will be the same as that returned by card or enum! The principle purpose is to provide a 'key' for use in maps so that most values will hash into the domain of the map directly.

The two following fragments are intended to illustrate the reasoning. They both have identical functionality. Assuming the use of the standard input channel to get a value (ignoring for the purposes of illustration any error handling), compare -

card_map : FMAP{CARD,TARGET} := FMAP{CARD,TARGET}::create ;

val : TRI_STATE := TRI_STATE::create(IN::get_str) ;
card_map := card_map.insert(val.hash,target_50m) ; ...

with the non-hashed version -

card_map : FMAP{TRI_STATE,TARGET} := FMAP{TRI_STATE,TARGET}::create ;

val : TRI_STATE := TRI_STATE::create(IN::get_str) ;
card_map := card_map.insert(val,target_50m) ; ...

The hashed version will probably be slightly faster than the non-hashed one, but they are functionally equivalent.

binstr

Conversion to a binary string is, of course, the inverse of creation from a binary string, thus
val := TRI_STATE::create(bin_string) ;

answer : BOOL := bin_string = val.binstr

leaves answer identically true. The purpose of this is to simplify storing data on a storage device for export and/or re-import on some future program execution.

write

A prototype of this routine could be implemented as something very simple like -

write(bfile : BIN_FILE) is
bfile := bfile + binstr
end

str

This is the inverse operation of creation from a string. However, the value of answer may not be true!

str_val : STR := IN::get_str ;

val : TRI_STATE := TRI_STATE::create(str_val) ;
answer : BOOL := val.str = str_val

The reason for the value which answer has is given earlier in these examples!

str

This is the inverse operation of creation from a string, this time using the given culture conversion data. However, the value of answer may still not be true!

str_val : STR := IN::get_str ;

val : TRI_STATE := TRI_STATE::create(str_val, other_lib) ;
answer : BOOL := val.str = str_val

The reason for this more difficult equality problem is hinted at earlier in these examples.

fmt

Formatting of an enumeration is carried out using the anchored formatting mechanism. Do remember, however, that while this routine is visible for direct use, it will generally be much easier to use the formatter (see the FMT class) to create the individual formats as desired. This first version uses the default repertoire and encoding, thus the following could be used to format a right-aligned string -

fmt_descr : ANCHORED_DESCR :=
ANCHORED_DESCR::create(LIBCHARS::default.Space,8,0) ;

res : STR := val.fmt(fmt_descr)

which will result in res containing

"     Yes"
in an English environment if the value happened to be TRI_STATE::Yes!

fmt

This formatting variant is used where the cultural formatting is to be done in accordance with the given data, thus

fmt_descr : ANCHORED_DESCR :=
ANCHORED_DESCR::create(other_lib.Space,8,0) ;

res : STR := val.fmt(fmt_descr,other_lib)

which will result in res containing

"    Nein"
in a German environment if the value happened to be TRI_STATE::Yes and the encoding was the same!


Specification Index Language Index Section 8 Index
Comments or enquiries should be made to Keith Hopper.
Page last modified: Tuesday, 30 May 2000.
Produced with Amaya