1...FP lucidasans 2...FP palatino 3.FP palatino 4." .fp 6 RR R 5.nr PI 2n 6.de P1 7.DS L 8.ft CW 9.ps -1 10.vs -1u 11.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i 6.75i 7.5i 12.. 13.de P2 14.ft R 15.ps +1 16.vs +1u 17.DE 18.. 19.de s1 20.DS 21.br 22.ft I 23.. 24.de s2 25.br 26.DE 27.ft R 28.. 29...ds CF "Copyright 2000 Lucent Technologies Inc. Modifications Vita Nuova Limited. 30.TL 31The Limbo Programming Language 32.AU 33Dennis M. Ritchie 34.br 35(Revised 2005 by Vita Nuova) 36.SP .5i exactly 37.PP 38Limbo is a programming language intended for applications 39running distributed systems on small computers. 40It supports modular programming, 41strong type checking at compile- and run-time, 42interprocess communication over typed channels, 43automatic garbage collection, 44and simple abstract data types. 45It is designed for safe execution even on 46small machines without hardware memory protection. 47.PP 48In its implementation for the Inferno operating system, 49object programs generated by the Limbo compiler run 50using an interpreter for a fixed virtual machine. 51Inferno and its accompanying virtual machine run either stand-alone 52on bare hardware 53or as an application under conventional operating systems like 54Unix, Windows 2000, Linux, FreeBSD, MacOSX, and Plan 9. 55For most architectures, including 56Intel x86, ARM, PowerPC, MIPS and Sparc, Limbo object programs 57are transformed on-the-fly into instructions for the underlying hardware. 58.NH 1 59Overview and introduction 60.PP 61A Limbo application consists of one or more 62.I modules , 63each of which supplies an interface declaration and 64an implementation part. 65A module that uses another module 66includes its declaration part. 67During 68execution, a module dynamically attaches another module by 69stating the other module's type identifier and a place from which to load 70the object code for its implementation. 71.PP 72A module declaration specifies the functions and data it will make visible, 73its data types, and constants. 74Its implementation part defines the functions and data visible at its interface and 75any functions associated with its data types; 76it may also contain definitions for functions used only internally and 77for data local to the module. 78.PP 79Here is a simple module to illustrate the flavour of the language. 80.P1 811 implement Command; 82 832 include "sys.m"; 843 include "draw.m"; 85 864 sys: Sys; 87 885 Command: module 89 { 906 init: fn (ctxt: ref Draw->Context, argv: list of string); 917 }; 92.P2 93.P1 948 # The canonical "Hello world" program, enhanced 959 init(ctxt: ref Draw->Context, argv: list of string) 9610 { 9711 sys = load Sys Sys->PATH; 9812 sys->print("hello world\en"); 9913 for (; argv!=nil; argv = tl argv) 10014 sys->print("%s ", hd argv); 10115 sys->print("\en"); 10216 } 103.P2 104A quick glance at the program reveals that 105the syntax of Limbo is influenced by C in its expressions, 106statements, and some conventions (for example, look at lines 13-14), 107and also by Pascal and its successors (the declarations on lines 4, 6, 9). 108When executed in the Inferno environment, the program writes 109.CW hello 110.CW world 111somewhere, then echoes its arguments. 112.PP 113Let's look at the program line-by-line. 114It begins (line 1) by saying that this is the implementation of module 115.CW Command . 116Line 2 includes a file (found in a way analogous to C's 117.CW #include 118mechanism) named 119.CW sys.m . 120This file defines the interface to module 121.CW Sys ; 122.ds CF 123it says, in part, 124.P1 125Sys: module { 126 PATH: con "$Sys"; 127 . . . 128 print: fn (s: string, *): int; 129 . . . 130}; 131.P2 132This declares 133.CW Sys 134to be the type name for a module containing among other things a 135function named 136.CW print ; 137the first argument of 138.CW print 139is a string. 140The 141.CW * 142in the argument list specifies that further arguments, of 143unspecified type, may be given. 144.PP 145Line 3 includes 146.CW draw.m ; 147only one piece of information, mentioned below, 148is used from it. 149Line 4 declares the variable 150.CW sys 151to be of type 152.CW Sys ; 153its name will be visible throughout the remainder of the file 154describing this module. 155It will be used later to refer to an instance of the 156.CW Sys 157module. 158This declaration initializes it to 159.CW nil ; 160it still needs to be set to a useful value. 161.PP 162Lines 5-7 constitute the declaration of 163.CW Command , 164the module being implemented. 165It contains only a function named 166.CW init , 167with two arguments, a 168.CW ref 169.CW Draw->Context 170and a list of strings, 171and it doesn't 172return any value. 173The 174.CW ref 175.CW Draw->Context 176argument would be used if the program did any 177graphics; it is a data type defined in 178.CW draw.m 179and refers to the display. 180Since the program just writes text, it won't be used. 181The 182.CW init 183function isn't special to the Limbo language, 184but it is conventional in the environment, 185like 186.CW main 187in C. 188.PP 189In a module designed to be useful 190to other modules in an application, it would be wise to 191take the module declaration for 192.CW Command 193out, put it in a separate file called 194.CW command.m 195and use 196.CW "include 197.CW command.m 198to allow this module and others to refer to it. 199It is called, for example, by the program loader in the Inferno 200system to start the execution of applications. 201.PP 202Line 8 is a comment; everything from the 203.CW # 204to the end of line is ignored. 205.PP 206Line 9 begins the definition for the 207.CW init 208function that was promised in the module's declaration 209(line 6). 210The argument that is a list of strings is named 211.CW argv . 212.PP 213Line 11 connects the program 214being written to the 215.CW Sys 216module. 217The first token after 218.CW load 219is the target module's name as defined by its interface 220(here found in the 221.CW include 222on line 2) 223The next token is the place 224where the code for the module can be found; it is a string 225that usually names a file. 226Conventionally, in the Inferno system, 227each module contains a constant declaration for the name 228.CW PATH 229as a string that names the file where 230the object module can be found. 231Loading the file is performed dynamically during 232execution except for a few modules built 233into the execution environment. 234(These include 235.CW Sys ; 236this accounts for the peculiar file name 237.CW "$Sys" 238as 239the value of 240.CW PATH .) 241.PP 242The value of 243.CW load 244is a reference to the 245named module; line 11 assigns it 246to the variable 247.CW sys 248for later use. 249The 250.CW load 251operator dynamically loads the code for the named 252module if it is not already present and instantiates 253a new instance of it. 254.PP 255Line 12 starts the work by printing a familiar message, 256using the facilities provided by module 257.CW Sys 258through its handle 259.CW sys ; 260the notation 261.CW sys->print(...) 262means to call the 263.CW print 264function of the module referred to by 265.CW sys . 266The interface of 267.CW Sys 268resembles a binding to some of 269the mechanisms of Unix and the ISO/ANSI C library. 270.PP 271The loop at lines 13-14 takes the 272.CW "list 273.CW of 274.CW string 275argument to 276.CW init 277and iterates over it using the 278.CW hd 279(head) and 280.CW tl 281(tail) operators. 282When executed, this module combines the 283traditional `Hello world' and 284.CW echo . 285.NH 1 286Lexical conventions 287.PP 288There are several kinds of tokens: 289keywords, identifiers, constants, strings, expression operators, 290and other separators. 291White space (blanks, tabs, new-lines) is ignored except that 292it serves to separate tokens; sometimes it is required 293to separate tokens. 294If the input has been parsed into tokens up to a particular 295character, the next token is taken to include the longest 296string of characters that could constitute a token. 297.PP 298The native character set of Limbo is Unicode, 299which is identical with the first 16-bit plane of the ISO 10646 standard. 300Any Unicode character may be used in comments, or in strings 301and character constants. 302The implementation assumes that source files use the UTF-8 representation, 303in which 16-bit Unicode characters are represented as sequences 304of one, two, or three bytes. 305.NH 2 306Comments 307.PP 308Comments begin with the 309.CW # 310character and extend to the end of the line. 311Comments are ignored. 312.NH 2 313Identifiers 314.PP 315An identifier is a sequence of letters and digits 316of which the first is a letter. 317Letters are the Unicode characters 318.CW a 319through 320.CW z 321and 322.CW A 323through 324.CW Z , 325together with the underscore character, and 326all Unicode characters with encoded values greater than 160 327(A0 hexadecimal, the beginning of the range corresponding to Latin-1). 328.PP 329Only the first 256 characters in an identifier 330are significant. 331.NH 2 332Keywords 333.PP 334The following identifiers are reserved for use as keywords, 335and may not be used otherwise: 336.P1 337.ta 1i 2i 3i 4i 5i 338 adt alt array big 339 break byte case chan 340 con continue cyclic do 341 else exit fn for 342 hd if implement import 343 include int len list 344 load module nil of 345 or pick real ref 346 return self spawn string 347 tagof tl to type 348 while 349.P2 350The word 351.CW union 352is not currently used by the language. 353.NH 2 354Constants 355.PP 356There are several kinds of constants for denoting values of the 357basic types. 358.PP 359.NH 3 360Integer constants 361.PP 362Integer constants have type 363.CW int 364or 365.CW big . 366They can be represented in several ways. 367.PP 368Decimal integer constants consist of a sequence of decimal 369digits. 370A constant with an explicit radix 371consists of a decimal radix followed by 372.CW R 373or 374.CW r 375followed by the digits of the number. 376The radix is between 2 and 36 inclusive; 377digits above 10 in the number 378are expressed using letters 379.CW A 380to 381.CW Z 382or 383.CW a 384to 385.CW z . 386For example, 387.CW 16r20 388has value 32. 389.PP 390The type of a decimal or explicit-radix number is 391.CW big 392if its value exceeds 393.CW 2\u31\d\(mi1 , 394otherwise it is 395.CW int . 396.PP 397Character constants consist of a single Unicode 398character enclosed within single-quote characters 399.CW ' . 400Inside the quotes the following escape sequences represent 401special characters: 402.DS 403\f(CW\e\e\fR backslash 404\f(CW\e'\fR single quote 405\f(CW\e"\fR double quote 406\f(CW\ea\fR bell (BEL) 407\f(CW\eb\fR backspace (BS) 408\f(CW\et\fR horizontal tabulation (HT) 409\f(CW\en\fR line feed (LF) 410\f(CW\ev\fR vertical tabulation (VT) 411\f(CW\ef\fR form feed (FF) 412\f(CW\er\fR carriage return (CR) 413\f(CW\eu\fIdddd \fRUnicode character named by 4 hexadecimal digits 414\f(CW\e0\fR NUL 415.DE 416Character constants have type 417.CW int . 418.NH 3 419Real constants 420.PP 421Real constants consist of a sequence of decimal digits 422containing one period 423.CW . 424and optionally followed by 425.CW e 426or 427.CW E 428and then by a possibly signed integer. 429If there is an explicit exponent, the period is 430not required. 431Real constants have type 432.CW real . 433.NH 3 434Strings 435.PP 436String constants are sequences of Unicode characters contained in double 437quotes. 438They cannot extend across source lines. 439The same escape sequences listed above for character 440constants are usable within string constants. 441.PP 442Raw (uninterpreted) string constants are sequences of Unicode characters 443contained in backquotes. 444They can extend across source lines and thus include newlines. 445They contain no character escapes. 446The only character that cannot appear inside an uninterpreted string is a backquote, because that delimits the string. 447.PP 448Both forms of string constant have type 449.CW string . 450.NH 3 451The nil constant 452.PP 453The constant 454.CW nil 455denotes a reference to nothing. 456It may be used where an object of a reference 457type is expected; 458otherwise uninitialized values of reference type 459start off with this value, it can be assigned to 460reference objects, and reference types can be 461tested for equality with it. 462(The keyword has other uses as well.) 463.NH 2 464Operators and other separators 465.PP 466The operators are 467.P1 468.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6.0i 6.5i 469 + - * / % & | ^ 470 == < > <= >= != << >> 471 && || <- :: 472 = += -= *= /= %= &= |= ^= <<= >>= 473 := 474 ~ ++ -- ! ** 475.P2 476The other separators are 477.P1 478.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 479 : ; ( ) { } [ ] 480 , . -> => 481.P2 482.NH 1 483Syntax notation 484.PP 485In this manual, Limbo syntax is described by a modified BNF 486in which syntactic categories are named in an 487.I italic 488font, and literals in 489.CW typewriter 490font. 491Alternative productions are listed on separate lines, and 492an optional symbol is indicated with 493the subscript ``opt.'' 494.NH 1 495Types and objects 496.PP 497Limbo has three kinds of objects. 498.I Data 499objects exist in the storage associated with 500a module; they can be manipulated by arithmetic operations, 501assignment, selection of component entities, and other concrete 502operations. 503Each data object has a type that determines what can be stored 504in it and what operations are applicable. 505.PP 506The second kind of object is the 507.I function . 508Functions are characterized by the types of the arguments they 509accept and the values they return, and are associated with 510the modules in which they are defined. 511Their names can be made visible in their module's declaration, 512or they can be encapsulated within the 513.CW adt 514(abstract data types) of their modules, 515or they can exist privately within their module. 516.PP 517Finally, Limbo programs are organized into 518.I modules : 519a named collection of constants, abstract data types, 520data, and functions made available by that module. 521A module declaration displays the 522members visible to other modules; 523the module's implementation 524defines both the publicly visible members and its 525private parts, including the data objects it uses. 526A module that wishes to use 527the facilities of another includes its declaration in order to 528understand what it exports, but 529before using them it explicitly loads the new module. 530.NH 2 531Types 532.PP 533Limbo has several basic types, some built-in higher abstractions, 534and other ways of composing new types. 535In declarations and some other places, constructions naming 536a type are used. 537The syntax is: 538.s1 539type: 540 data-type 541 function-type 542.s2 543Functions will be discussed in §7 below. 544First, data types will be explored. 545.NH 2 546Data types 547.PP 548The syntax of data types is 549.s1 550data-type: 551 CbyteI 552 CintI 553 CbigI 554 CrealI 555 CstringI 556 tuple-type 557 Carray of Idata-type 558 Clist of Idata-type 559 Cchan of Idata-type 560 adt-type 561 Cref Iadt-type 562 Cref Ifunction-type 563 module-type 564 module-qualified-type 565 type-name 566 567data-type-list: 568 data-type 569 data-type-list C,I data-type 570.s2 571Objects of most data types have 572.I value 573semantics; when they 574are assigned or passed to functions, the destination receives a copy of the 575object. 576Subsequent changes to the assigned object itself have no effect on 577the original object. 578The value types are 579.CW byte , 580.CW int , 581.CW big , 582.CW real , 583.CW string , 584the 585.CW tuple 586types, and 587abstract data types or 588.CW adt . 589The rest have 590.I reference 591semantics. 592When they are assigned, the quantity actually assigned 593is a reference to (a pointer to) an underlying object 594that is not copied; thus changes or operations on 595the assigned value affect the original object. 596Reference types include lists, arrays, channels, modules, 597.CW ref 598.CW adt , 599and 600.CW ref 601.CW fn 602types. 603.NH 3 604Basic types 605.PP 606The five basic data types are denoted by 607.CW byte , 608.CW int , 609.CW big , 610.CW real , 611and 612.CW string . 613.PP 614Bytes are unsigned 8-bit quantities. 615.PP 616Integers 617.CW int ) ( 618are 32-bit signed quantities represented in two's complement 619notation. 620Large integers 621.CW big ) ( 622are 64-bit signed quantities represented in two's complement notation. 623.PP 624Real numbers 625.CW real ) ( 626are 64-bit quantities represented in the 627IEEE long floating notation. 628.PP 629The 630.CW byte , 631.CW int , 632.CW big , 633and 634.CW real 635types are collectively called arithmetic types. 636.PP 637Strings are rows of Unicode characters. 638They may be concatenated and extended character-by-character. 639When a string is indexed with a single subscript, it yields an integer 640with the Unicode encoding of the character; 641when it is indexed by a range, it yields another string. 642.NH 3 643Tuple type 644.PP 645The 646.I tuple 647type, denoted 648.s1 649tuple-type: 650 C( Idata-type-listC )I 651.s2 652is a type consisting of an ordered collection of two or more objects, 653each having its own data type. 654For each tuple type, the types of the members are 655fixed, but need not be identical; 656for example, a function might return a tuple containing 657an integer and a string. 658Each tuple type is characterized solely by the 659the order and identity of the types it contains. 660Objects of tuple type may be assigned to a list of identifiers (to pick out the 661components), and a parenthesized, comma-separated list of expressions 662denotes a tuple. 663.NH 3 664Array types 665.PP 666The 667.I array 668type describes a dynamically-sized row of objects, all of the same 669type; it is indexed starting from 0. 670An array type is denoted by 671.s1 672 Carray of Idata-type 673.s2 674The size of an array is not part of its type; instead 675it is part of the value. 676The 677.I data-type 678may itself be an array, to achieve a multidimensional array. 679.NH 3 680List types 681.PP 682A 683.I list 684is a sequence of like-typed objects; its denotation is 685.s1 686 Clist of Idata-type 687.s2 688A list is a stack-like object, optimized for 689a few operations: get the head (the first object), 690get the tail (the rest of the list), place an object at the beginning. 691.NH 3 692Channel types 693.PP 694A 695.I channel , 696whose type is written 697.s1 698 Cchan of Idata-type 699.s2 700is a communication mechanism capable of sending and receiving objects of the 701specified type to another agent in the system. 702Channels may be used to communicate between local processes; 703using library procedures, they may be connected 704to named destinations. 705In either case 706.I send 707and 708.I receive 709operations may be directed to them. 710For example, 711.P1 712 chan of (int, string) 713.P2 714is the type of a channel that transmits tuples consisting of 715an integer and an string. 716Once an instance of such a channel (say 717.CW c ) 718has been declared and initialized, 719the statement 720.P1 721 c <-= (123, "Hello"); 722.P2 723sends such a tuple across it. 724.NH 3 725Abstract data types 726.PP 727An abstract data type or 728.I adt 729is an object that can contain data objects of several 730different types and declare 731functions that operate on them. 732The syntax for declaring an 733.CW adt 734is given later. 735Once an 736.CW adt 737has been declared, the identifier associated with it 738becomes a data-type name. 739.s1 740adt-type: 741 identifier 742 module-qualified-type 743.s2 744.PP 745There is also a 746.CW ref 747.CW adt 748type representing a reference (pointer) to an 749.CW adt . 750It is denoted 751.s1 752 Cref Iadt-type 753.s2 754where the identifier is the name of an 755.CW adt 756type. 757.NH 3 758Module types 759.PP 760A module type name is an identifier: 761.s1 762module-type: 763 identifier 764.s2 765The identifier is declared as a module identifier by a 766.I module-declaration , 767as described in §6.5 below. 768An object of module type serves as a handle for the 769module, and is used to access its functions. 770.NH 3 771Module-qualified type 772.PP 773When an 774.CW adt 775is declared within a module declaration, the type name of that 776.CW adt 777is not generally visible to the rest of the program unless a specific 778.CW import 779request is given (see §6.6, §10 below). 780Without such a request, when 781.CW adt 782objects implemented by a module are declared by a client 783of that module, the 784.CW adt 785type name is qualified: 786.s1 787module-qualified-type: 788 identifier C->I identifier 789.s2 790Here the first identifier is either the name of a module 791or a variable of the module type; 792the second is the name of a type 793mentioned in the module declaration. 794.NH 3 795Function reference types 796.PP 797A function reference type represents a reference to a function of a given type. 798It is written as 799.s1 800 Cref Ifunction-type 801.s2 802Function types are discussed in §4.3 below. 803.NH 3 804Named types 805.PP 806Finally, data types may be named, using a 807.CW type 808declaration; this is discussed in §6.4 below. 809.s1 810type-name: 811 identifier 812.s2 813.NH 2 814Function types 815.PP 816A function type characterizes the arguments and return value of 817a function. The syntax is 818.s1 819function-type: 820 Cfn Ifunction-arg-ret 821 822function-arg-ret: 823 C( Iformal-arg-listOC ) IraisesO 824 C( Iformal-arg-listOC ) : Idata-type raisesO 825 826formal-arg-list: 827 formal-arg 828 formal-arg-listC , Iformal-arg 829 830formal-arg: 831 nil-or-ID-listC : Itype 832 nil-or-IDC : self refO Iidentifier 833 nil-or-IDC : self Iidentifier 834 C*I 835 836nil-or-ID-list: 837 nil-or-ID 838 nil-or-ID-list C, Inil-or-ID 839 840nil-or-ID: 841 identifier 842 CnilI 843 844raises: 845 Craises ( Inil-or-ID-listC )I 846 CraisesI nil-or-ID 847 848.s2 849That is, the denotation of a function type has the keyword 850.CW fn 851followed by a comma-separated list of its arguments 852enclosed in parentheses, 853and perhaps followed by the type the function returns. 854Absence of a return value means that the function returns no 855value: it is a procedure. 856The names and types of arguments are specified. 857However, the name of an argument may be replaced by 858.CW nil ; 859in this case it is nameless. 860For example, 861.P1 862 fn (nil: int, nil: int): int 863 fn (radius: int, angle: int): int 864 fn (radius, angle: int): int 865.P2 866all denote exactly the same type, 867namely a function of two integers that returns an integer. 868As another example, 869.P1 870 fn (nil: string) 871.P2 872is the type of a function that takes a string argument 873and returns no value. 874.PP 875The 876.CW self 877keyword has a specialized use within 878.CW adt 879declarations. 880It may be used only for the first argument 881of a function declared within an 882.CW adt ; 883its meaning is discussed in §6.3 below. 884.PP 885The star character 886.CW * 887may be given as the last argument in a function type. 888It declares that 889the function is variadic; during a call, actual arguments at its 890position and following are passed in a manner 891unspecified by the language. 892For example, the type of the 893.CW print 894function of the 895.CW Sys 896module is 897.P1 898 fn (s: string, *): int 899.P2 900This means that the first argument of 901.CW print 902is a string and that other arguments may be given when the function 903is called. 904The Limbo language itself has no way of accessing these arguments; 905the notation is an artifice for describing facilities 906built into the runtime system, such as the 907.CW Sys 908module. 909.PP 910The type of a function includes user-defined exceptions that it raises, 911which must be listed in a corresponding 912.CW raises 913clause. 914.NH 1 915Limbo programs 916.PP 917Limbo source programs that implement modules are stored in files, 918conventionally named with the suffix 919.CW .b . 920Each such file begins with a single 921.CW implement 922directive naming the type of the module being implemented, 923followed by a sequence of declarations. 924Other files, conventionally named with the suffix 925.CW .m , 926contain declarations for things obtainable from other modules. 927These files are incorporated by an 928.CW include 929declaration in the implementation modules that need them. 930At the top level, a program consists of a sequence 931of declarations. 932The syntax is 933.s1 934program: 935 Cimplement Iidentifier-listC ; Itop-declaration-sequence 936 937top-declaration-sequence: 938 top-declaration 939 top-declaration-sequence top-declaration 940 941top-declaration: 942 declaration 943 identifier-listC := IexpressionC ;I 944 identifier-listC = IexpressionC ;I 945 C( Iidentifier-listC ) := IexpressionC ;I 946 module-declaration 947 function-definition 948 adt-declaration 949.s2 950The 951.CW implement 952declaration at the start identifies the type of the module that 953is being implemented. 954The rest of the program consists of a sequence of various kinds of 955declarations and definitions that announce the names 956of data objects, types, and functions, and also create 957and initialize them. 958It must include a module declaration for the module 959being implemented and the objects it announces, 960and may also include declarations for the functions, data 961objects, types, and constants used privately within the module 962as well as declarations for modules used by it. 963.PP 964Declarations are used both at the top 965level (outside of functions) and also inside functions 966and module declarations. 967Some styles of declaration 968are allowed only in certain of these places, 969but all will be discussed together. 970.PP 971Most implementation modules provide an implementation for one type of module. 972Several module types may be listed, however, in the 973.CW implement 974declaration, when the implementation module implements them all. 975When the same name appears in more than one such module type, it must 976have the same type. 977.NH 1 978Declarations 979.PP 980Declarations take several forms: 981.s1 982declaration: 983 identifier-listC : ItypeC ;I 984 identifier-listC : ItypeC = IexpressionC ;I 985 identifier-listC : con IexpressionC ;I 986 Iidentifier-listC : import Iidentifier C;I 987 identifier-listC : typeI typeC ;I 988 identifier-listC : exceptionI tuple-typeO 989 Cinclude Istring-constantC ;I 990 991identifier-list: 992 identifier 993 identifier-listC , Iidentifier 994 995expression-list: 996 expression 997 expression-listC , Iexpression 998.s2 999.NH 2 1000Data declarations 1001.PP 1002These forms constitute the basic way to declare and 1003initialize data: 1004.s1 1005 identifier-listC : ItypeC ;I 1006 identifier-listC : ItypeC = IexpressionC ;I 1007.s2 1008A comma-separated sequence of identifiers is followed by a colon 1009and then the name of a type. 1010Each identifier is declared as having that type and denotes a 1011particular object 1012for rest of its scope (see §11 below). 1013If the declaration contains 1014.CW = 1015and an expression, the type must be a data type, and 1016all the objects are initialized from 1017the value of the expression. 1018In a declaration at the top level 1019(outside of a function), the expression must be 1020constant (see §8.5) or an array initialized with constant expressions; 1021the bound of any array must be a constant expression. 1022Lists and 1023.CW ref 1024.CW adt 1025types may not be initialized at the top level. 1026If an object is not explicitly initialized, then 1027it is always set to 1028.CW nil 1029if it has a reference type; 1030if it has arithmetic type, then it is set to 0 1031at the top level and is undefined if it occurs 1032within a function. 1033.PP 1034For example, 1035.P1 1036 i, j: int = 1; 1037 r, s: real = 1.0; 1038.P2 1039declares 1040.CW i 1041and 1042.CW j 1043as integers, 1044.CW r 1045and 1046.CW s 1047as real. 1048It sets 1049.CW i 1050and 1051.CW j 1052to 1, 1053and 1054.CW r 1055and 1056.CW s 1057to 1.0. 1058.PP 1059Another kind of declaration is a shorthand. 1060In either of 1061.s1 1062 identifierC := IexpressionC ;I 1063 C( Iidentifier-listC ) := IexpressionC ;I 1064 1065.s2 1066identifiers on the left are declared using the type of the expression, 1067and are initialized with the value of the expression. 1068In the second case, the expression must be a tuple or an 1069.CW adt , 1070and the types and values attributed to the identifiers 1071in the list are taken from the members of the tuple, or the 1072data members of the 1073.CW adt 1074respectively. 1075For example, 1076.P1 1077 x: int = 1; 1078.P2 1079and 1080.P1 1081 x := 1; 1082.P2 1083are the same. 1084Similarly, 1085.P1 1086 (p, q) := (1, 2.1); 1087.P2 1088declares the identifiers on the left as 1089.CW int 1090and 1091.CW real 1092and initializes them to 1 and 2.1 respectively. 1093Declarations with 1094.CW := 1095can also be expressions, and are discussed again in §8.4.4 below. 1096.NH 2 1097Constant declarations 1098.PP 1099The 1100.CW con 1101declaration 1102.s1 1103 Iidentifier-listC : conI expressionC ;I 1104.s2 1105declares a name (or names) for constants. 1106The 1107.I expression 1108must be constant (see §8.5). 1109After the declaration, 1110each identifier in the list may be used anywhere a constant 1111of the appropriate type is needed; 1112the type is taken from the type of the constant. 1113For example, after 1114.P1 1115 Seven: con 3+4; 1116.P2 1117the name 1118.CW Seven 1119is exactly the same as the constant 7. 1120.PP 1121The identifier 1122.CW iota 1123has a special meaning in the expression in a 1124.CW con 1125declaration. 1126It is equivalent to the integer constant 1127.CW 0 1128when evaluating the expression for the first (leftmost) identifier declared, 1129.CW 1 1130for the second, and so on numerically. 1131For example, the declaration 1132.P1 1133 M0, M1, M2, M3, M4: con (1<<iota); 1134.P2 1135declares several constants 1136.CW M0 1137through 1138.CW M4 1139with the values 1, 2, 4, 8, 16 respectively. 1140.PP 1141The identifier 1142.CW iota 1143is not reserved except inside the expression 1144of the 1145.CW con 1146declaration. 1147.NH 2 1148adt declarations 1149.PP 1150An 1151.CW adt 1152or abstract data type contains data objects and functions that 1153operate on them. 1154The syntax is 1155.s1 1156adt-declaration: 1157 IidentifierC : adt { Iadt-member-listOC } ;I 1158 1159adt-member-list: 1160 adt-member 1161 adt-member-list adt-member 1162 1163adt-member: 1164 identifier-listC : cyclicO Idata-typeC ;I 1165 identifier-listC : con IexpressionC ;I 1166 identifier-listC : Ifunction-typeC ;I 1167 Cpick { Ipick-member-listC }I 1168.s2 1169After an 1170.I adt-declaration , 1171the identifier becomes the name of the type of that 1172.CW adt . 1173For example, after 1174.P1 1175 Point: adt { 1176 x, y: int; 1177 add: fn (p: Point, q: Point): Point; 1178 eq: fn (p: Point, q: Point): int; 1179 }; 1180.P2 1181the name 1182.CW Point 1183is a type name for an 1184.CW adt 1185of two integers and two 1186functions; the fragment 1187.P1 1188 r, s: Point; 1189 xcoord: int; 1190 ... 1191 xcoord = s.x; 1192 r = r.add(r, s); 1193.P2 1194makes sense. 1195The first assignment selects one of the data members of 1196.CW s ; 1197the second calls one of the function members of 1198.CW r . 1199.PP 1200As this example indicates, 1201.CW adt 1202members are accessed by mentioning an object with the 1203.CW adt 1204type, a dot, and then the name of the member; 1205the details will be discussed in §8.13 below. 1206A special syntactic indulgence is available for functions declared within an 1207.CW adt : 1208frequently such a function 1209receives as an argument the same object used to access it 1210(that is, the object before the dot). 1211In the example just above, 1212.CW r 1213was both the object being operated on and the first argument to the 1214.CW add 1215function. 1216If the first formal argument of a function declared in an 1217.CW adt 1218is marked with the 1219.CW self 1220keyword, then in any calls to the function, the 1221.CW adt 1222object is implicitly passed to the function, and 1223is not mentioned explicitly in the actual argument list 1224at the call site. 1225For example, in 1226.P1 1227 Rect: adt { 1228 min, max: Point; 1229 contains: fn(r: self Rect, p: Point): int; 1230 }; 1231 1232 r1: Rect; 1233 p1: Point; 1234 ... 1235 if (r1.contains(p1)) ... 1236.P2 1237because the first argument of the 1238.CW contains 1239function is declared with 1240.CW self , 1241the subsequent call to it automatically passes 1242.CW r1 1243as its first argument. The 1244.CW contains 1245function itself is defined elsewhere with this first 1246argument explicit. 1247(This mechanism is analogous to the 1248.I this 1249construct in C++ and other languages, 1250but puts the special-casing at the declaration site and makes it explicit.) 1251.PP 1252If 1253.CW self 1254is specified in the declaration of a function, it must also be 1255specified in the definition as well. For example, 1256.CW contains 1257would be defined 1258.P1 1259 Rect.contains(r: self Rect, p: Point) 1260 { 1261 . . . 1262 } 1263.P2 1264.PP 1265The 1266.CW adt 1267type in Limbo 1268does not provide control over the visibility 1269of its individual members; if any are accessible, all are. 1270.PP 1271Constant 1272.CW adt 1273members follow the same rules as ordinary constants (§6.2). 1274.PP 1275The obsolete 1276.CW cyclic 1277modifier will be discussed in §11.1. 1278.NH 3 1279pick adts 1280.PP 1281An 1282.CW adt 1283which contains a 1284.CW pick 1285member is known as a 1286.I pick 1287.I adt . 1288A 1289.CW pick 1290.CW adt 1291is Limbo's version of a 1292.I "discriminated union" . 1293An 1294.CW adt 1295can only contain one 1296.CW pick 1297member and it must be the last component of the 1298.CW adt . 1299Each 1300.I identifier 1301enumerated in the 1302.I pick-tag-list 1303names a variant type of the 1304.CW pick 1305.CW adt . 1306The syntax is 1307.s1 1308pick-member-list: 1309 pick-tag-listC =>I 1310 pick-member-list pick-tag-listC =>I 1311 pick-member-list identifier-listC : cyclicO Idata-typeC ;I 1312.s2 1313.s1 1314pick-tag-list: 1315 identifier 1316 pick-tag-listC or Iidentifier 1317.s2 1318.PP 1319The 1320.I pick-member-list 1321contains a set of data members for each 1322.I pick-tag-list . 1323These data members are specific to those variants of the 1324.CW pick 1325.CW adt 1326enumerated in the 1327.I pick-tag-list . 1328The 1329.CW adt 1330data members found outside of the 1331.CW pick 1332are common to all variants of the 1333.CW adt . 1334A 1335.CW pick 1336.CW adt 1337can only be used as a 1338.CW ref 1339.CW adt 1340and can only be initialized from a value of one of its variants. 1341For example, if 1342.CW Constant 1343is a 1344.CW pick 1345.CW adt 1346and 1347.CW Constant.Real 1348is one of its variant types then 1349.P1 1350 c : ref Constant = ref Constant.Real("pi", 3.1); 1351.P2 1352will declare 1353.CW c 1354to have type 1355.CW ref 1356.CW Constant 1357and initialize it with a value of the variant type 1358.CW ref 1359.CW Constant.Real . 1360.NH 2 1361Type declarations 1362.PP 1363The type declaration 1364.s1 1365 Iidentifier-listC : typeI data-type ;I 1366.s2 1367introduces the identifiers as synonyms for the 1368given type. 1369Type declarations are transparent; that is, 1370an object declared with the newly-named 1371type has the same type as the one it abbreviates. 1372.NH 2 1373Module declarations 1374.PP 1375A module declaration collects and packages declarations of 1376.CW adt , 1377functions, constants and simple types, and creates an 1378interface with a name 1379that serves to identify the type of the module. 1380The syntax is 1381.s1 1382module-declaration: 1383 IidentifierC : module { Imod-member-listOC } ;I 1384 1385mod-member-list: 1386 mod-member 1387 mod-member-list mod-member 1388 1389mod-member: 1390 identifier-listC : Ifunction-typeC ;I 1391 identifier-listC : Idata-typeC ;I 1392 adt-declarationC ;I 1393 identifier-listC : con Iexpression C;I 1394 identifier-listC : type Itype C;I 1395.s2 1396After a module declaration, the named 1397.I identifier 1398becomes the name of the type of that module. 1399For example, the declaration 1400.P1 1401Linear: module { 1402 setflags: fn (flag: int); 1403 TRUNCATE: con 1; 1404 Vector: adt { 1405 v: array of real; 1406 add: fn (v1: self Vector, v2: Vector): Vector; 1407 cross: fn (v1: self Vector, v2: Vector): Vector; 1408 dot: fn (v1: self Vector, v2: Vector); 1409 make: fn (a: array of real): Vector; 1410 }; 1411 Matrix: adt { 1412 m: array of array of real; 1413 add: fn (m1: self Matrix, m2: Matrix): Matrix; 1414 mul: fn (m1: self Matrix, m2: Matrix): Matrix; 1415 make: fn (a: array of array of real): Matrix; 1416 }; 1417}; 1418.P2 1419is a module declaration for a linear algebra package that 1420implements two 1421.CW adt , 1422namely 1423.CW Vector 1424and 1425.CW Matrix , 1426a constant, 1427and a function 1428.CW setflags . 1429The name 1430.CW Linear 1431is the type name for the module, and it may be used to declare 1432an object referring to an instance of the module: 1433.P1 1434 linearmodule: Linear; 1435.P2 1436Before the module can be used, it must be loaded, for example in 1437the style: 1438.P1 1439 linearmodule = load Linear "/usr/dmr/limbo/linear.dis"; 1440 if (linearmodule == nil) { 1441 sys->print("Can't load Linear\en"); 1442 exit; 1443 } 1444.P2 1445The 1446.CW load 1447operator is discussed more fully in §8.4.5 below. 1448.PP 1449To initialize data declared as part of a module 1450declaration, an assignment expression may be used at the top level. 1451For example: 1452.P1 1453 implement testmod; 1454 testmod: module { 1455 num: int; 1456 }; 1457 . . . 1458 num = 5; 1459.P2 1460The right side of the assignment must be a constant expression (§8.5). 1461.NH 2 1462Declarations with 1463.CW import 1464.PP 1465These declarations take the form 1466.s1 1467 Iidentifier-listC : import Iidentifier C;I 1468.s2 1469Identifiers for entities 1470declared within a module declaration are normally 1471meaningful only in a context that 1472identifies the module. 1473The 1474.CW import 1475declaration lifts the names of specified members of a module 1476directly into the current scope. 1477The use of 1478.CW import 1479will be discussed more fully in §8.1.4 below, after the syntax 1480for expressions involving modules has been presented. 1481.NH 2 1482Exception declarations 1483.PP 1484Exceptions represent run-time errors not data objects or values. 1485Exception declarations have the form: 1486.s1 1487 identifier-listC : exceptionI tuple-typeO 1488.s2 1489Each identifier gives a compile-time name to a distinct user-defined run-time error, 1490signaled at run-time by a 1491.CW raise 1492statement that quotes that identifier, as described below. 1493An exception optionally includes a tuple of data values that qualifies the exception; 1494the types of those values are provided by the tuple type in this declaration. 1495.NH 2 1496Declarations with 1497.CW include 1498.PP 1499The string following the 1500.CW include 1501keyword names 1502a file, which is inserted into the program's 1503text at that point. 1504The included 1505text is treated like text literally present. 1506Conventionally, included files declare 1507module interfaces and are named with the suffix 1508.CW .m . 1509The directories to be searched for included files 1510may be specified to the Limbo compiler command. 1511Include files may be nested. 1512.NH 1 1513Function definitions 1514.PP 1515All executable code 1516is supplied as part of a function definition. 1517The syntax is 1518.s1 1519function-definition: 1520 function-name-part function-arg-retC { IstatementsC }I 1521 1522function-name-part: 1523 identifier 1524 function-name-partC . Iidentifier 1525.s2 1526The syntax of the statements in a function will be discussed in §9 below. 1527As a brief example, 1528.P1 1529 add_one(a: int): int 1530 { 1531 return a+1; 1532 } 1533.P2 1534is a simple function 1535that might be part of the top level of a module. 1536.PP 1537Functions that are declared within an 1538.CW adt 1539use the qualified form of definition: 1540.P1 1541 Point: adt { 1542 x, y: int; 1543 add: fn (p: Point, q: Point): Point; 1544 eq: fn (p: Point, q: Point): int; 1545 } 1546 . . . 1547 Point.add(p: Point, q: Point): Point 1548 { 1549 return Point(p.x+q.x, p.y+q.y); 1550 } 1551.P2 1552Because an 1553.CW adt 1554may contain an 1555.CW adt , 1556more than one qualification is possible. 1557.NH 1 1558Expressions 1559.PP 1560Expressions in Limbo resemble those of C, although some 1561of the operators are different. 1562The most salient difference between Limbo's expression 1563semantics and those of C is that Limbo 1564has no automatic coercions between types; in Limbo every 1565type conversion is explicit. 1566.NH 2 1567Terms 1568.PP 1569The basic elements of expressions are terms: 1570.s1 1571term: 1572 identifier 1573 constant 1574 real-constant 1575 string-constant 1576 CnilI 1577 C( Iexpression-listC )I 1578 termC . Iidentifier 1579 termC -> Iterm 1580 termC ( Iexpression-listOC )I 1581 termC [ IexpressionC ]I 1582 termC [ IexpressionC : IexpressionC ]I 1583 termC [ IexpressionC : ]I 1584 termC ++I 1585 termC --I 1586.s2 1587The operators on terms all associate to the left, 1588and their order of precedence, with tightest listed first, is as follows: 1589.P1 1590 . 1591 -> 1592 () [] ++ -- 1593.P2 1594.NH 3 1595Simple terms 1596.PP 1597The first five kinds of term are constants and identifiers. 1598Constants have a type indicated by their syntax. 1599An identifier used in an expression is often a previously declared 1600data object with a particular data type; when used as a term 1601in an expression 1602it denotes the value stored in the object, and the term has 1603the declared object's type. 1604Sometimes, as discussed below, identifiers used in expressions 1605are type names, function names, or module identifiers. 1606.NH 3 1607Parenthesized terms 1608.PP 1609A comma-separated list of expressions enclosed in parentheses 1610is a term. 1611If a single expression is present in the list, 1612the type and value are those of the expression; 1613the parentheses affect only the binding 1614of operators in the expression of which the term 1615is a part. 1616If there is more than one expression in the list, 1617the value is a tuple. 1618The member types 1619and values are taken from those of the expressions. 1620.NH 3 1621Selection 1622.PP 1623A term of the form 1624.s1 1625 termC . Iidentifier 1626.s2 1627denotes selection of a member of an 1628.CW adt 1629or one element from a tuple. 1630.PP 1631In the first case, 1632the term must be a 1633type name or yield an object; 1634its type must be 1635.CW adt 1636or 1637.CW ref 1638.CW adt ; 1639the identifier must be a member of the 1640.CW adt . 1641The result denotes the named member (either a data object 1642or a function). 1643.PP 1644In the second case, 1645the term must yield a value of a tuple type, 1646and the identifier must have the form \f(CWt\fP\fIn\fP 1647where 1648.I n 1649is a decimal number giving the index (starting from 0) of an element of the tuple. 1650The result is the value of that element. 1651.NH 3 1652Module qualification 1653.PP 1654A term of the form 1655.s1 1656 termC -> Iterm 1657.s2 1658denotes module qualification. 1659The first term identifies a module: either it is a module type name, 1660or it is an expression of module type. 1661The second term is a constant name, type, or function specified within 1662that module's declaration. 1663Either the module type name or 1664an object of the module's type suffices to qualify constants and types; 1665functions directly exported by the module or contained within its 1666.CW adt 1667must be qualified by an object of the module's type, initialized with 1668.CW load . 1669.PP 1670An example using an abridged version of an example above: given 1671.P1 1672 Linear: module { 1673 setflags: fn(flag: int); 1674 TRUNCATE: con 1; 1675 Vector: adt { 1676 make: fn(v: array of real): Vector; 1677 v: array of real; 1678 }; 1679 }; 1680.P2 1681one might say 1682.P1 1683 lin := load Linear "/dis/linear.dis"; 1684 a: array of real; 1685 1686 v1: lin->Vector; 1687 v2: Linear->Vector; 1688 lin->setflags(Linear->TRUNCATE); 1689 v1 = lin->(Linear->Vector).make(a); 1690 v1 = lin->v1.make(a); 1691 v1 = lin->v1.add(v1); 1692 v1.v = nil; 1693.P2 1694Here, the declarations for 1695.CW v1 1696and 1697.CW v2 1698are equivalent; either a module type name (here, 1699.CW Linear ) 1700or a handle (here, 1701.CW lin ) 1702suffices to identify the module. 1703In the call to 1704.CW setflags , 1705a handle 1706is required for the call itself; 1707the type name is sufficient for the constant. 1708.PP 1709When calling a function associated with an 1710.CW adt 1711of another module, it is necessary to identify 1712both the module and the 1713.CW adt 1714as well as the function. 1715The two calls to the 1716.CW make 1717function illustrate two ways of doing this. 1718In the first, 1719.P1 1720 v1 = lin->(Linear->Vector).make(a); 1721.P2 1722the module handle 1723.CW lin 1724is specified first, then 1725the type name of the 1726.CW Vector 1727.CW adt 1728within it, and then the function. 1729In the second call 1730.P1 1731 v1 = lin->v1.make(a); 1732.P2 1733instead of using a type name to specify the 1734.CW adt , 1735an instance of an object of the appropriate type is 1736used instead. 1737In the first example, the parentheses are required because 1738the qualification operators associate to the left. 1739.P1 1740 v1 = lin->Vector.make(a); # Wrong 1741 v1 = lin->Linear->Vector.make(a); # Wrong 1742.P2 1743The first is wrong because the same 1744.CW lin 1745can't serve as a qualifier for both the type and the call; 1746the second is wrong because 1747.CW lin->Linear 1748is meaningless. 1749.PP 1750Using 1751.CW import 1752makes the code less verbose: 1753.P1 1754 lin := load Linear "/usr/dmr/limbo/linear.dis"; 1755 Vector, TRUNCATE, setflags: import lin; 1756 a: array of real; 1757 1758 v1: Vector; 1759 v2: Vector; 1760 setflags(TRUNCATE); 1761 v1 = Vector.make(a); 1762 v1 = v1.make(a); 1763 v1 = v1.add(v1); 1764 v1.v = nil; 1765.P2 1766.NH 3 1767Function calls 1768.PP 1769The interpretation of an expression in the form 1770.s1 1771 termC ( Iexpression-listOC ) 1772.s2 1773depends on the declaration of the term. 1774If it is the (perhaps qualified) name of an 1775.CW adt , 1776then the expression is a cast; this is discussed in §8.2.11 below. 1777If the term is either the (perhaps qualified) name of a function 1778or a value of a function reference type, and 1779the expression means a function call; this is discussed here. 1780.PP 1781A plain identifier as the 1782.I term 1783can name a function defined 1784in the current module or imported into it. 1785A term qualified by using the selection operator 1786.CW . 1787specifies a function member of an 1788.CW adt ; 1789a term using 1790.CW -> 1791specifies a function defined in another module. 1792.PP 1793The 1794.I term , 1795including a plain identifier denoting a variable of function reference type, 1796can also yield a function reference value. 1797The value specifies both a function and its module, 1798established when the value was created, 1799and cannot be qualified by the 1800.B -> 1801specifier. 1802.PP 1803Function calls in Limbo 1804create a copy of each argument of value type, 1805and the execution of a function cannot 1806affect the value of the corresponding actual argument. 1807For arguments of reference type, 1808execution of the function may affect the value of the object 1809to which the reference refers, although it cannot 1810change the argument itself. 1811The actual arguments to a function are evaluated 1812in an unspecified order, 1813although any side effects caused by argument evaluation 1814occur before the function is called. 1815.PP 1816Function calls may be directly or indirectly recursive; 1817objects declared within each function are distinct from 1818those in their dynamic predecessors. 1819.PP 1820Functions (§4.3, §7) may either return a value 1821of a specified type, or return no value. 1822If a function returns a value, it has the specified type. 1823A call to a function that returns no value may appear only as the 1824sole expression in a statement (§9.1). 1825.PP 1826A function name is converted to a reference to that function when it appears 1827in a context requiring a function reference type, including assignment to a variable, 1828as an actual parameter, or the return value of a function. 1829The resulting reference value includes the appropriate module value for the function name, 1830following the rules given above for implicit and explicit qualifiers, and imports. 1831For example, the following program fragment defines a table of commands: 1832.P1 1833 Cmd: adt { 1834 c: int; 1835 f: ref fn(a: array of string): int; 1836 }; 1837 1838 mkcmds(): array of Cmd 1839 { 1840 return array[] of { 1841 ('.', editdot), 1842 ('a', editadd), 1843 ('d', editdel), 1844 ('?', edithelp), 1845 ('w', editwrite), 1846 ('q', editquit), 1847 }; 1848 } 1849 1850 editdot(a: array of string): int 1851 { 1852 ... 1853 } 1854 \&... 1855 editquit(a: array of string): int 1856 { 1857 ... 1858 } 1859.P2 1860which might be used as follows: 1861.P1 1862 cmd := mkcmds(); 1863 ... 1864 for(i := 0; i < len cmd; i++) 1865 if(cmd[i].c == c){ 1866 cmd[i].f(args); 1867 return; 1868 } 1869 error("unknown command"); 1870.P2 1871.NH 3 1872Subscripting and slicing 1873.PP 1874In a term of the form 1875.s1 1876 termC [ IexpressionC ]I 1877.s2 1878the first term must be an array or a string, and the 1879bracketed expression must have 1880.CW int 1881type. 1882The whole term 1883designates a member of the array or string, indexed by the bracketed expression; 1884the index origin is 0. 1885For an array, the type of the whole term is 1886the type from which the array is constructed; 1887for a string, the type is an 1888.CW int 1889whose value is the Unicode character at that position in the string. 1890.PP 1891It is erroneous to refer to a nonexisting 1892part of an array or string. 1893(A single exception to this rule, discussed in §8.4.1 below, 1894allows extending a string by assigning a character at its end.) 1895.PP 1896In a term of the form 1897.s1 1898 termC [ IexpressionC : IexpressionC ]I 1899.s2 1900the first term must be an array or a string, and the whole term 1901denotes a slice of it. 1902The first expression is the lower bound, and the second 1903is the upper. 1904If 1905.CW e1 1906is the first expression and 1907.CW e2 1908is the second, then in 1909.CW a[e1:e2] 1910it must be the case that 1911.CW "0<=e1, e1<=e2, e2<=len a" , 1912where 1913.CW len 1914gives the number of elements in the array or string. 1915When the term is an array, the value is an 1916array of the same type beginning at the indicated 1917lower bound and extending to the element just before 1918the upper bound. 1919When the term is a string, the value is similarly the substring 1920whose first character is indexed by the lower bound 1921and whose last character lies just before the upper bound. 1922.PP 1923Thus, for both arrays and strings, the number of elements in 1924.CW "a[e1:e2] 1925is equal to 1926.CW e2-e1 . 1927.PP 1928A slice of the form 1929.CW a[e:] 1930means 1931.CW "a[e:len a]. 1932.PP 1933When a string slice is assigned to another string or passed as an 1934argument, a copy of its value is made. 1935.PP 1936A slice of an array produces a reference to the designated subarray; 1937a change to an element of either the original array or 1938the slice is reflected in the other. 1939.PP 1940In general, slice expressions cannot be the subject of 1941assignments. 1942However, as a special case, an array slice expression of the 1943form 1944.CW a[e1:] 1945may be assigned to. 1946This is discussed in §8.4.1. 1947.PP 1948The following example shows how slices 1949can be used to accomplish what would 1950need to be done with pointer arithmetic in C: 1951.P1 1952 fd := sys->open( ... ); 1953 want := 1024; 1954 buf := array[want] of byte; 1955 b := buf[0:]; 1956 while (want>0) { 1957 got := sys->read(fd, b, want); 1958 if (got<=0) 1959 break; 1960 b = b[got:]; 1961 want -= got; 1962 } 1963.P2 1964Here the array 1965.CW buf 1966is filled by successive calls to 1967.CW sys->read 1968that may supply fewer bytes than requested; each call 1969stores up to 1970.CW want 1971bytes 1972starting at 1973.CW b[0] , 1974and returns the number of bytes stored. 1975The invariant is that the slice 1976.CW b 1977always refers to the part of the array still to be stored into. 1978.NH 3 1979Postfix increment and decrement 1980.PP 1981A term of the form 1982.s1 1983 termC ++I 1984.s2 1985is called a 1986.I post-increment . 1987The term must be an lvalue (see §8.4 below) and must have an 1988arithmetic type. 1989The type and value of the whole term is 1990that of the incremented term. 1991After the value is taken, 1 of the appropriate 1992type is added to the lvalue. 1993The result is undefined if the same object is changed 1994more than once in the same expression. 1995.PP 1996The term 1997.s1 1998 termC --I 1999.s2 2000behaves analogously to the increment case except 2001that 1 is subtracted from the lvalue. 2002.PP 2003.NH 2 2004Monadic expressions 2005.PP 2006Monadic expressions are expressions with 2007monadic operators, together with a few more 2008specialized notations: 2009.s1 2010monadic-expression: 2011 term 2012 monadic-operator monadic-expression 2013 Carray [ IexpressionC ] of Idata-type 2014 Carray [ IexpressionOC ] of { Iinit-listC }I 2015 Clist of { Iexpression-listC }I 2016 Cchan of Idata-type 2017 Cchan [ IexpressionC ] of Idata-type 2018 data-type monadic-expression 2019 2020monadic-operator: one of 2021 C+ - ! ~ ref * ++ -- <- hd tl lenI 2022.s2 2023.NH 3 2024Monadic additive operators 2025.PP 2026The 2027.CW - 2028operator produces the negative of its operand, which 2029must have an arithmetic type. 2030The type of the result is the same as the type of 2031its operand. 2032.PP 2033The 2034.CW + 2035operator has no effect; it is supplied only for 2036symmetry. 2037However, its argument must have an arithmetic type 2038and the type of the result is the same. 2039.NH 3 2040Logical negation 2041.PP 2042The 2043.CW ! 2044operator yields the 2045.CW int 2046value 1 if its operand 2047has the value 0, and yields 0 otherwise. 2048The operand must have type 2049.CW int . 2050.NH 3 2051One's complement 2052.PP 2053The 2054.CW ~ 2055operator yields the 1's complement of its 2056operand, which must have type 2057.CW int 2058or 2059.CW byte . 2060The type of the result is the same as that of its operand. 2061.NH 3 2062Reference and indirection operators 2063.PP 2064If 2065.I e 2066is an expression of an 2067.CW adt 2068type, then 2069.CW ref 2070.I e 2071is an expression of 2072.CW ref 2073.CW adt 2074type whose value refers to (points to) an anonymous object with value 2075.I e . 2076The 2077.CW ref 2078operator differs from the unary 2079.CW & 2080operator of C; it makes a new object and returns a reference 2081to it, rather than generating a reference to an existing object. 2082.PP 2083If 2084.I e 2085is an expression of type 2086.CW ref 2087.CW adt , 2088then 2089.CW * 2090.I e 2091is the value 2092of the 2093.CW adt 2094itself. 2095The value of 2096.I e 2097must not be 2098.CW nil . 2099.PP 2100For example, in 2101.P1 2102 Point: adt { ... }; 2103 p: Point; 2104 pp: ref Point; 2105 p = Point(1, 2); 2106 pp = ref p; # pp is a new Point; *pp has value (1, 2) 2107 p = Point(3, 4); # This makes *pp differ from p 2108 *pp = Point(4, 5); # This does not affect p 2109.P2 2110the expression 2111.CW *pp 2112at first refers to a copy of the value stored in 2113.CW p , 2114so 2115.CW "*pp == p 2116is true; however, when 2117.CW p 2118is changed later, 2119.CW *pp 2120does not change. 2121.NH 3 2122Prefix increment and decrement 2123.PP 2124A monadic expression of the form 2125.s1 2126 C++ Imonadic-expression 2127.s2 2128is called a 2129.I pre-increment . 2130The monadic expression must be an lvalue (see §8.4 below) and must have an 2131arithmetic type. 2132Before the value is taken, 1 of the appropriate type 2133is added to the lvalue. 2134The type and value of the whole expression is 2135that of the now incremented term. 2136The result is undefined if the same object is changed 2137more than once in the same expression. 2138.PP 2139The term 2140.s1 2141 C-- Imonadic-expression 2142.s2 2143behaves analogously to the increment case except 2144that 1 is subtracted from the lvalue. 2145.NH 3 2146Head and tail 2147.PP 2148The operand of the 2149.CW hd 2150operator must be a non-empty list. 2151The value is the first member of the list 2152and has that member's type. 2153.PP 2154The operand of the 2155.CW tl 2156operator must be a non-empty list. 2157The value is the tail of the list, 2158that is, the part of the list after its 2159first member. 2160The tail of a list with one member is 2161.CW nil . 2162.NH 3 2163Length 2164.PP 2165The operand of the 2166.CW len 2167operator is a string, an array, or a list. 2168The value is an 2169.CW int 2170giving the number of elements currently in the item. 2171.NH 3 2172Tagof 2173.PP 2174The operand of the 2175.CW tagof 2176operator is a monadic expression of type 2177.CW ref 2178.CW adt 2179that refers to a 2180.CW pick 2181.CW adt . 2182or the type name of a 2183.CW pick 2184.CW adt 2185or one of its variants. 2186The value is an 2187.CW int 2188giving a unique value for each of the variants and for the 2189.CW pick 2190.CW adt 2191type itself. 2192.NH 3 2193Channel communication 2194.PP 2195The operand of the communication operator 2196.CW <- 2197has type 2198.CW chan 2199.CW of 2200.I sometype . 2201The value of the expression 2202is the first unread object previously sent over that 2203channel, and has the type associated with the channel. 2204If the channel is empty, the program delays 2205until something is sent. 2206.PP 2207As a special case, the operand of 2208.CW <- 2209may have type 2210.CW array 2211.CW of 2212.CW chan 2213.CW of 2214.I sometype . 2215In this case, all of the channels in the array are tested; 2216one is fairly selected from those that have data. 2217The expression yields a tuple of type 2218.CW (int, 2219.I sometype 2220.CW ) ; 2221its first member gives the index of the channel from 2222which data was read, and its second member is the 2223value read from the channel. 2224If no member of the array has data ready, the expression delays. 2225.PP 2226Communication channels are treated more fully in §9.8 and 2227§9.13 below with the discussion of the 2228.CW alt 2229and 2230.CW spawn 2231statements. 2232.NH 3 2233Creation of arrays 2234.PP 2235In the expressions 2236.s1 2237 Carray [ IexpressionC ] of Idata-type 2238 Carray [ IexpressionOC ] of { Iinit-listC ,OC }I 2239.s2 2240the value is a new array of the specified type. 2241In both forms, the 2242.I expression 2243must be of type 2244.CW int , 2245and it supplies the size of the array. 2246In the first form, the type is given, 2247and the values in the array are initialized as 2248appropriate to the underlying type. 2249In the second form, a comma-separated list of values to initialize 2250the array is given, optionally followed by a trailing comma. 2251The type of the array is taken from the types of 2252the initializers, which must all be the same. 2253The list of initializers has the syntax 2254.s1 2255init-list: 2256 element 2257 init-listC , Ielement 2258 2259element: 2260 expression 2261 expressionC => Iexpression 2262 C* => Iexpression 2263.s2 2264In an 2265.I init-list 2266of plain expressions (without 2267.CW => ), 2268the members of the array 2269are successively initialized with the corresponding 2270elements of the init-list. 2271An element of the form 2272.CW e1=>e2 2273initializes the member of the array at subscript 2274.CW e1 2275with the expression 2276.CW e2 . 2277After such an element has been given, subsequent 2278simple elements (without 2279.CW => ) 2280begin initializing at position 2281.CW e1+1 2282and so on. 2283Each of the first expressions must be of type 2284.CW int 2285and must evaluate to a constant (§8.5). 2286.PP 2287If an element of the form 2288.CW * 2289.CW =>e2 2290is present, all members of the array not otherwise 2291initialized are set to the value 2292.CW e2 . 2293The expression 2294.CW e2 2295is evaluated for each subscript position, 2296but in an undefined order. 2297For example, 2298.P1 2299 arr := array[3] of { * => array[3] of { * => 1 } }; 2300.P2 2301yields a 2-dimensional array (actually an array of arrays) filled with 2302.CW 1 's. 2303.PP 2304If the expression giving the size of the array is omitted, its size 2305is taken from the largest subscript of 2306a member explicitly initialized. 2307It is erroneous to initialize a member twice. 2308.NH 3 2309Creation of lists 2310.PP 2311The value of an expression 2312.s1 2313 Clist of { Iexpression-listC }I 2314.s2 2315is a list consisting of the expressions given. 2316The types of the expressions must be identical, 2317and this type is the underlying type of the list. 2318The first expression is the head of the list, and the 2319remaining expressions are a list constituting its tail. 2320Where a list is expected, 2321.CW nil 2322specifies an empty list. 2323.NH 3 2324Creation of channels 2325.PP 2326The value of 2327.s1 2328 Cchan of Idata-type 2329.s2 2330is an initialized channel of the specified type. 2331Just a declaration of a channel leaves it initialized only to 2332.CW nil ; 2333before it can be used it must be created. For example, 2334.P1 2335 ch: chan of int; # just declares, sets ch to nil 2336 . . . 2337 ch = chan of int; # creates the channel and assigns it 2338.P2 2339Such a channel is unbuffered. 2340The value of 2341.s1 2342 Cchan [ IexpressionC ] of Idata-type 2343.s2 2344is an initialized channel of the specified type. 2345The 2346.I expression 2347must be of type 2348.CW int , 2349and sets the size of the channel's buffer. 2350If the size is zero, the channel is unbuffered, as for the first form. 2351.NH 3 2352Casts 2353.PP 2354An expression of the form 2355.s1 2356 data-type monadic-expression 2357.s2 2358in which a type name is followed by an expression 2359is called a 2360.I cast , 2361and converts the monadic expression to the named type. 2362Only certain specialized forms are provided for. 2363.NH 4 2364Arithmetic casts 2365.PP 2366In arithmetic casts, the named type must be one of 2367.CW byte , 2368.CW int , 2369.CW big , 2370or 2371.CW real , 2372and the monadic-expression must have arithmetic type. 2373For example, 2374.P1 2375 byte 10 2376.P2 2377is an expression of 2378.CW byte 2379type and value 10. 2380When real values are converted to integral ones, 2381they are rounded to the nearest integer, and away from 0 2382if there is a tie. 2383The effect of overflow during conversion is undefined. 2384.NH 4 2385Casts to strings 2386.PP 2387Here the named data type is 2388.CW string . 2389In a first form, the monadic expression has arithmetic type 2390.CW byte , ( 2391.CW int , 2392.CW big , 2393or 2394.CW real ) 2395and the value is a string containing the decimal representation 2396of the value, which may be either positive or negative. 2397A 2398.CW real 2399operand is converted as if by format 2400.CW %g , 2401and if the result is converted back to 2402.CW real , 2403the original value will be recovered exactly. 2404.PP 2405In a second form, 2406the monadic expression has type 2407.CW array 2408.CW of 2409.CW byte . 2410The value is a new string containing the Unicode characters 2411obtained by interpreting the bytes in the array as a UTF-8 representation 2412of that string. 2413(UTF-8 is a representation of 16-bit Unicode characters as one, 2414two, or three bytes.) 2415The result of the conversion is undefined if the byte array 2416ends within a multi-byte UTF-8 sequence. 2417.NH 4 2418Casts from strings 2419.PP 2420In a first form, the monadic expression is a string, 2421and the named type is an arithmetic type. 2422The value is obtained by converting the string to 2423that type. Initial white space is ignored; after a possible 2424sign, conversion 2425ceases at the first character not part of a number. 2426.PP 2427In a second form, the named type is 2428.CW array 2429.CW of 2430.CW byte 2431and the monadic-expression is a string. 2432The value is a new array of bytes containing the UTF-8 representation 2433of the Unicode characters in the string. 2434For example, 2435.P1 2436 s := "Ångström"; 2437 a := array of byte s; 2438 s = string a; 2439.P2 2440takes the string 2441.CW s 2442apart into bytes in the second line, 2443and puts it back in the third. 2444The length of 2445.CW s 2446is 8, because it contains that many characters; 2447the length of 2448.CW a 2449is larger, because some of its characters require more than 2450one byte in the UTF-8 representation. 2451.NH 4 2452Casts to 2453.CW adt 2454and 2455.CW ref 2456.CW adt 2457.PP 2458Here the named type is that of an 2459.CW adt 2460or 2461.CW ref 2462.CW adt , 2463and the monadic expression is a comma-separated list of expressions 2464within parentheses. 2465The value of the expression is an instance of an 2466.CW adt 2467of the named type whose data members are initialized with 2468the members of the list, or whose single data member 2469is initialized with the parenthesized expression. 2470In case the type is 2471.CW ref 2472.CW adt , 2473the value is a reference to the new 2474instance of the 2475.CW adt . 2476.PP 2477The expressions in the list, read in order, correspond with the data 2478members of the 2479.CW adt 2480read in order; their types and number must agree. 2481Placement of any function members of the 2482.CW adt 2483is ignored. 2484For example, 2485.P1 2486 Point: adt { 2487 x: int; 2488 eq: fn (p: Point): int; 2489 y: int; 2490 }; 2491 . . . 2492 p: Point; 2493 p = Point(1, 2); 2494.P2 2495puts in 2496.CW p 2497a 2498.CW Point 2499whose 2500.CW x 2501value is 1 and whose 2502.CW y 2503value is 2. 2504The declaration and assignment could also be written 2505.P1 2506 p := Point(1, 2); 2507.P2 2508.NH 2 2509Binary expressions 2510.PP 2511Binary expressions are either monadic expressions, 2512or have two operands and an infix operator; 2513the syntax is 2514.s1 2515binary-expression: 2516 monadic-expression 2517 binary-expression binary-operator binary-expression 2518 2519binary-operator: one of 2520 C** * / % + - << >> < > <= >= == != & ^ | :: && ||I 2521.s2 2522All these binary operators are left-associative except for 2523.CW ** 2524and 2525.CW :: , 2526which associate to the right. 2527Their precedence is as listed here, with tightest first: 2528.P1 2529 ** 2530 * / % 2531 + - 2532 << >> 2533 < > <= >= 2534 == != 2535 & 2536 ^ 2537 | 2538 :: 2539 && 2540 || 2541.P2 2542.NH 3 2543Exponentiation 2544.PP 2545The 2546.CW ** 2547operator accomplishes exponentiation. 2548The type of the left operand must be 2549.CW int , 2550.CW big 2551or 2552.CW real . 2553The type of the right operand must be 2554.CW int . 2555The result has the type of the left operand. 2556The operator is right associative, thus 2557.P1 2558 3**4*2 = (3**4)*2 = 81*2 = 162 2559 -3**4 = (-3)**4 = 81 2560 2**3**2 = 2**(3**2) = 2**9 = 512 2561.P2 2562.NH 3 2563Multiplicative operators 2564.PP 2565The 2566.CW * , 2567.CW / , 2568and 2569.CW % 2570operators respectively accomplish multiplication, division, and remainder. 2571The operands must be of identical arithmetic type, and the result has that 2572same type. 2573The remainder operator does not apply to type 2574.CW real . 2575If overflow or division by 0 occurs, the result is undefined. 2576The absolute value of 2577.CW a%b 2578is less than the absolute value of 2579.CW b ; 2580.CW "(a/b)*b + a%b 2581is always equal to 2582.CW a ; 2583and 2584.CW a%b 2585is non-negative if 2586.CW a 2587and 2588.CW b 2589are. 2590.NH 3 2591Additive operators 2592.PP 2593The 2594.CW + 2595and 2596.CW - 2597operators respectively accomplish addition and subtraction 2598of arithmetic operands of identical type; 2599the result has the same type. 2600The behavior on overflow or underflow is undefined. 2601The 2602.CW + 2603operator may also be applied to strings; 2604the result is a string that is the concatenation of the operands. 2605.NH 3 2606Shift operators 2607.PP 2608The shift operators are 2609.CW << 2610and 2611.CW >> . 2612The left operand may be 2613.CW big , 2614.CW int , 2615or 2616.CW byte ; 2617the right operand is 2618.CW int . 2619The type of the value is the same as its left operand. 2620The value of the right operand must be non-negative 2621and smaller than the number of bits in the left operand. 2622For the left-shift operator 2623.CW << , 2624the fill bits are 0; 2625for the right-shift operator 2626.CW >> , 2627the fill bits are a copy of the sign for the 2628.CW int 2629case, and 0 for the 2630.CW byte 2631case. 2632.NH 3 2633Relational operators 2634.PP 2635The relational operators are 2636.CW < 2637(less than), 2638.CW > 2639(greater than), 2640.CW <= 2641(less than or equal), 2642.CW >= 2643(greater than or equal), 2644.CW == 2645(equal to), 2646.CW != 2647(not equal to). 2648The first four operators, which generate orderings, 2649apply only to arithmetic types 2650and to strings; the types of their operands 2651must be identical, except that a string may be 2652compared to 2653.CW nil . 2654Comparison on strings is lexicographic over the 2655Unicode character set. 2656.PP 2657The equality operators 2658.CW == 2659and 2660.CW != 2661accept operands of arithmetic, string, and reference types. 2662In general, the operands must have identical type, 2663but reference types and strings may be compared for identity with 2664.CW nil . 2665Equality for reference types occurs when the operands 2666refer to the same object, or when both are 2667.CW nil . 2668An uninitialized string, or one set to 2669.CW nil , 2670is identical to the empty string denoted 2671.CW \&"" 2672for all the relational operators. 2673.PP 2674The value of any comparison is the 2675.CW int 2676value 1 if the stated 2677relation is true, 0 if it is false. 2678.NH 3 2679Bitwise logical operators 2680.PP 2681The logical operators 2682.CW & 2683(and), 2684.CW ^ 2685(exclusive or) and 2686.CW | 2687(inclusive or) 2688require operands of the same type, 2689which must be 2690.CW byte , 2691.CW int , 2692or 2693.CW big . 2694The result has the same type and its 2695value is obtained by applying the operation 2696bitwise. 2697.NH 3 2698List concatenation 2699.PP 2700The concatenation operator 2701.CW :: 2702takes a object of any data type 2703as its left operand and a list as its right operand. 2704The list's underlying type must be the same as 2705the type of the left operand. 2706The result is a new list with the left operand 2707tacked onto the front: 2708.P1 2709 hd (a :: l) 2710.P2 2711is the same as 2712.CW a . 2713.NH 3 2714Logical operators 2715.PP 2716The logical 2717.I and 2718operator 2719.CW && 2720first evaluates its left operand. 2721If the result is zero, then the value of the 2722whole expression is the 2723.CW int 2724value 0. 2725Otherwise the right operand is evaluated; if 2726the result is zero, the value of the whole 2727expression is again 0; otherwise it is 1. 2728The operands must have the same arithmetic type. 2729.PP 2730The logical 2731.I or 2732operator 2733.CW || 2734first evaluates its left operand. 2735If the result is non-zero, then the value of the 2736whole expression is the 2737.CW int 2738value 1. 2739Otherwise the right operand is evaluated; if 2740the result is non-zero, the value of the whole 2741expression is again 1; otherwise it is 0. 2742The operands must have the same arithmetic type. 2743.NH 2 2744General Expressions 2745.PP 2746The remaining syntax for expressions is 2747.s1 2748expression: 2749 binary-expression 2750 lvalue-expression assignment-operator expression 2751 C( Ilvalue-expression-listC ) = Iexpression 2752 send-expression 2753 declare-expression 2754 load-expression 2755 2756assignment-operator: one of 2757 C= &= |= ^= <<= >>= += -= *= /= %=I 2758.s2 2759The left operand of an assignment can take only certain forms, called lvalues. 2760.s1 2761lvalue-expression: 2762 identifier 2763 CnilI 2764 termC [ IexpressionC ]I 2765 termC [ IexpressionC : ]I 2766 termC . Iidentifier 2767 C( Ilvalue-expression-listC )I 2768 C* Imonadic-expression 2769 2770lvalue-expression-list: 2771 lvalue 2772 lvalue-expression-listC , Ilvalue 2773.s2 2774.NH 3 2775Simple assignments with 2776.CW = 2777.PP 2778In general, the types of the left and right operands 2779must be the same; this type must be a data type. 2780The value of an assignment is its new left operand. 2781All the assignment operators associate right-to-left. 2782.PP 2783In the ordinary assignment with 2784.CW = , 2785the value of the right side is assigned to the object 2786on the left. 2787For simple assignment only, the left operand may be a 2788parenthesized list of lvalues and the right operand 2789either a tuple or an 2790.CW adt 2791whose data members correspond 2792in number and type to the lvalues in the list. 2793The members of the tuple, or 2794the data members of the 2795.CW adt , 2796are assigned in sequence to 2797lvalues in the list. 2798For example, 2799.P1 2800 p: Point; 2801 x, y: int; 2802 (x, y) = p; 2803.P2 2804splits out the coordinates of the point into 2805.CW x 2806and 2807.CW y . 2808These rules apply recursively, so that if one of the 2809components of the left side is a parenthesized list of lvalues, 2810it is assigned from a corresponding 2811.CW adt 2812or tuple on the right. 2813.PP 2814If the left operand of a simple assignment is an 2815.CW adt 2816and the right side is a tuple, then the assignment 2817assigns the members of the tuple to the 2818.CW adt 2819data members; these must correspond in number and type 2820with the members of the tuple. 2821.PP 2822The constant 2823.CW nil 2824may be assigned to an lvalue of any reference type. 2825This lvalue will compare equal to 2826.CW nil 2827until it is subsequently reassigned. 2828Such an assignment also 2829triggers the removal of the object referred to unless other references 2830to it remain. 2831.PP 2832The left operand of an assignment may be the constant 2833.CW nil 2834to indicate that a value is discarded. 2835This applies in particular to any of the lvalues in 2836a tuple appearing on the left; to extend the examples above, 2837.P1 2838 (x, nil) = p; 2839.P2 2840assigns the 2841.CW x 2842member of the Point 2843.CW p 2844to the variable 2845.CW x . 2846.PP 2847A special consideration applies to 2848strings. 2849If an 2850.CW int 2851containing a Unicode character is assigned to a subscripted 2852string, the subscript 2853is normally required to lie within the string. 2854As a special case, the subscript's value may be equal to 2855the length of the string (that is, just beyond its end); 2856in this case, the character is appended to 2857the string, and the string's length increases by 1. 2858.PP 2859A final special case applies to array slices in the form 2860.CW e1[e2:] . 2861Such expressions may lie on the left of 2862.CW = . 2863The right side must be an array of the same type as 2864.CW e1 , 2865and its length must be less than or equal to 2866.CW "(len e1)-e2. 2867In this case, the 2868elements in the array on the right replace the elements of 2869.CW e1 2870starting at position 2871.CW e2 . 2872The length of the array is unchanged. 2873.NH 3 2874Compound assignments 2875.PP 2876A compound assignment with 2877.I op\f(CW=\fP 2878is interpreted in terms of the plain assignment; 2879.P1 2880 e1 \fIop\f(CW= e2; 2881.P2 2882is equivalent to 2883.P1 2884 e1 \f(CW= (e1) \fIop \f(CW(e2); 2885.P2 2886except that 2887.CW e1 2888is evaluated only once. 2889.NH 3 2890Send expressions 2891.PP 2892A 2893.I send-expression 2894takes the form 2895.s1 2896send-expression: 2897 lvalue-expressionC <- = Iexpression 2898.s2 2899In the expression 2900.P1 2901 e1 <- = e2 2902.P2 2903the lvalue 2904.CW e1 2905must have type 2906.CW chan 2907.CW of 2908.I type , 2909and 2910.CW e2 2911must be of that type. 2912The value of 2913.CW e2 2914is sent over the channel. 2915If no task is executing a 2916channel receive operation on the specified channel, and the channel is unbuffered or its buffer 2917is full, the sender blocks. 2918Task synchronization is discussed in §9.8 and §9.13 below. 2919.NH 3 2920Declare-expressions 2921.PP 2922A 2923.I declare-expression 2924is an assignment that also declares identifiers on its left: 2925.s1 2926declare-expression: 2927 lvalue-expressionC := Iexpression 2928.s2 2929Each of the constituent terms in the 2930.I lvalue-expression 2931must be an identifier or 2932.CW nil . 2933A plain identifier on the left 2934is declared as having the type of the expression, 2935and it is initialized with the expression's value. 2936When a parenthesized list of identifiers is given, the expression 2937must be a tuple or an 2938.CW adt , 2939and the individual identifiers in the list are declared and initialized 2940with the members of the tuple, or the data members of the 2941.CW adt . 2942As with ordinary assignments, the keyword 2943.CW nil 2944may stand for an identifier whose declaration and assignment 2945are skipped. 2946.PP 2947The value and type of a declare-expression are the same as those of the expression. 2948.NH 3 2949Load expressions 2950.PP 2951A 2952.I load-expression 2953has the form 2954.s1 2955load-expression: 2956 Cload Iidentifier expression 2957.s2 2958The identifier is the identifier of a module, that is, the type 2959name declared in a 2960.CW module 2961declaration. 2962The expression following 2963.CW load 2964has type 2965.CW string 2966and names a file containing the 2967compiled form of the module. 2968The 2969.CW load 2970expression yields a handle for referring to the functions provided 2971by a module and its 2972.CW adt . 2973.PP 2974Execution of 2975.CW load 2976brings the file containing the module into local memory and dynamically type-checks 2977its interface: the run-time system ascertains that 2978the declarations exported by the module are compatible 2979with the module declaration visible in the scope of the 2980.CW load 2981operator (see §11.2). 2982In the scope of a module declaration, the types and constants 2983exported by the module may be referred to without a handle, but 2984the functions and data exported by the module 2985(directly at its top level, or within its 2986.CW adt ) 2987may be called only using a valid 2988handle acquired by the 2989.CW load 2990operator. 2991.PP 2992The value of 2993.CW load 2994is 2995.CW nil 2996if the attempt to load fails, either because the file containing 2997the module can not be found, or because the found module does not 2998export the specified interface. 2999.PP 3000Each evaluation of 3001.CW load 3002creates a separate instance of the specified module; 3003it does not share data with any other instance. 3004.NH 2 3005Constant expressions 3006.PP 3007In several places a constant expression is required. 3008Such an expression contains operands that are 3009identifiers previously declared with 3010.CW con , 3011or 3012.CW int , 3013.CW big , 3014.CW real , 3015or 3016.CW string 3017constants. 3018These may be connected by any of the following operators: 3019.P1 3020.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 3021 + - * / % & | ^ 3022 == < > <= >= != << >> 3023 && || 3024 ~ ! 3025.P2 3026together with arithmetic and string casts, and parentheses for 3027grouping. 3028.NH 2 3029Expression evaluation 3030.PP 3031Expressions in Limbo are not reordered by the compiler; 3032values are computed in accordance with the parse of the expression. 3033However there is no guarantee of temporal evaluation order for expressions 3034with side effects, except in the following circumstances: 3035function arguments are fully evaluated before the function 3036is called; the logical operators 3037.CW && 3038and 3039.CW || 3040have fully defined order of evaluation, as explained above. 3041All side effects from an expression in one statement are 3042completed before the next statement is begun. 3043.PP 3044In an expression containing a constant subexpression (in the 3045sense of §8.5), the constant subexpression is evaluated at 3046compile-time with all exceptions ignored. 3047.PP 3048Underflow, overflow, and zero-divide conditions during integer 3049arithmetic produce undefined results. 3050.PP 3051The 3052.CW real 3053arithmetic of Limbo is all performed in IEEE double precision, 3054although denormalized numbers may not be supported. 3055By default, 3056invalid operations, zero-divide, overflow, and underflow 3057during real arithmetic are fatal; inexact-result is quiet. 3058The default rounding mode is round-to-nearest-even. 3059A set of routines in the 3060.CW Math 3061library module permits independent control of these modes within each thread. 3062.NH 1 3063Statements 3064.PP 3065The executable code within a function definition consists 3066of a sequence of statements and declarations. 3067As discussed in the Scope section §11 below, 3068declarations become effective at the place they appear. 3069Statements are executed in sequence except as discussed below. 3070In particular, the optional labels on some of the statements are used with 3071.CW break 3072and 3073.CW continue 3074to exit from or re-execute the labeled statement. 3075.s1 3076statements: 3077 (empty) 3078 statements declaration 3079 statements statement 3080 3081statement: 3082 expressionC ;I 3083 C;I 3084 C{ IstatementsC }I 3085 Cif ( IexpressionC ) Istatement 3086 Cif ( IexpressionC ) IstatementC else Istatement 3087 labelO Cwhile ( IexpressionOC ) Istatement 3088 labelO Cdo IstatementC while ( IexpressionOC ) ;I 3089 labelO Cfor ( IexpressionOC ; IexpressionOC ; IexpressionOC ) Istatement 3090 labelO Ccase IexpressionC { Iqual-statement-sequenceC }I 3091 labelO Calt { Iqual-statement-sequenceC }I 3092 labelO Cpick IidentifierC := IexpressionC { Ipqual-statement-sequenceC }I 3093 Cbreak IidentifierOC ;I 3094 Ccontinue IidentifierOC ;I 3095 Creturn IexpressionOC ;I 3096 Cspawn ItermC ( Iexpression-listOC ) ;I 3097 Cexit ;I 3098 C{ IstatementsC } exceptionI identifierOC{ Iqual-statement-sequenceC }I 3099 Craise IexpressionOC ;I 3100.s2 3101.s1 3102label: 3103 identifier C:I 3104.s2 3105.NH 2 3106Expression statements 3107.PP 3108Expression statements consist of an expression followed by 3109a semicolon: 3110.s1 3111 expressionC ;I 3112.s2 3113Most often expression statements are assignments, but other expressions 3114that cause effects are often useful, for example calling a function 3115or sending or receiving on a channel. 3116.NH 2 3117Null statement 3118.PP 3119The null statement consists of a lone semicolon. 3120It is most useful for supplying an empty body 3121to a looping statement with internal side effects. 3122.NH 2 3123Blocks 3124.PP 3125Blocks are 3126.I statements 3127enclosed in 3128.CW {} 3129characters. 3130.s1 3131 C{ IstatementsC }I 3132.s2 3133A block starts a new scope. 3134The effect of any declarations within a block disappears 3135at the end of the block. 3136.NH 2 3137Conditional statements 3138.PP 3139The conditional statement takes two forms: 3140.s1 3141 Cif ( IexpressionC ) Istatement 3142 Cif ( IexpressionC ) IstatementC else Istatement 3143.s2 3144The 3145.I expression 3146is evaluated; it must have type 3147.CW int . 3148If it is non-zero, then the first 3149.I statement 3150is executed. 3151In the second form, the second 3152.I statement 3153is executed if the 3154.I expression 3155is 0. 3156The statement after 3157.CW else 3158is connected to the nearest 3159.CW else -less 3160.CW if . 3161.NH 2 3162Simple looping statements 3163.PP 3164The simple looping statements are 3165.s1 3166 labelO Cwhile ( IexpressionOC ) Istatement 3167 labelO Cdo IstatementC while ( IexpressionOC ) ;I 3168.s2 3169In both cases the expression must be of type 3170.CW int . 3171In the first form, the 3172.I expression 3173is first tested against 0; 3174while it is not equal, the 3175.I statement 3176is repeatedly executed. 3177In the second form, the 3178.I statement 3179is executed, and then, while the 3180.I expression 3181is not 0, the statement is repeatedly executed. 3182If the 3183.I expression 3184is missing, it is understood to be non-zero. 3185.NH 2 3186.CW for 3187statement 3188.PP 3189The 3190.CW for 3191statement has the form 3192.s1 3193 labelO Cfor ( Iexpression-1OC ; Iexpression-2OC ; Iexpression-3OC ) Istatement 3194.s2 3195It is equivalent to 3196.s1 3197 expression-1C ;I 3198 Cwhile ( Iexpression-2C ) { 3199 Istatement 3200 expression-3C ; 3201 C}I 3202.s2 3203in the absence of 3204.CW continue 3205or 3206.CW break 3207statements. 3208Thus (just as in C), the first expression is an initialization, 3209the second a test for starting and continuing the loop, and the third 3210a re-initialization for subsequent travels around the loop. 3211.NH 2 3212.CW case 3213statement 3214.PP 3215The 3216.CW case 3217statement transfers control to one of several places 3218depending on the value of an expression: 3219.s1 3220 labelO Ccase IexpressionC { Iqual-statement-sequenceC }I 3221.s2 3222The expression must have type 3223.CW int , 3224.CW big 3225or 3226.CW string . 3227The 3228.CW case 3229statement is followed by sequence of 3230qualified statements, which are statements labeled by 3231expressions or expression ranges: 3232.s1 3233qual-statement-sequence: 3234 qual-listC =>I 3235 qual-statement-sequence qual-listC =>I 3236 qual-statement-sequence statement 3237 qual-statement-sequence declaration 3238 3239qual-list: 3240 qualifier 3241 qual-listC or Iqualifier 3242 3243qualifier: 3244 expression 3245 expressionC to Iexpression 3246 C*I 3247.s2 3248A 3249.I qual-statement-sequence 3250is a sequence of 3251statements and declarations, each of which 3252is preceded by one or more qualifiers. 3253Syntactically, the qualifiers are 3254expressions, expression ranges with 3255.CW to , 3256or 3257.CW * . 3258If the expression mentioned after 3259.CW case 3260has 3261.CW int 3262or 3263.CW big 3264type, 3265all the expressions appearing in the qualifiers 3266must evaluate to integer constants of the same type (§8.5). 3267If the expression has 3268.CW string 3269type, all the qualifiers must be 3270string constants. 3271.PP 3272The 3273.CW case 3274statement is executed by comparing 3275the expression at its head with the constants 3276in the qualifiers. 3277The test is for equality in the case 3278of simple constant qualifiers; 3279in range qualifiers, the test determines 3280whether the expression is greater than or 3281equal to the first constant and less than 3282or equal to the second. 3283.PP 3284None of the ranges or constants may overlap. 3285If no qualifier is selected and 3286there is a 3287.CW * 3288qualifier, 3289then that qualifier is selected. 3290.PP 3291Once a qualifier is selected, control passes 3292to the set of statements headed by that 3293qualifier. 3294When control reaches the end of that set 3295of statements, control passes to the end 3296of the 3297.CW case 3298statement. 3299If no qualifier is selected, the 3300.CW case 3301statement is skipped. 3302.PP 3303Each qualifier and the statements following it 3304up to the next qualifier together form a separate 3305scope, like a block; declarations within this scope 3306disappear at the next qualifier (or at the end of 3307the statement.) 3308.PP 3309As an example, this fragment separates small numbers 3310by the initial letter of their spelling: 3311.P1 3312 case i { 3313 1 or 8 => 3314 sys->print("Begins with a vowel\en)"; 3315 0 or 2 to 7 or 9 => 3316 sys->print("Begins with a consonant\en"); 3317 * => 3318 sys->print("Sorry, didn't understand\en"); 3319 } 3320.P2 3321.NH 2 3322.CW alt 3323statement 3324.PP 3325The 3326.CW alt 3327statement transfers control to one of several groups 3328of statements depending on the readiness of communication 3329channels. 3330Its syntax resembles that of 3331.CW case : 3332.s1 3333 labelO Calt { Iqual-statement-sequenceC }I 3334.s2 3335However, the qualifiers take a form different 3336from those of 3337.CW case . 3338In 3339.CW alt , 3340each qualifier must be a 3341.CW * , 3342or an expression containing a communication 3343operator 3344.CW <- 3345on a channel; 3346the operator may specify either sending or receiving. 3347For example, 3348.P1 3349 outchan := chan of string; 3350 inchan := chan of int; 3351 alt { 3352 i := <-inchan => 3353 sys->print("Received %d\en", i); 3354 3355 outchan <- = "message" => 3356 sys->print("Sent the message\en"); 3357 } 3358.P2 3359The 3360.CW alt 3361statement is executed by testing each of 3362the channels mentioned in the 3363.I qual-list 3364expressions for ability to send or receive, 3365depending on the operator; 3366if none is ready, the program blocks 3367until at least one is ready. 3368Then a random choice from the ready channels is selected 3369and control passes to the associated set 3370of statements. 3371.PP 3372If a qualifier of the form 3373.CW * 3374is present, then the statement does not block; 3375if no channel is ready the statements associated with 3376.CW * 3377are executed. 3378.PP 3379If two communication operators are present 3380in the same qualifier expression, only the leftmost one is 3381tested by 3382.CW alt . 3383If two or more 3384.CW alt 3385statements referring to the same receive (or send) 3386channel are executed in different 3387threads, the requests are queued; 3388when the channel becomes unblocked, the thread 3389that executed 3390.CW alt 3391first is activated. 3392.PP 3393As with 3394.CW case , 3395each qualifier and the statements following it 3396up to the next qualifier together form a separate 3397scope, like a block; declarations within this scope 3398disappear at the next qualifier (or at the end of 3399the statement.) 3400Thus, in the example above, the scope of 3401.CW i 3402in the arm 3403.P1 3404 i := <-inchan => 3405 sys->print("Received %d\en", i); 3406.P2 3407is restricted to these two lines. 3408.PP 3409As mentioned in the specification 3410of the channel receive operator 3411.CW <- 3412in §8.2.8, that operator can take an array of channels as an argument. 3413This notation serves as a kind of simplified 3414.CW alt 3415in which all the channels have the same type 3416and are treated similarly. 3417In this variant, 3418the value of the communication expression is a tuple 3419containing the index of the 3420channel over which a communication was received and 3421the value received. 3422For example, in 3423.P1 3424 a: array [2] of chan of string; 3425 a[0] = chan of string; 3426 a[1] = chan of string; 3427 . . . 3428 (i, s) := <- a; 3429 # s has now has the string from channel a[i] 3430.P2 3431the 3432.CW <- 3433operator waits until at least one of the 3434members of 3435.CW a 3436is ready, selects one of them at random, 3437and returns the index and the transmitted string 3438as a tuple. 3439.PP 3440During execution of an 3441.CW alt , 3442the expressions in the qualifiers are evaluated in an undefined 3443order, and in particular subexpressions may be evaluated before 3444the channels are tested for readiness. 3445Therefore qualifying expressions should not invoke side effects, 3446and should avoid subparts that might delay execution. 3447For example, in the qualifiers 3448.P1 3449 ch <- = getchar() => # Bad idea 3450 ich <- = next++ => # Bad idea 3451.P2 3452.CW getchar() 3453may be called early in the elaboration of the 3454.CW alt 3455statement; if it delays, the entire 3456.CW alt 3457may wait. 3458Similarly, the 3459.CW next++ 3460expression may be evaluated before testing the readiness of 3461.CW ich . 3462.NH 2 3463.CW pick 3464statement 3465.PP 3466The 3467.CW pick 3468statement transfers control to one of several groups of statements 3469depending upon the resulting variant type of a 3470.CW pick 3471.CW adt 3472expression. The syntax resembles that of 3473.CW case : 3474.s1 3475 labelO Cpick IidentifierC := IexpressionC { Ipqual-statement-sequenceC }I 3476.s2 3477The expression must have type 3478.CW ref 3479.CW adt 3480and the 3481.CW adt 3482must be a 3483.CW pick 3484.CW adt . 3485The 3486.CW pick 3487statement is followed by a sequence of qualified statements, which are 3488statements labeled by the 3489.CW pick 3490variant names: 3491.s1 3492pqual-statement-sequence: 3493 pqual-listC =>I 3494 pqual-statement-sequence pqual-listC =>I 3495 pqual-statement-sequence statement 3496 pqual-statement-sequence declaration 3497 3498pqual-list: 3499 pqualifier 3500 pqual-listC or Ipqualifier 3501 3502pqualifier: 3503 identifier 3504 C*I 3505.s2 3506A 3507.I pqual-statement-sequence 3508is a sequence of statements and declarations, each of which 3509is preceded by one or more qualifiers. 3510Syntactically, the qualifiers are identifiers, identifier lists (constructed with 3511.CW or ), 3512or 3513.CW * . 3514The identifiers must be names of the variant types of the 3515.CW pick 3516.CW adt . 3517The 3518.CW pick 3519statement is executed by comparing the variant type of the 3520.CW pick 3521.CW adt 3522referenced by the expression at its head with the variant type names in the qualifiers. 3523The matching qualifier is selected. 3524None of the variant type names may appear more than once. 3525If no qualifier is selected and there is a 3526.CW * 3527qualifier, then that qualifier is selected. 3528.PP 3529Once a qualifier is selected, control passes 3530to the set of statements headed by that qualifier. 3531When control reaches the end of that set of statements, 3532control passes to the end of the 3533.CW pick 3534statement. 3535If no qualifier is selected, the 3536.CW pick 3537statement is skipped. 3538.PP 3539Each qualifier and the statements following it 3540up to the next qualifier together form a separate 3541scope, like a block; declarations within this scope 3542disappear at the next qualifier (or at the end of 3543the statement.) 3544.PP 3545The 3546.I identifier 3547and 3548.I expression 3549given in the 3550.CW pick 3551statement are used to bind a new variable to a 3552.CW pick 3553.CW adt 3554reference expression, and within the statements associated with the 3555selected qualifier the variable can be used as if it were of the corresponding 3556variant type. 3557.PP 3558As an example, given a 3559.CW pick 3560.CW adt 3561of the following form: 3562.P1 3563 Constant: adt { 3564 name: string; 3565 pick { 3566 Str or Pstring => 3567 s: string; 3568 Real => 3569 r: real; 3570 } 3571 }; 3572.P2 3573the following function could be used to print out the value of 3574an expression of type 3575.CW "ref Constant" : 3576.P1 3577 printconst(c: ref Constant) 3578 { 3579 sys->print("%s: ", c.name); 3580 pick x := c { 3581 Str => 3582 sys->print("%s\en", x.s); 3583 Pstring => 3584 sys->print("[%s]\en", x.s); 3585 Real => 3586 sys->print("%f\en", x.r); 3587 }; 3588 } 3589.P2 3590.NH 2 3591.CW break 3592statement 3593.PP 3594The 3595.CW break 3596statement 3597.s1 3598 Cbreak IidentifierO C;I 3599.s2 3600terminates execution of 3601.CW while , 3602.CW do , 3603.CW for , 3604.CW case , 3605.CW alt , 3606and 3607.CW pick 3608statements. 3609Execution of 3610.CW break 3611with no identifier 3612transfers control to 3613the statement after the innermost 3614.CW while , 3615.CW do , 3616.CW for , 3617.CW case , 3618.CW alt , 3619or 3620.CW pick 3621statement in which it appears as a substatement. 3622Execution of 3623.CW break 3624with an identifier 3625transfers control to the next statement after the unique enclosing 3626.CW while , 3627.CW do , 3628.CW for , 3629.CW case , 3630.CW alt , 3631or 3632.CW pick 3633labeled with that identifier. 3634.NH 2 3635.CW continue 3636statement 3637.PP 3638The 3639.CW continue 3640statement 3641.s1 3642 Ccontinue IidentifierO C;I 3643.s2 3644restarts execution of 3645.CW while , 3646.CW do , 3647and 3648.CW for 3649statements. 3650Execution of 3651.CW continue 3652with no identifier 3653transfers control to the end of 3654the innermost 3655.CW while , 3656.CW do , 3657or 3658.CW for 3659statement in which the 3660.CW continue 3661appears as a substatement. 3662The expression that controls the loop is tested 3663and if it succeeds, execution continues in the loop. 3664The initialization portion of 3665.CW for 3666is not redone. 3667.PP 3668Similarly, execution of 3669.CW continue 3670with an identifier transfers control to the end of the enclosing 3671.CW while , 3672.CW do , 3673or 3674.CW for 3675labeled with the same identifier. 3676.NH 2 3677.CW return 3678statement 3679.PP 3680The 3681.CW return 3682statement, 3683.s1 3684 Creturn IexpressionOC ;I 3685.s2 3686returns control to the caller of a function. 3687If the function returns a value (that is, if its definition 3688and declaration mention a return type), 3689the expression must be given and it must have the same type that the 3690function returns. 3691If the function returns no value, the expression 3692must generally be omitted. 3693However, if a function returns no value, and its 3694last action before returning is to call 3695another function with no value, then it may 3696use a special form of 3697.CW return 3698that names the function being called. 3699For example, 3700.P1 3701 f, g: fn(a: int); 3702 f(a: int) { 3703 . . . 3704 return g(a+1); 3705 } 3706.P2 3707is permitted. 3708Its effect is the same as 3709.P1 3710 f(a: int) { 3711 . . . 3712 g(a+1); 3713 return; 3714 } 3715.P2 3716This 3717.I "ad hoc 3718syntax offers the compiler a cheap opportunity to recognize 3719tail-recursion. 3720.PP 3721Running off the end of a function is equivalent to 3722.CW return 3723with no expression. 3724.NH 2 3725.CW spawn 3726statement 3727.PP 3728The 3729.CW spawn 3730statement creates a new thread of control. 3731It has the form 3732.s1 3733 Cspawn ItermC ( Iexpression-listOC ) ;I 3734.s2 3735The term and expression-list are taken to be 3736a function call. 3737Execution of 3738.CW spawn 3739creates an asynchronous, independent thread 3740of control, which calls the function in the new thread context. 3741This function may access the accessible objects 3742in the spawning thread; the two threads share 3743a common memory space. 3744These accessible objects include the data global to 3745the current module and reference data passed to the 3746spawned function. 3747Threads are preemptively scheduled, so that 3748changes to objects used in common between 3749threads may occur at any time. 3750The Limbo language provides no explicit synchronization 3751primitives; §12.3 shows examples of how to use channel 3752communication to control concurrency. 3753.NH 2 3754.CW exit 3755statement 3756.PP 3757The 3758.CW exit 3759statement 3760.s1 3761 Cexit ;I 3762.s2 3763terminates a thread and frees any resources 3764belonging exclusively to it. 3765.NH 2 3766.CW raise 3767statement 3768.PP 3769The 3770.CW raise 3771statement 3772.s1 3773 Craise IexpressionOC ;I 3774.s2 3775raises an exception in a thread. 3776The 3777.I expression 3778is either a string describing the failure, or an exception name and its parameter values, if any. 3779If an expression is not given, the 3780.CW raise 3781statement must appear in the body of an exception handler; it raises the currently active exception. 3782.NH 2 3783Exception handler 3784.PP 3785Various errors in a Limbo program can be detected only at run-time. 3786These include programming errors such as an attempt to index outside the bounds of an array, 3787system errors such as exhausting memory, and user-defined exceptions 3788declared at compile-time by exception declarations and caused at run-time by the 3789.CW raise 3790statement. 3791A group of statements can have an associated exception handler: 3792.s1 3793 C{ IstatementsC } exceptionI identifierOC{ Iqual-statement-sequenceC }I 3794.s2 3795The first run-time exception raised by any of the 3796.I statements , 3797or functions they call, 3798that is not handled by an exception handler enclosing the statement raising the exception 3799will terminate execution of the 3800.I statements 3801at that point, and transfer control to the clause in the sequence of qualified statements 3802that matches the exception. 3803An exception represented by a string is matched by a qualifier that is either the same 3804string value, or a prefix of it followed by 3805.CW * . 3806The optional identifier following 3807.CW exception 3808is set to the value of the exception string for the execution of the qualified statement. 3809If execution of the qualified statement completes, control passes to the statement following 3810the exception-handling statement. 3811.PP 3812A qualified statement labeled by a user-defined exception name matches that exception. 3813If the exception has parameters, the identifier following 3814.CW exception 3815will be be declared and initialized as a tuple of the parameter values for the scope 3816of the qualified statement, allowing the values to be recovered by tuple assigment. 3817.PP 3818The qualifier 3819.CW * 3820matches any string or user-defined exception. 3821An exception that is raised and not successfully handled by a thread will terminate the thread. 3822.NH 3823Referring to modules; 3824.CW import 3825.PP 3826As discussed above, modules present 3827constants, functions, and types 3828in their interface. 3829Their names may be the same as names 3830in other modules or of local objects or types within 3831a module that uses another. 3832Name clashes are avoided because references 3833to the entities presented by a module are 3834qualified by the module type name or an object 3835of that module type. 3836.PP 3837For example, 3838after the module and variable declarations 3839.P1 3840 M: module { 3841 One: con 1; 3842 Thing: adt { 3843 t: int; 3844 f: fn(); 3845 }; 3846 g: fn(); 3847 }; 3848 m: M; 3849.P2 3850the name 3851.CW One 3852refers to the constant defined in 3853module 3854.CW M 3855only in the contexts 3856.CW M->One 3857or 3858.CW m->One ; 3859the name 3860.CW Thing 3861as the particular data type 3862associated with the 3863.CW M 3864module can be referred to only in contexts 3865like 3866.P1 3867 th1: M->Thing; 3868 th2: m->Thing; 3869.P2 3870Finally, to call a function defined either as a top-level 3871member of the module, or as a member of one of its 3872.CW adt , 3873it is necessary to declare, and also dynamically initialize using 3874.CW load , 3875a handle for the module. 3876Then calls of the form 3877.P1 3878 m->g(); 3879 m->th1.f(); 3880.P2 3881become appropriate. 3882It is possible to use just the type name of a module to qualify 3883its constants and types because constants and types can be understood 3884without having the code and data present. 3885Calling a function declared by a module or one of its 3886.CW adt 3887requires loading the module. 3888.PP 3889The 3890.CW import 3891declaration 3892.s1 3893 Iidentifier-listC : import Iidentifier C;I 3894.s2 3895lifts the identifiers in the 3896.I identifier-list 3897into the scope in which 3898.CW import 3899appears, so that they are usable without a qualifier. 3900The identifier after the 3901.CW import 3902keyword is either 3903a module identifier, or an identifier declared as having 3904that type. 3905The initial list of identifiers specifies those 3906constants, 3907types, 3908and functions of the module whose names are promoted. 3909In the case of constants and types, 3910.CW import 3911merely makes their names accessible without using a qualifier. 3912In the example above, if the 3913.CW module 3914declaration above had been followed by 3915.P1 3916 One, Thing: import M; 3917.P2 3918then one could refer to just 3919.CW One 3920instead of 3921.CW M->One ; 3922similarly an object could be declared like 3923.P1 3924 th: Thing; 3925.P2 3926For functions, and also 3927.CW adt 3928with functions as members, 3929.CW import 3930must specify a module 3931variable (as opposed to a module identifier). 3932Each imported name is associated with the specified module 3933variable, and the current value of this module variable 3934controls which instance of the module will 3935be called. 3936For example, after 3937.P1 3938 g, Thing: import m; 3939.P2 3940then 3941.P1 3942 g(); 3943.P2 3944is equivalent to 3945.P1 3946 m->g(); 3947.P2 3948and 3949.P1 3950 th: Thing; 3951 th.f(); 3952.P2 3953is equivalent to 3954.P1 3955 th: M->Thing; 3956 m->th.f(); 3957.P2 3958When the module declaration for the module being 3959implemented is encountered, an implicit 3960.CW import 3961of all the names of the module is executed. 3962That is, given 3963.P1 3964 implement Mod; 3965 . . . 3966 Mod: module { 3967 . . . 3968 }; 3969.P2 3970the constants and types of 3971.CW Mod 3972are accessed as if they had been imported; 3973the functions declared in 3974.CW Mod 3975are imported as well, and refer dynamically to the 3976current instance of the module being implemented. 3977.NH 3978Scope 3979.PP 3980The scope of an identifier is the lexical range of 3981a program throughout which the identifier means a particular 3982type of, or instance of, an object. 3983The same identifier may be associated with several 3984different objects in different parts of the same program. 3985.PP 3986The names of members of an 3987.CW adt 3988occupy a separate, nonconflicting space from other identifiers; 3989they are declared in a syntactically distinct position, 3990and are always used in a distinguishable way, namely 3991after the 3992.CW . 3993selection operator. 3994Although the same scope rules apply to 3995.CW adt 3996members as to other identifiers, their names may 3997coincide with other entities in the same scope. 3998.PP 3999Similarly, the names of constants, functions, and 4000.CW adt 4001appearing 4002within a 4003.CW module 4004declaration are ordinarily qualified either with 4005the name of the module or with a module variable 4006using the 4007.CW -> 4008notation. 4009As discussed above, the 4010.CW import 4011declaration lifts these names into the current scope. 4012.PP 4013Identifiers declared in a top-declaration 4014(§5) have scope that lasts from the 4015declaration throughout the remainder of the 4016file in which it occurs, unless it is overridden 4017by a redeclaration of that name within an inner 4018scope. 4019Each function definition, and each block 4020within a function, 4021introduces a new scope. 4022A name declared within the block or function 4023(including a formal argument name of a function) 4024has a scope that begins 4025at the completion of its declaration and lasts until 4026the end of the block or function. 4027If an already-declared identifier is redeclared within 4028such an inner scope, the declaration previously in 4029force is used in any initialization expression 4030that is part of the new declaration. 4031.PP 4032As discussed above, within 4033.CW case 4034.CW alt 4035and 4036.CW pick , 4037each qualifier 4038and the statements following it form an inner 4039scope just like a block. 4040.PP 4041The scope of a label is restricted to the 4042labeled statement, 4043and label names may coincide with those of other 4044entities in the same scope. 4045.NH 2 4046Forward referencing 4047.PP 4048In general, names must be declared before they are used. 4049.PP 4050The first exception to this rule is that a 4051function local to a module need not have a 4052declaration at all; it is sufficient to give 4053its definition, and that definition may appear anywhere 4054in the module. 4055.PP 4056The general rule implies that no 4057.CW adt 4058may contain, as a member, an 4059.CW adt 4060not previously declared (including an instance of itself). 4061A second exception to this rule applies to 4062.CW ref 4063.CW adt 4064types. 4065An 4066.CW adt 4067may contain a member whose type is a 4068.CW ref 4069to itself, or to another 4070.CW adt 4071even if the second 4072.CW adt 4073has not yet been declared. 4074.PP 4075For example, a tree structure where nodes contain references to children can be declared and created as follows: 4076.P1 4077 Tree: adt { 4078 l: ref Tree; 4079 r: ref Tree; 4080 v: int; 4081 }; 4082 4083 t1a := ref Tree(nil, nil, 0); 4084 t1b := ref Tree(nil, nil, 1); 4085 t1c := ref Tree(nil, nil, 2); 4086 t2 := Tree(t1a, t1b, 0); 4087 t2.l = t1c; # replace reference to t1a by reference to t1c 4088.P2 4089The tree structure resulting above is non-circular, since no 4090.CW adt 4091value refers back to itself directly or indireclty. 4092Circular data structures can also be created. For example, 4093.P1 4094 Graph: adt { 4095 next: ref Graph; 4096 v: int; 4097 }; 4098 4099 g1 := ref Graph(nil, 0); 4100 g2 := ref Graph(g1, 1); 4101 g1.next = g2; 4102.P2 4103creates a pair of nodes that refer to each other. 4104.PP 4105Limbo implementations guarantee to 4106destroy all data objects not involved in circular data structures 4107immediately after they become non-referenced by active 4108tasks, whether because 4109their names go out of scope or because they are assigned new values. 4110This property has visible effect because certain system resources, 4111like windows and file descriptors, can be seen outside the program. 4112In particular, if a reference to such a resource is held only within an 4113.CW adt , 4114then that resource too is destroyed when the 4115.CW adt 4116is. 4117Circular data structures can also be created. 4118When they become unreferenced except by themselves, they will 4119be garbage-collected eventually, but not instantly. 4120.PP 4121An earlier version of the language required circular references to be annoted by the word 4122.CW cyclic , 4123but that is no longer required. 4124The notation can still be seen in some system source code, because the 4125.CW cyclic 4126qualifier is taken into account in type checking, as described below, and some instances remain to provide backward compatibility. 4127.NH 2 4128Type equality and compatibility 4129.PP 4130In an assignment and in passing an actual argument to a function, 4131the types of the target and the expression being assigned or 4132passed must be equal (with certain exceptions, e.g. assignment of 4133.CW nil 4134to a reference type). 4135When a function is defined, its type must be equal to the type 4136of a function with the same name if one is in scope. 4137Type equality is determined as follows. 4138.PP 4139Two basic types are equal if and only if they are identical. 4140.PP 4141Two tuple types are equal if and only if they are composed 4142of equal types in the same order. 4143.PP 4144Two array types are equal if and only if they are arrays 4145of equal types. 4146The size of an array is not part of its type. 4147.PP 4148Two list types are equal if and only if they are composed 4149of equal types. 4150.PP 4151Two channel types are equal if and only if they transmit 4152equal types. 4153.PP 4154Two 4155.CW adt 4156types are equal if and only if their data members 4157have the same names and correspondingly 4158equal types, including any 4159.CW cyclic 4160attribute. 4161The order of member declaration is insignificant, and 4162constant and function members of an 4163.CW adt 4164do not enter into the comparison, 4165nor does the name of the 4166.CW adt 4167type itself. 4168In particular, with the declarations 4169.P1 4170 A: adt { x: ref B; }; 4171 B: adt { x: ref A; }; 4172.P2 4173the types 4174.CW A 4175and 4176.CW B 4177are equal. 4178.PP 4179Two 4180.CW ref 4181.CW adt 4182types are equal if and only if they are references to equal 4183.CW adt 4184types. 4185.PP 4186Two module types are equal if and only if their data and function members 4187have the same names and correspondingly equal types; the order 4188of their mention is insignificant. 4189Constant members and type members do not enter into the comparison. 4190.PP 4191Two function types are equal if and only if their return 4192values have the same type 4193and their argument lists have correspondingly equal types. 4194Any 4195.CW self 4196attributes given to arguments must match. 4197Names given to arguments do not enter into the comparison. 4198.PP 4199A type name has the same type as the type from 4200which it was constructed. 4201.PP 4202When a module is loaded, the module stored 4203in the file system must have a type that is 4204.I compatible 4205with the type mentioned in the 4206.CW load 4207expression. 4208The type of the stored module 4209type is compatible with the mentioned type if and only if 4210all data members of the two types are equal in name and type, 4211and all 4212.CW adt 4213or functions actually mentioned by the program executing 4214.CW load 4215have names and types equal to corresponding members of 4216the stored module. 4217.NH 4218Examples 4219.PP 4220Because Limbo was designed for the Inferno environment, several 4221of these examples consist of simplified versions of already simple 4222Inferno applications in a prototype Inferno implementation. 4223Some appreciation for the resources available in this environment 4224should become evident, but its full description is available 4225elsewhere; 4226the discussion here will focus on language features. 4227However, several of the programs use facilities 4228from the module 4229.CW Sys , 4230which provides an interface to a file system and its methods 4231resembling those of Unix or Plan 9, 4232as well as other useful library facilities. 4233.PP 4234Some of the programs are annotated with line numbers; 4235they are there only for descriptive purposes. 4236.NH 2 4237A simple command interpreter module 4238.PP 4239This version of a shell program reads from a keyboard and 4240executes `commands' typed by the user. 4241Its own interface has the type of a 4242.CW Command 4243module, and that is the type of the things it executes. 4244In particular, it can call modules like the 4245.CW hello 4246example at the beginning of the paper. 4247.P1 42481 implement Command; 4249 42502 include "sys.m"; 42513 include "draw.m"; 4252 42534 sys: Sys; 42545 stdin: ref Sys->FD; 4255 42566 Command: module 42577 { 42588 init: fn(nil: ref Draw->Context, nil: list of string); 42599 }; 4260.P2 4261After the boilerplate on lines 1-3, the variables 4262.CW sys 4263and 4264.CW stdin 4265are declared on lines 4 and 5. 4266The I/O operations of the 4267.CW Sys 4268module use the 4269.CW ref 4270.CW FD 4271type to refer to open files. 4272.P1 427310 init(ctx: ref Draw->Context, nil: list of string) 427411 { 427512 427613 427714 buf := array[256] of byte; 4278 427915 sys = load Sys Sys->PATH; 428016 stdin = sys->fildes(0); 4281 428217 for(;;) { 428318 sys->print("$ "); 428419 n := sys->read(stdin, buf, len buf); 428520 if(n <= 0) 428621 break; 428722 (nw, arg) := 4288 sys->tokenize(string buf[0:n], " \et\en"); 428923 if(nw != 0) 429024 exec(ctx, arg); 429125 } 429226 } 4293.P2 4294Line 10: conventionally, stand-alone modules are started 4295by calling their 4296.CW init 4297functions. 4298The 4299.CW Command 4300module follows this convention. 4301The arguments are presented as a list of strings. 4302In this simple example, the command interpreter itself 4303ignores its argument, so it need not be given a name. 4304.PP 4305Local variables are declared on lines 12-14; line 15 4306loads the 4307.CW Sys 4308module and stores a handle for it in the variable 4309.CW sys . 4310Line 16 creates an 4311.CW FD 4312for the standard input by calling the 4313.CW fildes 4314function of the 4315.CW Sys 4316module using the 4317.CW -> 4318operator; the notation 4319.CW modhandle->func(...) 4320specifies a call to the function named 4321.CW func 4322in the module currently referred to by 4323.CW modhandle . 4324(In general there can be several modules of the same type and name 4325active, and there can also be unrelated modules containing identically 4326named functions. 4327The 4328.CW import 4329declaration, described in §6.6 above, can be used to abbreviate 4330the references when names do not clash.) 4331.PP 4332The loop on lines 17-25 prints a prompt (line 18), reads a line from 4333the standard input (line 19), parses it into tokens (line 22), and 4334executes the command. 4335.PP 4336The function call 4337.CW sys->tokenize 4338is worth discussing as an example of style. 4339It takes two strings as arguments. 4340The characters in the second string are interpreted as separators 4341of tokens in the first string. 4342It returns a tuple whose first member is the number of 4343tokens found, and whose second is a list of strings 4344containing the tokens found: its declaration is 4345.P1 4346 tokenize: fn (s: string, sep: string): (int, list of string); 4347.P2 4348In the example, the second argument is 4349\f(CW" \et\en"\fP, 4350so that the routine returns the number of, and a list of, 4351`words' separated by blanks, tabs, and new-lines. 4352The free use of strings, lists, and tuple-returning 4353functions is common in Limbo. 4354.PP 4355The 4356.CW sys->read 4357routine gathers an array of bytes into 4358.CW buf . 4359Thus the expression for the first argument of 4360.CW sys->tokenize 4361converts this array to a string by slicing the 4362array with 4363.CW [0:n] , 4364using the actual number of bytes 4365gathered by the 4366.CW read , 4367and using a cast. 4368.PP 4369At lines 23-24, if there were any words found, 4370.CW exec 4371is called: 4372.P1 437327 exec(ctx: ref Draw->Context, args: list of string) 437428 { 437529 c: Command; 437630 cmd, file: string; 4377 437831 cmd = hd args; 4379 438032 file = cmd + ".dis"; 438133 c = load Command file; 438234 if(c == nil) 438335 c = load Command "/dis/"+file; 4384 438536 if(c == nil) { 438637 sys->print("%s: not found\en", cmd); 438738 return; 438839 } 438940 c->init(ctx, args); 439041 } 4391.P2 4392On lines 31 and 32 of 4393.CW exec , 4394.CW cmd 4395is set to the first of the words in the argument list, 4396and the string 4397.CW .dis 4398is concatenated to it (to account for the fact that Limbo 4399object program files are conventionally named using this suffix). 4400On line 33 an attempt is made to load the named module 4401from the derived file name; it will fail if the file 4402does not exist. 4403The attempt will succeed, 4404and a non-nil handle assigned to 4405.CW c , 4406if the file is found, and if 4407the module stored in that file does in fact implement the 4408.CW Command 4409module type. 4410In case this fails, lines 34-35 make another attempt, after prefixing 4411.CW /dis/ 4412to the file name. 4413.PP 4414If either attempt to get a handle to the named module 4415succeeds, 4416.CW c 4417will contain a valid handle to it; line 40 calls its 4418.CW init 4419function, passing it the whole argument list. 4420When it returns, the 4421.CW exec 4422function returns, and the main loop resumes. 4423.NH 2 4424Infrared remote control 4425.PP 4426This example shows two instances of a module 4427for interfacing to a TV remote control; one 4428is for the real remote, which in this case 4429is connected to a serial port on a set-top 4430box, and the other is simulated for testing 4431programs running on a regular operating 4432system. 4433The techniques of special interest are the 4434dynamic use of modules and the communication 4435using a channel. 4436.PP 4437The module is used by creating a channel and passing 4438it to the module's 4439.CW init 4440function, 4441which returns a success/error indicator and starts an 4442asynchronous process to read the remote control. 4443The user of the module executes a receive 4444on the channel whenever it wishes to accept 4445a button-push. 4446.PP 4447The (abridged) module declaration is 4448.P1 4449Ir: module 4450{ 4451 # Codes buttons on IR remote control 4452 Zero: con 0; 4453 One: con 1; 4454 . . . 4455 Mute: con 23; 4456 Error: con 9999; 4457 4458 init: fn(chan of int): int; 4459 PATH: con "/dis/ir.dis"; 4460 SIMPATH: con "/dis/irsim.h"; 4461}; 4462.P2 4463The implementation for the `real' remote control is 4464.P1 4465implement Ir; 4466 4467include "ir.m"; 4468include "sys.m"; 4469FD, Dir: import Sys; 4470 4471sys: Sys; 4472 4473init(keys: chan of int): int 4474{ 4475 cfd, dfd: ref FD; 4476 4477 sys = load Sys Sys->PATH; 4478 4479 cfd = sys->open("/dev/eia1ctl", sys->OWRITE); 4480 if(cfd == nil) 4481 return -1; 4482 sys->fprint(cfd, "b9600"); 4483 4484 dfd = sys->open("/dev/eia1", sys->OREAD); 4485 cfd = nil; 4486 4487 spawn reader(keys, dfd); 4488 return 0; 4489} 4490.P2 4491The 4492.CW init 4493routine accepts a 4494.CW chan 4495argument; it will be used by the module to 4496send codes for the buttons pressed by the user. 4497In this routine, the calls to 4498.CW sys->open 4499and 4500.CW sys->fprint 4501open and set up the device data and control files 4502.CW /dev/eia1 4503and 4504.CW /dev/eia1ctl 4505used to communicate with the device itself. 4506The important step is at the end: the 4507.CW spawn 4508statement creates a new, 4509asynchronous task to read the device, using a routine 4510that is passed the communications channel and the 4511FD for the device: 4512.P1 4513reader(keys: chan of int, dfd: ref FD) 4514{ 4515 n, ta, tb: int; 4516 dir: Dir; 4517 b1:= array[1] of byte; 4518 b2:= array[1] of byte; 4519 4520 # find the number of bytes already 4521 # queued and flush that many 4522 (n, dir) = sys->fstat(dfd); 4523 if(n >= 0 && dir.length > 0) { 4524 while(dir.length) { 4525 n = sys->read(dfd, 4526 array[dir.length] of byte, 4527 dir.length); 4528 if(n < 0) 4529 break; 4530 dir.length -= n; 4531 } 4532 } 4533.P2 4534.P1 4535loop: for(;;) { 4536 n = sys->read(dfd, b1, len b1); 4537 if(n <= 0) 4538 break; 4539 ta = sys->millisec(); 4540 # Button pushes are pairs of characters 4541 # that arrive closer together than 4542 # 200 ms. Longer than that is likely 4543 # to be noise. 4544 for(;;) { 4545 n = sys->read(dfd, b2, 1); 4546 if(n <= 0) 4547 break loop; 4548 tb = sys->millisec(); 4549 if(tb - ta <= 200) 4550 break; 4551 ta = tb; 4552 b1[0] = b2[0]; 4553 } 4554 # map the character pair; the significant 4555 # bits are the lowest 5. 4556 case ((int b1[0]&16r1f)<<5) | (int b2[0]&16r1f) { 4557 975 => n = Ir->Zero; 4558 479 => n = Ir->One; 4559 . . . 4560 791 => n = Ir->Mute; 4561 * => n = Ir->Error; 4562 } 4563 # found a button-push; send the value 4564 keys <-= n; 4565 } 4566 keys <-= Ir->Error; 4567} 4568.P2 4569The code in the middle is related to noise-filtering 4570and is uninteresting in detail except as it illustrates 4571some of the methods provided by the 4572.CW Sys 4573module; the crucial actions are found at the bottom, 4574where the routine sends either 4575a true button-push or an error code over the channel to 4576the module's client. 4577.PP 4578Here is another implementation of the same interface. 4579Its 4580.CW init 4581function performs the same kind of initialization 4582as the other version, but using the operating system's 4583keyboard files 4584.CW /dev/cons 4585and 4586.CW /dev/consctl . 4587In the Inferno environment, operations corresponding to the Unix 4588`stty' primitive are accomplished by writing messages to 4589a control file associated with the file that handles the data. 4590.P1 4591implement Ir; 4592 4593include "ir.m"; 4594include "sys.m"; 4595FD: import Sys; 4596 4597sys: Sys; 4598cctlfd: ref FD; 4599 4600init(keys: chan of int): int 4601{ 4602 dfd: ref FD; 4603 4604 sys = load Sys Sys->PATH; 4605 4606 cctlfd = sys->open("/dev/consctl", sys->OWRITE); 4607 if(cctlfd == nil) 4608 return -1; 4609 sys->write(cctlfd, array of byte "rawon", 5); 4610 4611 dfd = sys->open("/dev/cons", sys->OREAD); 4612 if(dfd == nil) 4613 return -1; 4614 4615 spawn reader(keys, dfd); 4616 return 0; 4617} 4618.P2 4619A fine point: the variable 4620.CW cctlfd 4621that contains the FD for the control device is 4622declared external to the 4623init function, even though it appears to be used 4624only inside it. 4625Programming cleanliness suggests that 4626its declaration be moved inside, but here that 4627won't work; 4628device control files 4629in Inferno retain settings like `raw mode' only 4630while they remain open. 4631If 4632.CW cctlfd 4633were declared inside 4634.CW init , 4635then returning from 4636.CW init 4637would destroy the last reference to the FD for the control file, 4638and the device would be closed automatically. 4639.PP 4640The reader function for this module has the same structure as the first 4641example, but doesn't have to worry about a noisy infrared detector: 4642.P1 4643reader(keys: chan of int, dfd: ref FD) 4644{ 4645 n: int; 4646 b:= array[1] of byte; 4647 4648 for(;;) { 4649 n = sys->read(dfd, b, 1); 4650 if(n != 1) 4651 break; 4652 case int b[0] { 4653 '0' => n = Ir->Zero; 4654 '1' => n = Ir->One; 4655 . . . 4656 16r7f => n = Ir->Mute; 4657 * => n = Ir->Error; 4658 } 4659 keys <-= n; 4660 } 4661 keys <-= Ir->Error; 4662} 4663.P2 4664The following module can be used to test the above code. 4665It simply prints the name of the button that was pressed. 4666.P1 4667implement Irtest; 4668 4669include "sys.m"; 4670include "draw.m"; 4671FD: import Sys; 4672include "ir.m"; 4673 4674Irtest: module 4675{ 4676 init: fn(nil: ref Draw->Context, nil: list of string); 4677}; 4678ir: Ir; 4679sys: Sys; 4680.P2 4681.P1 4682init(nil: ref Draw->Context, nil: list of string) 4683{ 4684 c: int; 4685 stderr: ref FD; 4686 irchan := chan of int; 4687 4688 sys = load Sys Sys->PATH; 4689 stderr = sys->fildes(2); 4690 4691 # If the real IR remote application can 4692 # be found, use it, otherwise use the simulator: 4693 ir = load Ir Ir->PATH; 4694 if(ir == nil) 4695 ir = load Ir Ir->SIMPATH; 4696 if(ir == nil) { 4697 # %r format code means the last system error string 4698 sys->fprint(stderr, "load ir: %r\en"); 4699 return; 4700 } 4701 if(ir->init(irchan) != 0) { 4702 sys->fprint(stderr, "Ir.init: %r\en"); 4703 return; 4704 } 4705 names := array[] of { 4706 "Zero", 4707 "One", 4708 . . . 4709 "Mute", 4710 }; 4711 for(;;) { 4712 c = <-irchan; 4713 if(c == ir->Error) 4714 sys->print("Error %d\en", c); 4715 else 4716 sys->print("%s\en", names[c]); 4717 } 4718} 4719.P2 4720Finally, here is a snippet from a movie application that 4721uses the IR module; it demonstrates how 4722.CW alt 4723is useful for dealing with multiple events. 4724This is only one of the functions of the 4725movie module, so not everything is defined. 4726It uses the 4727.CW Mpeg 4728module, which actually 4729copies the MPEG data stream to the screen 4730asynchronously. 4731Its 4732.CW play 4733function takes, as one of its arguments, 4734a channel; 4735before starting to play it writes a 4736string on the channel. 4737An empty string indicates success at 4738locating the movie; a non-empty 4739string contains an error message. 4740When it finishes, it writes another string. 4741.P1 4742movie(entry: ref Dbinfo, cc: chan of int) 4743{ 4744 i: int; 4745 m: Mpeg; 4746 b: ref Image; 4747 4748 m = load Mpeg Mpeg->PATH; 4749 if (m == nil) 4750 return; 4751 # make a place on the screen 4752 w := screen.window(screen.image.r); 4753 4754 mr := chan of string; 4755 s := m->play(w, 1, w.r, entry.movie, mr); 4756 if(s != "") 4757 return; 4758 # wait for the end of the movie 4759 # while watching for button pushes 4760 for(;;) { 4761 alt { 4762 <-mr => 4763 return; 4764 i = <-cc => 4765 case i { 4766 Ir->Select => 4767 m->ctl("stop"); 4768 Ir->Up or Ir->Dn => 4769 m->ctl("pause"); 4770 } 4771 } 4772 } 4773} 4774.P2 4775.NH 2 4776Monitors 4777.PP 4778Statically allocated storage within a module is accessible to 4779all the functions of that module, 4780and there is no explicit mechanism in Limbo for synchronizing 4781concurrent updates to this storage from several tasks. 4782However, it is straightforward to build a variety of concurrency-control 4783mechanisms by using channel communications. 4784.PP 4785An example is a module that implements a 4786.CW Monitor 4787abstract data type. 4788Each instance of 4789.CW Monitor 4790has a 4791.CW lock 4792and an 4793.CW unlock 4794operation; 4795calling 4796.CW lock 4797delays if another task holds the lock; calling 4798.CW unlock 4799releases the lock and enables any other task attempting 4800to execute 4801.CW lock . 4802.P1 4803implement Monitors; 4804 4805Monitors: module 4806{ 4807 Monitor: adt { 4808 create: fn(): Monitor; 4809 lock: fn(m: self Monitor); 4810 unlock: fn(m: self Monitor); 4811 ch: chan of int; 4812 }; 4813}; 4814.P2 4815.P1 4816Monitor.create(): Monitor 4817{ 4818 m := Monitor(chan of int); 4819 spawn lockproc(m.ch); 4820 return m; 4821} 4822.P2 4823.P1 4824Monitor.lock(m: self Monitor) 4825{ 4826 m.ch <- = 0; 4827} 4828.P2 4829.P1 4830Monitor.unlock(m: self Monitor) 4831{ 4832 <- m.ch; 4833} 4834.P2 4835.P1 4836lockproc(ch: chan of int) 4837{ 4838 for (;;) { 4839 <- ch; # wait for someone to lock 4840 ch <- = 0; # wait for someone to unlock 4841 } 4842} 4843.P2 4844It would be used like this: 4845.P1 4846mp: Mon; 4847Monitor: import mp; 4848mp = load Mon "..."; 4849l := Monitor.create(); 4850\. . . 4851l.lock(); 4852# region of code to be protected; 4853# only one thread can execute here at once. 4854l.unlock(); 4855.P2 4856The 4857.CW create 4858method of 4859.CW Monitor 4860allocates an instance of a 4861.CW Monitor 4862containing an initialized channel. 4863It also creates a thread executed in the 4864.CW lockproc 4865routine, which repeatedly reads from the channel, 4866then writes on it. 4867The values transmitted over the channel are of no 4868interest; it is the pure fact of communication that is put to use. 4869The 4870.CW lock 4871routine sends a message; in the idle state, the 4872.CW lockproc 4873thread reads it and the sender proceeds. 4874Meanwhile, 4875.CW lockproc 4876tries to send a message over the same channel. 4877If another thread attempts to 4878.CW lock , 4879there is no reader for the channel, and so its transmission will block. 4880At some point, the thread that gained the lock 4881calls 4882.CW unlock , 4883which receives from the channel. 4884Depending on timing, this reception enables execution of either 4885.CW lockproc 4886or one of the threads attempting to send via 4887.CW lock . 4888.PP 4889There is a simpler implementation of 4890.CW Monitor , 4891using a buffered channel. 4892The 4893.CW create 4894operation simply allocates a channel with a one-element buffer: 4895.P1 4896Monitor.create(): Monitor 4897{ 4898 return Monitor(chan[1] of int); 4899} 4900.P2 4901The 4902.CW lock 4903and 4904.CW unlock 4905operations have the same implementation. 4906Because of the buffer, when a process locks an unlocked 4907.CW Monitor , 4908the send succeeds but fills the channel. 4909Subsequent attempts to 4910.CW lock 4911will therefore block as long as the channel is full. 4912.CW Unlock 4913removes the value from the channel, making it empty, 4914and allowing another 4915.CW lock 4916to proceed. 4917The 4918.CW lockproc 4919is not needed. 4920Note that a program using the module would not need to be recompiled to 4921use the new implementation, because the module's signature and use 4922remains the same. 4923This is the implementation of the 4924.CW Lock 4925module in the Limbo library for Inferno. 4926.PP 4927Limbo channels are usually unbuffered: 4928a sender blocks until there 4929is a receiver, and processes synchronise at each communication. 4930Buffered channels are used sparingly in Limbo programs, typically to improve throughput or, 4931less often, in specialized ways as in the monitor example above. 4932.NH 2 4933Guarding sends and receives 4934.PP 4935In some applications, a process takes input from one channel, 4936and sends it on to another channel, possibly having transformed it. 4937In case the input and output processes run at different rates, 4938the process itself acts as a buffer, holding a queue of values internally. 4939If the input process were faster than the output process, the queue 4940would accumulate values faster than they are consumed, exhausting memory. 4941To prevent that, when the queue reaches a specified limit, the process should guard against 4942receiving from the input channel, but continue sending to the output channel. 4943Conversely, when the queue is empty, it should not attempt to send. 4944The 4945.CW alt 4946statement allows a process to choose between sending and receiving based on 4947which channels are ready, but the process must also account for the current state 4948of the queue. 4949This example shows a way to make a buffered 4950channel of strings from an unbuffered channel. 4951It is written as a module whose 4952.CW bufchan 4953function takes a 4954.CW chan 4955.CW of 4956.CW string 4957and a size as argument, and returns a new channel; 4958it creates an asynchronous task that accepts input from the argument 4959channel and saves up to 4960.CW size 4961strings, meanwhile trying to send them to its user. 4962.P1 4963implement Bufchan; 4964Bufchan: module { 4965 bufchan: fn(c: chan of string, size: int): chan of string; 4966}; 4967 4968xfer(oldchan, newchan: chan of string, size: int) 4969{ 4970 temp := array[size] of string; 4971 fp := 0; # first string in buffer 4972 n := 0; # number of strings in buffer 4973 dummy := chan of string; 4974 sendch, recvch: chan of string; 4975 s: string; 4976 4977 for (;;) { 4978 sendch = recvch = dummy; 4979 if (n > 0) 4980 sendch = newchan; 4981 if (n < size) 4982 recvch = oldchan; 4983 alt { 4984 s = <-recvch => 4985 temp[(fp+n)%size] = s; 4986 n++; 4987 4988 sendch <- = temp[fp] => 4989 temp[fp++] = nil; 4990 n--; 4991 if (fp>=size) 4992 fp -= size; 4993 } 4994 } 4995} 4996.P2 4997.P1 4998bufchan(oldchan: chan of string, size: int): chan of string 4999{ 5000 newchan := chan of string; 5001 spawn xfer(oldchan, newchan, size); 5002 return newchan; 5003} 5004.P2 5005The module is somewhat specialized, but it illustrates 5006useful programming techniques. 5007The most interesting occurs in 5008.CW xfer , 5009which does the work. 5010The problem 5011.CW xfer 5012faces is that it doesn't want to receive input when its 5013buffer is full, nor to try to send when it has nothing to 5014transmit. 5015The solution here is to use a dummy channel 5016on which nothing is ever sent or received; in the 5017.CW alt 5018statement, 5019that channel substitutes for the real input channel 5020when the buffer is full, and for the output channel 5021when the buffer is empty. 5022.PP 5023The module could be used in the following way: 5024.P1 5025Bufchan: module { 5026 PATH: con "/dis/lib/bufchan.dis"; 5027 bufchan: fn(c: chan of string, size: int): chan of string; 5028}; 5029\. . . 5030bufc := load Bufchan Bufchan->PATH; 5031sourcech := chan of string; 5032 5033# ... (here, hand off sourcech to a process that 5034# reads strings from it and copies them to ch) 5035ch: chan of string = bufc->bufchan(sourcech, 10); 5036\. . . 5037s := <- ch; 5038\. . . 5039.P2 5040.NH 1 5041Syntax summary 5042.PP 5043This section summarizes the grammar of Limbo 5044above the lexical level; constants and identifiers 5045are left undefined. 5046.PP 5047