Getting Started | Documentation | Glish | Learn More | Programming | Contact Us |
Version 1.9 Build 1556 |
|
All Glish scripts are executed by the Glish interpreter. This program is invoked as:
-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.5compiles 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:
glish -info
.
If this file is found, it is executed.
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.
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 % glishshows using Glish interactively to evaluate the product of [1, 2, 3] times [2, 3, 4] to get [2, 6, 12].
Glish version 2.1.
- 1:3 * 2:4
[2 6 12]
- (end-of-file)
largo 131 %
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 ).
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 nthe 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: