Chapter 2. Items, Values, Types, and Declarations

The heart of any Rosetta specification is a collection of items that represent observable quantities associated with a system. They represent a collection of things that, if properly described, provide a precise system model that can be reasoned about to predict behaviors. By defining item properties and relationships between items, a Rosetta specification defines expectations on their collective behavior and the system they represent.

An item is defined by a declaration that associates it with a type and optional value. The type represents the collection of values the item can legally assume. Rosetta types are formed from sets using traditional set operations, comprehension and extension. The optional value makes an item a constant by associating a specific value with it. Values are defined in the traditional sense as terms that are in irreducible, normal form.

Like type systems in programming languages, the Rosetta type system specifies constraints by associating a type, like integer or set (character), with an item. Unlike traditional programming language type systems, Rosetta types may be defined by comprehension using a property to filter an existing type. Thus, a Rosetta type asserts properties on an item by restricting it to a set of values or defining a property the item must have to be of a particular type. Using types to specify properties in this way is a critical part of Rosetta specification. The first step in this process is understanding item declaration and how types and values are associated with an item.

Labels, Values, and Types

All Rosetta definition structures are represented semantically as items with a label, type, and value properties. The item label provides a name for the item that is used to reference it in the specification. In the Rosetta expression x=y+1, the labels x and y refer to the declared items with those respective labels. The item value specifies a value associated with the item. In the Rosetta expression x=y+pi, the value of the item labeled x is constrained to be equal to the value of the item labeled y plus the value of the item labeled pi. The item type is a set that specifies a collection of values the item can legally take. Given an item v whose type is the set T, the value associated with v must always be an element of the set T.

Labels

A Rosetta label represents a legal name for a Rosetta item. The rules for writing labels in Rosetta are similar to those of other languages. A label must start with a letter, which may be followed by any number of letters and digits. Single underscore characters (_) may be included to enhance readability, but they may not occur at the beginning or end of a label. Examples of legal labels are:

a N timeout MaxTravel Min_Travel port1 port_2a

Examples of illegal labels are:

3a              // starts with a digit
_id             // starts with underscore
packet_         // ends with underscore
sequence__0     // two successive underscores

The case of characters in labels is not significant. The following labels are all treated as the same:

pressure Pressure PRESSURE

While we have a great deal of flexibility in choosing item labels to aid readability of specifications, there are some labels we cannot use, since they are reserved as keywords. These keywords provide the syntactic structure of a Rosetta model and are listed in Table 2.1. Note that, as in item labels, case is insignificant. In this book, we follow the convention of setting keywords in boldface to distinguish them from item labels.

Table 2.1. Rosetta keywords

and

data

facet

let

or

then

array

definitions

false

library

output

top

assumptions

design

forall

 

of

translators

as

div

from

max

 

true

 

dom

functors

min

package

type

be

domain

 

mod

  

begin

 

if

multiset

ran

use

between

element

implications

 

rem

 

body

else

implies

nand

ret

var

bottom

elseif

in

nmax

  
 

end

infinity

nmin

sel

where

case

enumeration

input

not

sequence

with

combinators

exists

interaction

nor

set

 

component

export

interface

null

sharing

xnor

constant

 

is

 

sub

xor

    

subtype

 

Values

A Rosetta value is a structure or term in normal form that cannot be further evaluated. Although not all normal forms are values, all values are normal forms. The simplest Rosetta values represent numbers, characters, and booleans. Examples of such values include the numbers 1 and 3.1415, the characters ‘a’ and ‘@,’ and the boolean constants true and false. Such values are elemental values and cannot be decomposed. We form composite values from other values like the constant sequence [1,2,3,4], the constant set {high, low, unknown}, and the multiset constant {*1,2,3,1,2*}. The sequence of sets [{}, {1}, {2,3}] is also a composite value because it is formed from other values.

All elements of a specification are items that have associated types and thus potential values — a function item has an associated function value, a facet item has an associated facet value, and an element of a constructed type has a constructed value. A function value is an anonymous function that encapsulates an expression with a collection of parameters. Rosetta function values are pure functions in that they may only specify a functional relationship between their parameters and output values. A facet value represents the basic unit of Rosetta specification and is associated with facets, domains, components, and packages. Finally, constructed values result from the application of constructors associated with constructed types. Rosetta constructed types provide mechanisms for users to define completely new types by specifying type constructor functions and observer functions for a collection of values.

Types

A Rosetta type defines a collection of values that constrains the value of an item. Within the Rosetta language system, all types are values and appear as sets. Technically, not all types are sets, but set operations are always available on them. This fact and its implications will be discussed extensively in subsequent chapters. For now it is sufficient to understand that an item’s value must be an element of its type.

If one Rosetta type is a subtype of another, then it follows that every element of the subtype is a member of the supertype. This is precisely the definition of subset. It follows that Rosetta subset relations also indicate subtype relationships. The following relationships are examples of this principle:

integer =< real // integer is a subtype of real
integer < real  // integer is a proper subtype of real

real >= integer // real is a supertype of integer
real > integer  // real is a proper supertype of integer

