next up previous contents index
Next: Debugging Glish Scripts and Up: Using Glish Previous: Using Glish

The Glish Interpreter

 

  All Glish scripts are executed by the Glish interpreter. This program     is invoked as:

    -v is an optional verbose flag indicating that the interpreter should report on its activity. If specified once then its reports the name and value of each event it receives from a client. If specified twice then it both does this reporting, and reports each event as it queues it for ``notification" (i.e., triggering of whenever statements), and as it removes the notification from the queue and actually performs it.

    -l is an optional load flag. It indicates that these files should be loaded initially before doing anything else. Multiple -l flags can be used to load several Glish script files before either going to interactive mode or running another script.

    bindings is an optional list of environment variable bindings of the form:

var = value

file is the optional name of the source file to compile and execute. By convention such files end in a ``.g" suffix. If file is missing or if the first argument is ``-'', then Glish runs interactively (§ 11.1.1, page gif).

args is an optional list of arguments to pass to the Glish script; if present, args may optionally (for backward compatibility) be delimited from the preceding     file using the special argument ``-". ``-'' may also be used in lieu of an initial file to specify that the interpreter should run interactively (§ 11.1.1, page gif).

The Glish interpreter adds the given bindings to the environment, compiles the listed files, and then executes the result with the given args. For example,  

    glish host=cruncher myscript.g 10 12.5
will compile the script myscript.g and run it with argv equal to "10 12.5" (see § 9.11, page gif, for a discussion of the argv global); the record field environ.host will equal "cruncher" (see § 9.11, page gif, for a discussion of the environ global).

Prior to compiling the specified files, the interpreter attempts to       evaluate local customization files. It first looks for a local system wide .glishrc file. The location of this file is established at build time. Next it attempts to find a user customization file. If the   $GLISHRC environment variable is set and contains the path to a valid file. Glish uses the file it names as the user's the customization file. If the variable is not set then it looks     for the file ``.glishrc", first checking the current directory and then the user's home directory. If it finds the file then it compiles it before proceeding with the files on the command line.

If you don't specify any arguments, or if you give the ``-'' argument instead of a source file name, then Glish is run interactively, discussed in the next section. § 11.1.2, page gif then discusses execution of a Glish script more generally.  

Using Glish Interactively

 

  When run interactively, the Glish interpreter     prompts with a dash (``- ") for input. At this prompt you may type any legal Glish statement (or expression, since expressions are statements). This prompt changes   to a plus sign (``+ ") if you need to type some more input to complete the statement you've begun. Glish then executes the statement and prints the result, continuing until you type an end-of-file (usually control-D). For example,  

largo 130 % glish
Glish version 2.1.
- 1:3 * 2:4
[2 6 12]
- (end-of-file)
largo 131 %
shows using Glish interactively to evaluate the product of [1, 2, 3] times [2, 3, 4] to get [2, 6, 12].

There are no restrictions on interactive use. In particular, you may create clients and execute whenever statements, and you may execute scripts stored in files by include'ing them (§ 4.14, page gif).

How Glish Executes a Script

 

    When Glish executes a script, it first attempts to read and parse the entire file. If this succeeds, it then executes the parsed file starting with the first statement and proceeding through all the statements. If the initial parsing fails, no part of the file is executed.

When a function is encountered, the Glish interpreter compiles the function into a parse tree for later use, and then proceeds to the next statement. In this example:  

    func increment(x)
        {
        return x + 1
        }

    n := 1
    n := increment(n)
    print n
since the first statement is the definition of the increment function. The interpreter processes the functin and then proceeds to assign 1 to the global n, to call increment with this value and assign the result to n, and then to print the result.

  When a whenever is executed, Glish simply makes a note that in the future if it sees the indicated events it should execute the body of the whenever. But an important point is that whenever Glish is executing a statement block (such as when it initially   executes a script), it does not process any incoming events until after done executing the entire block. For example,  

    d := client("demo")
    d->init([5, 3])
    whenever d->init_done do
        print "done initializing demo"
    do_some_other_work()
when executed will create the client demo and send it an init event with a value of [5, 3], then sets up a whenever for dealing with d's init_done event, and finally calls the function do_some_other_work. Only after this function returns will the Glish interpreter begin reading any events d may have generated (in particular, a init_done event). Any events generated while Glish is executing a block of statements are not lost but merely queued for later processing.

This rule regarding when events are read is particularly important   in an example like the one above; the rule means that we do not have to worry about setting up a whenever for dealing with d's init_done event prior to sending an init event to d, even though perhaps d will generate this even immediately after receiving the init event, which may occur before the interpreter executes the whenever (because d's client is a process separate from the interpreter process).

One important effect of this rule, however, is that it may have unintuitive consequences when dealing with subsequences. In particular, the following program:

    x := 1

    subseq print_x()
        {
        whenever self->print do
            print x
        }

    p := print_x()
    p->print()
    x := 2
    p->print()
prints 2 followed by 2, not 1 followed by 2. This is because x is assigned to 2 before the first Glish processes the first print event sent to print_x.

Changing this sequence to:

    x := 1

    subseq print_x()
        {
        whenever self->print do
            print $value
        }

    p := print_x()
    p->print(x)
    x := 2
    p->print(x)
produces the expected output of 1 followed by 2.  

The rule of no event processing until Glish is done executing the statement block holds also when it is executing the body of a whenever statement. One exception to this rule is that     executing an await statement (§ 7.6, page gif) suspends execution of the block, so Glish begins processing events again until the await condition is met, at which point Glish continues executing the block.

  When the interpreter is processing events it first processes any pending events (those that have already arrived, or were generated by event-send's to subsequences during the last statement block's execution). If processing one of these events leads to the generation of additional events (again, those sent to subsequences) then these events, too, are processed, until all pending events have been exhausted.

At this point, the interpreter checks to see whether there are any clients   running. If not, it exits, since now there is no possibility of any further events being generated. If, however, there are some clients running, then the interpreter waits for one or more of them to generate an event. When this happens, the events are read and queued in an undetermined order and the interpreter again processes these pending events as described in the preceding paragraph.

Because the interpreter cannot tell which clients only generate events in response to events they've received, it cannot detect a condition in which it should exit because only these sorts of clients are running (and therefore no new events can be created). Usually scripts using   clients with this property can be modified to use exit statements (§ 5.8, page gif) when it is clear they are finished doing their work.

One final point regards the ordering of events, to which the following rules apply:

     


next up previous contents index
Next: Debugging Glish Scripts and Up: Using Glish Previous: Using Glish

Thu Nov 13 16:44:05 EST 1997