This is one of the STIPPLE Documentation pages.

STIPPLE Type Declarations

The syntax for define declarations is:
type_declaration
type_clause
new_type_name
parameter_name
generate_clause
generate_name
All define declarations must follow any module, import, and export declarations. Each define declaration automatically introduces a number of object and routine declarations. In addition, each type clause has the ability to generate a number of optional routines at the programmer's request. These optional routines are generated by listing them by name after the generate keyword. These optional routines are listed completely in the appropriate appendix. Each of the type clauses is discussed in the sub-sections that follow.

The identical Type Declaration

The syntax of the identical type declaration is:
identical_type_declaration
type_reference
type_name
The identical declaration creates a new type, called new_type_name, that is the same as other_type_reference in every way (very similar to a macro.) Objects of type new_type_name and other_type_reference are indistinguishable from one another. Internally, the compiler converts all references to new_type_name to other_type_reference. No objects or procedures are introduced by the identical declaration.
Some examples of the identical declaration are:

    define length
	identical unsigned
    define width
	identical unsigned
    define my_table
	identical table[unsigned, unsigned]
								
Since there are no new routines and objects introduced by the identical type clause, there is no associated appendix for identical.

The synonym Type Declaration

The syntax of the synonym type declaration is:
synonym_type_clause
other_type_reference
type_reference
type_name
The synonym type declaration creates a new type, called new_type_name, that has all of the same operations as other_type_name. Conceptually, the synonym declaration makes duplicates of all objects and procedure declarations of type other_type_name that are accessible to the current module. The synonym type declaration is not symmetric; if a new operation is defined for new_type_name it is not directly accessible to objects of type other_type_name.

For each synonym declaration, two conversion routines with the following signatures are introduced:

    procedure other_type_name_convert@new_type_name
	takes new_type_name
	returns other_type_name
	#: This routine takes an object of type
	#, {new_type_name} and returns an
	#, object of type {other_type_name}.

    procedure new_type_name_convert@other_type_name
	takes other_type_name
	returns new_type_name
	#: This routine takes an object of type
	#, {other_type_name} and returns an
	#, object of type {new_type_name}.
								
These two conversion routines simply take their argument in one type and return it in another type. When in-line compiler optimization is enabled, there is no code generated by either of these routines.

Some examples of the identical declaration follow:

    type apples
	synonym unsigned
    type oranges
	synonym unsigned
								
The compiler will emit an error message whenever an an attempt is made to add a variable of type apples to a variable of type oranges.

Appendix ? lists all of the objects and routines introduced by the synomym declaration.

The enumeration Type Declaration

The syntax of the enumeration type declaration is:
enumeration_type_clause
enumeration_name
The enumeration type declaration defines a new immutable type consisting of a list of objects. Each enumeration_name in the declaration defines an object named enumaeration_name@new_type_name. The enumeration type declaration can not be parameterized.

The following is an example of an enumeration type declaration:

    define primary_color
	enumeration
	    red
	    green
	    blue
								
The list of all objects and routines introduced by the enumeration declaration are described in appendix ??.

The range Type Declaration

The syntax of the range type declaration is:
range_type_clause
  • range other_type_name from from_object_reference to to_object_ref eol
other_type_name
  • identifier
from_object_reference
  • identifier
to_object_reference
  • identifier
The range declaration defines a new type that can take on values between from_object_reference and to_object_reference. While the range declaration can be parameterized, there are very few situations in which it makes sense to do so. The range declaration requires that other_type_name have the to_int operator be defined with the following signature:
    procedure new_type_name_convert@other_type_name
	takes other_type_name
	returns new_type_name
	#: This routine will convert its input from
	#, {other_type_name} to {new_type_name}
	#, and return it.

    procedure other_type_name_convert@new_type_name
	takes new_type_name
	returns other_type_name
	#: This routine will convert its input from
	#, {new_type_name} to {other_type_name}
	#, and return it.
								
All of the objects and routines provided by the range type declaration are described in appendix ??.

The record Type Declaration

The syntax of the record type declaration is:
record_type_clause
  • record eol
    indent
    { field_clause }+
    outdent
field_clause
  • field_name field_type_reference eol
field_name
  • identifier
field_type_reference
  • type_reference
type_reference
  • type_name { [ type_reference ,... ] }
type_name
  • identifier
It is an error to have duplicate field names in a record type declaration.

For each field in the record, two implicit access routines are defined:

    procedure field_name_get@new_type_name
	takes new_type_name
	returns field_type_reference
	#: This routine returns the value of the {field_name}
	#, field of {new_type_name}.

    procedure field_name_set@new_type_name
	takes new_type_name, field_type_reference
	returns_nothing
	#: This routine sets the {field_name} field of
	#, {new_type_name} to field_type.
								
