Getting Started Documentation Glish Learn More Programming Contact Us
Version 1.9 Build 1556
News FAQ
Search Home


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

Subsections



The Glish Interpreter

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

glish
[ -help ] [ -version ] [ -info ] [ -v[1-9] ] [ -vi ] [ -vf ] [ -w ] [ bindings ... ] [ -l file ... ] [ file ] [ - ] [ args ... ]

-help, -version, and -info all provide information about the Glish interpreter, and they are all optional. Indeed, using any of these flags causes the interpreter to print information and then exit. -help prints out all of the standard command line options. -version prints out the Glish version number. -info prints out information about the Glish installation including version number and directory information.

-v[1-9] is an optional verbose flag indicating that the interpreter should report on its activity. The number indicates the level of verboseness. For example, if -v1 is specified then it reports the name and value of each event it receives from a client. If -v2 is specified then in addition to reporting each event as it is received from a client, Glish also reports each event as it is queued for ``notification'' (i.e., triggering of whenever statements) and as it removes events from the notification queue to perform the notification (i.e., running a whenever statement).

-vi is an optional verbose flag indicating that the interpreter should list each file that is included by the interpreter. This results in a list of all of the files involved in running a particular script.

-vf is an optional verbose flag indicating that the interpreter should report each fail (See § 9.1, page [*]) which is not handled. A fail value is considered handled if is_fail() or type_name() is called with the fail value as a parameter.

-w is an optional verbose flag indicating that the interpreter should report the generation of each error string..

-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, with no -l flag, is the optional name of the source file to compile and execute. When supplied, it is the last parameter Glish examines. By convention such files end in a ``.g" suffix. When a file is supplied, it is executed. If there are no active clients, Glish exits after executing the file. If clients are active, Glish continues to run, processing events to and from the clients. When no file argument is supplied, Glish runs interactively (§ 13.1.1, page [*]).

args is an optional list of arguments to pass to the Glish script; if present, args may optionally 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 (§ 13.1.1, page [*]).

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
compiles the script myscript.g and runs it with argv equal to "10 12.5" (see § 10.11, page [*], for a discussion of the argv global); the record field environ.host will equal "cruncher" (see § 10.11, page [*], for a discussion of the environ global).

Prior to compiling the specified files, the interpreter attempts to evaluate local customization files. The order that it evaluates these is as follows:

$HOME/.glishrc.pre
First Glish looks for a file called ``.glishrc.pre'' in the user's home directory. If found, this file is executed.

$GLISHROOT/.glishrc
Next Glish looks for a local system wide .glishrc file. First it tries to find this file by looking in the directory specified by $GLISHROOT . If this environment variable is not defined or if no .glishrc file is found there, the default location for this file is checked. This location is established at build time. To see the default location, run glish -info. If this file is found, it is executed.

$GLISHRC or ./.glishrc or $HOME/.glishrc
Next Glish attempts to find a user customization file. Three locations are checked, and when a valid file is found, Glish does not check the other possible locations. Glish first checks the $GLISHRC environment variable. If it 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 or does not point to a valid file, Glish looks for a ``.glishrc" file in the current directory. If none is found, Glish looks in the user's home directory.

$HOME/.glishrc.post
finally glish tries to load a file called ``.glishrc.post'' from the user's home directory.

Next Glish proceeds with the files specified 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. § 13.1.2, page [*] 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.15, page [*]).


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
the first statement is the definition of the increment function. The interpreter processes the function, assigns 1 to the global n, calls increment with this value, assigns the result to n, and then prints 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 it is done executing the entire block. For example, when

    d := client("demo")
    d->init([5, 3])
    whenever d->init_done do
        print "done initializing demo"
    do_some_other_work()
is executed, it creates the client demo and sends it an init event with a value of [5, 3]. It 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. It means that you 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 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 [*]) suspends execution of the block. Therefore 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 because now there is no possibility of 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 [*]) 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 Clients Up: Using Glish Previous: Using Glish   Contents   Index
Please send questions or comments about AIPS++ to aips2-request@nrao.edu.
Copyright © 1995-2000 Associated Universities Inc., Washington, D.C.

Return to AIPS++ Home Page
2006-10-15