Rosetta item values must always be taken from their associated types. This fact is the heart of Rosetta type and constraint checking. As we will see, using a sophisticated and flexible type system allows assertion and verification of complex properties in a compact and readable form.

Item Declarations and Type Assertions

Item declarations occur in declarative regions, parameter lists, functions, and let forms where new variables and constants are required. Each item declaration creates a new item with a label and must be annotated with a type assertion. A Rosetta type assertion uses the assertion operator “::” to associate a type with an item. Whenever we use the notation x::T, we are asserting that the value associated with the item labeled x is a member of the type T. All declarations must include a type assertion, but type assertions may be used to indicate types anywhere in a Rosetta specification. Thus, type assertions are used to assign types to new items and to specify types for items in expressions.

Item Declarations

When the type assertion x::T appears in a declarative region such as a facet’s local declarations, a let clause or parameter list, it represents an item declaration or simply a declaration. A declaration of this form adds a new item labeled x to the current lexical context with the assertion that x is a member of type T.

Each declaration achieves three results: (i) it creates and labels a new item in the current scope; (ii) it assigns a type to the item, defining potential values for the item; and; (iii) it may bind a value to the item. If a declaration does not bind a value to an item, the item is considered a variable. If a declaration does bind a value to an item, the item is considered a constant.

An example of a Rosetta declaration that defines an item named mean is:

mean :: real is 13.5;

In this declaration, mean is the label of the new item and provides a name used to refer to the item. The type assertion operator assigns a type to the newly declared item. In this example, the type specified is real, requiring that any value associated with the item must be a real number. The type specification is followed by an optional value constraint specified by the is clause that binds the item’s value to a constant. In this example, the value of mean is equal to the constant value 13.5.

The value specified by the is clause is not an initialization value. The is clause asserts that the declared item’s value must always be equal to the specified value. Thus, the value of mean will always be 13.5 in the scope of this declaration. Such declarations are referred to as constant items or simply constants and can be identified by the presence of the is clause in the declaration.

We define a variable by excluding the is clause and value from an item declaration. Without this constraint, the value of the item is allowed to vary among all possible elements of its type. For example, the declaration:

variance :: real;

defines an item named variance whose type is real, but whose value is not constrained beyond the type in the declaration. When the label variance appears in the scope of this declaration, it refers to the value associated with variance. Unlike a constant declaration, the variable item’s value will be constrained elsewhere in the specification, rather than the declaration. Such declarations are referred to as variable items or simply variables and can be identified by the absence of the is clause in the definition.

A variable or constant may also include a constraint in the form of a where clause:

mode :: real where (mode > –5.0) and (mode < 5.0);

This declaration specifies that mode is an item of type real that must be between the values –5.0 and 5.0. The item’s value may vary like a variable, but must always satisfy the where clause predicate.

In general, all Rosetta item declarations take the following form:

items:: T [[ is e ]] [[ where p ]] ;

where items is a comma-separated list of one or more labels, e is an expression, and p is a predicate.

In the item declaration, T constrains the potential values of the items to the contents of a type. If the optional is clause is present, the new item is a constant item whose value is defined by the expression e. Otherwise, the new item is a variable item. If the optional where clause is present, then p must hold for all values the item takes on. If the item is constant, the where clause defines additional properties that must hold for the constant value. If the item is variable, the where clause defines additional properties beyond those defined by the type.

For example, the function declaration:

triangulate(x,y :: position) :: position;

declares two parameters of type position that may be used in the function body associated with triangulate. The declarations create the local parameters and the appropriate type assertions. In parameter declarations, the is and where clauses are not allowed.

Similarly, the facet declaration:

facet parity(x::input bit; z::output bit)::state_based is
  s::bit;
begin
  s' = x xor s;
  z = s';
end facet parity;

declares two parameters, x and z of type bit, representing component input and output, respectively. Like function parameters, the is and where clauses are not allowed in facet parameters. However, a parameter kind that specifies properties is allowed. Here, the input and output kinds provide directional information for parameters that will be used as ports. In the declarative region, s::bit defines a variable item and asserts that it is of type bit. These declarations are visible throughout the specification body along with the constraint that their values must come from the bit type.

The function and facet definition forms used thus far are simply syntactic sugar for a traditional declaration and can be expressed using the traditional declaration syntax. The function definition specifies a type constraint using the type assertion operator to define the function’s domain and range elements as type position. The facet definition contains a type assertion operator asserting the facet is of type state_based and identifying the domain that forms the basis for this specification. This type assertion can be observed following the facet’s parameter list and is no different than those defining parameters or variables. It asserts that the facet parity is a member of the state_based facet type.

Example 2.1. Basic declarations

package declaration_examples :: static is
  w :: integer;
  x :: real is 2.4;
  y,z :: string;
  a :: integer where a>5;
  b :: real is 2.6 where b > 1.0;
end package declaration_examples;

This example package defines six new items and groups them together into a reusable package structure. w defines a variable item of type integer while x defines a constant of type real whose value is specified as 2.6. The next declaration defines two variable items, y and z, both of type string. If an is clause were used in the string declaration, the result would be two constant items with the same value. Specifically:

