Pint User’s Guide
Part 1: The Language and Platform
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in section 21.2 on page 133.
Abstract
Pint is a π-calculus language platform which provides a translator written in SML/NJ and a hardware emulator written in Erlang. The platform is intended for investigation at the microprogramming level rather than for use as yet another high level language.
The language is similar to, but simpler than, Vasconcelos’ TyCO or Turner and Pierce’s Pict; it is automatically typed, asynchronous, higher-order, concurrent and distributed. It is not deterministic or sequenced. It is non-linear and has no polymorphism except for a few list operations. The semantics are taken from Pict.
The Pint language includes document type definition facilities for re-cursive element and attribute declarations but these are type based rather than syntax based as in SGML/XML. Pint supports the Oasis catalogue. The library provides a graphics system which offers functionality similar to Erlang’s GS through an interface based on passing elements to six built-in paths. A demonstration microprogram simulates and displays an ant raiding party.
The emulated hardware offers up to 227hardware channels on which the program’s paths are to be placed. We show examples of programming for the small footprint imposed by this hardware. The emulator provides trace and debugging facilities and will operate at up to 10000 reductions per second on a 1GHz PC. The translator, emulator and documentation, a 260 page book, are GPLed.
Part 1 — The Language and Platform i
1 Introduction to the Pint language 1
1.1 π-calculus hardware . . . 8
1.2 Footprint . . . 9
1.3 Software . . . 10
1.4 Sample session . . . 10
2 ISO Latin 9 12 2.1 Entering those characters which are not on your keyboard . . . 12
3 Catalogue 17 4 Syntax 21 4.1 Document type declaration . . . 22
4.2 Paths . . . 23 4.3 Remote paths . . . 24 4.4 Values . . . 25 4.5 Abstractions . . . 28 4.6 Patterns . . . 29 4.7 Processes . . . 30 4.8 Declarations . . . 32 5 Types 40 5.1 Introduction — the syntactic gap . . . 40
5.2 Typing . . . 40
5.3 Pint’s type system . . . 41
5.4 Different kinds of path types . . . 43
5.5 Explaining type errors — a conjecture . . . 43
6 Semantics 46 6.1 Symbols, sets and mappings . . . 46
6.2 The pattern matching problem . . . 47
6.3 Reduction . . . 47
7 Arithmetic and Logic Unit, ALU 49 7.1 ALU boolean operations . . . 50
7.2 ALU integer operations . . . 50
7.3 ALU floating point operations . . . 51
7.4 ALU list operations . . . 53
7.5 ALU Unicode operations . . . 53
8 Bosses and workers 55
9 Programming for a small footprint 56
9.1 Boxes and garbage collection . . . 56
9.1.1 Programming support for garbage collection, ¶fin . . . 57
9.1.2 Translate-time box assignment . . . 58
9.1.3 Run time box assignment . . . 59
9.1.4 The garbage collector . . . 62
9.2 Looping . . . 63
9.3 A better factorial n: fac_tr . . . 64
9.4 A better evenodd n . . . 65
9.5 A general purpose for . . . 67
9.6 Reversing a string . . . 69
9.6.1 Version 1: production code . . . 69
9.6.2 Version 2: na¨ıve functional style . . . 69
9.6.3 Version 3: functional style with accumulator . . . 70
9.7 When to use “prole” . . . 70
10 Data structures 72 10.1 Lists, records and tuples . . . 72
10.2 A value server . . . 72
10.3 An AVL tree . . . 74
10.4 Home brews . . . 76
11 Distributed Pint 77 11.1 Starting distributed Pint . . . 78
11.2 Node identification . . . 79
11.3 Authentification . . . 79
11.4 Pint facilities for distributed computation . . . 80
11.5 An example: ping . . . 82
12 Demonstration programs 85 12.1 Ant raiding party . . . 85
12.2 Higher order natural join . . . 89
12.2.1 Machiavelli . . . 89
12.2.2 The demonstration . . . 90
12.2.3 Natural join of two documents . . . 91
12.2.4 Query evaluation plan . . . 92
12.2.5 Summary . . . 95
13 Installation 96 13.1 Prerequisites . . . 96
13.2 Build Pint . . . 96
13.3 Using Erlang’s HiPE compiler . . . 99
13.4 Hardware emulator options . . . 100
14 Running Pint programs 102 14.1 Stopping Pint programs . . . 102
15.2 Run-time debugging . . . 104
15.2.1 The -trace option . . . 105
15.2.2 The postmortem dump . . . 108
15.2.3 The -debug option . . . 111
15.3 Debugging the translator and emulator . . . 111
15.3.1 Lexer . . . 111
15.3.2 Parser . . . 112
16 Internals 113 16.1 Translator data types . . . 113
16.1.1 The Oasis 9401 catalogue . . . 115
16.1.2 The total ordering for paths . . . 115
16.1.3 The total ordering for times . . . 116
16.1.4 The total ordering for names . . . 116
16.1.5 The total ordering for type functions . . . 116
16.1.6 The total ordering on boxes . . . 116
16.1.7 The total ordering on name contexts . . . 116
16.1.8 The total ordering on hints . . . 116
16.1.9 The total ordering on notation identifiers . . . 117
16.1.10 The total ordering for catalogue keys . . . 117
16.1.11 The total ordering for types . . . 117
16.1.12 The total ordering for kinds . . . 117
16.1.13 The total ordering for kind variables . . . 117
16.1.14 The total ordering for patterns . . . 118
16.1.15 Type Functions . . . 118
16.1.16 Document Type Definition . . . 118
16.1.17 Symbol Tables . . . 118
16.1.18 Type and kind Judgements . . . 119
16.1.19 Boxes . . . 119
16.1.20 Catalogue . . . 120
16.2 Message flows . . . 121
16.3 Environment variables . . . 122
17 Adding new library paths 123 17.1 The ALU technique for built-in paths . . . 123
17.2 The rng technique for library paths . . . 123
17.3 The “random number server” technique for library paths . . . 124
18 Other documentation 125 19 Comments and bug reports 126 19.1 Known bugs . . . 126
20 Further work 127
21 Licensing 128
21.1 The GNU General Public License . . . 128
21.2 GNU Free Documentation License . . . 133
Part 2 — The Library cxxxix 22 Basic file input and output 141 22.1 Open and close files . . . 142
22.2 Read from files . . . 142
22.3 Conversion to Unicode . . . 143
22.4 Write Unicode to file . . . 143
22.5 Style for basic file input and output . . . 144
22.6 Programming note . . . 145
23 Formatted input and output 146 24 Token scanning 153 24.1 Lexical analysis usingtok.io.scan . . . 154
25 OASIS catalogue access 155 26 Application initialization 160 26.1 Avoiding deadlocks . . . 162
27 Basic mathematical functions 163 28 Basic time management 165 28.1 Example . . . 166
29 System data 168 30 Pseudo random numbers 170 30.1 A random number server . . . 171
31 AVL trees 173 31.1 An example using avl.i.fold . . . 179
31.2 Accelerated AVL trees . . . 180
32 Graphic input and output 181 32.1 Graphic paths . . . 182
32.2 Graphic objects . . . 184
32.2.1 Graphic object identifier . . . 185
32.2.2 A type for each object . . . 186
32.3 Container objects . . . 187
32.4 Events . . . 188
32.4.1 User defined elements in event payload . . . 191
32.5 Event options . . . 192
32.6 Generic options . . . 194
32.6.4 Generic read options . . . 199 32.7 Frames . . . 201 32.7.1 The packer . . . 201 32.7.2 Frame options . . . 202 32.7.3 Packer demonstration . . . 202 32.8 Windows . . . 204 32.9 Canvas . . . 205 32.9.1 Arcs . . . 205 32.9.2 Images . . . 207 32.9.3 Lines . . . 208 32.9.4 Ovals . . . 208 32.9.5 Polygons . . . 209 32.9.6 Rectangles . . . 209 32.9.7 Text . . . 210
32.9.8 Canvas object demonstration . . . 210
32.10 Menus . . . 212
32.10.1 Menu . . . 212
32.10.2 Menu bar . . . 212
32.10.3 Menu button . . . 212
32.10.4 Menu cascade, menu check, menu normal, menu radio, menu separator . . . 213
32.10.5 Menu demonstration . . . 214
32.11 Scale . . . 215
32.11.1 Scale demonstration . . . 215
32.12 Grid and grid line . . . 216
32.13 Editor . . . 217
32.13.1 Editor read options . . . 218
32.13.2 Editor demonstration . . . 219
32.14 Buttons, radio buttons and check buttons . . . 221
32.14.1 Button configuration options . . . 222
32.14.2 Programming a button . . . 222
32.14.3 Programming many buttons . . . 223
32.14.4 Improved accessibility . . . 225
32.14.5 Button object demonstration . . . 226
32.15 Labels . . . 226
32.16 Text entry . . . 229
32.16.1 Text entry demonstration . . . 230
32.17 Listboxes . . . 231
32.17.1 Listbox configuration options . . . 232
32.17.2 Listbox read options . . . 233
32.17.3 List box entry demonstration . . . 233
32.22 Summary of options for graphic objects . . . 239
References 246 Index for Parts 1 and 2 250
List of Figures
1 This looks like some piece of agricultural equipment, but it represents a channel which is the basic component of the π-calculus machine. The machine contains many of these channels operating independently in par-allel. . . 82 The character set specified by International Standard 8859-15 [ISO99], known as ISO Latin 9. . . 16
3 A template boss creates a worker every time a value arrives. . . 55
4 The run-time box dictionary for gs_ex14 before garbage collection. . 60
5 The run-time box dictionary for gs_ex14 after final garbage collection. 61 6 Two views of a raiding party: the party approaches the food, and the return journey. . . 85
7 Document R3 marked up as <R3. . .> is the higher order natural join of R1, marked up as <R1. . .>and R2, marked up as <R2. . .>. . . 91
8 Message flows in the Pint hardware. Bold lines show synchronous messages. Other messages are asynchronous. . . 121
9 The Pint Graphic System (GS) provides six library paths used to man-age a graphic presentation and the user interactions. . . 181
10 Demo of defaults. . . 196
11 Initial presentation and appearance after resizing. . . 202
12 The canvas arc. . . 206
13 Canvas objects. . . 211
14 Three submenus. . . 214
15 Scale objects for selecting the colour of a window. . . 215
16 A simple editor. . . 219
17 “Press Me” button example. . . 222
18 Two buttons with custom behaviour. . . 223
19 Button objects. . . 227
20 “What’s your name” text entry example. . . 230
21 “Pick a fruit” list box example. . . 234
22 Font examples. The displayed window was 76mm wide. . . 236
List of Tables
1 Escape sequences for use in Unicode values. . . 262 Different kinds of path types. . . 44
3 The definition of ÷ and mod used by Pint. . . 50
4 The definition of quot and rem used by Pint. . . 51
5 The definition of abs used by Pint for integers. . . 51
9 Environment variables used by Pint. . . 122
10 Styling elements for basic file input and output. . . 145
11 Fields used by fwrite and fread. . . 150
12 Tokenize a Unicode value . . . 154
13 Access OASIS catalogue . . . 155
14 Access DELEGATE entries in OASIS catalogue . . . 156
15 Access DOCTYPE entries in OASIS catalogue . . . 156
16 Access DOCUMENT entry in OASIS catalogue . . . 156
17 Access DTDDECL entries in OASIS catalogue . . . 157
18 Access ENTITY entries in OASIS catalogue . . . 157
19 Access LINKTYPE entries in OASIS catalogue . . . 157
20 Access NOTATION entries in OASIS catalogue . . . 158
21 Access other entries in OASIS catalogue . . . 158
22 Access OVERRIDE entry in OASIS catalogue . . . 158
23 Access PUBLIC entries in OASIS catalogue . . . 159
24 Access SGMLDECL entry in OASIS catalogue . . . 159
25 Access SYSTEM entries in OASIS catalogue . . . 159
26 Elements for application initialization. . . 162
27 Elements for mathematical functions. . . 164
28 Remove item from AVL tree . . . 174
29 Remove list of items from AVL tree . . . 174
30 Create an empty AVL tree . . . 175
31 Insert an items into an AVL tree . . . 175
32 Insert a list of items into an AVL tree . . . 175
33 Is an AVL tree empty? . . . 176
34 Sequentially iterate a template through an AVL tree. . . 176
35 Look for item in AVL tree. . . 176
36 Concurrently iterate a template through an AVL tree. . . 177
37 Form list of items in AVL tree. . . 177
38 Create Unicode image of an AVL tree. . . 178
39 Fold a user template over an AVL tree . . . 179
40 Elements sent to the library pathGS.mgr.start . . . 182
41 Elements sent to the library pathGS.mgr.stop . . . 182
42 Elements sent to the library pathGS.mgr.create . . . 183
43 Elements sent to the library pathGS.mgr.destroy . . . 183
44 Elements sent to the library pathGS.mgr.config . . . 183
45 Elements sent to the library pathGS.mgr.read . . . 184
46 Elements representing graphic objects . . . 185
47 Element representing graphic object identifiers . . . 186
48 Elements representing graphic object types . . . 187
49 Container object relationships. . . 187
50 Elements which represent events. . . 191
51 Event options. . . 193
52 Generic options. . . 195
53 Generic options when parent is a frame. . . 198
55 Generic read options. . . 200 56 Packer options. . . 202 57 Frame options. . . 202 58 Window options. . . 204 59 Canvas options. . . 205 60 Arc options. . . 207 61 Image options. . . 208 62 Line options. . . 208 63 Menu options. . . 212
64 Menu button options. . . 213
65 Menu item options. . . 214
66 Scale options. . . 215
67 Editor options. . . 218
68 Editor read options. . . 219
69 Button options. . . 222
70 Button configuration options. . . 222
71 Label decoration elements. . . 228
72 Label options. . . 228
73 Text entry options. . . 230
74 Listbox options. . . 232
75 Listbox configuration options. . . 233
76 Listbox read options. . . 233
77 Generic fonts available in Pint graphics. . . 236
78 Indexed positions in a body of text. . . 237
79 Colours. . . 238
80 Attachment and alignment points for rectangles. . . 239
81 Summary of use of options with graphic objects. . . 245
1
1
Introduction to the Pint language
Welcome to Pint!. Part 1 of this User’s Guide describes the Pint language and plat-form — Pint is an experimental implementation of the π-calculus which emphasises its simplicity. This documentation assumes some familiarity with the π-calculus: see for example [Mil93, Mil99] for an introduction.
First of all, a very condensed summary of the language for language specialists. The Pint language is
• Automatically typed: All the π-calculus paths1 and variables are typed, and a path always carries values of the same type. The typing is done automatically by the translator. Processes are not typed.
• Asynchronous: When a message is sent, computation continues from the point at which the message was sent without regard to the reception of the message. It is possible to develop synchronous message passing.
• Higher-order: The values sent on paths may include other processes. • Polyadic: Multiple values may be sent in messages.
• Concurrent: Many different pieces of program may be executed at the same time. The hardware emulator reports on the concurrency achieved by a program. • Distributed: A program may be executed on more that one processor.
The language allows scope extrusion, discussed in chapter 9.1 on page 57, and input mobility. The language is not
• Deterministic: The reductions that may occur on each path happen indepen-dently of what is happening on other paths. The paths operate concurrently. This means that a program may have many different possible outcomes.
• Polymorphic: Except for a few basic list operations, operations accept only one type.
• Linear: More than one reduction may occur on a path.
• Sequenced: A set of concurrent processes (P || Q || R) is not rendered as a sequence of operations “P then Q then R”. The processes are executed concurrently on “parallel” hardware.
Now, let’s pause and ask what all that means for the programmer. The simplest approach is to look at that classic program “Hello World”.
1 <!DOCTYPE Pint PUBLIC "-//Pint//NOTATION Pint//EN" > 2 %% hello.pint
3 import "-//Pint//DTD Input output library//EN" 4 new c
5 offer
6 ( io.file.uwrite ! <Uwrite stdOut "Hello World\n" c c> 7 || c ? _ = ¶die
8 ) 1
Let’s take this program apart, line by line. To help identify the components, we adopt a colour code: this is a built-in ALU path,this is a library path,this is a notation,this is a keyword,this is a type or kind andthis is a type function.
<!DOCTYPE Pint All Pint programs are identified as such by an SGML/XML document type declaration [8879, prod 110][YBP+04, prod 28] just as HTML documents should be identified. The keyword DOCTYPE is always upper case and the document type name Pint is always mixed case as written here.
“Why”, you may ask, “do we need an SGML/XML declaration on top of something which is neither SGML nor XML?” Pint shares a lot of characteristics with SGML and XML: it allows the declaration of elements and their attributes in a structured way. It calls for conformance of the elements to a DTD, and may be used to markup structured documents. Yet it is does not conform to SGML/XML and is not designed to do so — on the contrary, it is intended as a vehicle to explore alternative markup techniques. The formal declaration at the top of every Pint program says that this is not SGML/XML and that it cannot be processed by an SGML/XML processor. It requires a Pint processor. This makes it clear to all markup specialists that Pint is not to be confused with SGML or XML.
PUBLIC "-//Pint//NOTATION Pint//EN" This is called the external identifier [8879, prod 73] and says that the rest of the document is written according to the Pint language specification (the document you are looking at right now). The part between quotes is called the formal public identifier [8879, prod 79] (FPI). The keyword NOTATION says that the document content requires a non-SGML/XML processor to handle it — specifically it requires a Pint processor.
> This terminates the document type declaration.
%% hello.pint Anything between the first “%” and the end of the line is a comment. You may also use ML style comments (* ... *).
import "-//Pint//DTD Input output library//EN" Use the paths of the input out-put library program to provide outout-put.
new c We need a path which we decide to call “c”. This path is different to every other path, even if some other path defined previously was also called “c”.
offer Offer the following process to the π-calculus hardware. In this case the process consists of two concurrent processes, separated by a “||”.
( io.file.uwrite ! <Uwrite stdOut "Hello Worldn" c c> The first of the two concurrent processes sends (that’s what the “!” means) a value <· · ·> on the library path io.file.uwrite. Sending a value on a path is one of the two basic processes in Pint. The other is receiving a value on a path. In the case of the library pathio.file.uwrite the reception is inside the library program “io”. The value is an SGML/XML-like element of type io defined in the Pint library, and consists of
3
specified in a document type definition (DTD) in the library. In Pint the start tags have no closing “>” and the element content consists entirely of attributes which may, unlike SGML/XML, be marked up.
The U inUwrite means “Unicode” since the characters are represented inter-nally by their Unicode numbers.
stdOut The first attribute says that the output is to the user’s screen. "Hello World\n" The second attribute is the text to be displayed.
c The third attribute is the name of a path on which the value “{}” is sent if the output succeeds.
c The fourth attribute is the name of a path on which the value “{}” is sent if the output fails.
> This is the element’s end tag. As you see, its simpler than SGML/XML. || c ? _ = ¶die Concurrently, that’s what the “||” means, we expect to receive
(that’s what the “?” means) a value on the path c, but we do not care what that value is, so it’s represented by a don’t care wildcard “_”.
When the “send” and “receive” successfully communicate on path c, we say that a π-calculus reduction occurs, and this is the basic action of the π-calculus machine. During the reduction, the process written after the “=” is offered in turn to the hardware. In this case it’s the pre-defined process ¶die which means “stop the machine”.
)
It should be clear by now that Pint is a lower level language than say C, Scheme, ML or TyCO. That’s why it’s better to think of working in Pint as microprogramming — low level coding very close to the hardware, providing the hardware with a personality which in turn may allow further higher-level “programming” or other human use.
Before we can run the “Hello World” program we need to give it a name and a place in the catalogue of programs. This is done by placing the entry
9 ENTITY hello "examples/hello.pint" Hello world
--in the file catalog. It declares the program --in file examples/hello.p--int to have the name hello.
We can now compile and run the program with the command 10 9> pi(hello) .
and we see the result2 11 ok
12 Hello World
The Pint hardware emulator also tells us that there were 5 π-reductions which were 1. A dummy reduction which offers the whole program to the hardware.
2
2. The library path io.file.uwrite receives the <Uwrite · · ·> element and offers an instance of itself to the hardware to perform the work.
3. A working instance of the library pathio.file.uwritereceives the<Uwrite· · ·> element and offers its process to the hardware, which displays Hello World on the screen, and then sends the value {} on path c.
4. Path c receives the value {} and offers its process ¶die to the hardware. 5. The process ¶die terminates the program and stops the hardware.
Execution of a π-calculus program consists of nothing more than a (long) succession of π-reductions as values are received on paths, with an offer of a further process to the hardware at each reduction.
But why do we need that step 2? Why didn’t step 2 display Hello World? The answer is that io.file.uwrite is a template, a permanent input process waiting to receive a sequence of values. Executing its process may require many π-reductions so by creating a worker instance of itself for each value received io.file.uwrite allows the workers to proceed concurrently, taking maximum advantage of the hardware. We will also see later that this two-step process facilitates recursion which is needed for looping. Let’s look at another, more sophisticated example, let’s compute factorial(n) using a recursive template.
13 <!DOCTYPE Pint PUBLIC "-//Pint//NOTATION Pint//EN" > 14 %% fac.pint
15 import
16 "-//Pint//NONSGML Formatted input output library//EN" 17 def fac {n r} =
18 let new neq0 new ngt0
19 out ( alu.int.comp ! {n 0 neq0 neq0 ngt0} 20 || neq0 ? {} = r!1
21 || ngt0 ? {} =
22 let new kn1 new kf1
23 out ( alu.int.- ! {n 1 kn1} 24 || kn1 ? n1 = fac ! {n1 kf1} 25 || kf1 ? f1 = alu.int.× ! {n f1 r} ) 26 end 27 ) 28 end
As before, we will now review this program line by line.
import "-//Pint//NONSGML Formatted input output library//EN" We will use the Pint library program for formatted output. This is roughly the equivalent of C’s printf.
def fac {n r} = The key word defintroduces a permanent input process known as a template. There should probably be a ? between the fac and the {n r} but it was omitted in the Pict language [Tur95, PT00] and Pint has followed much of Pict’s syntax.
5
integer value whose factorial is required, and a path on which to send the result respectively. In this sense, a template behaves like a function in ML. The remainder of the program is the process to be offered to the hardware each time a value is received on path fac
let new neq0 new ngt0 Before we continue we need to specify some paths which will carry signals that n < 0, n = 0 or n > 0.
out ( alu.int.comp ! {n 0 neq0 neq0 ngt0} You are probably used to seeing the construction let. . .in. . .end in languages such as ML. Pint has a similar con-struction, but the in becomesoutto emphasize that scope extrusion is probably happening. Scope extrusion means that you may find the paths you have declared re-appearing outside thelet. . .endconstruction.
The rest of the line sends the value {n 0 neq0 neq0 ngt0} on the built-in path
alu.int.comp, which is considered to be a part of the arithmetic and logic unit (ALU) in the hardware. This piece of hardware will send a handclap, i.e. the value {}, on path neq0, neq0 or ngt0 according as n < 0, n = 0 or n > 0.
The value {n 0 neq0 neq0 ngt0} is known as a record . Unlike ML’s records, Pint records use white space to separate the fields.3 Erlang has a similar feature, but calls it a tuple.
|| neq0 ? {} = r!1 If a handclap {} is received on path neq0 then we know that n ≤ 0 and we send the value 1 on path r.
|| ngt0 ? {} = If a handclap {} is received on path ngt0 then we know that n > 0 and we evaluate n × factorial(n − 1).
let new kn1 new kf1 We need paths to carry the values n − 1 and factorial(n − 1). “kn1” is the “kontinuation path with value n − 1”.
out ( alu.int.- ! {n 1 kn1} Ask built-in path alu.int.- to evaluate n−1 and send the result on path kn1.
|| kn1 ? n1 = fac ! {n1 kf1} Concurrently, that’s what the sign || means, we wait on path kn1 to receive value n − 1 which is assigned to variable n1. As a part of this π-reduction we offer a process which sends n − 1 on path fac. This can be read as “evaluate factorial(n − 1) and send the result on path kf1”.
|| kf1 ? f1 = alu.int.× ! {n f1 r} ) Concurrently, we wait on path kf1 to receive value factorial(n − 1) which is assigned to variable f1. As a part of this π-reduction we offer a process which sends n and factorial(n − 1) on built-in path
alu.int.× and says “evaluate n × factorial(n − 1), and send the answer on path r”.
end ) end Pint is very fussy about matching up the parentheses andend’s, so let’s do that.
We will also need a driver for template fac.
3In this example, all the optional field labels have been omitted. Such omission of labels is common
29 val n = 100 30 new c1 new c2 31 offer 32 ( fac!{n c1} 33 || c1?N = 34 ( fwrite!{stdOut
35 <Format [<_u "Factorial ">,
36 <_i n>, 37 <_u " = ">, 38 <_i N>, 39 <_u "\n">]> 40 c2 c2} 41 || c2?_ = ¶die 42 ))
Let’s take this driver line by line
val n = 100 Let’s use a name for the number whose factorial we will compute. It makes program maintenance easier.
new c1 new c2 We will need two new paths to carry the value factorial(n) and a handclap respectively.
offer We offer the following pair of concurrent processes to the hardware.
( fac ! {n c1} Send value n on path fac and tell fac that we want the result on path c1. A handclap {} is an empty record.
|| c1 ? N = Concurrently, we wait on path c1 to receive factorial(n) and assign its value to N.
( fwrite ! {stdOut As part of the π-reduction on path c1, we offer to library tem-plate fwrite a record which begins with the destination of our output. Library templatefwriteinterprets the contents of this record as an instruction to generate output to a file or in this case standard output. The record continues:
<Format [<_u "Factorial ">, Element <Format. . .> does for Pint what the format string with its “. . . %. . . %. . . ” does for C’s printf. Pint is a strongly typed language, which makes the technique used in C impossible, so we re-place C’s format string with an SGML/XML style markup of the output. This is now perfectly acceptable to Pint’s type checker. See chapter 23 on page 146 for more detail, and for an erudite discussion of the problem, and a solution for functional programmers, see Olivier Danvy’s article [Dan98]. The only attribute ofFormatis a list of elements representing the consecutive output fields. Note that list elements in Pint are separated by commas. <_i n>, Format and output the value of integer n.
<_u " = ">, Format and output the given string of characters. The “u” in _u means that the characters are represented internally by their Unicode numbers.
<_i N>, Format and output the value of N.
1.1 π-calculus hardware 7
c2 c2} If the output succeeds, send a handclap on path c2, and if it fails, send a handclap on path c2.
|| c2?_ = ¶die Concurrently, wait on path c2 for a handclap, and when it comes, stop the hardware.
)) Let’s be fussy about matching parentheses.
To run the fac program we first give it a name and a place in the catalogue of programs in file catalog.
43 ENTITY fac "examples/fac.pint" -- fac(n), naive --We can now compile and run the program with the command
44 9> pi(fac) . and we see the result
45 ok
46 Channel allocation of 64 exhausted. 47 Use command pi(prog,n) to raise limit.
What’s gone wrong here? The “ok” means that program compiled correctly, but once it started to execute, the hardware complained. By default the hardware allocates 64 channel s to carry the paths defined by the program, but fac seems to be calling for more than this. We follow the advice given, and use the second parameter of the command pi to increase the channel allocation.
48 10> pi(fac,1000) . 49 ok
50 Factorial 100 = 933262154439441526816992388562667004907159 51 6826438162146859296389521759999322991560894146397615651828 52 6253697920827223758251185210916864000000000000000000000000
Program fac is very space-inefficient; it needs at least4 5n + 45 channels to run, and takes 11n + 101 π-reductions. The program has an O(n) footprint — we will see later how to reduce this to O(1).
Exercise 1. If the order of the three processes on lines 23, 24 and 25 on page 4 were reversed, what would be the result of the program?
Exercise 2. Is it possible to write a Pint program containing concurrent processes in which changing the order of the processes in the source code changes the output of the program?
1. pattern matching 2. substitute value for pattern variable 3. update process −> process’ abstraction, i.e. pattern=process Execution of
send values and abstractions to other channels process’ process’ offer reduction value
This is the channel’s memory
path.fig
Figure 1: This looks like some piece of agricultural equipment, but it represents a channel which is the basic component of the π-calculus machine. The machine contains many of these channels operating independently in parallel.
1.1 π-calculus hardware
The Pint program is assumed to run on a very simple computer: the basic component is the channel5 shown in figure 1.
Each program has available to it a set of channels; by default there are 64, but this may be increased with the pi/26 command. Whenever the hardware meets a new or
defdeclaration it assigns a channel to process the traffic on the associated path. As the hardware executes the program, it meets output processes (that’s the ! sign) and input processes (that’s the ? sign). The output process has the general form p ! v so the hardware places the value v in the feeder of the channel which is managing the path p. Similarly, the input process has the general form p ? hpatterni=hprocessi so the hardware places the hpatterni=hprocessi in the feeder of the channel which is managing path p. The values and abstractions wait in the feeder in the order in which they arrived and are processed in that order. This “waiting in order” is specific to Pint, it is not a part of the π-calculus.
The π-calculus literature [Mil99, ch 9.6] calls the expression hpatterni=hprocessi an abstraction and we will use the same term.
When a channel’s feeder contains at least one value and at least one abstraction, then reduction of the oldest value and the oldest abstraction occurs — this is the basic operation of the Pint hardware.
(hvaluei | habstractioni) → hprocessi[hvaluei/hpatterni] (1) 4When run with the option -gc 1. Without this it requires even more paths.
5
We reserve the term “channel” for hardware. The corresponding software is called a “path”.
6This notation reveals the origins of Erlang as a program written in Prolog. It means a function
1.2 Footprint 9
The term on the right hand side of (1) is read as “the process, after the value has been matched with the pattern, and then substituted in the process”. For example
(3 | n = alu.int.+ ! {n 1 r1}) →alu.int.+ ! {n 1 r}[3/n] (2) →alu.int.+ ! {3 1 r} (3) What does this say? A value and an abstraction are reduced to a process process’ which is obtained by
1. Performing a pattern matching operation between the value and the pattern taken from the abstraction. In the example we see that value 3 matches the pattern variable n.
2. Substituting the value 3 for variable n in the process taken from the abstraction to produce process’.7
The value 3 and the process taken from the abstraction disappear — only the new process process’ remains, and this is offered to the hardware for execution. The execution may discover further input and output processes which feed other channels, and the program continues its reductions until either it meets the process ¶die, the process ¶postmortem or there is no channel left which has both a value and an abstraction in the feeder.
The channels in the π-calculus machine operate independently of one another, not necessarily at the same frequency and not necessarily in phase. However to make the operations easier to understand, we introduce the notion of cycle. We consider that the hardware cycles though its operation with one reduction possible at each cycle. The cycles are labelled 1,2,. . . and the hardware labels each reduction with the number of the lowest cycle in which the reduction could occur. If you run a program with the trace option turned on, a trace of the reductions is placed in the log file which gives the cycle number assigned to each reduction. See 15.2.1 on page 105.
Some paths are built into the hardware to provide rapid execution of basic arithmetic and logic operations. The ALU , Arithmetic and Logic Unit, is described in chapter 7 on page 49. Further paths, which form the Pint library are also available. These offer, for example, input and output operations as described in chapter 22 on page 141.
The Pint programmer’s job is to describe the initial configuration of a network of software paths, which will be assigned to the hardware channels. The machine is then launched and the configuration evolves in a non-deterministic fashion as each channel performs reductions whenever possible. This evolution may, or may not, terminate. 1.2 Footprint
The hardware has only a limited number of channels, the maximum is currently 32768 with release 8 of Erlang, 262144 with Erlang release 9, and 227 = 134217727 in release R10B-7. It is an easy exercise for a programmer to write a program which loops, using more and more channels and finally, in a few milliseconds, overwhelms the machine. The number of hardware channels required by a program is called the footprint and must be less than the hardware capacity. The good news is that the hardware channels may be used with one software path name, dropped and later re-used with another path name.
7
This is similar to the management of memory by malloc and free, so well known to the C language programmer.
A part of the skill of programming in the π-calculus at the low level used in the Pint language is to keep the footprint of a program bounded and as low as possible. This makes the programming more complicated, so we will give easily-understood examples of na¨ıve programming and then repeat the example but with a bounded footprint.
1.3 Software
The Pint language is supported by a translator written in ML [Ull98, Pau96] which translates the Pint program to the industrial-strength, distributed, concurrent, func-tional language Erlang [AVWW, BV99]. The Erlang program emulates the hardware of the Pint machine.
The Pint translator has been tested using the open source SML/NJ compiler version 110.44 and run-time library available at http://www.smlnj.org/ and the “hardware” has been tested with the open source Erlang compiler and run-time library versions R9C and R10B available at http://www.erlang.org.
1.4 Sample session
Here is an edited sample of output from Pint as the programmer compiles and runs “Hello World”. First launch the Pint emulator:
53 joe@olive:~> cd pint-0.3.2 54 joe@olive:~/pint-0.3.2> ./pint
55 Erlang (BEAM) emulator version 5.3.6.2 [source] [hipe] 56 Eshell V5.3.6.2 (abort with ^G)
57 ([email protected])1>
58 joe 12:18 Translating OASIS catalogue ... 59 joe 12:21 Compiling build_catalogue.erl ... 60 joe 12:22 Launching catalogue server ... 61 joe 12:22 build_catalogue loaded.
62 Pint machine now available.
63 Run program: pi(myprog). pi(myprog,N).
64 Quit: quit(). or Ctl-g q Don’t forget the "." 65 Emergency: killall -i run.x86-linux
1.4 Sample session 11
66 pi(hello) .
67 joe 27:37 Translating OASIS catalogue ... 68 joe 27:37 Compiling build_catalogue.erl ... 69 joe 27:38 Updating OASIS catalogue server ...
70 joe 27:38 Translating ~joe/pint-0.3.2/examples/hello.pint 71 val it = true : bool
72 - val it = () : unit
73 joe 27:39 Reading ~joe/pint-0.3.2/catalog ...
74 joe 27:39 Reading ~joe/pint-0.3.2/examples/ants.config ... 75 joe 27:39 Translating hello
76 from ~joe/pint-0.3.2/examples/hello.pint ... 77 joe 27:39 Translating -//Pint//DTD Input output library 78 from ~joe/pint-0.3.2/lib/io.dtd ... 79 val it = () : unit
80
-81 joe 27:39 Compiling ~joe/pint-0.3.2/examples/hello.erl ... 82 ok
83 Hello World
84 Load for: ’[email protected]’.
85 hello: 5 pi-reductions on 5 channels in 0.661 secs 86 Hardware: 5 cycles at 7.6 Hz, avg concurrency 1.00. 87 5 channels issued at 7.6 /sec,
88 holding time 0.332 sec, load 2.5 Erlang. 89 ([email protected])2>
2
ISO Latin 9
Pint source programs are encoded using the ISO Latin 9 character set [ISO99] which is a variant of ISO Latin 1 which in turn is subset of the Unicode [TUC03] characters. ISO Latin 9 is presented in table 2. Each entry gives the octal code used by ML-Lex, the character position, the value expressed in hexadecimal, and an approximation for the glyph. Note that the Euro symbol in position 164 has Unicode value U+20AC. 2.1 Entering those characters which are not on your keyboard
The Emacs editor and others provide techniques for entering ISO Latin 9 characters which are not on your keyboard. The simplest way for Emacs users is to use Mule and toggle the input method to ISO Latin 9. However this does not cover all the possible ISO Latin 9 characters. The remaining characters such as ¶ may be entered by following the instructions given for “Inserting text” by the Emacs documentation:
If you need to insert a control character or a character whose code is above 200 octal, you must ”quote” it by typing the character ‘Control-q’ (‘quoted-insert’) first. (This character’s name is normally written ‘C-q’ for short.) There are two ways to use ‘C-q’:
• ‘C-q’ followed by any non-graphic character (even ‘C-g’) inserts that character.
• ‘C-q’ followed by a sequence of octal digits inserts the character with the specified octal character code. You can use any number of octal digits; any non-digit terminates the sequence. If the terminating character is <RET>, it serves only to terminate the sequence; any other non-digit is itself used as input after terminating the sequence.
When multibyte characters are enabled, the octal codes 0200 through 0377 are not valid as characters; if you specify a code in this range, ‘C-q’ assumes that you intend to use some ISO Latin-N character set, and converts the specified code to the corresponding Emacs character code. You select which ISO Latin character set though your choice of language environment.
To use decimal or hexadecimal instead of octal, you should set the variable ‘read-quoted-char-radix’ to 10 or 16. If the radix is greater than 10, some letters starting with ‘a’ serve as part of a character code, just like digits.
A numeric argument to ‘C-q’ specifies how many copies of the quoted character should be inserted.
If you are an Emacs user and you wish to enter ISO Latin 9 characters in hexadecimal rather than octal, add the following lines to your file .emacs.
90 ;; Enter hexadecimal characters using C-q 91 (setq read-quoted-char-radix 16)
2.1 Entering those characters which are not on your keyboard 13 \000 0 00x NUL \020 16 10x DLE \001 1 01x STX \021 17 11x DC1 \002 2 02x SOT \022 18 12x DC2 \003 3 03x ETX \023 19 13x DC3 \004 4 04x EOT \024 20 14x DC4 \005 5 05x ENQ \025 21 15x NAK \006 6 06x ACK \026 22 16x SYN \007 7 07x BEL \027 23 17x ETB \010 8 08x BS \030 24 18x CAN \011 9 09x HT \031 25 19x EM \012 10 0ax LF \032 25 1ax SUB \013 11 0bx VT \033 27 1bx ESC \014 12 0cx FF \034 28 1cx FS \015 13 0dx CR \035 29 1dx GS \016 14 0ex SO \036 30 1ex RS \017 15 0fx SI \037 31 1fx US \040 32 20x SP \060 48 30x
0
\041 33 21x!
\061 49 31x1
\042 34 22x”
\062 50 32x2
\043 35 23x#
\063 51 33x3
\044 36 24x$
\064 52 34x4
\045 37 25x%
\065 53 35x5
\046 38 26x&
\066 54 36x6
\047 39 27x’
\067 55 37x7
\050 40 28x(
\070 56 38x8
\051 41 29x)
\071 57 39x9
\052 42 2ax*
\072 58 3ax:
\053 43 2bx+
\073 59 3bx;
\054 44 2cx,
\074 60 3cx<
\055 45 2dx-
\075 61 3dx=
\056 46 2ex.
\076 62 3ex>
\057 47 2fx/
\077 63 3fx?
continuing from previous page \100 64 40x
@
\120 80 50xP
\101 65 41xA
\121 81 51xQ
\102 66 42xB
\122 82 52xR
\103 67 43xC
\123 83 53xS
\104 68 44xD
\124 84 54xT
\105 69 45xE
\125 85 55xU
\106 70 46xF
\126 86 56xV
\107 71 47xG
\127 87 57xW
\110 72 48xH
\130 88 58xX
\111 73 49xI
\131 89 59xY
\112 74 4axJ
\132 90 5axZ
\113 75 4bxK
\133 91 5bx[
\114 76 4cxL
\134 92 5cx\
\115 77 4dxM
\135 93 5dx]
\116 78 4exN
\136 94 5exˆ
\117 79 4fxO
\137 95 5fx \140 96 60x‘
\160 112 70xp
\141 97 61xa
\161 113 71xq
\142 98 62xb
\162 114 72xr
\143 99 63xc
\163 115 73xs
\144 100 64xd
\164 116 74xt
\145 101 65xe
\165 117 75xu
\146 102 66xf
\166 118 76xv
\147 103 67xg
\167 119 77xw
\150 104 68xh
\170 120 78xx
\151 105 69xi
\171 121 79xy
\152 106 6axj
\172 122 7axz
\153 107 6bxk
\173 123 7bx{
\154 108 6cxl
\174 124 7cx|
\155 109 6dxm
\175 125 7dx}
\156 110 6exn
\176 126 7ex∼
\157 111 6fxo
\177 127 7fx DEL2.1 Entering those characters which are not on your keyboard 15
continuing from previous page
\200 128 80x CTRL \220 144 90x CTRL \201 129 81x CTRL \221 145 91x CTRL \202 130 82x CTRL \222 146 92x CTRL \203 131 83x CTRL \223 147 93x CTRL \204 132 84x CTRL \224 148 94x CTRL \205 133 85x CTRL \225 149 95x CTRL \206 134 86x CTRL \226 150 96x CTRL \207 135 87x CTRL \227 151 97x CTRL \210 136 88x CTRL \230 152 98x CTRL \211 137 89x CTRL \231 153 99x CTRL \212 138 8ax CTRL \232 154 9ax CTRL \213 139 8bx CTRL \233 155 9bx CTRL \214 140 8cx CTRL \234 156 9cx CTRL \215 141 8dx CTRL \235 157 9dx CTRL \216 142 8ex CTRL \236 158 9ex CTRL \217 143 8fx CTRL \237 159 9fx CTRL \240 160 a0x NBSP \260 176 b0x ◦ \241 161 a1x
¡
\261 177 b1x±
\242 162 a2xc|
\262 178 b2x 2 \243 163 a3x¿
\263 179 b3x 3 \244 164 a4x =C
\264 180 b4xZ
ˇ
\245 165 a5xU
\265 181 b5xµ
\246 166 a6xS
ˇ
\266 182 b6x¶
\247 167 a7x§
\267 183 b7x·
\250 168 a8xˇs
\270 184 b8xˇ
z
\251 169 a9xc
\271 185 b9x 1 \252 170 aax a \272 186 bax o \253 171 abx \273 187 bbx \254 172 acx¬
\274 188 bcxŒ
\255 173 adx SHY \275 189 bdxœ
\256 174 aexr
\276 190 bexY
¨
\257 175 afx¯
\277 191 bfx¿
continuing from previous page \300 192 c0x
A
`
\320 208 d0xÐ
\301 193 c1xA
´
\321 209 d1xN
˜
\302 194 c2xA
ˆ
\322 210 d2xO
`
\303 195 c3xA
˜
\323 211 d3xO
´
\304 196 c4xA
¨
\324 212 d4xO
ˆ
\305 197 c5x˚
A
\325 213 d5xO
˜
\306 198 c6xÆ
\326 214 d6xO
¨
\307 199 c7xC
¸
\327 215 d7x×
\310 200 c8xE
`
\330 216 d8xØ
\311 201 c9xE
´
\331 217 d9xU
`
\312 202 caxE
ˆ
\332 218 daxU
´
\313 203 cbxE
¨
\333 219 dbxU
ˆ
\314 204 ccx`I
\334 220 dcxU
¨
\315 205 cdx´I
\335 221 ddxY
´
\316 206 cexˆI
\336 222 dexÞ
\317 207 cfx¨I
\337 223 dfxß
\340 224 e0x`
a
\360 240 f0xð
\341 225 e1x´
a
\361 241 f1x˜
n
\342 226 e2xˆ
a
\362 242 f2x`
o
\343 227 e3x˜
a
\363 243 f3x´
o
\344 228 e4x¨
a
\364 244 f4xˆ
o
\345 229 e5x˚
a
\365 245 f5x˜
o
\346 230 e6xæ
\366 246 f6x¨
o
\347 231 e7x¸c
\367 247 f7x÷
\350 232 e8x`
e
\370 248 f8xø
\351 233 e9x´
e
\371 249 f9x`
u
\352 234 eaxˆ
e
\372 250 fax´
u
\353 235 ebx¨
e
\373 251 fbxˆ
u
\354 236 ecx`ı
\374 252 fcx¨
u
\355 237 edx´ı
\375 253 fdx´
y
\356 238 eexˆı
\376 254 fexþ
\357 239 efx¨ı
\377 255 ffx¨
y
17
3
Catalogue
The Organization for the Advancement of Structured Information Standards (OASIS) has published a widely followed resolution [Gro97] aimed as easing the interchange of SGML/XML documents. This chapter describes Pint’s adherence to this industry stan-dard.
OASIS was founded in 1993 under the name SGML Open as a consortium of vendors and users devoted to developing guidelines for interoperability among products that support the Standard Generalized Markup Language (SGML). OASIS changed its name in 1998 to reflect an expanded scope of technical work, including the Extensible Markup Language (XML) and other related standards. See http://www.oasis-open.org/who/. Pint is intended as a platform-independent system, however it has to operate on top of specific operating systems and allow use of the operating system’s file system. The notion of “file” is already very general in Unix-like operating systems, but OASIS seeks to be even more general and refers to a file as an “entity”.
Pint uses an OASIS catalogue8 [Gro97] which has the file name catalog9 and must appear in the current working directory of the translator. Because of this, Pint is able to adopt the following techniques:
1. Each reference to a library program in a Pint program is to a formal public iden-tifier given to the program, not to the file itself. There is a corresponding PUBLIC record in the catalogue.
2. Each reference to a file (or entity) in a Pint program is to a name given to the file, not to the file itself. There is a corresponding ENTITY record in the catalogue. 3. For each installation, there will be a conversion between the names used in the
Pint program and the real file name. This conversion is provided by a catalogue of names and the support for the catalogue built into the Pint system.
This use of a catalogue makes it easier to separate the work of an application programmer from that of the programmer working on the library. Each works with respect to a catalogue established by the system administrator.
Pint reads the catalogue before compiling begins. Note that Pint is not a validat-ing system for the OASIS catalogue and is tolerant of certain bafflvalidat-ing details which a validator should reject. When the emulated hardware is started, a catalogue server is launched from which the emulated hardware reads the catalogue entries. The catalogue entries are also available to Pint programs through library paths; see chapter 25 on page 155 for details.
OASIS recommendation 9401 requires that the keywords BASE, CATALOG, DELEGATE, DOCTYPE, DOCUMENT, DTDDECL, ENTITY, LINKTYPE, NO, NOTATION, OVERRIDE, PUBLIC, SGMLDECL, SYSTEM and YES be case-insensitive. Everything else is case sensitive.
The basic Pint catalogue distributed with Pint specifies the homes of the file con-taining the examples, the demonstration program and the library programs. It may be extended and shared with other programs at will.
Typical entries reveal the whereabouts of the library programs and the user’s pro-grams:
8
The document you are reading usually follows European spelling: hence the “ue”.
92 Catalogue for Pint --93 Coding examples
--94 BASE /mnt/home/rprice/pint/examples 95 ENTITY hello hello.pint Hello world --96 Include this other catalogue
--97 CATALOG my_catalog
98 Library DTDs and notations --99 BASE /mnt/home/rprice/pint/lib
100 PUBLIC "-//Pint//DTD Graphic system library//EN" GS.dtd 101 PUBLIC "-//Pint//DTD Input output library//EN" io.dtd 102 Other stuff, e.g. ISO-HTML
--103 BASE /mnt/home/rprice/15445
104 PUBLIC "ISO/IEC 15445:2000//DTD HTML//EN" 15445.dtd
The different records made possible by the OASIS catalogue are used as follows by Pint:
- - comment - - Comments in an OASIS catalogue respect the SGML rules for com-ments, they begin and end with the two characters “- -”.
BASE soi The BASE keyword specifies that relative storage object identifiers in the right hand side of entries following this entry in the current catalogue entry file should be resolved relative to the storage object identifier of this base entry. For example:
105 BASE /mnt/home/rprice/pint/examples 106 ENTITY hello hello.pint
says program “hello” is to be found in file /mnt/home/rprice/pint/examples/ hello.pint.
CATALOG soi The storage object identifier indicates the position of an additional cat-alogue file to be processed afer the current catcat-alogue file. For example:
107 CATALOG ants.config
says where the initialisation file for program “ants” is to be found.
DELEGATE DOCTYPE DOCUMENT DTDDECL These records are not used by Pint. See 25, 25, 25 and 25 on page 156 for a description.
ENTITY name soi The ENTITY keyword tells the entity manager to use the associated storage object identifier to locate the text corresponding to this entity name. See the example on line 106. In Pint, there is an ENTITY record in the catalogue for each program you write.
LINKTYPE OVERRIDE These records are not used by Pint. See 25 and 25 on page 158 for a description.
19
108 NOTATION AVL "Hardware representation of AVL tree"
says that the hardware representation of AVL tree has type stream AVL but can only be processed by custom “hardware”.
PUBLIC public_identifier soi The PUBLIC keyword tells the entity manager to use the associated storage object identifier to locate the text corresponding to this public identifier. For example:
109 PUBLIC "-//Pint//DTD Graphic system library//EN" GS.dtd
says where the graphic system library is to be found with respect to the current BASE value. Note that since the formal public identifier contains embedded spaces, it is written in quotes. In Pint, there is a PUBLIC record for each library program. SGMLDECL This record is not used by Pint. See 25 on page 159 for a description. Other information The Organization for the Advancement of Structured
Informa-tion Standards (OASIS) has generously allowed “other informaInforma-tion” to be placed in the OASIS catalogue. The grammar to be respected is
other information = keyword,
ps+, (symbol | non-symbol token | literal) (ps+, (non-symbol token | literal))*
The use of such entries is application specific, and Pint adopts the following con-vention: The “other information” shall be in the form of key-value pairs. The key shall be the “keyword” together with the first “(symbol | non-symbol token | literal)”. The value shall be the remaining list, possibly empty, of “(non-symbol token | literal)”. A typical use in Pint is to specify a parameter for a program, e.g:
110 Probability that the ant will sniff the pheromone. --111 ants prob_sniff "0.750" "0.999"
Here the key is ants prob_sniff and the value is "0.750" "0.999".
Note that since the “other information” has no keyword to assist the parsing of the catalogue, it is advisable to quote all the values, but not the keyword. A value may be quoted "0.750" or ’0.750’. See 25 on page 158 for further details. These catalogue entries have common components:
FPI The formal public identifier is defined by SGML [Gol90, clause 10.2]. The charac-ter set is restricted to the minimum data [Gol90, clause 10.1.7] of SGML’s reference concrete syntax: space, a-zA-Z0-9 and the 11 characters ’()+,-./:=?. FPI’s ap-pear in the DOCTYPE declaration that should be at the top of all valid HTML pages. Here is an example from the ultra-strict ISO-HTML:
The FPI says who owns this identifier. In this case “ISO/IEC 15445:2000” says that the owner is the International Standard for ISO-HTML [ISO00], “DTD” says what it contains, a Document Type Definition, “HTML” says for what, and “EN” says in what human language the document is written.
FSI The formal system identifier is defined10 as part of the SGML General Facil-ities, currently part of the Technical Corrigendum to HyTime, ISO/IEC 10744 [GNEKN97, Annex A.6]. The only FSI’s that Pint supports are storage object identifiers (soi) which are absolute or relative directory and file names. Pint does not currently support URLs.
keyword The keyword uses the restricted system characters, i.e. any printable ISO latin 9 character except LIT ("), LITA (’), white space and the five characters \/.<>.
ppi partial public identifiers are not currently supported by Pint.
soi The storage object identifier is a system dependent way of specifying the location of some file. If the soi specifies a relative path name, the path is relative to the location of the catalogue file itself, unless a previous occurrence of a BASE entry has occured in this catalogue file, in which case the path specified by the soi is relative to the BASE.
The soi’s accept the ISO latin 9 character set, and are to be quoted if needed to distinguish them from keywords of other catalogue entries.
sysid system identifiers are delimited by LIT (") or LITA (’) and contain any printable ISO latin 9 character except the delimiting LIT or LITA.
10Strictly speaking, the HyTime specification does not define FSIs, it merely provides Formal System
21
4
Syntax
The syntax of Pint was originally based closely on the Pict language [Pie98], but was later changed to use keywords such as let,out,endand anonrather than (, , ) and \. We use || to compose concurrent processes rather than Pict’s |. The symbol | is used in Pint to indicate a choice of patterns. Pint uses ML’s keyword asinstead of the symbol @ in layered patterns. Records are wrapped in the more conventional { and } instead of [ and ] which are used for lists. Pict’s keyword run has been replaced by offer
since more than a simple declaration is required to ensure that the associated process is really executed by the hardware. The addition of elements also introduced some new syntax. Nevertheless, Pint should still be readable (well, perhaps almost readable) to a Pict programmer.
A Pint program is a required document type declaration, chapter 4.1, followed by a possibly empty sequence of import declarations, chapter 4.8, followed by a possibly empty sequence of other declarations, chapter 4.8.
If the program includes one or more offerdeclarations, chapter 4.8, it may lead to π-calculus reductions when loaded onto the hardware.
White space Extra white space may be applied at will in all the conventional places to clarify a program. The white space characters are shown in table 1 on page 26. Line comments The percent character “%” in any position except within a value of type unicode or within a block comment begins a line comment which continues up to the end of the line, but does not include the end-of-line. A line comment may comment out a “(*” or a “*)” token which delimits a block comment.
Block comments The token “(*” in any position except within a value of type
unicode or within a line comment begins a block comment which continues up to and includes the matching “*)” token, which may be in any position except within a value of typeunicode or within a line comment. A block comment may comment out the “%” character which begins a line comment.
Nested block comments are also allowed: (* · · · (* · · · *) · · · *).
Keywords The Pint language uses the characters shown in table 2 on page 16 and has the following keywords11: and,anon,as,bool,case,def, ¶die, elatt,else,
end,false, ¶fin,if,import,int,let,list,new,of,offer,out, ¶postmortem,
prole,real,stdErr,stdIn, stdNull,stdOut,stream,then,unicode, url and
val.
Separators White space is used a separator in records, elements and lists of declara-tions. The comma character “,” is used as a separator in lists. E.g. {[1,2] [3,4] [5,6]}
Names hnamei The Pint language uses names for programs, paths, parameters for abstractions and templates, template names, record field labels, notations, type functions and user defined types. A name begins with a letter which is an alpha-betic character in one of the ranges A-Z, a-z, ˇS, ˇs, ˇZ, ˇz, Œ-¨Y, `A-¨O, Ø-¨o, ø-¨y, - or _ and continues with zero or more letters or digits 0-9.
11
Examples are x, selec¸c~ao, Array_146, _, Marie-Fran¸coise .
By convention, we write the names of variables beginning with a lower case letter12, and the names of type functions beginning with an upper case letter.
Names beginning with “_” are special cases in Pint in the same way that “_” is a special case in languages such as ML or Erlang. The leading “_” says that we will not be using this argument13. This is almost the same as the wild card of ML and Erlang. However the Pint wild card must be typable.
Pint thus has many possible wild cards, e.g. _warning _error_code. Why not have one single wild card “_” to cover all the cases? The reason is that if we did that, the variable “_” could potentially have many different types, and since Pint is not polymorphic, we would not be able to determine a precise, ground type for the variable. The solution in Pint is to have many possible wild cards, each with its own ground type. It is also convenient to use a more descriptive name as a reminder of what is being ignored.
The wild card is used in patterns to indicate that we don’t care about this value. E.g. val {real,_imag} = z says that we don’t care to know the imaginary part of a complex number z.
In practice it is possible to use the simple “_” in almost all cases.
Exercise 3. Write a program which requires the use of two or more different wild cards, or explain why such a program cannot exist.
4.1 Document type declaration
All Pint programs are required to carry an SGML/XML document type declaration [8879, prod 110][YBP+04, prod 28]. This declaration states formally that although this document may appear to contain SGML/XML elements and attributes it is not an SGML/XML document, and cannot be processed by an SGML/XML processor. It requires a Pint processor. A language which cannot be processed by an SGML/XML processor is known to SGML experts and XML specialists as a “NOTATION”.
All Pint programs version 0.3.2 have the formal public identifier (FPI) "-//Pint//NOTATION Pint//EN"
and carry the following document type declaration:
<!DOCTYPE Pint PUBLIC "-//Pint//NOTATION Pint//EN" >
You may add more white space before and after the name Pint and the keyword PUBLIC, and before the final >, however the FPI must be written as shown. This is a restriction with respect to SGML. You may not place comments before or within a Pint document type declaration.
12
Well, most of the time at least.
4.2 Paths 23
4.2 Paths
All computation in the π-calculus is attached to a device known as a path. From the software point of view, its the identifier which ties together the input and output involved in a reduction, and from the hardware point of view it’s the rˆole played by the basic piece of the computer: the channel, which performs the reduction.
The general syntax is
hpathi ::=hnamei (4)
| hremote pathi (5)
| hprojectioni (6)
There are three forms of path: simple (4), see the discussion of names for examples, remote (5), see chapter 4.3 on page 24, and dotted (6) which are known as projections.
hprojectioni ::=hnamei.hfieldi (7)
hfieldi ::=hattributei.hfieldi (8)
| hattributei (9)
A projection (7) has a root which is the name of a record or element, followed by one or more attributes attached with periods: for examplerns.uniform.ints. The projection extracts a labelled attribute from a record or element. For example, if we are given the record val my_alu = {add=alu.int.+ sub=alu.int.-}, then the output process my_alu.add ! {2 2 c} will ask alu.int.+to add 2 and 2.
hattributei ::=hlabeli (10)
So far, all the projections we have seen are from records. “What happens”, you might ask, “if we want to project attribute num from an element defined by:
112 elatt prisoner = Inmate of name:unicode * num:int
113 | Cell of num:int * building:unicode
Which num will be chosen, the prisoner’s number or the cell number?” To clarify this, Pint requires that when projecting a field from an element, the programmer must specify the type function used to tag the element instance as well as the field label. The attribute takes the syntax shown in (11) or (12):
|<htyfuni hlabeli> (11)
|htyfuni hlabeli (12)
htyfuni::=hlabeli (13)
If scarface is a name of type prisoner, you can project the prisoner’s number using the dotted path scarface.Inmate num. You can project the cell number using the path scarface.Cell num.
Exercise 4. Write a program which cheats by trying to project a cell number from an Inmate element.
4.3 Remote paths
Pint is a distributed language: this means that a program written in the Pint language may call for computation on more than one processor, and these processors may be spread across several sites. The only way to persuade a remote processor to do work for you is to send a value to one of its paths. This requires some way of addressing a path on a remote processor.
Pint programs may spread their computations over a network14of processors, each of which may carry one or more user accounts running Pint emulators. Each Pint emulator in the network is called a node.
The Pint language provides a notation for specifying a path on a distant node. Such a path is known as a remote path. The general syntax is based on RFC’s 1738 [BLMM94] and 1808 [Fie95]:
hremote pathi ::=x-pi://huseri@hhosti/hprogi#hremote namei (14) A remote path (14) is a URL (Uniform Resource Locator) containing a scheme, and four fields which are further described by (15), (17), (20) and (22). The scheme of the URL, “x-pi” is written with the prefix “x-” which says that this protocol is experimental and not registered with IANA’s official registry of URL schemes [IAN]. You must write the scheme in lower-case characters.
huseri ::=userid defined on host system (15)
| _ (16)
The huseri (15) is the userid of the account which is running the Pint emulator. There is a special case: the single underscore character “_”. This says “take the userid of the account on which the program is translated”, and which is shown at the command prompt of the translating system.
hhosti ::=Fully qualified domain name (17)
| IP address (18)
| _ (19)
The hhosti (17) is the fully qualified domain name (FQDN) of the remote node which is running the Pint emulator. There is a special case: the single underscore character “_”. This says “take the FQDN of the node on which the program is translated”, and which is shown at the command prompt of the translating system. The node may also be specified using the IPv4 dotted quad notation.
hprogi ::=Program name (20)
| _ (21)
4.4 Values 25
The hprogi (20) is the program running on the remote node, and identified by the name of the program entity. This is the same as the entity name which you use in the command pi(prog,N) to launch the program in the remote node. Clearly this entity name must also appear in the catalogue in the remote node. There is a special case: the single underscore character “_”. This says “take the program name from the program being translated”.
hremote namei ::=hnamei (22)
The hremote namei (22) is the name of a path in a Pint program running on the remote node to which we wish to send some value. See chapter 4 on page 21 for a discussion of names for paths. Note that this path will have type ∧3 which means that it cannot be a template, which would have type ∧o and cannot receive local values, which would require type ∧a. In other words, this path must be dedicated to receiving values from other nodes.
It is often convenient to give short aliases to long URLs using aval declaration. 4.4 Values
The Pint language supports a range of values:
Boolean values The boolean values aretrueandfalse. In practice these values are less useful than one might think, but they were included in Pint for compatibility with Pict. It is usually simpler to represent “true” and “false” with two separate paths.
114 def bool_to_paths {b p-true p-false} = 115 if b then p-true!{} else p-false!{}
Integer values The integer numbers are written in the style ∼1, 25, 8288. Large integers are possible: 4927492515511210043330985984000000. Note the use of ∼ as a negative sign15 rather than -.
Real values Pint presents the emulated hardware’s floating-point numbers as real numbers in the manner of a high level language. This is an abstraction and a simplification of the notion of floating point, and conformance to IEEE Std 754 [IEE90] is lost. For example, there is no notion of NaN in Pint. See [Gol91] for a tutorial, and [Kah96] for a discussion.
The real numbers are written with decimal point and fractional part16in the style 3.14159 or ∼2.718. An exponent may be added, e.g. ∼2.7e11 or 1.3E∼25. Again, note the use of ∼ as a negative sign rather than - for both mantissa and exponent.
Unicode string values Many programming languages provide “strings” which are usually sequences of characters. There is no type “char” in Pint and the equivalent of a string is the typeunicode. Theunicodetype contains lists of integers which are Unicode codes [TUC03]. Since Pint is an ISO Latin 9 language, the integer 15There is no equivalent unary positive sign. It is an error to writeval N = +10.
16
Character Meaning * = white space \b Backspace
\e Escape
\f Form feed *
\n Line feed (Unix/Linux newline) * \r Carriage return * \s Space * \t Horizontal tabulate * \v Vertical tabulate * \\ Backslash \" Double quote \c Character c
Table 1: Escape sequences for use in Unicode values.
values found in values of typeunicode are those corresponding to the characters in ISO Latin 9. For example the capital letter E has the integer value 69 and the Euro symbol has the integer value 8364. The effect of integer values other than those of ISO Latin 9 is undefined.
The values of type unicode are enclosed in double quotes. There are several techniques for entering ISO Latin 9 characters which are not available on the keyboard.
• Pint offers the familiar escaped character sequences. The characters marked * are white space characters.
• Use the techniques offered by your editor, see chapter 2.1.
• Type in the Unicode value in the form U+xyzw: for example Voil`a is typed as "VoilU+00e0". Characters which cannot be typed are expressed by their hexadecimal Unicode numbers.
The characters between the leading " and the trailing " must all be on the same line. You are not allowed to write
116 val msg = "Hello 117 World"
If you need to write a unicodevalue with embedded new lines, either write 118 val msg = "Hello\nWorld"
or
119 val msg = "Hello\n" ... 120 "World"