1.TL 2Program Development under Inferno 3.AU 4Roger Peppé 5rog@vitanuova.com 6.SH 7Introduction 8.PP 9Inferno provides a set of programs that, used in 10combination, provide a powerful development environment 11in which to write Limbo programs. 12.I Limbo (1) 13is the compiler for the Limbo language; there 14are versions that run inside and outside the Inferno 15environment. 16.I Acme (1) 17is an integrated window system and editor, and the 18preferred source-code editing tool within Inferno. 19The Limbo debugger, 20.I wm-debug (1), 21allows interactive inspection of running Limbo programs. 22.I Stack (1) 23allows a quick inspection of the execution stack of a 24currently running process. 25.SH 26Getting started 27.PP 28This document assumes that you have already managed 29to install Inferno and have managed to obtain an Inferno 30window, running the Inferno window manager, 31.I wm (1). 32The document 33\&``Installing Inferno'' in this volume has details on this. 34If running within emu, it is worth giving Inferno 35as large a window as possible, as it cannot be resized later. 36This paper assumes that you are using a three-button mouse, as it is 37not feasible to use Acme without a three-button mouse. 38(if you have a two button mouse with a ``mouse wheel'', 39the wheel can be used as the middle button). 40The first thing to do is to get Acme going. By clicking 41on the Vita Nuova logo at the bottom left of the window, 42you can display a menu naming some preconfigured commands. 43If this has an ``Acme'' entry, then just clicking on that entry 44will start acme. If not, then click on the ``Shell'' entry, 45and type 46.P1 47acme 48.P2 49to start it up. The Acme window should then appear, 50filling most of the screen (the window manager toolbar 51should still be visible). 52.SH 53Acme basics 54.PP 55For a general overview and the rationale behind Acme, see ``Acme: 56A User Interface for Programmers'', elsewhere in this volume, 57and for detailed documentation, see 58.I acme (1). 59The basics are as follows: 60.PP 61Acme windows are text-only and organised into columns. 62A distinctive feature of Acme is that there are no graphical 63title bars to windows; instead, each window (and additionally 64each column, and the whole Acme window itself) has 65a textual 66.I tag , 67which can be edited at will, and is initially primed to contain 68a few appropriate commands. 69.PP 70An Acme command is just represented by text; any textual 71command word may be executed simply by clicking with the middle 72mouse button on the word. (See ``Acme mouse commands'', below). 73If Acme recognizes the word that has been clicked on 74as one of its internal commands (e.g. Put, Undo), then it will take the appropriate 75action; otherwise it will run the text as a shell command. 76(See 77.I sh (1)). 78.SH 79Acme mouse commands 80.PP 81Mouse usage within Acme is somewhat more versatile 82than in most other window systems. Each of the three 83mouse buttons has its own action, and there are also 84actions bound to 85.I chords 86of mouse buttons (i.e. mouse buttons depressed simultaneously). 87Mouse buttons are numbered from left (1) to right (3). 88Button 1 follows similar conventions to other window systems - 89it selects text; a double click will select a line if at the beginning or end 90of a line, or match brackets if on a bracket character, or select 91a word otherwise. 92Button 2, as mentioned above, executes an 93Acme command; a single click with button 2 will execute 94the single word under the click, otherwise the swept text 95will be executed. 96Button 3 is a general ``look'' operator; if the text under the 97click represents a filename, then Acme will open a new 98window for the file and read it in, otherwise it will search 99within the current window for the next occurrence of the 100text. 101Clicking button 2 or button 3 on some text already selected 102by button 1 causes the click to refer exactly to the text 103selected, rather than gathering likely-looking characters 104from around the click as is the default. 105.PP 106There are two mouse chord sequences which are 107commonly used in Acme (and you will find that some 108other programs in the system also recognise these sequences, 109e.g. 110.I wm-sh (1)). 111They are both available once some text 112has been selected by dragging the mouse with button 1, 113but before the button has been released. At this point, 114touching button 2 will delete the selected text and save 115it in Acme's 116.I snarf 117buffer; clicking button 3 replaces the selected text with the contents 118of the snarf buffer. Before button 1 has been released, 119these two buttons reverse each other's actions, so, for 120example, selecting some text with button 1, keeping button 1 121held down, then clicking button 2 and button 3 in succession, 122will save the selected text in the snarf buffer while leaving the 123original intact. 124The following table summarises the mouse commands in 125Acme: 126.KS 127.TS 128center box; 129l l . 130B1 Select text. 131B2 Execute text. 132B3 Open file or search for text. 133B1-B2 Cut text. 134B1-B3 Paste text. 135B2-B3 Cancel the pending B2 action. 136B3-B2 Cancel the pending B3 action. 137.TE 138.ce 139.I "Acme mouse command summary" 140.KE 141 142.SH 143Scrolling and resizing Acme windows 144.PP 145The scroll bars in Acme are somewhat different from 146conventional scroll bars (including the scroll bars found 147in other parts of Inferno). Clicking, or dragging, with 148button-2 on the scrollbar acts the most like the conventional 149behaviour, namely that the further down the scroll bar 150you click, the further down the file you are shown. 151.PP 152True to form, however, Acme doesn't omit to make 153the other buttons useful: button-1 and button-3 154move backwards and forwards through the file respectively. 155The nearer the top of the scrollbar the mouse, the 156slower the movement. Holding one of these buttons 157down on the scrollbar will cause the scrolling motion 158to auto-repeat, so it is easy to scroll gently through the 159entire file, for instance. 160.PP 161The small square at the top left of each Acme window is 162the handle for resizing the window. Dragging this square 163from one place to another (within Acme) will move the 164window to the new place. A single button click in this square 165will grow the window: button 1 grows it a little bit; button 2 166grows it as much as possible without obscuring the other 167window titles in the column; button 3 grows it so it covers 168the whole column (all other windows in the column are 169obscured). 170.SH 171Creating a new file 172.PP 173All Limbo programs are composed of 174.I modules 175and each module is stored in its own file. To write a Limbo 176program, you need to write at least one module, 177the Limbo 178.I "source file" , 179which will then be compiled into Dis code which can 180then be run by the Inferno Virtual Machine (VM). 181The first step is to decide where to store the file. 182When Acme starts up, it creates a new window containing 183a list of all the files in the directory in which it was started 184(usually your home directory). As a consequence of the 185mouse rules above, a click of button-3 on any of those 186filenames in that window will open a new window 187showing that file or, if it is a directory, a list of the 188files and directories it contains. 189.PP 190An important aspect in Acme's mouse commands, is 191that the command is interpreted 192.I "relative to the window's current directory", 193where the current directory is determined from 194the filename in the window's tag. For instance, 195Acme commands executed in the tag or body of 196a window on the file 197.CW "/usr/joebloggs/myfile.txt" 198would run in the directory 199.CW /usr/joebloggs . 200.PP 201So, to create a new file in Acme, first open the 202directory in which to create the file. (If this is 203your home directory, then it's probably already on the screen; 204otherwise, you can just type (anywhere) the name of 205the directory, and button-3 click on it. If the directory 206does not exist, then no window will be created. 207Then, within the directory's window or its tag, 208choose a name, 209.I filename , 210for your file (I'll use 211.CW myprog 212from here on, 213for explanatory convenience) 214, type the text: 215.P1 216New \fIfilename\fP.b 217.P2 218select this text (the Escape key can also be used to highlight 219text that you have just typed), and button-2 click on it. 220This should create a new empty window in which you 221can edit your Limbo source file. It will also create a 222window giving a warning that the file does not 223currently exist - you can get rid of this by clicking 224with button-2 on the text 225.CW Del 226in the tag of that window. 227.SH 228Editing the source file 229.PP 230You can now edit text in the new window. 231Type in the following program: 232.P1 233implement Myprog; 234include "sys.m"; 235 sys: Sys; 236include "draw.m"; 237 238Myprog: module { 239 init: fn(nil: ref Draw->Context, argv: list of string); 240}; 241 242init(nil: ref Draw->Context, argv: list of string) 243{ 244 sys = load Sys Sys->PATH; 245 sys->print("Hello, world\en"); 246} 247.P2 248When typing it in, note that two new commands have appeared 249in the tag of the new window: 250.CW Put 251and 252.CW Undo . 253.CW Put 254saves the file; 255.CW Undo 256undoes the last change to the file, and successive 257executions of 258.CW Undo 259will move further back in time. In case you move 260too far back accidentally, there is also 261.CW Redo , 262which redoes a change that you have just undone. 263Changes in the body of any window in Acme can be undone 264this way. 265.PP 266Click with button-2 on the 267.CW Put 268command, and the file is now saved and ready to be 269compiled. If you have problems at this point (say 270Acme complains about not being able to write the 271file), you have probably chosen an inappropriate 272directory, one in which you do not have write permission, 273in which to put the file. In this case you can change the 274name of the file simply by editing its name in the window's 275tag, and clicking on 276.CW Put 277again. 278.SH 279Compiling the source file 280.PP 281Now, you are in a position to compile the Limbo program. 282Although you can execute the Limbo compiler directly 283from the tag of the new file's window, it is usually more 284convenient to do it from a shell window. To start a shell 285window, type 286.CW win '' `` 287at the right of the tag of the new file's window, select 288it, and click with button-2 on it. 289A new window should appear showing a shell prompt (usually 290.CW "; " '' `` 291or 292.CW "% " ''). `` 293At this, you can type any of the commands mentioned 294in Section 1 of the Programmer's Manual. 295Note that, following Acme's usual rule, the shell has 296started up in the same directory as the new file; 297typing 298.P1 299lc 300.P2 301at the prompt will show all the files in the directory, 302including hopefully the newly written Limbo file. 303.PP 304Type the following command to the shell: 305.P1 306limbo -g myprog.b 307.P2 308If you typed in the example program correctly, 309then you'll get a short pause, and then another shell 310prompt. This indicates a successful compilation (no 311news is good news), in which case you will now have 312two new files in the current directory, 313.CW myprog.sbl 314and 315.CW myprog.dis . 316The 317.CW -g 318option to the 319.CW limbo 320command directed it to produce the 321.CW myprog.sbl 322file, which contains symbolic information 323relating the source code to the Dis executable file. 324The 325.CW myprog.dis 326file contains the actual executable file. 327At this point, if you type 328.CW lc , 329to get a listing of the files in the current directory, 330and then click with button-2 on the 331.CW myprog.dis 332file, and you should see the output ``Hello, world''. 333You could also just type 334.CW myprog 335at the shell prompt. 336.PP 337If you are normal, however, the above compilation 338probably failed because of some mistyped characters 339in the source code; and for larger newly created programs, 340in my experience, this 341is almost invariably the case. 342If you got no errors in the above 343compilation, try changing 344.CW sys->print 345to 346.CW print , 347saving the file again, 348and continue with the next section. 349.SH 350Finding compilation errors 351.PP 352When the Limbo compiler finds errors, it prints 353the errors, one per line, each one looking something 354like the following: 355.P1 356myprog.b:13: print is not declared 357.P2 358This shows the filename where the error has occurred, 359its line number in the file, and a description of the error. 360Acme's button-3 mouse clicking makes it extremely easy 361to see where in the source code the error has occurred. 362Click with button-3 anywhere in the filename on the 363line of the compilation error, and Acme will automatically 364take the cursor to the file of that name and highlight 365the correct line. 366.PP 367If there had been no currently appropriate open Acme 368window representing the file, then a new one would 369be created, and the appropriate line selected. 370.PP 371Edit 372.CW myprog.b 373until you have a program that compiles successfully 374and produces the ``Hello, world'' output. 375For a program as simple as this, that's all there 376is to it - you now know the essential stages involved in 377writing a Limbo program; there's just the small matter 378of absorbing the Limbo language and familiarising 379yourself with the libraries (``The Limbo Programming Language'' 380elsewhere in this volume, 381and 382.I intro (2) 383are the two essential starting points here). 384.SH 385Finding run-time errors 386.PP 387For larger programs, there is the problem of programs 388that die unexpectedly with a run-time error. This 389will happen when, for instance, a Limbo program uses a reference 390that has not been initialised, or refers to an out-of-bounds 391array element. 392.PP 393When a Limbo program dies with a run-time exception, 394it does not go away completely, but remains hanging 395around, dormant, in a 396.I broken 397state; the state that it was in when it died may 398now be examined at leisure. To experiment with this, 399edit the Myprog module above to delete the line 400that loads the 401.CW Sys 402module 403.CW "sys = load Sys" ...), ( 404and recompile the program. 405.PP 406This time when you come to run 407.CW myprog , 408it will die, printing a message like: 409.P1 410sh: 319 "Myprog":module not loaded 411.P2 412The number 413.CW 319 414is the 415.I "process id" 416(or just 417.I pid ) 418of the broken process. The command 419.CW ps , 420which shows all currently running processes, 421can be used at this point - you will see a line like this: 422.P1 423 319 245 rog broken 64K Myprog 424.P2 425The first number is the pid of the process; 426the second is the 427.I "process group" 428id of the process; the third field gives the 429owner of the process; the fourth gives its state 430(broken, in this case); the fifth shows the current 431size of the process, and the last gives the name 432of the module that the process is currently running. 433.PP 434The 435.CW stack 436command can be used to quickly find the line 437at which the process has broken; type: 438.P1 439 stack \fIpid\fP 440.P2 441where 442.I pid 443is the number mentioned in the ``module not loaded'' 444message (319 in this case). 445It produces something like the following output: 446.P1 447init() myprog.b:12.1, 29 448unknown fn() Module /dis/sh.dis PC 1706 449.P2 450As usual, a quick button-3 click on the 451.CW myprog.b 452part of the first line takes you to the appropriate 453part of the source file. The reason that the program 454has died here is that, in Limbo, all external modules 455must be explicitly loaded before they can be used; to 456try to call an uninitialised module is an error 457and causes an exception. 458.SH 459More sophisticated debugging 460.PP 461.CW Stack 462is fine for getting a quick summary of the state 463in which a program has died, but there are 464times when such a simple post-mortem analysis 465is inadequate. The 466.CW wm/deb 467(see 468.I wm-deb\fR(1))\fP 469command provides an interactive windowing 470debugger for such occasions. 471It runs outside Acme, 472in the default window system. A convenient way 473to start debugging an existing process is 474to raise 475.CW wm/task 476(``Task Manager'' on the 477main menu), select with the mouse the process 478to debug, and click ``Debug''. This will start 479.CW wm/deb 480on that process. Before it can start, the debugger will ask 481for the names of any source files that it has not been 482able to find (usually this includes the source for 483the shell, as the module being debugged is often 484started by the shell, and so the top-level function will 485be in the shell's module). 486.PP 487.CW Wm/deb 488can be used to debug multiple threads, to inspect 489the data structures in a thread, and to interactively 490step through the running of a thread (single stepping). 491See 492.I wm-deb (1) 493for details. 494 495\" further afield? 496\" other development tools? 497\" tools to come? 498