Tutorial15 Scripting Language




Prev | Up | Next | Back | Forward | Online Documentation Home Page

Contents:

Introduction

The scripting language of Ada-ASSURED is based on Scheme. The principle reference for Scheme is:

which is included in the Ada-ASSURED Scripting Language supplemental manual.

Scheme is a powerful general-purpose programming language derived from LISP. Although its syntax may be unfamiliar to you, it is easy to master. The real benefit of Scheme, however, is not its syntactic simplicity, but its semantic power.

The scripting language is actually a dialect of Scheme known as STk. The principle reference for STk is:

which is also included in the Ada-ASSURED Scripting Language supplemental manual.

STk implements most of Scheme and has numerous extensions. The STk Reference Manual describes STk by explaining its differences from Scheme.

Although STk extends Scheme with the ability to manipulate windows implemented with the Tk widget set, Ada-ASSURED's scripting language, as of this release, is a dialect of STk known as SNOW, standing for ``Scheme with NO Windows''. Future releases of Ada-ASSURED are likely to support full STk.

GrammaTech has extended SNOW with features specific to Ada-ASSURED, which are described in this chapter. All references to Scheme in this chapter refer to the SNOW dialect of STk.

Role of Scripting

Scripting plays numerous roles in Ada-ASSURED:

As delivered, Ada-ASSURED uses scripting for several features:

Invoking Scripts

Two environment variables control the search for script files:

In normal operation, both script variables are established automatically and need not be set manually.

Scripts can be invoked in several ways:

Script Execution

Script execution is synchronous and blocks interaction until the script either terminates or requests interactive input. Scripts terminate either (i) normally, (ii) with an error, or (iii) by asynchronous interruption.

Interactive Input and Output

Scripts may request input from the user in three ways: (i) from the *transcript* buffer, (ii) from a dialog box, and (iii) from an *input* buffer.

The *transcript* buffer implements a ``glass teletype interface'' to the script interpreter: if no script is being executed when RETURN is struck in *transcript*, the line is passed to the script interpreter for execution. If a script is being executed when RETURN is struct in *transcript*, the entire line on which the insertion cursor is positioned is sent to the script as input. If no input is available when a script does a read on standard input, the script pauses until the input becomes available. Input not fully consumed is buffered for later reads. While the script is paused for input, all windows of the editor are active.

Procedure sg:make-dialog creates a simple synchronous dialog box for entering string parameters. While the script is paused for input, all windows of the editor are active.

Procedure sg:input creates an *input* buffer initialized with an editable term value. The modified value in the buffer is returned when command terminate-input is invoked. While the script is paused for input, all windows of the editor are active.

Warning: scripts that request input must be written with care because user interaction when the script is paused for input can change the editor's state.

Script output is directed to the *transcript* buffer. Most, but not all, messages sent to standard error are also directed to *transcript*. There are a few exceptions that are directed to the standard error stream of the Ada-ASSURED process, so some messages may appear in the shell window from which the editor was invoked.

Normal Termination

When a script is invoked using eval-string, eval-selection, eval-buffer, or if the script was invoked by striking RETURN in *transcript*, then the result of evaluating a script is written to *transcript*.

Asynchronous Interruption

After a script has been running for a short while, an interruption dialog box is popped up. This gives the user a chance to interrupt a runaway script. Clicking on the Interrupt button causes the script to be interrupted asynchronously. The interrupt dialog box is popped down if a running script pauses for input; it pops up again when the script resumes execution.

In a few rare cases, execution of a script cannot be interrupted using the interruption dialog box. For example, this can occur when the entire Ada-ASSURED process blocks because the script is waiting on an external event such as termination of an active process, or a blocking read from a file descriptor. In such cases, the script can be interrupted by sending the editor process an interrupt. This can be done by typing ^C in the window from which Ada-ASSURED was invoked, or by finding the process id of the editor process and

X issuing the command (from UNIX) kill -2 pid.
MS killing the process using the Task Manager.

The following Scheme variables control the interrupt dialog box:

sg:interrupt-waittime1variable
This is an integer value that specifies the number of microseconds to wait before popping up the interrupt dialog box for the first time. The default value specifies that it will appear after one second.

sg:interrupt-waittime2variable
This is an integer value that specifies how often to check the interrupt dialog box to see whether the interrupt button has been pressed. The default value specifies 200 milliseconds.

Termination on Error

A runtime error terminates a script. For example, a script terminates if a procedure is called with the wrong number of arguments or arguments of the wrong type. An appropriate error message and stack trace is directed to *transcript*, after which control returns to the editor.

Batch Mode

Batch mode is initiated by invoking Ada-ASSURED with the -b flag. In batch mode, Ada-ASSURED is controlled wholly by scripts and there is no user interaction. Other differences are:

Batch mode is a separately licensed feature of Ada-ASSURED.

Notation

Argument names are italicized in the sample calls given below for procedures. Thus the line

indicates that the procedure sg:change-view takes two arguments, a string string and a boolean boolean. When the argument name is also the name of a Scheme type, the argument must be a value of the given type. Thus, the first argument of sg:change-view must be a string. The following naming conventions also imply type restrictions:

obj any object
list, list1, ... listj, ... list
x, x1, ... xj, ... real number
k, k1, ... kj, ... exact integer

Built-in Commands

The simplest scripts just perform sequences of editing operations by invoking procedures that correspond to editing commands.

The procedure for command c is named sg:c. For example, Scheme procedure sg:exit performs the same operation as command exit. Each such procedure returns #t if the command is successful, and #f otherwise. Some commands also set a global status code that can be interrogated to determine additional information about the command's execution. See Section Status.

