• No results found

Evaluation of core language declarations

In document SML# Document Version 4.0.0 (Page 97-100)

14.8 Top-level execution

16.1.1 Evaluation of core language declarations

Execution of an interactive program is done by evaluating a list of declaration sequentially. Evaluation of a core language declaration has the effect of evaluating the components, such as expressions, contained in the declaration, and binding the identifiers defined in the declaration to the values generated by the evaluation of the components. Generated values are either static or dynamic.

Static values are compile-time value generated by the compiler. They are one of the following.

infix operator status This indicates that an identifier is parsed as an infix operator. It also has the associatibity (right associative or left associative) and association strength (from 0 to 9).

constructor status This indicates that an identifier status is a data constructor. An identifier with the constructor status only matches with the corresponding constructor in pattern marching.

type constructor Type constructors are newly defined types generated by datatype declarations. Para-metric types with type parameters can be defined.

type Types specify a static property of a dynamic values produced by executing the corresponding program fragment.

16.1. PROGRAMS IN THE INTERACTIVE MODE 91 The SML# compiler statically evaluates declarations and generates static values, and bind names defined in the declarations to those static values. For declarations such as ⟨valDecl⟩ that implies program execution, the compiler generates executable code, which when executed, constructs dynamic values at runtime and binds names to those dynamic values.

Dynamic values are one of the following.

Built-in values Runtime data of built-in types defined in Chapter 18. They include atomic values, lists, arrays, and vectors. For example, values of type int32 are 32-bit signed integers whose representation is defined by the underlying machine architecture.

Function closures They are runtime representations of values of function types.

Data constructors They are built-in functions to construct datatype representations.

Exception closures They are built-in functions to construct exception values.

Records They are values of record and tuple types.

Datatype representation They are generated by data constructors defined in datatype declarations.

Exception values They are generated by exception constructors.

The following show a summary of the generated static and dynamic values for each of declarations.

declaration class static values bindings dynamic values bindings assigned to

infix declaration infix status variables, constructor names

val delaration types dynamic values corresponding to types variables

val rec delaration types function closures variables

function delaration types function closures variables

data type delaration type constructors type constructor names

constructor status data constructors data constructor names

type alias delaration type function type constructor names

exception delaration constructor status exception constructors exception constructor names exception delaration depending on the contents depending on the contents depending on the contents We outline declaration evaluation and the resulting value bindings below. The detailed syntax and

semantics of each of these declaration classes are given in Chapter 23.

⟨infixDecl⟩ This is a declaration of the form infix id. The identifier id is given infix operator property.

n is optional. The following shows a simple example.

# infix 7 *;

# infix 8 ^;

# fun x ^ y = if y = 0 then 1 else x * x ^ (y - 1);

val ^ = fn : int * int -> int

# val a = 4 * 3 ^ 2 val a = 36 : int

Since * and ^ has infix precedence 7 and 8, respectively, 4 * 3 ^ 2 is elaborated to *(4, ^ (3,2)).

⟨valDecl⟩ This is a declaration of the form val pat = exp. Evaluation is done by evaluating exp and checking whether the resulting dynamic value matches pat. If it matches then variables in pat are bound to the corresponding values of the result. The simplest example is the following variable binding.

# val x = 1;

val x = 1 : int

In this example, variable x is bound to the result of evaluating expression 1, namely static type int and dynamic value 1.

# val (x, y) = (1, 2);

val x = 1 : int val y = 2 : int

The details of expressions ⟨exp⟩ and patterns are given in Chapter 19 and 20. .

⟨valRecDecl⟩ Val declarations restricted to (mutually recursive) functions.

# val rec even = fn x => if x = 0 then true else odd (x - 1)

> and odd = fn x => if x = 1 then true else odd (x - 1);

val even = fn : int -> bool val odd = fn : int -> bool

In this declaration, each identifier is bound to the corresponding type and function value.

⟨funDecl⟩ This is for mutually recursive function definitions.

# fun even x = if x = 0 then true else odd (x - 1)

> and odd x = if x = 1 then true else odd (x - 1);

val even = fn : int -> bool val odd = fn : int -> bool

In this declaration, each identifier is bound to the corresponding type and function value.

⟨datatypeDecl⟩ This defines new mutually recursive type constructors.

# datatype foo = A of int | B of bar and bar = C of bool | D of foo;

datatype bar = C of bool | D of foo datatype foo = A of int | B of bar

# D (A 3);

val it = D (A 3) : bar

Evaluation of this declaration generates two new type constructors (with no type parameter) foo and bar and the identifiers foo and bar are bound to them. It also generate data constructors A, B and C, D for foo and bar, respectively, and the identifiers to them. These identifiers are given the constructor status.

As in the above explanation, in this manual, we generally identify type constructors such as foo and data constructors such as A with their names foo and A.

⟨typeDecl⟩ This bind an identifier to a type or a type function.

# type ’a foo = ’a * ’a;

type ’a foo = ’a * ’a

# fun f (x:int foo) = x;

val f = fn : int * int -> int * int

Evaluation of this generates a type function that takes a type parameter represented by ’a and returns a type ’a * ’a, and binds identifier foo to this type function. In the scope of this declaration, τ foo is used as an alias of τ * τ .

⟨exceptionDecl⟩ This defines exception constructors.

# exception Foo of int;

exception Foo of int

Evaluation of this declaration generates a new exception constructor with a parameter of type int.

In the scope of this declaration, the identifier foo is given the constructor status and is bound to the exception constructor.

⟨localDecl⟩ Declarations between local and in are local until end.

16.1. PROGRAMS IN THE INTERACTIVE MODE 93

The scope of the declaration val x = 2 is until end. The variable x is not visible from outside of this local declaration and therefore only y is printed in the interactive session.

In document SML# Document Version 4.0.0 (Page 97-100)