y,x :: string is "Hello_World";

results in two items whose values are both the constant string "Hello_World".

The final two declarations use the where clause to define constraints on possible values. The declaration of a is constrained to allow only values greater than 5 while the declaration of b must be greater than 1.0. In the latter declaration, the constraint can be verified immediately because b’s value is known. In the former, the constraint must be placed in the context of another expression to be verified.

Type Assertions

The type assertion operator may also be included in expressions when specifiers need to attribute additional type information to an item. In the definition:

z = x::integer + y::integer;

the type assertion operator is used to add type information to an expression, not to declare a new item. If type assertions are omitted:

z = x + y;

the Rosetta type system is used to determine the types of x and y. The type assertions tell processing tools to add an assertion that x and y are of type integer rather than invoking the type inference system. Such uses of the type assertion relation are simply called type assertions and differ from declarations in that they do not create new items.

Type assertions must be used with care, as nothing prevents assertions from introducing inconsistencies in specifications. However, they are quite useful when an item’s type cannot be inferred automatically, when a prior type inference activity requires documenting, or when the type inference process needs a hint to proceed.

Universal Operations

Table 2.2 defines defines operators defined over all Rosetta values and types. Type assertion and subtype and supertype relations support forming type assertions and declarations, and asserting subtype and supertype relationships. Because the type of these relations is boolean, the use of top does not introduce problems.

Table 2.2. Operators defined over all Rosetta items

Operator

Syntax

Expression type

Type assertion

x :: T

T

Set membership

x in T

boolean

Subtype and proper subtype

S =< T, S < T

boolean

Supertype and proper supertype

S >= T, S > T

boolean

Equality and inequality

A = B, A /= B

boolean

Equivalence

S == T

boolean

We have seen how the type assertion operator declares items and makes type assertions. Note that the type of the type assertion operator is not boolean, but is the asserted type. Although this may appear odd, it allows embedding of type assertions in other expressions. For example:

1::integer – 1::real;

is not legal if the type assertion operation is boolean. Even if it were legal, it does not mean what we intended to say. If the type of the type assertion operation 1::integer is integer, then traditional type checking works as expected. Along the same lines, if 1::integer evaluates to 1, then evaluation also behaves as expected. Specifically:

1. 1::integer + –1::real
2. == 1 + –1::real
3. == 1 + –1
4. == 0

The set membership operator, x in T, provides the canonical element operation from set theory. The operator is true if its first argument is an element of its second argument. From the user’s perspective, the set membership operation is equivalent to the type assertion operation because types look like sets. In general, types are not sets, but always look like sets to the specifier. Unlike type assertions, the type of the set membership operator is boolean, allowing it to be used in terms and other boolean statements.

The subtype and supertype relations define relationships among types, again treating types like sets. We will see later that subtype relations correspond with subset relations and supertype relations with superset relations.

Equality and inequality define traditional equality relations. If x=y is asserted, then the value of x is the same as the value of y. This is not the same as assignment, where x is assigned the value of y after executing the statement. In the C and C++ programming languages, the following notation would be used to increment the value in variable a, assuming that a is an integer:

a = a + 1;

This expression is inconsistent in Rosetta, as it asserts that the integer value associated with a is equal to its successor. In a traditional programming language, the semantics of the statement are that the value of a following statement execution is equal to the value of a prior to execution plus 1. Rosetta allows a similar concept when state and state change are a part of the computation model in use. Specifically:

a' = a + 1;

asserts that a in the next state is equal to a in the current state plus 1. Rosetta simply makes the distinction between current and next state visible to the specifier, rather than hiding it in the semantics of assignment. This allows Rosetta specifications to use different next-state definitions based on the computational model being used.

When we make the assertions:

A = 1
(a^2 + 2*a*b + b^2) = (a+b)^2
sqrt(x)*sqrt(x) = x
A/= 1

we are defining axioms over the values and items involved. Although this is true for any Rosetta term, mistakes tend to be made when thinking of equality and assignment as the same operation. Rosetta has no assignment operator and thus equality must always be viewed as a relation between values instead of assignment.

Rosetta also provides an equivalence operator that is semantically identical to equality. The distinction is that equivalence binds after virtually all other operations, avoiding confusing parentheses. As an example, consider the following two equivalent terms:

(f(x) = b) = (g(y,z) = d)
f(x) = b == g(y,z) = d

Dropping the parentheses from the first term results in a semantics quite different than intended. To see the distinction, we can make the left associativity of equality explicit using parentheses:

(((f(x) = b) = g(y,z)) = d)

Making equality right associative or making equality bind later introduces different problems. However, using equivalence solves the problem. Because equivalence binds last, explicitly parenthesizing the second term above results in exactly the desired semantics:

(f(x) = b) == (g(y,z) = d)

Parentheses can be eliminated because of the low precedence of equivalence. The resulting specification is more intuitive and easy to write. The equivalence relation is used extensively to provide definitions for functions and terms. Throughout this and subsequent chapters, equivalence is used extensively to provide definitions. Rosetta specifications also use equivalence to provide definitions where other mechanisms limit expressiveness.

 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.136.168