Most commands have no parameters; the corresponding Scheme procedures also have no parameters. Commands with parameters, i.e., those that pop up dialog boxes, correspond to Scheme procedures with parameters. These are listed below with descriptions of their arguments. See Section Using Ada-ASSURED for full descriptions of the commands.



Primitive Procedures and Forms

Defining or Redefining Commands

New commands can be created and the behavior of existing commands can be redefined. Each command has a name, which is a string, and an action, which is a procedure. The action procedure is called whenever the command is invoked. If the command is successful, the action should return #t, otherwise it should return #f. All commands have the option of setting or clearing the global status, as described in Section Status. Procedure sg:make-dialog can be used to define commands with parameters, as described in Section Input / Output.

(sg:add-command string proc)procedure
Define (or redefine) a command named string with action procedure proc. Return #t.

(sg:delete-command string)procedure
Delete command named string. Return #t if the command named string was deleted and #f otherwise.

(sg:current-command string)procedure
If the command named string has a Scheme procedure bound to it, return it. If the command is a primitive command or has some other kind of procedure bound to it, return (), otherwise return #f.

Status

Status information consists of a collection of five status variables. Commands use status to report progress and error conditions. A command with nothing to report leaves the status unchanged.

When a command is invoked directly by name, keybinding, or mouse click, the status is reported immediately in a status-pane or alert-box message. The status is then cleared. In contrast, when a command (say c) is invoked from within a script by calling the corresponding Scheme procedure (say sg:c), status is not reported immediately. This enables scripts to consult the return code and selectively report status information. The status information will be overwritten when the next invoked command sets status. Status is reported when a command that invokes a script terminates. To suppress the reporting of status upon script termination, a script can call sg:status-clear! before returning or set the variable sg:interactive-mode to #f.

Commands, transforms, and actions defined or redefined in Scheme can establish status information using the variables and procedures described below. When such a command is invoked directly by name, keybinding, or mouse click, the status will be reported in the normal manner, and will then be cleared.

sg:status-codevariable
The status code is an integer. Status codes set by built-in commands are all positive. Negative status codes are reserved for use by script writers. A status code of 0 corresponds to the neutral status established by sg:clear-status!.

sg:status-messagevariable
The status message is a textual description of the status.

sg:status-classvariable
The status class is a characterization used (primarily) to determine how the status is displayed when sg:status-flush is called. The classes are #\s, #\e, and #\a. Class #\s messages are displayed silently in the status pane of a window; these are typically advisories of no great consequence. Class #\e messages are like class #\s messages, with the exception that a bell is rung (or flashed) when the message is displayed. Class #\a messages are displayed in an alert box that requires user confirmation.

sg:message-buffervariable
The textual name of the buffer current at the time the status was set.

sg:message-windowvariable
The textual name of the window current at the time the status was set.

sg:max-message-historyvariable
A list of the most recent messages is saved in the current browser. The maximum length of this list is controlled by the variable sg:max-message-history. This variable specifies the maximum length of the list of messages saved in the browser.

(sg:set-status! n string char)procedure
Status variables should not normally be set individually. Rather, they should be set using sg:set-status!, which is equivalent to

(set! sg:status-code n)
(set! sg:status-message string)
(set! sg:status-class char)
(set! sg:status-buffer (sg:current-buffer))
(set! sg:status-window (sg:current-window))

(sg:flush-message )procedure
If sg:status-code is nonzero, display sg:status-message and call sg:clear-status!. In interactive mode, the message is displayed in the status pane (with or without bell), or in an alert box, according to sg:status-class. In batch mode, the message is directed to stderr.

