Annotation of researchv10dc/vol2/snocone/snocone.ms, revision 1.1.1.1

1.1       root        1: .so ../ADM/mac
                      2: .XX snocone 297 "The Snocone Programming Language"
                      3: .nr dP 2
                      4: .nr dV 3p
                      5: .EQ
                      6: delim $$
                      7: .EN
                      8: .ds S4 \s-2SNOBOL4\s0
                      9: .de Sx
                     10: .P1 0
                     11: ..
                     12: .de Sy
                     13: .P2
                     14: ..
                     15: .de Tx
                     16: .IP "" 5
                     17: ..
                     18: .de Ty
                     19: .PP
                     20: ..
                     21: .TL
                     22: The Snocone Programming Language
                     23: .AU
                     24: Andrew Koenig
                     25: .AI
                     26: .MH
                     27: .AB
                     28: .PP
                     29: \*(S4 is a well-known programming language with convenient
                     30: semantics and clumsy syntax.
                     31: Following the pattern of Ratfor and \s-2EFL\s0,
                     32: we have added ``syntactic sugar'' to
                     33: \*(S4, with an eye toward making it easier to use.
                     34: We call the result
                     35: .I Snocone.
                     36: .PP
                     37: This paper describes the Snocone language in enough
                     38: detail that people not familiar with \*(S4 can
                     39: learn to use it, although previous familiarity
                     40: with \*(S4 will help.
                     41: .AE
                     42: .2C
                     43: .NH 1
                     44: Introduction
                     45: .PP
                     46: The semantics of the \*(S4 programming language |reference(poage griswold)
                     47: include such unusual and useful
                     48: features as
                     49: dynamic typing,
                     50: a general-purpose garbage collector,
                     51: excellent character string facilities,
                     52: associative arrays,
                     53: and strong run-time diagnostics.
                     54: Griswold|reference(snobol4 applications),
                     55: Gimpel|reference(gimpel snobol4),
                     56: and others have documented many ways of
                     57: doing things in \*(S4 that can only be accomplished
                     58: with much more difficulty in other languages.
                     59: .PP
                     60: Unfortunately, the control structures of
                     61: \*(S4 are archaic, and the fact that
                     62: blank is an operator tends to encourage certain types
                     63: of errors that are hard to detect.
                     64: Other aspects of the language make it a nuisance
                     65: to construct large programs out of small parts.
                     66: .PP
                     67: To ameliorate some of these problems,
                     68: we have designed and implemented a new language
                     69: that provides some syntactic sugar for \*(S4.
                     70: The obvious name for such a language is
                     71: .I Snocone .
                     72: .PP
                     73: The design of the Snocone language was inspired by
                     74: Ratfor|reference(kernighan ratfor)
                     75: and \s-2EFL\s0|reference(efl cstr).
                     76: Like \s-2EFL\s0, and unlike Ratfor, Snocone is a self-contained
                     77: programming language, rather than a proper superset of
                     78: \*(S4.
                     79: Like Ratfor, and unlike \s-2EFL\s0, the Snocone translator
                     80: makes no attempt to produce \*(S4 output that is
                     81: easy for humans to understand.
                     82: .PP
                     83: Hanson|reference(ratsno)
                     84: has written a similar, but simpler preprocessor
                     85: for \*(S4.
                     86: His preprocessor is like Ratfor
                     87: in that it does not change the statements in
                     88: the basic language but rather adds new syntax.
                     89: .PP
                     90: Griswold|reference(rebus)
                     91: has written a preprocessor for a language
                     92: similar to Snocone,
                     93: the syntax of which is based on Icon|reference(icon language)
                     94: rather than on C or \s-2EFL\s0.
                     95: His preprocessor is written in C,
                     96: and uses Yacc for its parsing.
                     97: .PP
                     98: In contrast, Snocone has a syntax roughly
                     99: based on C and is written in Snocone.
                    100: .SH
                    101: What's nice about \*(S4
                    102: .PP
                    103: Variables in \*(S4 are dynamically typed:
                    104: the type of any variable is the type of the
                    105: value most recently assigned to it.
                    106: Thus, declarations are unnecessary, and, in fact,
                    107: \*(S4 has no declarations as such
                    108: (except that procedures can have local variables).
                    109: .PP
                    110: All operators and built-in functions check
                    111: their argument types;
                    112: each argument is converted automatically
                    113: to an appropriate type.
                    114: A run-time diagnostic message results
                    115: if a conversion is impossible.
                    116: For instance, if an addend
                    117: is a string, \*(S4 will try
                    118: to convert it to an integer or real number,
                    119: depending on the form of its value.
                    120: If the value is inappropriate to convert to
                    121: a numeric type, the program will halt.
                    122: .PP
                    123: Like Lisp, and unlike most other languages,
                    124: \*(S4 does not have any explicit mechanism for
                    125: returning memory to the system.
                    126: Rather, the implementation must detect
                    127: when memory is no
                    128: longer needed and make that memory available
                    129: for re-use.
                    130: This makes the language harder to implement,
                    131: but easier to use.
                    132: One nice by-product of this sort of memory
                    133: allocator is that \*(S4 programs tend
                    134: to be free of arbitrary size limitations.
                    135: .PP
                    136: One \*(S4 data type is the
                    137: .I pattern ,
                    138: which describes an (arbitrarily complex)
                    139: set of character strings.
                    140: Briefly, the language incorporates a general
                    141: top-down backtracking parser.
                    142: This parser is so easy to use that it
                    143: is the usual way of dealing with strings
                    144: in \*(S4.
                    145: .PP
                    146: Another useful data type is the
                    147: .I table .
                    148: A table is like a one-dimensional array, except that
                    149: its subscripts are not limited to being integers.
                    150: For instance, a compiler symbol table might be maintained
                    151: as a \*(S4 table, with the subscript being the identifier
                    152: and the value being some structure which holds the desired
                    153: information about that identifier.
                    154: .PP
                    155: An interesting and unusual semantic idea in \*(S4 is
                    156: that of
                    157: .I "statement failure" .
                    158: Many operations can easily encounter conditions that
                    159: preclude their execution.
                    160: For example, an attempt may be made to access a non-existent
                    161: array element, read beyond the last record of a file,
                    162: search a string for a pattern that it does not contain,
                    163: or even make a comparison that gives an unexpected result.
                    164: When this happens, the operation
                    165: .I fails .
                    166: Usually, the failure of an operation implies the failure
                    167: of the statement of which it is a part.
                    168: While statement failure is not an error condition,
                    169: it can be tested.
                    170: In fact, conditional transfer on the success or
                    171: failure of a statement is virtually the only
                    172: kind of control structure in \*(S4.
                    173: .PP
                    174: A good implementation of \*(S4 is
                    175: Macrospitbol, by Dewar and McCann|reference(spitbol).
                    176: This is a portable threaded-code interpreter, which
                    177: is fast and robust enough to be used for ``production''
                    178: purposes.
                    179: For example, on a VAX-11/780 it translates about 150
                    180: statements per second and executes about 5,000.
                    181: .PP
                    182: \*(S4 implementations in general have excellent
                    183: run-time diagnostic facilities.
                    184: The language definition includes ways of tracing
                    185: programs for debugging, and of trapping almost any
                    186: kind of run-time error.
                    187: .SH
                    188: What's not nice about \*(S4
                    189: .PP
                    190: Here is a simple \*(S4 program to add the
                    191: integers between 1 and 1000:
                    192: .P1 0
                    193:        sum = 0
                    194:        term = 1
                    195: loop   sum = sum + term
                    196:        term = term + 1
                    197:        LE(term,1000)           :s(loop)
                    198:        OUTPUT = "The sum is " sum
                    199: END
                    200: .P2
                    201: .PP
                    202: The first two lines of this program assign values to
                    203: variables.
                    204: The name
                    205: .CW loop
                    206: in the third line is a label; it is recognized as such
                    207: because it begins the line without any white space
                    208: ahead of it.
                    209: .PP
                    210: The fifth line calls a built-in function to compare the
                    211: value of the variable
                    212: .CW term
                    213: to 1000.
                    214: \*(S4 has no comparison operators: all comparisons are
                    215: done by
                    216: .I predicate
                    217: functions that either return the null string if the condition
                    218: being tested is true or fail if the condition is false.
                    219: The \f(CW:s(loop)\fP at the end of the line
                    220: is a conditional
                    221: .B "go to" :
                    222: it causes control to transfer to the label
                    223: .CW loop
                    224: if the statement succeeds, and to the following
                    225: statement if it fails.
                    226: .PP
                    227: In contrast, the program looks like this in Snocone:
                    228: .P1 0
                    229: sum = 0
                    230: term = 1
                    231: do {
                    232:        sum = sum + term
                    233:        term = term + 1
                    234: } while (term <= 1000)
                    235: OUTPUT = "The sum is " && sum
                    236: .P2
                    237: .PP
                    238: In the past fifteen years, the trend in programming
                    239: language design has been overwhelmingly toward
                    240: programming languages with control structures that
                    241: make it reasonable to write programs with at most
                    242: a very few
                    243: .B "go to"
                    244: statements.
                    245: \*(S4 exhibits almost the exact opposite of this trend:
                    246: essentially the only control structure in \*(S4 is
                    247: a form of conditional
                    248: .B "go to"
                    249: statement.
                    250: There is no block structure, and all labels are global.
                    251: Thus, writing a \*(S4 program requires a constant effort
                    252: to invent new label names, and to choose names that have
                    253: at least some chance of telling the reader whether their
                    254: use is local or global.
                    255: .PP
                    256: The programmer's job is not made any easier by the peculiar way
                    257: \*(S4 handles subroutines.
                    258: \*(S4 subroutines are defined at run time by a built-in
                    259: function called \f(CWDEFINE\fP.
                    260: Its argument is a
                    261: .I prototype
                    262: of the subroutine to be defined \-
                    263: a character string that describes how the
                    264: subroutine is to be used.
                    265: The subroutine's entry point is the label with the same name.
                    266: Because the statement bearing this label is not special
                    267: in any other way, it must be placed where it will not
                    268: be executed in the ordinary course of events.
                    269: The call to \f(CWDEFINE\fP, on the other hand, must
                    270: be executed before the subroutine it defines can be used.
                    271: .PP
                    272: This leads \*(S4 programmers into contortions.
                    273: To keep the \f(CWDEFINE\fP call near the subroutine body,
                    274: one must invent yet another label:
                    275: .P1 0
                    276:         DEFINE("square(x)")    :(square.end)
                    277: square  square = x * x         :(RETURN)
                    278: square.end
                    279: .P2
                    280: Alternatively, one can put all the \f(CWDEFINE\fP calls
                    281: in one place, at the cost of moving the body of each
                    282: subroutine arbitrarily far from where its prototype appears.
                    283: .PP
                    284: The Snocone programmer has an easier job:
                    285: .P1 0
                    286: procedure square (x) {
                    287:        return x * x
                    288: }
                    289: .P2
                    290: .SH
                    291: Motivation
                    292: .PP
                    293: Snocone's purpose, then, is to make it easy for a
                    294: programmer used to a block-structured language like C
                    295: to write programs that have the freedom and semantic flexibility
                    296: of \*(S4.
                    297: To this end, we have changed the \*(S4 language in several ways.
                    298: .PP
                    299: First, we introduced an explicit concatenation operator.
                    300: \*(S4 uses blank for concatenation, so
                    301: .P1 0
                    302: y = f(x)
                    303: .P2
                    304: is a function call, but
                    305: .P1 0
                    306: y = f (x)
                    307: .P2
                    308: assigns to \f(CWy\fP the concatenation of the 
                    309: values of the variables
                    310: \f(CWf\fP and \f(CWx\fP.
                    311: We chose \f(CW&&\fP to represent concatenation because
                    312: \*(S4 programs often use concatenation for the same purpose
                    313: that C programs use \f(CW&&\fP.
                    314: .PP
                    315: Second, we allow much the same freedom with spaces that
                    316: C does, with one exception:  newline ends a statement.
                    317: Statements may be continued onto multiple lines in much the
                    318: same way as in \s-2EFL\s0 programs: a line is continued
                    319: if it ends with an
                    320: operator or some kind of open bracket.
                    321: .PP
                    322: Third, we have added procedure and structure declarations.
                    323: These things are accomplished in \*(S4 by calling built-in
                    324: subroutines, and the context of the calls is often obscure.
                    325: .PP
                    326: Finally, we have introduced control structures similar to
                    327: those in C and other block-structured languages: the
                    328: \f(CWif\fP, \f(CWwhile\fP, \f(CWfor\fP, and \f(CWdo\fP statements.
                    329: .NH 1
                    330: Language Description
                    331: .NH 2
                    332: Lexical Conventions
                    333: .PP
                    334: Blanks (spaces and tabs, but not newlines) may not appear within a
                    335: token, but may freely separate tokens.
                    336: Comments begin with a \f(CW#\fP
                    337: character and end at the end of the line.
                    338: .PP
                    339: Constants may be integers, reals, or strings.
                    340: There are no signed
                    341: numeric constants.
                    342: Integers range from 0 to $2 sup 31 - 1$.
                    343: Real constants
                    344: are short-precision only, and must contain either a decimal point or an
                    345: \f(CWE\fP (or \f(CWe\fP).
                    346: String constants may be delimited by single or double quotes
                    347: with the same meaning.
                    348: Characters in quotes receive no special
                    349: interpretation.
                    350: A single quote may appear in strings delimited by
                    351: double quotes, and vice versa.
                    352: .EQ
                    353: delim off
                    354: .EN
                    355: .PP
                    356: Identifiers may be of any length.
                    357: All characters in an identifier are
                    358: significant, but their case is presently not significant.
                    359: Case may
                    360: become significant in the future.
                    361: An identifier is a non-empty
                    362: sequence of letters and digits, beginning with a letter.
                    363: Underscore
                    364: (_) is a letter.
                    365: The same identifier may be used independently to
                    366: represent a procedure, label, or variable.
                    367: .NH 2
                    368: Statement Separation
                    369: .PP
                    370: Snocone delimits statements much like the Shell|reference(bstj shell)
                    371: (the command interpreter in the
                    372: .UX
                    373: operating system)|reference(unix cacm ritchie thompson)
                    374: or \s-2EFL\s0.
                    375: A statement is
                    376: ended either by a semicolon or newline, except that if the last token
                    377: on a line is an operator or open parenthesis or bracket, the next line
                    378: is automatically considered as part of the current statement.
                    379: Newlines
                    380: may also separate clauses of compound statements, so
                    381: .P1 0
                    382: if (a < 0)
                    383:        a = 0
                    384: .P2
                    385: is acceptable and means the same as
                    386: .P1 0
                    387: if (a < 0) a = 0
                    388: .P2
                    389: or, spreading things as much as possible:
                    390: .P1 0
                    391: if (
                    392: a <
                    393: 0)
                    394: a =
                    395: 0
                    396: .P2
                    397: .NH 2
                    398: File Inclusion
                    399: .PP
                    400: The contents of an arbitrary file can be incorporated into
                    401: the program by writing an
                    402: .I "include line"
                    403: in one of the following four forms:
                    404: .P1 0
                    405: #include "\fIfile\fP"
                    406: #include '\fIfile\fP'
                    407: #include <\fIfile\fP>
                    408: #include {\fIfile\fP}
                    409: .P2
                    410: Spaces may appear between \f(CW#\fP and \f(CWinclude\fP.
                    411: The contents of the named file are substituted for
                    412: the \f(CWinclude\fP line.
                    413: .PP
                    414: The exact behavior of an \f(CWinclude\fP line depends
                    415: on the delimiters surrounding the file name.
                    416: If quotes are used (single or double), the file is
                    417: sought in the current directory.
                    418: If brackets are used (angle brackets or curly braces),
                    419: the file is sought in an installation-dependent
                    420: system library
                    421: (\f(CW/usr/lib/snocone\fP on our systems).
                    422: If double quotes or angle brackets are used, the
                    423: file is included unconditionally, even if the same
                    424: file is included several times.
                    425: If single quotes or curly braces are used,
                    426: the file will only be included once, even if it
                    427: is named in several \f(CWinclude\fP lines.
                    428: .PP
                    429: This latter behavior is useful in the following sort of situation.
                    430: Suppose that procedure
                    431: .I proc1
                    432: is defined in
                    433: file
                    434: .I proc1.h ,
                    435: and procedure
                    436: .I proc2
                    437: is defined
                    438: in file
                    439: .I proc2.h .
                    440: A program that calls both
                    441: .I proc1
                    442: and
                    443: .I proc2
                    444: might then contain:
                    445: .P1 0
                    446: #include "proc1.h"
                    447: #include "proc2.h"
                    448: .P2
                    449: Now, suppose that
                    450: .I proc1
                    451: is changed to call
                    452: .I proc2 .
                    453: If
                    454: .I proc1.h
                    455: is made to contain
                    456: .P1 0
                    457: #include "proc2.h"
                    458: .P2
                    459: then our hypothetical sample program will wind
                    460: up with two copies of
                    461: .I proc2.h
                    462: and will therefore run into trouble with duplicate
                    463: procedure definitions.
                    464: If, however,
                    465: .I proc1.h
                    466: contains:
                    467: .P1 0
                    468: #include 'proc2.h'
                    469: .P2
                    470: and the main program contains:
                    471: .P1 0
                    472: #include 'proc1.h'
                    473: #include 'proc2.h'
                    474: .P2
                    475: then
                    476: .I proc2
                    477: will be defined only once.
                    478: .NH 2
                    479: Expression Evaluation, Success, and Failure
                    480: .PP
                    481: Evaluating an expression has one of three
                    482: outcomes: a value, failure, or error.
                    483: .PP
                    484: Errors normally result in a diagnostic message
                    485: and termination of the program, and arise
                    486: from the usual sorts of things:
                    487: overflow, underflow,
                    488: division by zero, impossible conversions,
                    489: running out of memory, and so on.
                    490: .PP
                    491: Failure, on the other hand, is not an error
                    492: condition.
                    493: An expression that fails is merely one that
                    494: does not yield a value.
                    495: Examples of expressions that fail include
                    496: attempts to refer to non-existent array
                    497: elements,
                    498: attempts to read beyond end of file,
                    499: and even comparisons that yield unexpected results.
                    500: For instance, the expression
                    501: .P1 0
                    502: a < b
                    503: .P2
                    504: yields a null string if \f(CWa\fP is indeed less than \f(CWb\fP,
                    505: and fails otherwise.
                    506: .PP
                    507: Most operators fail if any of their operands fails.
                    508: The few exceptions will be noted below.
                    509: .PP
                    510: An expression that always either yields a null string or fails
                    511: is sometimes called a
                    512: .I predicate .
                    513: Testing such expressions for success or failure in \f(CWif\fP,
                    514: \f(CWwhile\fP, and \f(CWdo\fP statements is the primary way
                    515: of affecting the flow of control
                    516: in Snocone.
                    517: .NH 2
                    518: Data Types, Declarations, and Scope
                    519: .PP
                    520: Variables in Snocone are dynamically typed: a variable has the type of
                    521: the value most recently assigned to it.
                    522: Except for a few predefined variables
                    523: (described under
                    524: .I "pattern matching" ),
                    525: all variables have the null string as their initial values.
                    526: All variables are global, but procedures
                    527: can nominate variables whose
                    528: values will automatically be saved at
                    529: entry and restored at exit.
                    530: The only declarations define
                    531: structures:
                    532: .P1 0
                    533: struct cons {car, cdr}
                    534: .P2
                    535: In effect, this declaration defines three procedures named
                    536: \f(CWcons\fP, 
                    537: \f(CWcar\fP,
                    538: and \f(CWcdr\fP.
                    539: The value of \f(CWcons(a,b)\fP is a newly-created
                    540: \f(CWcons\fP object with \f(CWa\fP and \f(CWb\fP
                    541: as the values of its \f(CWcar\fP and \f(CWcdr\fP fields,
                    542: respectively.
                    543: The fields, in turn, are accessed by similarly-named
                    544: functions.
                    545: For instance, the \f(CWcdr\fP field of \f(CWcons\fP structure \f(CWx\fP
                    546: is accessed as \f(CWcdr(x)\fP.
                    547: Thus this program:
                    548: .P1 0
                    549: struct cons {car, cdr}
                    550: a = cons (3, cons (4, 5))
                    551: OUTPUT = car (cdr (a))
                    552: .P2
                    553: prints \f(CW4\fP.
                    554: The procedures corresponding to field names may
                    555: be used as the target of an assignment:
                    556: .P1 0
                    557: car (a) = "Hello"
                    558: .P2
                    559: Snocone offers other data types than those described above.
                    560: While
                    561: numeric constants cannot be negative, variables and expressions
                    562: suffer from no such restriction.
                    563: Strings may be of any length up
                    564: to an implementation-defined upper bound, usually many thousands
                    565: of characters.
                    566: All variables have the null string as their
                    567: initial value.
                    568: .PP
                    569: Aggregate values come in two types: arrays and tables.
                    570: Each type
                    571: is created by a built-in procedure with the same name.
                    572: Thus:
                    573: .P1 0
                    574: a = ARRAY (20)
                    575: .P2
                    576: creates a 20-element array, initializes each element to the null
                    577: string, and assigns it to a.
                    578: The second argument to the array
                    579: procedure is an initializing value:
                    580: .P1 0
                    581: a = ARRAY (20, -1)
                    582: .P2
                    583: makes a an array of 20 elements, each with value \-1.
                    584: To get
                    585: multi-dimensional arrays, express the dimensions as a string:
                    586: .P1 0
                    587: a = ARRAY ('4,5', -1)
                    588: .P2
                    589: One can also give explicit lower bounds:
                    590: .P1 0
                    591: a = ARRAY ('-10:10')
                    592: .P2
                    593: The default lower bound is 1.
                    594: .PP
                    595: Array elements are referenced by Algol-like subscripts:
                    596: .P1 0
                    597: a[i,j] = a[i,j] + b[i,k] * c[k,j]
                    598: .P2
                    599: Each array element behaves as a variable, and can therefore have
                    600: a value of any data type, independently of any other element.
                    601: .PP
                    602: A table is like a one-dimensional array whose subscripts are not
                    603: restricted to integers:
                    604: .P1 0
                    605: t = TABLE (20)
                    606: .P2
                    607: The argument to the \f(CWTABLE\fP procedure is an estimate of the maximum
                    608: number of elements that will actually be stored in the table.
                    609: If substantially more elements than
                    610: this are stored, access will
                    611: begin to slow down.
                    612: On the other hand, giving too large an
                    613: initial value wastes space.
                    614: Once a table has been created, any
                    615: value can be used for a subscript.
                    616: \f(CWt[a]\fP and \f(CWt[b]\fP will refer to
                    617: the same element if and only if a and b are identical.
                    618: The
                    619: precise meaning of ``identical'' is given with the description of
                    620: the \f(CW::\fP and \f(CW:!:\fP operators;
                    621: suffice it to say that \f(CW3\fP and \f(CW"3"\fP are
                    622: not identical, and that after executing
                    623: .P1 0
                    624: a = b
                    625: .P2
                    626: \f(CWa\fP and \f(CWb\fP are
                    627: identical regardless of what values they had before.
                    628: .NH 2
                    629: Binary Operators
                    630: .PP
                    631: The following operators are grouped in order of decreasing priority.
                    632: Unless otherwise stated, they are left-associative.
                    633: .IP "\f(CW. $\fP"
                    634: Pattern value assignment (see Patterns)
                    635: .IP "\f(CW^\fP"
                    636: Exponentiation (right-associative).
                    637: The right argument
                    638: must be an integer.
                    639: If both arguments are integers,
                    640: the right argument must be non-negative
                    641: .IP "\f(CW* / %\fP"
                    642: .br
                    643: Multiplication, division, and remainder.
                    644: As in C,
                    645: and as not in \*(S4, multiplication and
                    646: division have the same precedence.
                    647: .IP "\f(CW+ -\fP"
                    648: Addition and subtraction.
                    649: .IP "\f(CW== != < > <= >= :==: :!=:\fP"
                    650: .IP "\f(CW:<: :>: :<=: :>=: :: :!:\fP"
                    651: .br
                    652: Comparison predicates.
                    653: Each of these operators returns
                    654: a null string if the indicated relation holds,
                    655: and fails if not.
                    656: The first six do
                    657: numeric comparisons: an error results if either
                    658: operand cannot be converted to a number.
                    659: The next six do string comparisons: an error results
                    660: if either operand cannot be converted to a string.
                    661: The last two test if the two operands are identical.
                    662: Values of different data types are never identical.
                    663: Strings and numbers are identical if their data types and values match.
                    664: Other values are identical if they refer to the same object.
                    665: .IP "\f(CW&&\fP"
                    666: Concatenation.
                    667: The left operand is evaluated
                    668: first; if its evaluation fails, the \f(CW&&\fP operator fails.
                    669: Otherwise, the right operand is
                    670: evaluated, and \f(CW&&\fP fails if the right operand fails.
                    671: If either operand is the null string, the
                    672: result is the other operand, even if that operand is not a string.
                    673: Otherwise, both operands are
                    674: converted to strings and the result is their concatenation.
                    675: An error results if either
                    676: operand cannot be converted to a string.
                    677: Note that if the operands of \f(CW&&\fP are predicates,
                    678: \f(CW&&\fP can be used as a kind of logical conjunction.
                    679: .IP "\f(CW||\fP"
                    680: Logical disjunction.
                    681: The left operand is evaluated first; if it
                    682: succeeds, its value is the value of \f(CW||\fP.
                    683: Otherwise, the value is that of the right operand.
                    684: If both operands fail, \f(CW||\fP fails.
                    685: .IP "\f(CW|\fP"
                    686: Pattern alternation.
                    687: See
                    688: .I "pattern matching"
                    689: for details.
                    690: .IP "\f(CW=\fP"
                    691: Assignment.
                    692: This operator is right-associative.
                    693: .IP "\f(CW?\fP"
                    694: Pattern match operator.
                    695: The left operand is
                    696: converted to a string and searched for the first
                    697: substring that matches the pattern given by the right operand.
                    698: If no such substring is found, the operator fails.
                    699: If the left operand is a variable, \f(CW?\fP may be used on the left
                    700: side of an assignment.
                    701: .NH 2
                    702: Unary Operators
                    703: .PP
                    704: Unary operators bind more tightly than all binary
                    705: operators.
                    706: .IP "\f(CW+ -\fP"
                    707: Unary plus and minus.
                    708: The result is always
                    709: numeric, so unary plus is sometimes used for type conversion.
                    710: Because unary operators bind so tightly, expressions that look like negative
                    711: constants behave that way for all practical purposes.
                    712: .IP "\f(CW.\fP"
                    713: Name operator.
                    714: The operand must be a variable;
                    715: the result is essentially a pointer to the variable, similarly
                    716: to the unary & operator in C.
                    717: The result of applying the \f(CWDATATYPE\fP function
                    718: to the result of the \f(CW.\fP operator is the string \f(CW"NAME"\fP.
                    719: .IP "\f(CW$\fP"
                    720: Indirection.
                    721: The operand is converted to a name;
                    722: the result is the object thus named.
                    723: \f(CW$\fP always yields an lvalue.
                    724: .IP "\f(CW?\fP"
                    725: Query.
                    726: If its operand fails, \f(CW?\fP fails.
                    727: If its operand succeeds, \f(CW?\fP yields a null string.
                    728: Useful for evaluating an expression solely for
                    729: its side effects.
                    730: .IP "\f(CW~\fP"
                    731: Logical negation.
                    732: If its operand fails, \f(CW~\fP yields a null string.
                    733: If the operand succeeds, \f(CW~\fP fails.
                    734: .IP "\f(CW&\fP"
                    735: Keyword value.
                    736: The operand must be the name of one of a restricted set of variables.
                    737: The lvalue result is a system variable, whose value affects the
                    738: execution of the program in some way.
                    739: System variables are discussed separately.
                    740: .IP "\f(CW@\fP"
                    741: Pattern cursor assignment.
                    742: See
                    743: .I "pattern matching"
                    744: for details.
                    745: .IP "\f(CW*\fP"
                    746: Deferred evaluation.
                    747: Returns a value of type \f(CWEXPRESSION\fP that
                    748: contains all the information necessary to evaluate the operand.
                    749: The operand is not actually evaluated at this time, but can be
                    750: evaluated later,
                    751: either by the \f(CWEVAL\fP procedure or implicitly during pattern matching.
                    752: .NH 2
                    753: Statements
                    754: .PP
                    755: Elements in brackets are optional.
                    756: If the description of a statement
                    757: is split over more than one line, the statement itself may be split
                    758: analogously.
                    759: Snocone does not have a null statement.
                    760: .Sx
                    761: \fIexpression\fP
                    762: .Sy
                    763: .Tx
                    764: The expression is evaluated for its side effects.
                    765: The result, if any, is discarded.
                    766: .Tm if S
                    767: .Ty
                    768: .Sx
                    769: if (\fIexpression\fP)
                    770:        \fIstatement1\fP
                    771: [ else
                    772:        \fIstatement2\fP ]
                    773: .Sy
                    774: .Tx
                    775: The parenthesized
                    776: .I expression
                    777: is evaluated.
                    778: If it
                    779: succeeds,
                    780: .I statement1
                    781: is executed, otherwise
                    782: .I statement2
                    783: is executed.
                    784: .Ty
                    785: .Sx
                    786: while (\fIexpression\fP)
                    787:        \fIstatement\fP
                    788: .Sy
                    789: .Tx
                    790: Behaves similarly to C: the
                    791: .I expression
                    792: is evaluated,
                    793: and if it succeeds, the
                    794: .I statement
                    795: is executed and
                    796: control passes back to the beginning of the \f(CWwhile\fP
                    797: statement.
                    798: Unlike C, Snocone has no
                    799: .I break
                    800: or
                    801: .I continue
                    802: statements.
                    803: .Ty
                    804: .Sx
                    805: do
                    806:        \fIstatement\fP
                    807: while (\fIexpression\fP)
                    808: .Sy
                    809: .Tx
                    810: Behaves similarly to C: the
                    811: .I "statement"
                    812: is executed, then the
                    813: .I expression
                    814: is evaluated, and if the
                    815: .I expression
                    816: succeeds, control passes back to the beginning of the \f(CWdo\fP
                    817: statement.
                    818: .Tm for        S
                    819: .Ty
                    820: .Sx
                    821: for (\fIexpression1\fP, \fIexpression2\fP, \fIexpression3\fP)
                    822:        \fIstatement\fP
                    823: .Sy
                    824: .Tx
                    825: Equivalent to:
                    826: .P1 0
                    827: \fIexpression1\fP
                    828: while (\fIexpression3\fP) {
                    829:        \fIstatement\fP
                    830:        \fIexpression2\fP
                    831: }
                    832: .P2
                    833: .Ty
                    834: .Sx
                    835: {
                    836:        \fIstatement list\fP
                    837: }
                    838: .Sy
                    839: .Tx
                    840: The statements in the list, which may contain zero or
                    841: more statements, are executed in sequence.
                    842: .Ty
                    843: .Sx
                    844: \fIlabel\fP: \fIstatement\fP
                    845: .Sy
                    846: .Tx
                    847: All labels are global (because all \*(S4
                    848: labels are global), even across procedure boundaries,
                    849: so they must be chosen with care.
                    850: A useful convention is
                    851: to begin a label inside a procedure body with the name
                    852: of the procedure and an underscore.
                    853: .Ty
                    854: .Sx
                    855: go to \fIlabel\fP
                    856: .Sy
                    857: .Tx
                    858: The space between \f(CWgo\fP and \f(CWto\fP is optional.
                    859: It is wise
                    860: not to jump from a point inside one procedure into another.
                    861: Program
                    862: execution may be terminated by jumping to the reserved
                    863: label \f(CWEND\fP.
                    864: Labels \f(CWRETURN\fP, \f(CWFRETURN\fP, \f(CWNRETURN\fP, \f(CWABORT\fP, and
                    865: \f(CWCONTINUE\fP are also reserved.
                    866: .Ty
                    867: .Sx
                    868: return [ \fIexpression\fP ]
                    869: .Sy
                    870: .Tx
                    871: The current procedure returns to its caller.
                    872: If the
                    873: .I expression
                    874: is given, the procedure yields that value.
                    875: If no
                    876: .I expression
                    877: is given, the value returned is that of
                    878: the variable with the same name as the procedure; if
                    879: that variable was not assigned in the procedure, the
                    880: null string is returned.
                    881: .Ty
                    882: .Sx
                    883: freturn
                    884: .Sy
                    885: .Tx
                    886: The current procedure returns and fails.
                    887: .Ty
                    888: .Sx
                    889: nreturn [ \fIexpression\fP ]
                    890: .Sy
                    891: .Tx
                    892: The current procedure returns \f(CW$(\fP\fIexpression\fP\f(CW)\fP as an
                    893: lvalue.
                    894: If the
                    895: .I expression
                    896: is not given, the indirection
                    897: is applied to the variable with the same name as the
                    898: procedure.
                    899: An error results if this variable was not
                    900: given a value inside the procedure.
                    901: .NH 2
                    902: Procedures
                    903: .PP
                    904: Here is an example of a procedure declaration:
                    905: .P1 0
                    906: procedure gcd (m, n) {
                    907:        while (m != n) {
                    908:                if (m > n)
                    909:                        m = m % n
                    910:                else
                    911:                        n = n % m
                    912:        }
                    913:        return m
                    914: }
                    915: .P2
                    916: .PP
                    917: Arguments are passed by value, but note that the value passed for
                    918: an aggregate argument (array, table, or structure) is really a
                    919: pointer to the aggregate itself.
                    920: .PP
                    921: If a procedure is called with too few arguments, extra null strings
                    922: are supplied as necessary.
                    923: If called with too many arguments, the extras
                    924: are quietly ignored.
                    925: .PP
                    926: Local variables can be nominated for a procedure:
                    927: .P1 0
                    928: procedure f(x) y, z {...
                    929: .P2
                    930: All variables are global, but name scoping is dynamic.
                    931: One way to look
                    932: at it is to imagine that when a procedure
                    933: is entered, all the variables defined in that procedure are saved and
                    934: set to null.
                    935: Those variables are then restored when the procedure returns.
                    936: .PP
                    937: Thus, the following example prints 5 and then 1:
                    938: .P1 0
                    939: a = 1
                    940: f()
                    941: g()
                    942: 
                    943: procedure f() a {
                    944:        a = 5
                    945:        g()
                    946: }
                    947: 
                    948: procedure g() {
                    949:        OUTPUT = a
                    950: }
                    951: .P2
                    952: The following example also prints 5 and then 1:
                    953: .P1 0
                    954: a = 1
                    955: b = .a
                    956: f()
                    957: g()
                    958: .P3
                    959: procedure f() a {
                    960:        a = 5
                    961:        g()
                    962: }
                    963: .P3
                    964: procedure g() {
                    965:        OUTPUT = $b
                    966: }
                    967: .P2
                    968: Local variables can only be associated with procedures.
                    969: Procedures are
                    970: recursive.
                    971: .NH 2
                    972: Input-Output
                    973: .PP
                    974: All I/O is done through ``associated variables''.
                    975: A variable may be
                    976: input-associated or output-associated (or both).
                    977: Whenever a value is
                    978: assigned to an output-associated variable, that value is automatically
                    979: written in the file associated with that variable.
                    980: Whenever a value
                    981: is requested for an input-associated variable, a line is read from the
                    982: file associated with that variable, and the contents of the line are
                    983: used for the value.
                    984: When the end of an input file is reached,
                    985: any attempts to access variables associated
                    986: with that file will fail.
                    987: .PP
                    988: Initially, the variable \f(CWOUTPUT\fP is output-associated with the standard
                    989: output file, the variable \f(CWINPUT\fP is input-associated with the standard
                    990: input file, and the variable \f(CWTERMINAL\fP is both input-
                    991: and output-associated
                    992: with the user's terminal.
                    993: .PP
                    994: Thus, the following program copies its standard
                    995: input to its standard output, a line at a time:
                    996: .P1 0
                    997: while (OUTPUT = INPUT) {}
                    998: .P2
                    999: .PP
                   1000: New associations are formed by the \f(CWINPUT\fP
                   1001: and \f(CWOUTPUT\fP procedures:
                   1002: .P1 0
                   1003: INPUT  (\fIname\fP, \fIchannel\fP, \fIfile\fP)
                   1004: OUTPUT (\fIname\fP, \fIchannel\fP, \fIfile\fP)
                   1005: .P2
                   1006: In both cases, 
                   1007: .I name
                   1008: is the name of the variable to be associated (the
                   1009: name of the variable
                   1010: .I x
                   1011: is \f(CW.x\fP), and
                   1012: .I file
                   1013: is the file to be used.
                   1014: .I Channel
                   1015: is a string that you will use to identify subsequent operations
                   1016: on that file.
                   1017: Internally, there is a one-to-one correspondence between
                   1018: channel names and file descriptors.
                   1019: .PP
                   1020: The file argument must not be given for other than the first call to
                   1021: \f(CWINPUT\fP or \f(CWOUTPUT\fP on a given channel, as a channel can only be
                   1022: connected to a single file.
                   1023: .PP
                   1024: Other procedures dealing with input-output are:
                   1025: .Tm SET        S
                   1026: .Sx
                   1027: SET (\fIchannel\fP, \fIoffset\fP, \fIwhence\fP)
                   1028: .Sy
                   1029: .Tx
                   1030: This function repositions the file specified by its
                   1031: first argument in a system-dependent manner.
                   1032: In implementations running under the
                   1033: .UX
                   1034: system, the behavior is similar to the
                   1035: .I lseek
                   1036: system call.
                   1037: .Ty
                   1038: .Sx
                   1039: REWIND (\fIchannel\fP)
                   1040: .Sy
                   1041: .Tx
                   1042: Repositions the named channel to the beginning of the file.
                   1043: .Ty
                   1044: .Sx
                   1045: ENDFILE (\fIchannel\fP)
                   1046: .Sy
                   1047: .Tx
                   1048: Indicates that you are done using the given channel.
                   1049: All variables associated through that channel are
                   1050: disassociated, output buffers are flushed (if any),
                   1051: and the file is closed.
                   1052: .Ty
                   1053: .Sx
                   1054: DETACH (\fIname\fP)
                   1055: .Sy
                   1056: .Tx
                   1057: Disassociates the named variable.
                   1058: Does not close
                   1059: the file: a later call to \f(CWINPUT\fP or \f(CWOUTPUT\fP can reassociate it.
                   1060: .NH 2
                   1061: Pattern Matching
                   1062: .PP
                   1063: A
                   1064: .I pattern
                   1065: is a data structure that describes a class of strings.
                   1066: Patterns
                   1067: are used by the \f(CW?\fP operator,
                   1068: which determines if the string given as its
                   1069: left operand contains a substring described by the pattern given as its
                   1070: right operand.
                   1071: The part of the Snocone system that
                   1072: does this is called the
                   1073: .I scanner .
                   1074: The input to the scanner is the string to be searched,
                   1075: called the
                   1076: .I subject ,
                   1077: and the pattern sought.
                   1078: .PP
                   1079: The scanner tries to find a substring of the
                   1080: subject that is matched by the pattern.
                   1081: It first looks at substrings starting at
                   1082: the first character of the subject.
                   1083: If it doesn't find one, it tries the ones
                   1084: starting at the second subject character,
                   1085: and so on.
                   1086: If the scanner cannot find an appropriate
                   1087: substring, the pattern match fails.
                   1088: .PP
                   1089: If the \f(CW&ANCHOR\fP system variable is
                   1090: nonzero, the scanner only looks at substrings
                   1091: that start at the first character of the
                   1092: subject.
                   1093: This is said to be an
                   1094: .I anchored
                   1095: pattern match.
                   1096: The \f(CW&ANCHOR\fP variable is zero at the
                   1097: start of program execution.
                   1098: .PP
                   1099: The important part of pattern matching is therefore
                   1100: determining whether the subject contains a
                   1101: substring that starts at a given character
                   1102: and matches a given pattern.
                   1103: To understand how this is done, we must
                   1104: take a closer look at patterns.
                   1105: .PP
                   1106: Every pattern is a concatenation of one or more
                   1107: .I elements ,
                   1108: each of which has zero or more
                   1109: .I alternatives .
                   1110: Each alternative may itself be an arbitrarily complicated pattern.
                   1111: Some patterns have alternatives that are determined
                   1112: dynamically as they are needed during pattern matching.
                   1113: .PP
                   1114: If a pattern has only one element, the scanner determines
                   1115: if it matches at a given point by trying to match each
                   1116: of the pattern's alternatives at that point.
                   1117: If no alternative matches at that point, the element
                   1118: cannot be matched.
                   1119: .PP
                   1120: If the pattern has more than one element,
                   1121: matching that pattern at a given point means:
                   1122: (a) finding an alternative for the first element
                   1123: of the pattern that matches a subject substring
                   1124: starting at the given point, and that also (b) allows
                   1125: the remaining elements of the pattern to match
                   1126: a substring that starts immediately after the
                   1127: substring matched in (a).
                   1128: .PP
                   1129: During pattern matching, the scanner keeps its place
                   1130: by means of an internal value called the
                   1131: .I cursor ,
                   1132: which represents the number of characters in the
                   1133: subject that precede the current location.
                   1134: These characters are counted from the beginning
                   1135: of the subject even when the scanner is trying
                   1136: to match a substring that starts at some other place
                   1137: in the subject.
                   1138: .PP
                   1139: The concatenation of two patterns \f(CWP1\fP and \f(CWP2\fP
                   1140: is a pattern whose elements
                   1141: are \f(CWP1\fP and \f(CWP2\fP.
                   1142: The alternation operator \f(CW|\fP similarly constructs alternatives.
                   1143: When a string is used as a pattern, it matches only itself.
                   1144: Thus,
                   1145: .P1 0
                   1146: "a" | "e" | "i" | "o" | "u"
                   1147: .P2
                   1148: is a pattern that matches any lower-case vowel.
                   1149: .PP
                   1150: Consider the following
                   1151: statement:
                   1152: .P1 0
                   1153: P1 = ("ab" | "a") && ("b" | "c")
                   1154: .P2
                   1155: This assigns to \f(CWP\fP a pattern with two elements.
                   1156: The first one matches
                   1157: either \f(CWab\fP or \f(CWa\fP, and the second matches either
                   1158: \f(CWb\fP or \f(CWc\fP.
                   1159: Look at:
                   1160: .P1 0
                   1161: "ab" ? P1
                   1162: .P2
                   1163: The scanner first tries the first alternative of the first element of
                   1164: P1 by matching \f(CWab\fP in the subject with \f(CWab\fP in the pattern.
                   1165: This alternative matches, so the element (\f(CW"ab"|"a"\fP) matches, and
                   1166: the scanner goes on to the second element (\f(CW"b"|"c"\fP).
                   1167: Here, it will be unsuccessful
                   1168: in matching both \f(CWb\fP and \f(CWc\fP,
                   1169: because it has already exhausted all the
                   1170: characters of the subject.
                   1171: Thus the scanner fails to match the second element of
                   1172: \f(CWP1\fP, and must back up and rematch the first element.
                   1173: Fortunately, the
                   1174: first element has an alternative in \f(CWa\fP;
                   1175: this matches, and now the scanner
                   1176: can try to match the second element (\f(CW"b"|"c"\fP) again.
                   1177: The first alternative (\f(CWb\fP) succeeds, so
                   1178: the \f(CW?\fP operator therefore succeeds.
                   1179: If we wanted to examine just how the pattern elements matched,
                   1180: we could have written:
                   1181: .P1 0
                   1182: P1a = ("ab"|"a").OUTPUT && ("b"|"c").OUTPUT
                   1183: "ab" ? P1a
                   1184: .P2
                   1185: This would print \f(CWa\fP and \f(CWb\fP on separate lines,
                   1186: showing that \f(CW"ab"|"a"\fP matched \f(CWa\fP and
                   1187: \f(CW"b"|"c"\fP matched \f(CWb\fP.
                   1188: .PP
                   1189: When any pattern is first encountered
                   1190: during pattern matching, it will match some string, and when the scanner
                   1191: backs into it, it may match some other string.
                   1192: Because many patterns behave
                   1193: differently on their initial match than when rematched, it is useful to
                   1194: describe the two cases separately.
                   1195: .PP
                   1196: For instance, when a string is used as a pattern, it initially matches
                   1197: itself.
                   1198: If the scanner later backs into it, it fails.
                   1199: .PP
                   1200: As another example, consider \f(CWP1|P2\fP.
                   1201: This pattern matches every
                   1202: possibility for \f(CWP1\fP, and when it has exhausted \f(CWP1\fP,
                   1203: then matches every
                   1204: possibility for \f(CWP2\fP before finally failing.
                   1205: .PP
                   1206: With this in mind, we can describe the various pattern-matching operators,
                   1207: procedures, and pre-defined variables:
                   1208: .IP "\f(CWP1 && P2\fP" 10
                   1209: Tries to match \f(CWP1\fP, fails if it can't.
                   1210: Then tries to match \f(CWP2\fP.
                   1211: If \f(CWP2\fP fails, tries the next alternative for
                   1212: \f(CWP1\fP, and then tries \f(CWP2\fP again.
                   1213: Eventually, it either
                   1214: runs out of alternatives for \f(CWP1\fP, in which case \f(CWP1&&P2\fP
                   1215: fails, or it finds alternatives for both \f(CWP1\fP and \f(CWP2\fP which
                   1216: allow them to match.
                   1217: .IP "\f(CWP1 | P2\fP"
                   1218: Tries to match \f(CWP1\fP.
                   1219: If successful, \f(CWP1|P2\fP matches the
                   1220: string that was matched by \f(CWP1\fP.
                   1221: Otherwise, matches whatever
                   1222: \f(CWP2\fP matches, and fails if \f(CWP2\fP fails.
                   1223: .IP "\f(CWP $ V\fP"
                   1224: Tries to match \f(CWP\fP.
                   1225: If \f(CWP\fP matches, a copy of the substring
                   1226: matched by \f(CWP\fP is immediately assigned to the variable \f(CWV\fP.
                   1227: .IP "\f(CWP . V\fP"
                   1228: Tries to match \f(CWP\fP.
                   1229: If the entire pattern match of which
                   1230: this element is a part is ultimately successful, a copy
                   1231: of the substring matched by \f(CWP\fP is assigned to \f(CWV\fP after
                   1232: the entire match completes.
                   1233: .IP "\f(CW@N\fP"
                   1234: Matches a null string, and immediately assigns
                   1235: cursor position to the variable \f(CWN\fP.
                   1236: The cursor position is
                   1237: the number of characters that precede this null string
                   1238: in the subject of the entire pattern match.
                   1239: Thus:
                   1240: .P1
                   1241: "abcde" ? @OUTPUT && "c"
                   1242: .P2
                   1243: prints \f(CW0\fP, \f(CW1\fP, and \f(CW2\fP on separate lines.
                   1244: .IP "\f(CWABORT\fP"
                   1245: The entire pattern match is aborted.
                   1246: .IP "\f(CWARB\fP"
                   1247: A pre-defined variable that matches anything at all.
                   1248: More specifically, it initially matches the null string.
                   1249: When backed into, it matches a string one character longer
                   1250: than the one it matched last time.
                   1251: .IP "\f(CWBAL\fP"
                   1252: A pre-defined variable that matches a non-empty parenthesis-
                   1253: balanced string.
                   1254: This string is balanced only with respect to parentheses,
                   1255: and not any other kinds of brackets.
                   1256: .IP "\f(CWFAIL\fP"
                   1257: A pre-defined variable that always fails to match.
                   1258: It
                   1259: is sometimes useful to force the scanner to try all
                   1260: alternatives for a pattern.
                   1261: For instance:
                   1262: .P1
                   1263: s ARB $ OUTPUT && FAIL
                   1264: .P2
                   1265: prints all substrings of \f(CWs\fP.
                   1266: .IP "\f(CWFENCE\fP"
                   1267: Initially matches the null string, but if the scanner
                   1268: backs into it, the entire pattern match is aborted.
                   1269: Identical to to \f(CW""|ABORT\fP.
                   1270: .IP "\f(CWREM\fP"
                   1271: Matches from the current position to the end of the
                   1272: subject.
                   1273: Identical to \f(CWRTAB(0)\fP.
                   1274: .IP "\f(CWSUCCEED\fP"
                   1275: Identical to \f(CWARBNO("")\fP
                   1276: .IP "\f(CWANY(s)\fP"
                   1277: Matches any single character in \f(CWs\fP.
                   1278: .IP "\f(CWARBNO(p)\fP"
                   1279: A pre-defined procedure that yields a pattern that matches
                   1280: zero or more copies of the pattern \f(CWp\fP.
                   1281: Initially matches
                   1282: the null string.
                   1283: Each time the scanner backs into it,
                   1284: it tries to extend the substring already matched by
                   1285: matching one more instance of \f(CWp\fP.
                   1286: .IP "\f(CWBREAK(s)\fP"
                   1287: Matches a string starting at the current position up to
                   1288: but not including the next character in the subject
                   1289: that is also found somewhere in \f(CWs\fP.
                   1290: Failure
                   1291: if no such character is found.
                   1292: No alternatives.
                   1293: .IP "\f(CWBREAKX(s)\fP"
                   1294: Like \f(CWBREAK\fP, but if backed into, it matches up to the
                   1295: next subject character also found in \f(CWs\fP, and so on.
                   1296: .IP "\f(CWLEN(n)\fP"
                   1297: Matches exactly \f(CWn\fP characters.
                   1298: .IP "\f(CWNOTANY(s)\fP"
                   1299: Matches any single character not in \f(CWs\fP.
                   1300: .IP "\f(CWPOS(n)\fP"
                   1301: If exactly \f(CWn\fP subject characters precede the current
                   1302: position, \f(CWPOS\fP matches the null string.
                   1303: Otherwise it
                   1304: fails.
                   1305: .IP "\f(CWRPOS(n)\fP"
                   1306: If exactly \f(CWn\fP subject characters remain to be matched,
                   1307: \f(CWRPOS\fP matches the null string.
                   1308: Otherwise it fails.
                   1309: .IP "\f(CWRTAB(n)\fP"
                   1310: If at least \f(CWn\fP subject characters remain in the subject,
                   1311: \f(CWRTAB\fP matches characters until exactly \f(CWn\fP remain.
                   1312: Otherwise
                   1313: it fails.
                   1314: .IP "\f(CWSPAN(s)\fP"
                   1315: Starting at the current position, matches as many characters
                   1316: as possible taken from \f(CWs\fP.
                   1317: .IP "\f(CWTAB(n)\fP"
                   1318: \f(CWTAB\fP matches from the current position forward up to
                   1319: and including the \f(CWn\fPth character of the subject.
                   1320: If more than \f(CWn\fP characters have already been matched
                   1321: in the subject string, \f(CWTAB\fP fails.
                   1322: .PP
                   1323: All pattern-valued procedures can take an unevaluated expression as argument.
                   1324: The expression will be evaluated when the pattern element is matched.
                   1325: .SH
                   1326: System Variables
                   1327: .PP
                   1328: The \f(CW&\fP operator looks at the name of its operand,
                   1329: not its value.
                   1330: For each of a small set of names, \f(CW&\fP yields a
                   1331: .I "system variable" ,
                   1332: whose value affects the operation of the system in some way.
                   1333: For instance, we have already seen \f(CW&ANCHOR\fP, which
                   1334: controls whether or not the scanner is restricted to examining
                   1335: initial substrings of the subject.
                   1336: The complete list of system variables is:
                   1337: .IP "\f(CW&ABORT\fP" 13
                   1338: The same value as the pre-defined variable \f(CWABORT\fP.
                   1339: .IP "\f(CW&ALPHABET\fP"
                   1340: A string that contains all the characters of the machine's
                   1341: collating sequence, in order.
                   1342: .IP "\f(CW&ANCHOR\fP"
                   1343: If zero, all pattern matches are unanchored,
                   1344: otherwise they are anchored.
                   1345: .IP "\f(CW&ARB\fP"
                   1346: The same value as the pre-defined variable \f(CWARB\fP.
                   1347: .IP "\f(CW&BAL\fP"
                   1348: The same value as the pre-defined variable \f(CWBAL\fP.
                   1349: .IP "\f(CW&CODE\fP"
                   1350: This variable is initially zero.
                   1351: Its value is returned to the operating system when the
                   1352: program finishes executing.
                   1353: .IP "\f(CW&DUMP\fP"
                   1354: This variable is initially zero.
                   1355: If it is 1 at the end of execution, the values of
                   1356: all variables are printed.
                   1357: If it is 2, the values of all array, table, and structure
                   1358: elements are also printed.
                   1359: .IP "\f(CW&FAIL\fP"
                   1360: The same value as the pre-defined variable \f(CWFAIL\fP.
                   1361: .IP "\f(CW&FENCE\fP"
                   1362: The same value as the pre-defined variable \f(CWFENCE\fP.
                   1363: .IP "\f(CW&FNCLEVEL\fP"
                   1364: The current level of procedure nesting.
                   1365: .IP "\f(CW&INPUT\fP"
                   1366: If this variable is set to 0, all
                   1367: input association is suspended.
                   1368: .IP "\f(CW&MAXLNGTH\fP"
                   1369: The maximum length of a string.
                   1370: This value cannot be increased beyond its
                   1371: initial value.
                   1372: .IP "\f(CW&OUTPUT\fP"
                   1373: If this variable is set to 0, all output is suppressed
                   1374: until it is again set nonzero.
                   1375: .IP "\f(CW&REM\fP"
                   1376: The same value as the pre-defined variable \f(CWREM\fP.
                   1377: .IP "\f(CW&STCOUNT\fP"
                   1378: A count of how many statements have been executed so far.
                   1379: Because this counts \*(S4 statements, not
                   1380: Snocone statements, it should be considered only approximate.
                   1381: .IP "\f(CW&STLIMIT\fP"
                   1382: When \f(CW&STCOUNT\fP reaches this value,
                   1383: execution terminates with an error message.
                   1384: It is initially 50000, and may be set freely.
                   1385: If it is set to a negative value, statement
                   1386: counting is disabled.
                   1387: .IP "\f(CW&SUCCEED\fP"
                   1388: The same value as the pre-defined variable \f(CWSUCCEED\fP.
                   1389: .NH 1
                   1390: Examples
                   1391: .NH 2
                   1392: Hello World
                   1393: .PP
                   1394: This is the canonical sample program:
                   1395: .P1 0
                   1396: OUTPUT = "Hello world!"
                   1397: .P2
                   1398: The present implementation of Snocone is case-insensitive
                   1399: in identifiers, but future versions may well become
                   1400: case-sensitive.
                   1401: If so, it is likely that pre-defined names, such as
                   1402: \f(CWINPUT\fP and \f(CWOUTPUT\fP, will have to be written
                   1403: in upper case.
                   1404: Keywords, such as \f(CWif\fP and \f(CWwhile\fP, will be
                   1405: written in lower case.
                   1406: .NH 2
                   1407: Topological Sorting
                   1408: .PP
                   1409: We now develop
                   1410: a topological sorting program based on the algorithm
                   1411: described on page 262 of
                   1412: .I "Fundamental Algorithms" |reference(knuth volume1).
                   1413: The reader may wish to compare this program with the
                   1414: \*(S4 program based on the same algorithm
                   1415: that appears on pages 221-222 of
                   1416: .I "The \*(S4 Programming Language" .
                   1417: .PP
                   1418: The input is
                   1419: a set of pairs of objects,
                   1420: where the first object in each pair
                   1421: is considered to precede the second.
                   1422: The output is a list of objects
                   1423: in a sequence that meets all the constraints
                   1424: implied by the input.
                   1425: In other words, the program generates
                   1426: a total ordering that includes a given
                   1427: partial ordering.
                   1428: .PP
                   1429: If the input contains a loop, the program
                   1430: will detect this fact and complain.
                   1431: .PP
                   1432: For example, given the following input:
                   1433: .P1
                   1434: letters alphanum
                   1435: numbers alphanum
                   1436: blanks optblanks
                   1437: numbers real
                   1438: numbers integer
                   1439: letters variable
                   1440: alphanum variable
                   1441: binary binaryop
                   1442: blanks binaryop
                   1443: unqalphabet dliteral
                   1444: unqalphabet sliteral
                   1445: sliteral literal
                   1446: dliteral literal
                   1447: integer literal
                   1448: real literal
                   1449: .P2
                   1450: the program will produce the following output:
                   1451: .P1
                   1452: letters
                   1453: numbers
                   1454: blanks
                   1455: binary
                   1456: unqalphabet
                   1457: alphanum
                   1458: real
                   1459: integer
                   1460: optblanks
                   1461: binaryop
                   1462: dliteral
                   1463: sliteral
                   1464: variable
                   1465: literal
                   1466: .P2
                   1467: .PP
                   1468: The basic strategy of the program is simple:
                   1469: for each object, we remember how many immediate predecessors
                   1470: it has, and store a list of all its immediate successors.
                   1471: When we have finished reading the input,
                   1472: we can immediately output the objects that have
                   1473: no predecessors.
                   1474: Each time we output an object, we remove it from
                   1475: the data structure and decrement the predecessor
                   1476: count of each of its immediate successors.
                   1477: .PP
                   1478: We will eventually reach a state in which we run
                   1479: out of objects without predecessors.
                   1480: When that happens, we are done.
                   1481: If any objects remain, they form a loop.
                   1482: .PP
                   1483: To reduce the time spent searching for objects
                   1484: without predecessors, we keep a queue of such
                   1485: objects.
                   1486: We must also keep a queue of the successors
                   1487: of each object.
                   1488: In both cases, we could use a stack instead of
                   1489: a queue, but using a queue tends to favor the
                   1490: order in which objects appeared in the input,
                   1491: which makes the output more intuitively useful.
                   1492: .PP
                   1493: The following structure declarations and subroutines
                   1494: manipulate queues.
                   1495: A queue consists of a header (of type \f(CWqueue\fP)
                   1496: which points to the first and last elements of
                   1497: a singly-linked list of queue elements (of type \f(CWqel\fP).
                   1498: .P1 0
                   1499: struct queue {head, tail}
                   1500: struct qel {obj, link}
                   1501: 
                   1502: .P3
                   1503: procedure enqueue (q, x) y {
                   1504:        if (head(q) :: "")
                   1505:                head(q) = tail(q) = qel(x)
                   1506:        else {
                   1507:                y = qel(x)
                   1508:                link(tail(q)) = y
                   1509:                tail(q) = y
                   1510:        }
                   1511: }
                   1512: .P3
                   1513: 
                   1514: procedure dequeue (q) x {
                   1515:        if (head(q) :: "")
                   1516:                freturn
                   1517:        x = head(q)
                   1518:        if ((head(q) = link(x)) :: "")
                   1519:                tail(q) = ""
                   1520:        return obj(x)
                   1521: }
                   1522: .P2
                   1523: .PP
                   1524: By convention, we use the null string to indicate
                   1525: the end of a list.
                   1526: This is convenient because uninitialized variables
                   1527: and structure fields and missing arguments are automatically set to
                   1528: the null string.
                   1529: Thus, the test
                   1530: .P1
                   1531: head(q) :: ""
                   1532: .P2
                   1533: is a convenient way of testing whether \f(CWhead(q)\fP
                   1534: has been set or not.
                   1535: .PP
                   1536: We represent each object as a structure containing
                   1537: the object's name (so we can print it), the count of
                   1538: immediate predecessors, and the queue of successors:
                   1539: .P1
                   1540: struct object {name, count, suc}
                   1541: .P2
                   1542: .PP
                   1543: Since we will be reading the names of objects
                   1544: rather than the objects directly, we will need
                   1545: to map names to objects.
                   1546: This can easily be done with a table and a mapping subroutine
                   1547: that creates elements in the table as needed:
                   1548: .P1 0
                   1549: namemap = TABLE()
                   1550: objects = queue()
                   1551: 
                   1552: procedure getobj (name) {
                   1553:     if ((getobj = namemap[name]) :: "") {
                   1554:         getobj = namemap[name] =
                   1555:             object (name, 0, queue())
                   1556:         enqueue (objects, getobj)
                   1557:         nobj = nobj + 1
                   1558:     }
                   1559: }
                   1560: .P2
                   1561: .PP
                   1562: This procedure uses the feature that if no return value
                   1563: is explicitly given, the value of the variable with the
                   1564: same name as the procedure is used.
                   1565: If an appropriate table element already
                   1566: exists, the \f(CW::\fP operator will fail
                   1567: and the value of \f(CWgetobj\fP will be the
                   1568: value retrieved from the table.
                   1569: As a side effect, we maintain a global queue of
                   1570: all known objects in \f(CWobjects\fP and
                   1571: count them in \f(CWnobj\fP.
                   1572: .PP
                   1573: Now that we can map from names to objects, it is
                   1574: an easy matter to enter a new relation into
                   1575: our data structure.
                   1576: Procedure \f(CWenter\fP takes the
                   1577: names of two objects:
                   1578: .P1 0
                   1579: procedure enter (p, q) {
                   1580:        p = getobj (p)
                   1581:        q = getobj (q)
                   1582:        count(q) = count(q) + 1
                   1583:        enqueue (suc(p), q)
                   1584: }
                   1585: .P2
                   1586: .PP
                   1587: We first locate the objects to which \f(CWp\fP
                   1588: and \f(CWq\fP refer, creating them if necessary.
                   1589: Since \f(CWp\fP precedes \f(CWq\fP, we increment
                   1590: the predecessor count of \f(CWq\fP and append
                   1591: \f(CWq\fP to the successor list of \f(CWp\fP.
                   1592: .PP
                   1593: Building the data structure is now just a matter of
                   1594: scanning the input file:
                   1595: .P1 0
                   1596: while (line = INPUT) {
                   1597:    if (line ? FENCE && BREAK(' ').p &&
                   1598:                SPAN(' ') && rem.q)
                   1599:         enter (p, q)
                   1600:     else
                   1601:         TERMINAL = "bad input line: " && line
                   1602: }
                   1603: .P2
                   1604: .PP
                   1605: The pattern match assumes that everything up to the first
                   1606: blank in the input line is the first object in a
                   1607: relation, and everything after the first blank is
                   1608: the second object.
                   1609: If the match fails, the program complains.
                   1610: .PP
                   1611: Once all the input has been read, we must initialize
                   1612: the queue of minimal objects (objects without predecessors).
                   1613: This was the reason for keeping a queue of all objects,
                   1614: which is now destroyed to build the queue of minimal objects.
                   1615: It is not necessary to destroy the queue, but it is more
                   1616: convenient because it is then possible to use \f(CWdequeue\fP:
                   1617: .P1 0
                   1618: zeroes = queue()
                   1619: 
                   1620: while (x = dequeue (objects))
                   1621:        if (count (x) == 0)
                   1622:                enqueue (zeroes, x)
                   1623: .P2
                   1624: .PP
                   1625: As long as there is a minimal object,
                   1626: we can print its name, delete it, and
                   1627: decrement the predecessor count of each
                   1628: of its successors.
                   1629: If we decrement a predecessor count to
                   1630: zero, that object is now minimal.
                   1631: .P1 0
                   1632: while (x = dequeue (zeroes)) {
                   1633:     nobj = nobj - 1
                   1634:     OUTPUT = name(x)
                   1635:     while (y = dequeue (suc (x))) {
                   1636:         if ((count(y) = count(y) - 1) == 0)
                   1637:             enqueue (zeroes, y)
                   1638:     }
                   1639: }
                   1640: .P2
                   1641: .PP
                   1642: This loop runs until there are no more minimal objects.
                   1643: If there are still elements remaining (\f(CWnobj\fP is nonzero),
                   1644: then those elements form a loop.
                   1645: .P1 0
                   1646: if (nobj != 0)
                   1647:     TERMINAL = "The ordering contains a loop."
                   1648: .P2
                   1649: .NH 1
                   1650: References
                   1651: .LP
                   1652: |reference_placement

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.