All of the objects and routines provided by the record type declaration are described in appendix ??.

The variant type declaration

The syntax of the variant type declaration is:
variant_type_clause
tag_name
tag_type_name
field_clause
field_name
field_type_reference
type_reference
type_name
The variant declaration defines a tagged variant object. A tagged variant object has a tag and an object reference. The tag value specifies the type of the object reference.

The tag name and all variant field names must be unique within a variant declaration; duplicate names will cause a compiler error. If the tag type is already defined, it must be from an enumeration type and there must be a one-to-one correspondence between the variant field names and the enumeration names; any mismatched variant field names and/or enumeration names will cause a compilation error. Alternatively, if the tag type is not already defined, the compiler will define it as an enumeration type that has the variant field names as the enumeration name.

All of the objects and routines provided by the variant type declaration are described in appendix ??.

The routine Type Declaration

The syntax for the routine type declaration is quite elaborate and follows below:
routine_type_clause
  • procedure_type_clause
  • iterator_type_clause
procedure_type_clause
  • procedure eol
    indent
    { routine_types_clause }
    { needs_clause }
    takes_clause
    returns_clause
    { signals_clause }
    outdent
iteratory_type_clause
  • iterator eol
    indent
    { routine_types_clause }
    { needs_clause }
    takes_clause
    yields_clause
    returns_clause
    { signals_clause }
    outdent
routine_types_clause
  • routine_types eol
    indent
    { named_routine_type_clause }+
    outdent
named_routine_type_clause
  • named_procedure_type_clause
  • named_iterator_type_clause
named_procedure_type_clause
  • procedure procedure_name eol
    indent
    takes_clause
    returns_clause
    { signals_clause }
    outdent
named_iterator_type_clause
  • iterator iterator_name eol
    indent
    takes_clause
    returns_clause
    yields_clause
    { signals_clause }
    outdent
procedure_name
  • identifier
iterator_name
  • identifier
needs_clause
  • needs eol
    indent
    { typed_object_or_routine }+
    outdent
typed_object_or_routine
  • needs_object_clause
  • needs_procedure_clause
  • needs_iterator_clause
needs_object_clause
  • object object_name @ type_name_eol
object_name
  • identifier
needs_procedure_clause
  • procedure procedure_name @ needs_type_name eol
    indent
    takes_clause
    returns_clause
    { signals_clause }
    outdent
needs_iterator_type_clause
  • iterator iterator_name @ needs_type_name eol
    indent
    takes_clause
    returns_clause
    yields_clause
    { signals_clause }
    outdent
needs_type_name
  • identifier
takes_clause
  • takes { type_reference }+ eol
  • takes_nothing eol
returns_clause
yields_clause
signals_clause
signal_name_clause
signal_name
type_reference
type_name
The routine type declaration is used to specify the types of routine variables. Routine variables can reference either procedures or iterators. Routines can also be parameterized. The takes clause specifies the input argument types (and hence implicitly the number inputs.) The returns clause specifies the return value types. A no_return clause specifies that the procedure will never return. The yields clause specifies iterator yield value types. Only iterators are permitted to have a yields clause. The signals clause specifies the names of each signal that the procedure may signal in addition to any signal value types returned with the signal. The needs clause specifies any objects or procedures needed for a parameterized procedure.

In general, STIPPLE requires that types exactly match when assignment takes place. Procedure variables are the exception to this rule. For a procedure variable, all of the signature clauses, except the signals clause, must exactly match. For the signals clause, a routine, A, with fewer signals can be assigned to a procedure variable, V, with more signals provided that whatever signals are defined in procedure A exactly match corresponding ones in V.

{Variadic clauses are missing.}

Consider the following routines:

    define binary_with_overflow
	procedure
	    takes integer, integer
	    returns integer
	    signals
		overflow
		underflow

    define binary_without_oveflow
	procedure
	    takes integer, integer
	    returns integer
								
The following code fragment provides a simple example the procedure variable assignment rules:
    overflow:: binary_with_overflow	
    no_overflow:: binary_without_overflow

    overflow := overflow		# Legal
    no_overflow := no_overflow		# Legal
    overflow := no_overflow		# Legal
    no_overflow := overflow		# Illegal
								
The following is an example of some parameterized procedure types:
    define sum_routine[type]
	procedure
	    takes vector[type]
	    returns type
	    needs
		object zero@type
		procedure add@type
		    takes type, type
		    returns type
		    signals
			overflow
			underflow
								

From here you can go to either the next chapter on STIPPLE Object and Routine Declarations or back to the table of contents.
Copyright (c) 1991 -- Wayne C. Gramlich. All rights reserved.