Stockhausen Operette 1 is based on Mozart and supports interoperability between Oz and Alice.
The Stockhausen compiler translates components into pickled Oz functors. It is possible to mix Oz and Alice code on a per-component basis. This document explains:
Values of basic types are mapped to corresponding Oz basic types. To support word operations, Mozart has been extended by a corresponding basic type.
| Alice Type | Oz Representation |
|---|---|
| int | Infinite-precision integer |
| char | Infinite-precision integer |
| word | Provided by boot module x-oz://boot/Word |
| real | Float |
| string | Byte string |
Alice records are translated to Oz records by mapping all labels consisting only of digits to the corresponding integer feature, and all labels containing a letter to the corresponding atom feature.
| Alice Type | Oz Representation |
|---|---|
| Unit value () resp. {} | Literal unit |
| Tuple | Tuple with label '#' |
| Record | Record with label '#' |
Conceptually, all Alice functions are unary. The typical idiom is to pass multiple arguments as a tuple of arguments. This case is treated specially by the Alice compiler.
| Alice Procedure | Oz Representation |
|---|---|
| Function in which every pattern is either an explicit n-tuple or a wildcard | n+1-ary procedure, having n input arguments and one output argument |
| Any other function | Binary procedure |
With a few exceptions simplifying interoperability, constructors of closed datatypes are mapped to atoms and constructors of open datatypes are mapped to names.
| Alice Type | Oz Representation |
|---|---|
| true, false | Literals true, false |
| ::, nil | '|', nil |
| Other constructors of closed datatypes | Atoms with corresponding print name |
| Constructors of open datatypes | Names |
Conceptually, all Alice constructors are unary. For interoperability, constructors syntactically declared taking a record as argument are treated as n-ary constructors.
| Alice Constructed Value | Oz Representation |
|---|---|
| Constructed value of an n-ary constructor, n > 0 | Record with the literal corresponding to the constructor as label and the argument record's labels as features |
| ref x | {NewCell x} |
For example, assuming a declaration
datatype t1 = C1 of int * int
the Alice expression C1 (1, 2) evaluates to the Oz value 'C1'(1 2) due to the constructor C1 being binary. However, assuming the declaration
datatype 'a t2 = C2 of 'a
the Alice expression C2 (1, 2) evaluates to the Oz value 'C2'(1#2) because the constructor C2 is unary.
Alice futures map directly to Oz transients. Promises are transparent on the Oz side.
| Alice Future | Oz Representation |
|---|---|
| Future | Future |
| By-need future | By-need future |
| Promise | Pair of boolean cell and logic variable; the cell is true if the promise is either fulfilled or failed |
Some abstract library types are implemented natively:
| Alice Library Type | Oz Representation |
|---|---|
| array | Array |
| vector | Tuple with label '#[]' |
| Cell.cell | Cell |
| Thread.thread | Thread |
| TextIO.instream, TextIO.outstream | Instanced of Open.file |
Alice modules are translated to Oz data structures such:
| Alice Module | Oz Representation |
|---|---|
| Structure | Record |
| Functor | Binary procedure |
Structure members are represented under record features. The feature names are computed as shown in the following table:
| Alice Identifier Class | Oz Feature Representation |
|---|---|
| Value or constructor, e.g., val x, constructor C | Identifier name as atom, e.g., 'x', 'C' |
| Structure or functor, e.g., structure S | Dollar-prefixed identifier as atom, e.g., '$S' |
Signatures and types are not yet represented at run-time. Note that signature coercion is not performed operationally, that is, all structure members are visible on the Oz side.
Alice components are translated into Oz functors:
| Alice Component | Oz Representation |
|---|---|
| Compiled component | Pickled functor |
The export of the generated functor is the record corresponding to the component considered as a single structure.
Alice exceptions are wrapped into alice(...) and raised as Oz error exceptions.
Alice compiled components are annotated with signatures denoting the expected types of the component it imports and the actual type of the structure it computes. Compatibility of actual and expected signatures is checked at link-time to guarantee type safety. The actual export signature is also loaded at compile time to perform binding analysis and type-checking.
For this reason, export signatures must first be provided for Oz functors before they can be imported into Alice components. This will be shown by an example.
Assume the following Oz functor is stored at URL F.ozf:
functor
import
System(show)
export
show: Show
define
fun {Show X} {System.show X} unit end
end
To import this component into Alice, we would write a signature file F.sig containing:
signature F_COMPONENT =
sig
val show: 'a -> unit
end
The Oz functor F.ozf can now be combined with the signature at F.sig into a typed component TypedF.ozf by invoking the Stockhausen compiler thus:
stoc --replacesign F.ozf F.sig TypedF.ozf
We can now import the component into Alice using an import announcement of the form
import val show from "TypedF.ozf"
Note that the name of the signature is ignored.
If the signature does not truthfully describe the Oz component, run-time type exceptions will be raised.
Since Oz does not type-check its imports at link-time, Alice components can be directly imported into Oz functors without conversion.
For example, assume the following Alice component is available at URL Example.ozf:
structure Example =
struct
fun count f xs =
List.foldr (fn (x, n) =>
if f x then n + 1 else n) 0 xs
end
An Oz functor could now import it as follows:
functor
import
System(show)
ExampleComponent('$Example': Example) at 'Example.ozf'
define
{System.show
{{Example.count fun {$ X} X == 0 end} [1 0 2 0]}}
end