(sg:clear-status! )procedure
Equivalent to
(set! sg:status-code 0)
(set! sg:status-message "")
(set! sg:status-class #\s)
(set! sg:status-buffer "")
(set! sg:status-window "")

Menus

Every window of Ada-ASSURED displays the same global menu tree. The root menu is displayed in the menubar. In general, each menu contains zero or more menu items. Each item in the menu tree is named. The name of a top-level menu is the same as the text in its button, e.g., File. The name of a menu item that invokes a command is the name of the command, e.g., new. A menu path is a dot-separated list of such names, e.g., File.new. The empty string or '() indicates the root menu. Menu paths are used for adding and deleting menu items. In addition, the name of a menu item is used to identify the item to X for the purposes of setting resources.

(sg:add-menu string1 string2 k char1 char2 string3 string4)procedure
Add an item to the menu specified by menu path string1. The text of the menu item will appear as string2 with mnemonic char1. The menu item will appear in position k of its enclosing menu, where position 0 is before the first item.

Parameter char2 specifies the item type:

  • #\b indicates a button,
  • #\t indicates a toggle,
  • #\s indicates a separator, and
  • #\c indicates a button that invokes a cascading menu.

Parameter string3 is only used if the item is a button or a toggle. It is the name of a boolean-valued function that is invoked every time the menu is pulled down. If the item is a button, the return value indicates whether it is sensitive. If the item is a toggle, the return value indicates if the toggle is on. This item may be '(), which behaves as if it were a constant function returning true.

Parameter string4 is the name of the command that will be invoked when the item is activated. For a toggle, this is usually the command that toggles the value. Parameter string4 may be '(). If a menu with the path name string4 already exists, it is replaced by the new item.

The following script adds a cascade button named Extra at the end of the Edit menu, and puts two buttons and a separator in it:

(sg:add-menu "Edit" "Extra" 99 #\null #\c '() "extra-menu")
(sg:add-menu "Edit.extra-menu" "One..." 0 #\O #\b "sg:one-valid?" "one")
(sg:add-menu "Edit.extra-menu" '() 1 #\null #\s '() "sep1")
(sg:add-menu "Edit.extra-menu" "Two..." 2 #\T #\b "sg:two-valid?" "two")

(sg:delete-menu string)procedure
Delete the item identified by menu path string from the menu tree. Do nothing if the item does not exist.

Structured Values

Each buffer of Ada-ASSURED contains a structured value known as a term. The set of all possible terms is partitioned into disjoint phyla. For example, some terms are elements of phylum expression, other terms are elements of phylum statement, etc.

An operator is a constructor function that maps argument terms to a result term. The arguments of an operator must be values (i.e., terms) of a specified type (i.e., phylum). An operator yields a result value (i.e., term) of a specified type (i.e., phylum). The number of arguments of an operator is its arity. For example, operator Sum takes two expression arguments and yields an expression result.

Within a phylum, different varieties of term are distinguished by the operator used to construct them. For example, phylum expression has operators Sum, Product, etc., and phylum statement has operators StatementAssignment, StatementIf, etc.

Phyla, operators, and terms are represented in Scheme as values of type phylum, operator, and term, respectively.

Phyla

The phyla of Ada-ASSURED are predefined and cannot be extended. They correspond roughly to the syntactic categories of Ada. For example, all expressions are elements of phylum expression, all statements are elements of phylum statement, etc. If you structurally select a phrase of Ada in a window, its phylum is displayed on the right side of the status pane. Phylum names are case sensitive.

Let p1 and p2 be phyla. Then (eq? p1 p2) is #t if and only if p1 and p2 resulted from the same call to sg:string->phylum. In contrast, (eqv? p1 p2) and (equal? p1 p2) are #t if and only if p1 and p2 resulted from calls to sg:string->phylum with equal arguments.

(sg:phylum? obj)procedure
Return #t if obj is a phylum, otherwise return #f.

(sg:string->phylum string)procedure
Return the phylum named string, or #f if no phylum with that name exists.

(sg:phylum->string phylum)procedure
Return the name of a phylum as a string.

Operators

The operators of Ada-ASSURED are predefined and cannot be extended. They correspond roughly to the constructs of Ada. For example, all expression sums are instances of operator Sum, all assignment statements are instances of operator StatementAssignment. Operator names are case sensitive.

Let o1 and o2 be operators. Then (eq? o1 o2) is #t if and only if o1 and o2 resulted from the same call to sg:string->operator. In contrast, (eqv? o1 o2) and (equal? o1 o2) are #t if and only if o1 and o2 resulted from calls to sg:string->operator with equal arguments.

(sg:operator? obj)procedure
Return #t if obj is an operator, otherwise return #f.

(sg:string->operator string)procedure
Return the operator named string, or #f if no operator with that name exists.

(sg:operator->string operator)procedure
Return the name of an operator as a string.

(sg:operator-phylum operator)procedure
Return the phylum of an operator.

(sg:operator-arity operator)procedure
Return the arity of an operator.

(sg:operator-parameter operator k)procedure
Return the phylum of parameter k of operator.

(sg:no-operators )procedure
Return the number of operators defined in the editor.

(sg:integer->operator k)procedure
The operators in the editor are numbered from zero to (sg:no-operators) minus one. This function returns the kth operator, or #f if k is out of range.

Terms

Terms are tree-structured values. Each term is either a constructed term or a primitive term. Primitive terms are described in the next section. A constructed term is the result of applying an operator of arity n to n argument terms of the correct phyla. The n argument terms are children of the term.

Each buffer of Ada-ASSURED contains a term, or more precisely, an attributed term. Attributed terms have some additional properties described in a separate subsection below. Terms constructed by procedure sg:build are not attributed but may contain attributed children.

Let t1 and t2 be terms. Then (equal? t1 t2) is #t if and only if t1 and t2 are structurally isomorphic terms. In contrast, (eq? t1 t2) is #t if and only if t1 and t2 either resulted from the same call to a term-returning procedure, e.g., sg:build, or are primitive Scheme values that are eq?. Two Scheme values t1 and t2 that are not eq? may, nonetheless, represent identical terms of Ada-ASSURED. In this case, (eqv? t1 t2) will be #t.

(sg:term? obj)procedure
Return #t if obj is a constructed term or a primitive term, otherwise return #f.

(sg:term-operator term)procedure
Return the operator of a term.

(sg:term-phylum term)procedure
Return the phylum of a term.

(sg:string->term string phylum)procedure
Returns term obtained by parsing string as phylum. This is the same as sg:parse. Not all phyla in the grammar can be parsed using this function. The phyla which are not parsable are marked with the string ``~p'' in the on-line Ada Grammar.

(sg:term->string selection)procedure
Returns string obtained by pretty-printing selection in BASEVIEW.

(sg:build operator term1 ... termn)procedure
Return an unattributed term that is an instance of operator and contains children term1, ..., termn. The value is undefined if the arity of operator is not n, or if, for some j, the phylum of termj does not correspond to the phylum of operator's j-th parameter. The value is undefined if operator is a primitive operator.

(sg:term-arity term)procedure
Return the arity of term.

(sg:child term k)procedure
Return child k of term. Argument k must be in the range 1 through (sg:term-arity term).

Primitive Phyla, Operators, and Terms

Primitive terms are values of the primitive phyla BOOL, INT, REAL, CHAR, and STR. Although these values are distinct from Scheme values, the correspondence

Phyla Scheme types
BOOL boolean
INT exact integer
REAL real
CHAR char
STR string

is so close that automatic coercions are provided back and forth. In particular, a Scheme primitive value can be passed as an argument to any procedure that requires a term argument of the corresponding phylum. Similarly, each procedure that returns a term coerces a primitive term result to the corresponding Scheme value on return. Thus, you can normally ignore the distinction between primitive terms and their corresponding Scheme values.

Procedure child* is an exception to the previous rule: it does not coerce a primitive result to a primitive Scheme value. Instead, it returns the actual child, i.e., an instance of one of the primitive operators _Bool, _Int, _Real, _Char, or _Str. Procedure child* is used whenever the identity of a primitive result or its properties as an attributed term are needed.

Suppose child i of attributed term t is primitive. Then (child* t i) is also an attributed term. In particular: (sg:parent (child* t i)) is t, and (sg:child-number (child* t i)) is i. In contrast, (child t i) coerces a primitive result to the corresponding Scheme value, and in the process, loses the identity and attribution properties of its result. In particular: (sg:attributed? (child t i)) is #f. Thus, (child t i) has no parent, no child number, and no attributes. On the other hand, if (child* t i) is a number, (+ (child t i) 1) is defined whereas (+ (child* t i) 1) is not.

(sg:term-primitive? obj)procedure
Return #t if obj is a term belonging to a primitive phylum, i.e., a term of one of the primitive phyla BOOL, INT, REAL, CHAR, and STR, or a value of one of the primitive Scheme types boolean, integer, real, char, and string. Return #f otherwise.

(sg:child* term k)procedure
Return child k of term. Values of primitive phyla (e.g., BOOL, INT, REAL, CHAR, and STR) are not coerced to corresponding Scheme primitive values. Argument k must be in the range 1 through (sg:term-arity term).

Placeholder and Completing Terms

Each phylum is associated with two terms of special significance: the placeholder term and the completing term. Typically, the placeholder term for phylum p is displayed as <p>. However, some phyla have compound placeholder terms. The completing term of optional phylum p is used to signify that a phrase of phylum p is ``omitted''. Completing terms of optional phyla are typically displayed as the null string.

(sg:placeholder-term phylum)procedure
Return the placeholder term for phylum.

(sg:completing-term phylum)procedure
Return the completing term for phylum.

Optional Phyla

Optional phyla are used to represent syntactic components that need not be present. Typically, when you move the structural selection away from the placeholder term of an optional phylum p, it is automatically changed into the phylum's completing term, which is displayed as the null string.

(sg:phylum-optional? phylum)procedure
Return #t if phylum is an optional phylum, otherwise return #f.

Term Sequences

A sequence of terms of the same phylum can be represented by a single term using two operators, one for pairing and the other for termination. For example, term sequence t1, ..., tn is represented by the term c[t1c[t2, ..., c[tnn[]]]], where c and n are appropriate pairing and terminating operators, and operator application is indicated by [ ]. This is analogous to the use of cons and nil for building lists in Scheme, except that for term sequences, different operators are used for different phyla. A phylum that contains two such operators, c and n, used for representing term sequences is called a sequence phylum.

(sg:phylum-sequence? phylum)procedure
Return #t if phylum is a sequence phylum, otherwise return #f.

(sg:term->term-list term)procedure
Argument term must be a term sequence c[t1c[t2, ..., c[tnn[]]]], where c and n are appropriate pairing and terminating operators. Return the list of terms (t1 ... tn).

(sg:term-list->term phylum list)procedure
Argument list must be a list of terms (t1...tm), where each ti is a term of the same phylum p, and phylum must be a sequence phylum for representing phylum p term sequences. Return the term that represents sequence t1, ..., tm. If m = 0, return the completing term for phylum.

Coercions Between Terms and Standard Scheme Values

Coercions from terms to standard Scheme values are provided by procedure explode, which converts only the top level of a term, and procedure explode*, which converts an entire term. Inverse coercions are provided by procedures implode and implode*.

(sg:explode term)procedure
If term is a primitive term, return its Scheme counterpart. If term is the term constructed by (sg:build o t1 ... tn), return the list (o' t1 ... tn), where o' is (sg:operator->string o).

(sg:explode* term)procedure
If term is a primitive term, return its Scheme counterpart. If term is the term constructed by (sg:build o t1 ... tn), return the list (o' t1' ... tn'), where o' is (sg:operator->string o) and t1', ..., tn' are the results of recursively applying procedure sg:explode* to t1, ..., tn, respectively.

(sg:implode obj)procedure
If obj is a primitive Scheme value of type bool, integer, real, char, or string, return the corresponding primitive term value. If obj is (o' t1...tn), where o' is the name of an arity n operator o, and t1, ..., tn are terms of the phyla required by o's arguments, return (sg:build o t1...tn). Otherwise return ().

(sg:implode* obj)procedure
If obj is a primitive Scheme value of type bool, integer, real, char, or string, return the corresponding primitive term value. If obj is (o' obj1'...objn'), where o' is the name of an arity n operator o, return (sg:implode obj1...objn), where obj1, ..., objn are the results of recursively applying sg:implode* to obj1'...objn', respectively. Return () if any such call would return ().

Attributed Terms

Each buffer contains an attributed term. If term t is attributed, so is (child* t k). The term returned by (child t k) is also attributed unless it is primitive, in which case it is coerced to a Scheme value.

Attributed terms are so named because they are decorated by attribute values that contain additional information about the term. The attribute value is itself a term, albeit an unattributed term. Attributes are described in a separate subsection below.

An attributed term may have at most one parent; unattributed terms never have parents. The parent of an attributed term is not necessarily attributed.

(sg:attributed? term)procedure
Return #t if term is an attributed term, otherwise return #f.

(sg:parented? term)procedure
Return #t if term is attributed and has a parent, otherwise return #f.

(sg:parent term)procedure
Return the parent of an attributed term that has one. Fail if term does not have a parent.

(sg:child-number term)procedure
Return what child number term is of its parent. It is an error if term is not parented.

(sg:elided? term)procedure
Return #t if term is currently elided, otherwise return #f.

Text Buffers

An attributed term may have an associated text buffer, i.e., a fragment of unparsed text. When a term with an associated text buffer is displayed in a window, the text buffer is displayed and the term is not. The term provides attribute values for the enclosing context regardless of whether it has an associated text buffer.

When a text buffer is associated with the apex of a sequence of terms, the first element of the sequence that is excluded from the range of the text buffer is the text buffer's exclusion.

(sg:has-text-buffer? term)procedure
Return #t if term is an attributed term and has an associated text buffer, otherwise return #f.

(sg:text-buffer term)procedure
Return the text of a text-buffer as a string if term has an associated text buffer, #f otherwise.

(sg:text-buffer-exclusion term)procedure
Return the term that is the exclusion of the text-buffer rooted at term. If there is no text buffer at term, or if there is no exclusion, return ().

Attributes

The apex of each attributed term contains zero or more attributes. Each attribute value is an unattributed term. The collection of attributes maintained by Ada-ASSURED is undocumented and subject to change in subsequent versions of the system.

(sg:term-attribute term string)procedure
Return the value of the attribute named string of term term or () if no such attribute exists. Term must be attributed. Parameter string can be any valid attribute name of term.

(sg:nullify string)procedure
Return #f if there is no buffer named string. Otherwise, nullify all attributes of the named buffer.

(sg:reattribute string)procedure
Return #f if there is no buffer named string. Otherwise, evaluate all attributes of the named buffer. The effect of sg:reattribute is unspecified unless the buffer is first nullified.

Pattern Matching

A term can be deconstructed using the pattern matching form sg:case.

(sg:case term (pattern body) ... )syntax
The subject to be matched is term. One or more occurrences of (pattern body) are permitted, where each pattern has the form described in Section Patterns, and each body is one or more expressions (like the body of a lambda expression). Each pattern must appear literally, i.e., it cannot be computed by evaluating a Scheme expression. Let pattern p be the leftmost pattern that matches term and let b be the corresponding body. Execute b in an environment in which the pattern variables of p are bound to fragments of term according to the pattern match, and return the value of the last expression of b. It is a runtime error if no pattern matches.

Patterns

Patterns are used in sg:case (described in Section Pattern Matching) and sg:add-transform (described in Section Transforms and Actions).

Patterns are defined inductively as follows:

Pattern p matches term t: Special rules apply when t is an attributed term with an associated text buffer. In this case, t is only matched by a wildcard or a pattern variable. If a pattern variable matches a text buffer, other occurrences of the same pattern variable must also match a text buffer containing the same text.

Buffers

Each buffer has a unique name, which is a string. When a file is read into a buffer, the basename of the file, i.e., the file name without path information, is used to construct the buffer name. If a buffer already exists with this name, the string <i> is appended, where i is an arbitrary number. Predefined buffers have names that begin and end with asterisks, e.g: *untitled*. Each buffer may be associated with a file. At all times, one buffer is designated as the current buffer.

(sg:current-buffer )procedure
Return the name of the current buffer.

(sg:buffer-term )procedure
(sg:buffer-term string)procedure
Return the attributed term contained in the buffer named string, or the current buffer if no argument is given. Return #f if the specified buffer does not exist.

(sg:buffer-list )procedure
Return a list of the names of all open buffers.

(sg:buffer-modified? string)procedure
Return #t if string is a buffer that has been modified since it was read in, or saved to a file. Return #f otherwise.

(sg:buffer-file string)procedure
Return the full pathname of the file associated with the buffer named string; return #f if the buffer named string has no associated file.

(sg:goto-buffer string1)procedure
(sg:goto-buffer string1 string2)procedure
Bring up a window for buffer string1. If this buffer is already in a window then raise that window, otherwise perform a switch-to-buffer and coerce the buffer to phylum string2. The default phylum name is ``TEXT''.

Windows

A list of windows is maintained. One of these is designated as the current window. This is usually the one from which an action has been initiated. Window names are strings of the form b[v]-i, where b is the name of the buffer being displayed in the window, v is the name of the view in which it is being displayed, and i is an arbitrary integer chosen so that windows displaying the same buffer are given different names. The [v] part may be omitted if the view is BASEVIEW. The -i part is also omitted if possible.

(sg:window-list )procedure
Return a list of the names of open windows.

(sg:current-window )procedure
Return the name of the current window.

(sg:window-exists string)procedure
If a window with name string exists, return #t, otherwise return #f.

(sg:window-buffer string)procedure
Return the name of the buffer associated with the window named string. Return #f if there is no buffer named string.

(sg:window-view string)procedure
Return the name of the view displayed by the window named string. Return #f if there is no buffer named string.

(sg:goto-window string1 boolean)procedure
(sg:goto-window string1 boolean string2)procedure
Bring up a window for file or buffer string1. If this buffer is already in a window then raise that window, otherwise perform an open. The open command is called with syntactic category string2 and defaults to ``TEXT'' if no string2 parameter is passed. The boolean parameter specifies whether to find a window for a file or a buffer. If boolean is #t then string1 is considered a pathname. If boolean is #f then string1 is considered a buffer name.

(sg:raise-window! string)procedure
Raise the window named string. Return #f if there is no window named string.

(sg:set-window! string)procedure
Set the current window to the window named string. If there is no window named string, then extract the name of the buffer and view from string (recall window names are of the form b[v]-i) and try to find a window that contains buffer b in view v. If no such window exists, create one and, if necessary, create a new buffer. (This is equivalent to (sg:switch-to-buffer b "YES") (sg:change-view v #f)). Return #t.

Selections

Selections are used to denote interior subterms. Each selection consists of an apex and a list of subterms excluded from consideration. Specifically, a selection is a list of one or more terms (a e1 ... en), where each ei, 0 <= i <= n, is a subterm of a. Term a is the apex of the selection, and each term ei is an excluded subterm. If n>0, the selection denotes the interior subterm a with each excluded term ei removed. If n=0, the selection consists of the entire term a. Thus, we identify the selection (a) with the term a. In particular, if term a is passed to a procedure that requires a selection argument, it is coerced to the selection (a).

Each edit buffer contains an attributed term and a structural selection that denotes a subterm of the buffer's attributed term. Structural selections have a restricted form: either (a) or (a\nbspe). The second form is only used to denote term subsequences, i.e., a is a term that represents term sequence t1,...,tm, and e is a suffix of that sequence. If e is the sequence tk+1,...,tm, selection (a\nbspe) denotes subsequence t1,...,tk. If e is the sequence terminator following tm, selection (a\nbspe) denotes the entire sequence t1,...,tm.

(sg:get-structural-selection )procedure
(sg:get-structural-selection string)procedure
Return the structural selection of the buffer named string, or the current buffer if no argument is given. Return #f if the specified buffer does not exist.

(sg:set-structural-selection! selection)procedure
Set the structural selection of the current buffer to selection and place the insertion cursor of the current window at the beginning of the selection. The selection must be a well-formed structural selection of the buffer, i.e., it must denote either a subterm or a sublist of the buffer's attributed term. If auto-parsing is enabled, an attempt is made to parse the current selection first. Return #t if the buffer was updated and #f otherwise.

(sg:structural-selection-apex )procedure
Equivalent to (car (sg:get-structural-selection)).

(sg:context )procedure
Equivalent to (sg:term-phylum (sg:structural-selection-apex)).

(sg:operator )procedure
Equivalent to (sg:term-operator (sg:structural-selection-apex)).

(sg:structural-selection-string )procedure
Return the string representation of the structural selection of the current window. Equivalent to
(sg:unparse
     (sg:window-view (sg:current-window))
     (sg:get-structural-selection))

(sg:selection )procedure
Return the string selected by the textual selection of the current browser.

(sg:set-selection! k1 k2)procedure
Set the textual selection of the current buffer to span characters k1 to k2. This always returns #t.

Parsing and Unparsing

Terms are abstract structured representations of objects. Coercion of a string into a term of a given phylum is parsing, and coercion of a term back into a string is unparsing.

There are two ways to customize Ada-ASSURED's prettyprinting conventions. First, certain variations have been anticipated and are easily selectable via style-enforcement parameters. Second, the built-in formatting rules used for unparsing terms can be accessed and changed. Because Ada-ASSURED's high-quality formatting requires complex rules, customers wishing to change the rules are strongly advised to consult with GrammaTech before doing so.

Unparsing of a term is determined by its unparsing rules. Each operator has one or two unparsing rules for each defined view. The first rule is the principle unparsing rule and the second, if defined, is the alternate unparsing rule.

An unparsing rule for an operator of arity n in a particular view consists of n + 1 resting place denoters and any number of unparsing items. The Scheme syntax for an unparsing rule is a list of the form: ( lhs separator rhs1 ... rhsk ), where lhs is a resting place denoter, separator is the string ``:'' or ``::='', and each rhsi is either a resting place denoter or an unparsing item. The following three tables define the valid resting place denoters and unparsing items.

The formatting commands available for string constants are summarized below. If %x is not one of the itemized formatting commands, its display is undefined. All such characters are reserved for future use. All characters that are not part of formatting commands are displayed as themselves. The result of displaying non-printable characters is not defined.

(sg:parse string phylum)procedure
If string parses successfully as phylum, return the corresponding term, otherwise return (). Not all phyla in the grammar can be parsed using this function. The phyla which are not parsable are marked with the string ``~p'' in the on-line Ada Grammar.

(sg:unparse string selection)procedure
Return the string obtained by prettyprinting selection in view string. Return #f if string is not a valid view name. The standard view is BASEVIEW.

(sg:get-unparsing-rule operator string boolean)procedure
Return the active unparsing rule for operator operator in view string. The principle unparsing rule is returned if boolean is #t and the alternate unparsing rule otherwise. Return #f if string is not a valid view name or if an alternate unparsing rule was requested, but the operator does not have an alternate rule defined.

(sg:set-unparsing-rule! operator string boolean list)procedure
Replace the unparsing rule for operator operator in view string with the rule defined by list. Replace the principle unparsing rule if boolean is #t and the alternate unparsing rule otherwise. Return #f and do nothing if string is not a valid view name or if the unparsing rule in list is invalid , otherwise return #t. The new rule is not added to the active unparsing rule set until the next call of sg:commit-unparsing-rules!. Note, a statically correct unparsing rule may still fail when interpreted in a particular context.

(sg:revert-unparsing-rule! operator string boolean)procedure
Use the built-in unparsing rule for operator operator in view string. This procedure removes all changes to the unparsing rule made by sg:set-unparsing-rule!. The change does not occur until the next call of sg:commit-unparsing-rules!.

(sg:commit-unparsing-rules! )procedure
Activate all the unparsing rule changes since the previous call to sg:commit-unparsing- rules!. These include new rules added by sg:set-unparsing-rule! and rules reset to their built-in values by sg:revert-unparsing-rule. Each change to the unparsing rule set is done in the order in which the respective calls were made, and then all buffers are re-attributed and prettyprinted.

(sg:abort-unparsing-rules! )procedure
Erase all unparsing rule changes since the last call of sg:commit-unparsing-rules!. These include new rules added by sg:set-unparsing-rule! and rules reset to their built-in values by sg:revert-unparsing-rule. All pending changes are removed.

Textual Editing

The text displayed in the current window is a string that is indexed from 0 through (- (sg:text-end) 1). The string is displayed as a sequence of lines, where character 0 begins line 1. The textual insertion point is immediately before character (sg:text-insertion-point). If a position is out of range (less than zero or greater than the number of characters in the window), the routine takes the position to be either zero or the position of the last character, respectively. With the exception of sg:text-replace!, none of the following operations have any side effects.

(sg:text-insertion-point )procedure
Return the character position of the insertion cursor in the current window. This is the character just after the insertion cursor.

(sg:text k1 k2)procedure
Return the text in the current window between character positions k1 and k2, inclusive of the character at k1, but exclusive of k2.

(sg:text-linestart k)procedure
Return the character position in the current window of the first character on the line that contains the character at position k.

(sg:text-lineend k)procedure
Return the character position in the current window of the last character on the line that contains the character at k.

(sg:text-wordstart k)procedure
Return the character position in the current window of the first character on the word that contains the character at position k.

(sg:text-wordend k)procedure
Return the character position in the current window of the last character on the word that contains the character at k.

(sg:text-scan k string1 string2 boolean)procedure
Scan the window text from character position k until pattern string1 is matched, and return the position of the leftmost matching character. If string2 is "forward", search forward; if string2 is "backward", search backwards. The search is case-sensitive if boolean is #t, and case-insensitive otherwise. If no match is found, -1 is returned.

(sg:text-line k)procedure
Return the character position of the first character on line k in the window.

(sg:text-end )procedure
Return one plus the character position of the last character in the window.

(sg:text-replace! k1 k2 string)procedure
Replace the text in the current window between k1 and k2 with string. The procedure is equivalent to selecting the text between positions k1 and k2 and then pasting string. In particular:
  • Fail if the buffer is read only.

  • Textually select characters k1 through k2. As a side effect, if the characters are not already in the structural selection, then structurally select the smallest phrase enclosing character positions k1 through k2, and move the textual insertion point to the left of the first character of the selection.

  • Fail if the structural selection is read only.

  • Replace characters k1 through k2 with string. As a side effect,

    • Turn the text of the structural selection into a text buffer, if necessary.

    • If the structural selection is a placeholder, erase the entire text buffer.
Return #t on success and #f on failure.

(sg:text-insert! string)procedure
Equivalent to
(let ((k (sg:text-insertion-point))) (sg:text-replace! k k string))

Line numbers

(sg:line-number )procedure
Return the number of the line that contains the insertion cursor in the current browser.

(sg:xline-number-max )procedure
Return the largest external line number of any node contained within the structural selection of the current buffer. If no node has an external line number, zero is returned.

(sg:xline-number-min )procedure
Return the smallest external line number of any node contained within the structural selection of the current buffer. If no node has an external line number, zero is returned.

(sg:term-xline-max selection)procedure
(sg:term-xline-max selection string)procedure
Return the largest external line associated with selection in the buffer string, or in the current buffer if no string is given. If no node in selection has an external line number, zero is returned.

(sg:term-xline-min selection)procedure
(sg:term-xline-min selection string)procedure
Return the smallest external line associated with selection in the buffer string, or in the current buffer if no string is given. If no node in selection has an external line number, zero is returned.

Structural Editing

(sg:replace! term1 term2)procedure
Remove attributed term1 from its context and replace it by a copy of term2. If attribution is enabled, re-attribute the attributed term into which term2 has been placed, as needed, to make its attributes consistent again. Any variable or pattern variable bound to term1 or to a constituent of term1 remains bound, but the context of the bound value is undefined after the replacement. The structural selection of the buffer containing term1 may change as a side effect. A runtime error occurs if term1 is not a subterm of some buffer.

Transforms and Actions

During editing, each buffer has an associated structural selection, either a subterm or a sublist of the buffer's contents. Transforms specify editor operations for restructuring the structural selection. Unlike commands, which are enabled or disabled based on global properties of a buffer, transforms are enabled or disabled based on what term is structurally selected and what other transforms take precedence. Invoking a transform replaces the selected term in the buffer.

Each transform has a name used to invoke it. The name is a string. Transform s can be invoked by entering any unique prefix of s in the command pane and striking RETURN. A transform can also be invoked by selecting it from either the Transform menu or the Context pane, both of which are updated whenever the structural selection changes.

Each transform has a documentation-file name, which is a string. If the documentation-file name for transform s is the empty string, the documentation is assumed to be stored in file s.html. Typically, this default is sufficient. The documentation-file name is useful in cases where the transform name is not a legal file name, or where several different transforms with different names share a common documentation file.

Each transform has a pattern and an enabling predicate. Patterns and pattern matching are described in Section Patterns. The enabling predicate returns a Boolean-valued Scheme expression. A transform matches if its pattern matches the structurally selected term and if its enabling predicate is #t when evaluated in the context of the bindings established by the pattern match. For the purpose of pattern matching, a sublist selection is considered to end with the appropriate list terminating operator.

Many transforms can have the same name, but at most one with a given name is enabled at a time. As distributed, Ada-ASSURED has numerous built-in transforms. These can be augmented using procedure sg:add-transform. Added rules take precedence over built-in rules; more recently added transforms take precedence over older transforms.

When the selection is a singleton subsequence, the enabled transforms also include those that would have matched had the selection been just the item of the subsequence. If two patterns with the same name match, one for the sequence phylum and the other for the item phylum, the transform for the sequence phylum takes precedence.

Each transform has a replacement expression that computes a replacement term. The replacement expression must be a pure expression that is side effect free. When a transform is invoked, the replacement expression is evaluated in the context of the bindings established by the pattern match, and its result replaces the structurally selected term. After a transform has been applied and the selection replaced, the buffer's attributes are updated, as necessary, so that all attributes are again consistent with their definitions.

If a pattern variable occurs more than once within the replacement expression, the constituent of the selection bound to that pattern variable will, in effect, be replicated. Any pattern variable never occurring in the replacement expression denotes a constituent of the selection that will be discarded when the transform is applied. Similarly, occurrences of a wildcard (_) in a pattern will be bound to components that will disappear as a result of the transformation.

Since the selection is not merely a term, but is an attributed term, pattern variables are necessarily bound to attributed terms. There are several consequences. First, the enabling condition of a transform can depend on the value of an attribute of the selection. Second, the selected term may contain text buffers that are incorporated into the replacement expression.

Actions are a variant of transform. Instead of a replacement expression whose value replaces the structural selection, an action has an action expression that is executed for its side effect. The value of the action expression is discarded, i.e., it is not used to replace the structural expression. Other than this, actions are indistinguishable from transforms.

(sg:add-transform string1 string2 phylum pattern expr1 expr2)syntax
Add a new transform named string1 for transforming structural selections of the given phylum. The transform has a pattern, an enabling predicate expr1, and a replacement expression expr2. The pattern must appear literally, i.e., it cannot be computed by evaluating a Scheme expression. The documentation-file is string2. The replacement expression expr2 should be a pure expression that has no side effects and computes a term. Return #t if the transform was added and #f otherwise.

(sg:add-action string1 string2 phylum pattern expr1 expr2)syntax
Add an action named string1, with documentation-file string2, that can be enabled at structural selections of the given phylum. The action has a pattern, an enabling predicate expr1, and an action expression expr2. The pattern must appear literally, i.e., it cannot be computed by evaluating a Scheme expression. The value of action expression expr2 is discarded, i.e., it is evaluated only for its side effects.

Suppose the structural selection denotes a subsequence of the term sequence t1,...,tm, say t1,...,tk. Because pattern matching is performed only on the structurally selected subsequence, a pattern variable denoting the subsequence after tk will be bound to a null sequence even though the suffix tk+1,...,tm occurs in the buffer. When action expression expr2 is evaluated, however, the entire attributed term is available.

(sg:delete-transform string phylum)procedure
Delete the most recently added transform or action for phylum named string. Return the number of transforms and actions deleted.

(sg:delete-all-transforms string phylum)procedure
Delete all added transforms and actions for phylum named string. Return the number of transforms and actions deleted.

(sg:delete-transforms-with-name string)procedure
Delete all added transforms and actions named string. Return the number of transforms and actions deleted.

(sg:delete-transforms-with-phylum phylum)procedure
Delete all added transforms and actions for phylum. Return the number of transforms and actions deleted.

(sg:delete-added-transforms )procedure
Delete all added transforms and actions. Return the number of transforms and actions deleted.

(sg:mask-transforms string phylum pattern)procedure
Suppress all transforms and actions named string if the structural selection of the current buffer is a term of the given phylum that is matched by the pattern.

Searching and Replacing

(sg:traverse selection (pattern body) ... )syntax
The subject to be traversed is a selection. One or more occurrences of (pattern body) are permitted, where each pattern has the form described in Section Patterns, and each body is one or more expressions (like the body of a lambda expression). Each pattern must appear literally, i.e., it cannot be computed by evaluating a Scheme expression. The selection is traversed in left-to-right preorder. If no pattern matches a given subterm, the traversal continues. Otherwise, let pattern p be the leftmost pattern that matches a given subterm and let b be the corresponding body. Execute b in an environment in which (a) the pattern variables of p are bound to fragments of the matched subterm, and (b) symbol $$ is bound to the given subterm.

The value returned from b controls how the traverse continues as follows:

'skip-children
After executing b, do not traverse the children of $$.
'abort
Immediately abandon the entire traverse.
'next
Continue the traverse from $$ by attempting to match it against the next pattern in the list.
'again
Repeat the traversal at $$. Note that unless subsequent executions of b return a different value, this may cause the traverse to execute b infinitely.
any other value
After executing body b, the traversal continues from the children of $$, if any. (If executing body b causes $$ to be replaced, the traversal continues at the children of the replacing subterm, if any.)

If not halted earlier, sg:traverse stops when it reaches any exclusions of selection. sg:traverse returns #f if no match occurs during the entire traversal, otherwise it returns #t.

(sg:traverse* selection (pattern body) ... )syntax
Same as sg:traverse, except that upon replacement of $$, the traversal continues, not at the children of the replacement, but at the apex of the replacement. This permits iterative rewriting at a given point in a term before the traversal continues. Note that the return value from body will override this behavior regardless of whether a replacement occurred.

(sg:ordered-traverse selection treeorder childorder boolean1 boolean2 (pattern body) ... )syntax
sg:ordered-traverse is the general form of sg:traverse. Traverse the tree visiting nodes in the order gi