resource resource_name
imports
constants, types, operation defs
body resource_name (parameter_list)
imports
declarations, statements, procs
final_code
end resource_name
|
The spec part
The body contains the code to implement the resource, and in particular implement any procs that correspond to operations declared in the spec. Local imports, variables, types, operations, etc. which are defined in the body are hidden from the outside world.
resource Stack
type result = enum(OK, OVERFLOW, UNDERFLOW)
op push(int item) returns result r
op pop(res int item) returns result r
body Stack(int size)
int store[1:size]
int top = 0
proc push(item) returns r {
if (top < size) { store[++top] = item; r = OK
} else if (top == size ) { r = OVERFLOW
}
}
proc pop(item) returns r {
if (top > 0) { item = store[top--]; r = OK
} else if (top == 0 ) { r = UNDERFLOW
}
}
end Stack
|
resource foo body foo (int x, y) # some code end foo |
can be written equivalently as
resource foo (int x, y) # some code end foo |
resource heap import graph op new_node (N_CLASS) returns ptr NODE op new_array (int) returns ptr [*] ptr NODE body heap () separate |
and elsewhere we may define:
body heap
proc new_node (class) returns n {
n = new(NODE)
n^.n_class = class
n^.visited = false
}
proc new_array (size) returns ap {
ap = new ([size] ptr NODE)
}
end heap
|
import id , id , ...It may appear anywhere that a declaration may appear. For example,
resource Stack_User()
import Stack
Stack.result x
...
end
|
declares a variable x whose type is declared in the spec of Stack. If the name of the type result is unique in this context then we could also write the declaration as
result x
|
There is one resource instance that is always created: the main resource of the program. This is the last resource which is compiled. It must not be imported by other resources, it cannot have parameters, and does not have a spec. It imports all the required resources and starts the ball rolling.
All other instances of resources that are required must created during program execution. Several instances of the same resource can be active in the same program.
A resource is created using a create expression, e.g.
create heap () |
This is an expression. It returns a resource capability, which acts as a reference to the resource that is created. A typical use would be
myheap = create heap () |
In this case myheap must have the type cap heap. To define and create a heap in a single declaration, we could write
cap heap myheap = create heap () |
Here is an example using the stack resource:
resource Stack_User()
import Stack
result x
cap Stack s1, s2
s1 = create Stack(10)
s2 = create Stack(20)
int y
s1.push(4); s1.push(37); s2.push(98)
if ((x = s1.pop(y)) != OK) { write("error")
} else { write(y)
}
if ((x = s2.pop(y)) != OK) { write("error")
} else { write(y)
}
end
|
final {
final_code
}
|
and is executed right before the resource instance disappears - for example a resource instance that has dynamically created a linked list should, as part of its final code, free the list.
global global_name
imports
declarations
end
|
The simplest form of global is used to declare constants, types and variables:
global global_name
imports
declarations
end
|
The general form permits a body. This enables initialization of variables as in, for example:
global Diagonal
const N = 20
real a[N,N] = ([N] ([N] 0.0))
body Diagonal
for [i = 1 to N]{ a[i,i] = i }
end Diagonal
|
It also enables the implementation of shared procedures. For example consider the following outline:
global Screen
op move_to (int x; int y)
op up (), down (), left (), right ()
op refresh ()
body Screen
proc move_to(x,y){
...
}
...
# declaration of procs for up, down, left, right, refresh
end Screen
|
Suppose that this global provides a library for screen management. Although this could be written as a resource, in order to share this resource between other resources we would then need to create an instance of Screen and pass a capability for that instance to the resources who wish to use it. In contrast, since Screen is declared as a global, then it can be used simply by importing it.