As mentioned up front VLS gets its flexibility through the use of Lisp type specifics files. This chapter expands on the syntax and semantics of these files.
The reader should note that since Lisp type specifics files can be modified or substituted by the user the command descriptions in this document depend on the original VLS packaged Lisp type specifics files.
VLS provides a set of Lisp type specifics files in the VLS installed
directory under the subdirectory types. These files all have the
.el file extension but only for the purpose of Elisp formatting,
they are not Elisp files. For example types/allegro.el.
Note however that some specifics files actually load some Lisp specific
Elisp code. Such Elisp code is under the directory types/elisp,
for example types/elisp/allegro.el.
Lisp type specifics files are not Elisp source files. They are
files that are strictly interpreted by VLS when running a VLS Lisp
shell. The only reason for giving them an .el extension is so
that they will be in Elisp mode for formatting. And they sometimes do
contain some Elisp code. And entry in a Lisp type specifics file can
one of four things:
1. A string 2. A list who's first entry is another list 3. A list who's first entry is a symbol 4. An Elisp comment
Anything else, for the time being, is ignored.
In the case of (1.), a string is interpreted as an absolute or relative path name of another Lisp type specifics file to be interpreted by VLS. In the case of (2.), a list whose first element is a list then it is interpreted as a list of Lisp specifics parameters to be interpreted by VLS. In the case of (3.), a list whose first element is a symbol the list is considered to be an Elisp s-expression and it is just evaluated by Elisp. In the case of (4.), Elisp comments are just ignored.
As mentioned in the previous section a Lisp Specifics file with an entry of a list who's first entry is a list is interpreted by VLS as a list of Lisp specifics parameters. Each sublist entry is a list of the form
(parameter-symbol parameter-value)
Where parameter-symbol is the symbol referenced by the VLS code to get a specific Lisp parameter value to support some VLS generalized action. This is the key to the flexibility of VLS and what allows VLS to provide a "vanilla" Lisp shell capability, that is the capability to adapt to any flavor of Lisp without changing the way things work in VLS. The parameter-value then can be one of five things
1. An Elisp specifics string 2. An Elisp s-expression that returns a specifics string 3. An Elisp list of specifics strings 4. An Elisp s-expression that returns a list of specifics strings 5. Any Elisp value
In the first four cases above the semantics of a "specifics string" is an Elisp string that VLS can send to the current List process where it will be interpreted as a legitimate input. In the case of (3.) and (4.) a list of specifics strings means that VLS should send that list sequentially to the current Lisp process.
In the case of (2.) and (4.) VLS will evaluate the Elisp s-expression
for either a specifics string or a list of specifics strings. And in
the case of (2.) and (4.) the Elisp s-expression can reference the
locally bound variable arg which is bound to the raw Emacs prefix
argument (nil, a number or list of a number). In some cases VLS will
dispatch on the Emacs prefix argument but in others the specifics
parameter is expected to do that dispatching in its Elisp code. In some
cases where a VLS command will dispatch on the prefix argument or does
not need the prefix argument it may pass some other value in the
arg local variable. Also if there needs to be more that one
argument the rest are passed in a local variable args which is a
list of the rest of the arguments. This document will indicate how each
parameter must interpret the arg and args variable,
See section Command Specifics Parameters.
The cases (1.) through (4.) above are meant for the command parameters
classified in the previous section that by convention have a c:
prefix. The cases of (1.) and (2.) also apply to the Lisp probe
specifics parameters with a prefix of p:. Lisp probes should not
use cases (3.) or (4.) since a single return value is required for
probes. The case of (5.) is for variables with a prefix of v:
and mechanism with a prefix of m:.
In all cases of specifics parameters recursion can be used. That is to
say, a parameter-value can refer to a previously established
parameter-value recursively. And any such recursively referenced
parameters must have been defined otherwise the parameter-value
will be an Elisp nil. The reference is done by invoking the VLS
function vls-spec
Function: vls-spec Meaning: Given a parameter-symbol will
return its parameter-value.
An example of this is the Common Lisp reset to top level message parameter
(c:reset-top-message "(progn (format t \"Reset to top level\") (values))")
where for example the Allegro specifics parameter c:top-listener
references this value
(c:top-listener (list ":reset" (vls-spec 'c:reset-top-message)))
The reader may wonder why strings are used in cases (1.) through (4.) instead of just s-expressions, since after all VLS only talks to Lisp processes. There are two reasons for this. First is that the syntax of some forms in any particular Lisp may not have a representation in Elisp forms. And second, some modern Lisp implementations add easy typing conveniences interpreted by their Lisp listeners in special cases, like break loops. And in these cases the easy typing conveniences are usually non-legitimate s-expressions.
As a convention VLS Lisp specifics parameters are named with Elisp symbols that start with the following letter prefixes
c: command m: mechanism p: probe v: variable
Although a convention every specifics parameter symbol name must have a colon as the second character. This is to insure that internal specifics parameter symbols will never accidentally clash with these specifics parameter symbols.
If the symbol if prefixed with a "c:" it means that the symbol defines a command parameter used by Lisp shell commands. The "p:" prefix means that the symbol defines a probe command sent to the current Lisp shell for collecting some information about the Lisp process. The "v:" prefix means that its symbol defines a variable used by VLS having a value specific to the type of Lisp. The "m:" prefix means its parameter value contains some internal VLS mechanism that is peculiar to the specific type of Lisp. It is helpful to classify the specifics parameters in this way and the subsections in this section are based on this classification.
When you execute a VLS command in a VLS Lisp shell buffer, like
vls-back-trace, it dispatches a command to the current Lisp
process using the value of one of the specifics parameters in this
subsection. These parameters must be a form that resolves to a string
or strings that represents a legitimate expression that will be
interpreted by the current Lisp process without error, Specifics
Parameter Forms. If a prefix argument is specified it is passed in
arg. If other than a prefix argument is passed in arg or
args it is explained separately for each parameter.
Lisp Specific Parameter: c:apropos Meaning: Used by the
vls-apropos command to do an apropos on the symbol that point in
on. The symbol is passed as the first of args.
Lisp Specific Parameter: c:back-trace Meaning: Used by the
vls-back-trace command to print a stack back-trace when in a
break handler. Prefix arguments should do something implementation
dependent and useful with the execution stack, like print out a more or
less detailed stack or more or less of a stack.
Lisp Specific Parameter: c:compile-file Meaning: Used by the
vls-compile-file command to compile the current buffer's file in
the current Lisp process. The file string is passed in arg.
Lisp Specific Parameter: c:current-frame Meaning: Used by the
vls-current-frame command to print out information about the
current stack frame in the current Lisp shell buffer.
Lisp Specific Parameter: c:compile Meaning: Used by various
commands to compile a definition who's symbol name is passed in
arg.
Lisp Specific Parameter: c:describe Meaning: Used by the
vls-describe command to describe the symbol that point in on.
The symbol is passed as the first of args.
Lisp Specific Parameter: c:down-stack Meaning: Used by the
vls-down-stack command to move down the run time stack one frame;
meaning to make that frame the current frame. A positive integer prefix
argument N should move down N frames. A C-u prefix argument
should move to the bottom of the stack.
Lisp Specific Parameter: c:exit-lisp Meaning: Used by the
vls-exit-lisp command to exit the Lisp process.
Lisp Specific Parameter: c:focus-process Meaning: For Lisps that
have multiprocessing and access to a process list, this parameter is
used by the vls-focus-process command to focus a Lisp listener on
the first process in a process list. A numeric prefix argument N should
focus the Nth process in a process list. A C-u prefix argument
should print the process list in the current Lisp shell buffer.
Lisp Specific Parameter: c:help Meaning: Used by the
vls-help command to print out a list of commands used by the
current Lisp in the current Lisp context. Typically these are
abbreviated commands as opposed to proper s-expressions, but they don't
have to be.
Lisp Specific Parameter: p:in-package Meaning: For Lisps that
have a symbol package system this expression should put the current Lisp
process in a given package. The package string is passed in arg.
Lisp Specific Parameter: c:load-file-print Meaning: Used by the
vls-load-source and vls-load-source-or-binary commands to
load the file passed in arg and to print the results of each
s-expression in the file.
Lisp Specific Parameter: c:load-file Meaning: Used by the
vls-load-source and vls-load-source-or-binary commands to
load the file passed in arg.
Lisp Specific Parameter: c:message Meaning: An expression that
prints a given message using the current Lisp process in the current
Lisp buffer. The message string is passed in arg. This
expression should not return a value if possible.
Lisp Specific Parameter: c:pop-listener Meaning: Used by the
vls-reset-listener command to "pop" the current listener into the
previous listener. The prefix argument argis always an integer N
and it means to pop the listeners to the Nth previous listener. For
example if the current Lisp was in a break listener and typed an
expression that signaled an error into another break listener, this
command were arg = 1 would pop back to the first break listener.
Lisp Specific Parameter: c:reset-top-message Meaning: If needed,
used by the c:top-listener specifics parameter to include a
string s-expression that will print that the Lisp process is at top
level after the first parameter's s-expression actually puts the process
in top level.
Lisp Specific Parameter: c:return-frame Meaning: Used by the
vls-return-frame command (usually during a break loop) to return
nil to the current stack frame call and continue the computation.
If a non-nil value is passed in the local arg variable
then return that value and do the same.
Lisp Specific Parameter: c:step-next Meaning: Used by the
vls-step command to step the Lisp stepper one step. If the
arg is an integer N then step N times.
Lisp Specific Parameter: c:step-over Meaning: Used by the
vls-step command to evaluate the current expression in
non-stepping mode and continue stepping.
Lisp Specific Parameter: c:top-listener Meaning: Used by the
vls-reset-listener command to pop the current Lisp into the top
level listener regardless of how many listeners nested deep the current
Lisp process is.
Lisp Specific Parameter: c:up-stack Meaning: Used by the
vls-up-stack command to move up the run time stack one frame;
meaning to make that frame the current frame. A positive integer prefix
argument N should move up N frames. A C-u prefix argument should
move to the top of the stack.
Lisp Specific Parameter: c:var-print Meaning: This expression
should pretty print if possible or just print if not possible a given
variable in the current Lisp buffer. The variable string is passed in
arg.
Lisp Specific Parameter: p:var-reset Meaning: This expression
should a reset the value for a given variable and then print that the
given variable name was reset and its new value. The variable name
string will be passed in arg. The reset value will be based on
the data type of the variable value. So if the type is number it should
be 0, if the type is a list it should be the empty list, if the type is
a string it should be the empty string, ... etc.
Lisp Specific Parameter: c:var-value Meaning: Used by the
vls-var-value command to return the value of a local variable in
a stack frame.
Lisp Specific Parameter: c:what-error Meaning: Used by the
vls-what-error command to print the current error being handled
by the Lisp process.
Lisp Specific Parameter: c:what-package Meaning: For Lisps that
have a symbol package system this parameter is used by the
vls-what-package command to display the current package in the
current Lisp process.
Some specifics parameters are needed for VLS internal mechanisms, such as adding specific documentation strings to VLS functions. This section describes those parameters.
Lisp Specific Parameter: m:more-doc Meaning: Indicates more
documentation string is to be added to the vanilla documentation string
of VLS commands. Its value must be a list of two element lists were
each two element list is of the form
(function-name additional-doc-string)
where function-name is a VLS function that needs additional specific documentation added to the vanilla documentation of function-name and additional-doc-string is that additional documentation string. A common use is to add additional documentation for command prefix arguments that have slightly different meaning for each specific Lisp type.
Lisp Specific Parameter: m:replace-doc Meaning: Indicates two
things. First, different from m:more-doc where more documentation
is added to the vanilla string, the whole vanilla documentation string
is replaced by this string. Its value must be a list of two element
lists were each two element list is of the form
(function-name replacement-doc-string)
where function-name is a VLS function that will have its
documentation replaced by replacement-doc-string. And thus,
second and equally important, since replacing the whole command
documentation VLS assumes that any predefined logic of the command
should not be used and instead the a VLS types parameter named
function-name will return a value being a string that is sent to
the current Lisp process. Note that in this case any Elisp logic for
the command, if even needed, must be performed by the Elisp code, if
any, specified as the parameter value. Also note that this implies that
whenever a m:replace-doc parameter is specified a
function-name parameter must be specified; otherwise the
replaced command will refuse to execute with an error.
The m:replace-doc parameter and its implications seems rather
complicated but is actually very simple, it simply triggers a specific
VLS command whose current Lisp buffer specific semantics are totally
different from any vanilla semantics. This is usually only necessary
when a Lisp implementation does not provide enough functionality to
implement the vanilla semantics but still wants to have such a specific
VLS command. Clisp for example prefers to prompt the user for a
return/continue value when in a break loop rather than have Emacs prompt
the user with a C-u prefix argument as the vanilla VLS command
vls-return-frame specifies. The Clisp type specifics file then
contains the following parameters to make this happen
(m:replace-doc
((vls-return-frame
"Return a value from the current stack frame and continue.")))
(vls-return-frame "Return")
The first parameter m:replace-doc changes the vanilla command
documentation and the second parameter vls-return-frame required
by virtue of the first, changes the behavior of the vanilla command
vls-return-frame for Clisp to just send the string "Return" to
the current Lisp process.
The probe specifics parameters are used by VLS to get some necessary
information from the current Lisp process. Each of these parameters
should be an Elisp string that contains an expression that when sent to
the current Lisp will return a value. In cases where there should be
instance values substituted in the Elisp string there should be
%s characters at that point in the s-expression.
Lisp Specific Parameter: p:bound-var-test Meaning: A predicate
that should be true if a given variable is bound in the current Lisp
process. There must be a %s where the name of the variable will
occur in the s-expression.
Lisp Specific Parameter: p:current-package Meaning: For Lisps
that have a symbol package system this should be an expression that will
return the current Lisp process package name.
Lisp Specific Parameter: p:package-predicate Meaning: For Lisps
that have a symbol package system this expression is a predicate that
should be true if the a given package exists. There must be a %s
where the package name should occur.
Variable specifics parameters are specific values that are needed by the VLS interface to the current Lisp process and buffer and can not be classified as commands, probes or internal mechanism. Or in other words everything else.
Lisp Specific Parameter: v:end-expression Meaning: A string of a
character or characters that the specific Lisp process needs to indicate
that all the data that is to be sent in fact has been sent. For example
in most Common Lisps this is the newline character. Note that this
works for any amount or kind of data sent to the Lisp process since
embedded end expression characters in the data are eaten by the parsing
of s-expressions.
Lisp Specific Parameter: v:eval-print-separator Meaning: After
evaluating a Lisp expression in the current Lisp buffer the characters in
this string will be inserted in the buffer before the return value is
printed. This is mean to be something like a newline or empty string
depending on how the specific Lisp process returns the return value
string.
Lisp Specific Parameter: v:global-debug-variable-prefix Meaning:
Used by VLS helper functions like vlsi-gvar-unique to
automatically create a global variable name that is unique for all
practical purposes. This prefix string will start the symbol name and
other parts of the variable name will be computed based on the usage.
Lisp Specific Parameter: v:has-packages Meaning: If this
parameter exits for the current Lisp and has a non-nil value then it
indicates the the current Lisp has a symbol package system. This means
that the current Lisp has more than one name-space for symbols, but
further means that it has some functionality for dealing with packages
like the in-package of Common Lisp. If some Lisp is invented
that has a symbols package system with a different functionality VLS may
have to be augmented to deal with that new functionality.
Lisp Specific Parameter: v:in-package-re Meaning: If the current
Lisp has v:has-packages non-nil and it has a form that puts the
current Lisp into a new symbol package then v:in-package-re
should be an Elisp regular expression that allows Elisp search functions
to use and successfully find such an expression in a buffer.
Lisp Specific Parameter: v:instrument-visual Meaning: A string
that serves as a comment for the current Lisp and the nature of the
comment indicates and delineates an instrument s-expression follows that
was inserted in the users code. The characters %s must appear in
the string where the instrument will be inserted.
For example this string for Common Lisp defaults to
"\n;; *Instrument* \n%s\n\n"
Note the newlines which also delineate the instrument s-expression from user code.
Lisp Specific Parameter: v:instruments Meaning: This is an Elisp
variable where the instruments for the current lisp are stored,
See section Creating Instruments. For example in Common Lisp the variable
vls-cl-instruments. Having the value of this parameter be an
Emacs variable rather than the instrument list itself gives the user a
bit more flexibility in maintaining his own instruments.
In composing Lisp specifics code, if the specific Lisp has a package
system then strictly speaking one needs to make sure that all lisp code
functions are of the fully qualified package form
package:function. For example in Common Lisp specifying
lisp:car instead of just car. The reason is that when
sending code to the current Lisp process, the current package may not
use the given package.
Considering that doing this is too pedantic VLS chooses not to do this in the given set of Lisp specifics parameters for the sake of making it easier to add specifics Lisp code. The risk of course is that if the symbols used are not in the current Lisp process package then then a VLS command may break with an undefined function. But this should be rare and seldom be a problem. If it does become a problem then a future version of VLS would probe the Lisp process to make sure that the current package is copacetic and if not put the process in a package that is.
It is important to understand issues of Lisp prompts in any Lisp shell. Lisp prompts can be problematical to a Lisp shell if not handled properly. Not all such things that are thus problematical are strictly speaking Lisp prompts. A "proem" is a kind of introductory text and this document uses the term "proem" to refer to such Lisp prompts that are not really prompts. In a Lisp read-eval-print loop, more modern referred to as a "Lisp listener", there is a continuous loop where the Lisp process reads an s-expression from the user, evaluating it and then returning the value and printing it. It most modern Lisps an option is to have a prompt printed asking for the user input to be read. Some Lisps will also have a proem to introduce the printed return value, like for example printing "Value: " followed by the actual return value.
For prompts where there is white-space before and after the prompt there
will never be a problem in VLS. There is almost always a white-space
before a prompt since traditionally read-eval-print loops emit a newline
character after the printing of each return value. If not VLS provides
a specifics parameter v:eval-print-separator for this purpose.
If there is no white-space after the prompt the VLS command
vls-eval-previous for example might include the prompt in the
value to be evaluated. For example if you specified a prompt of
"Enter:" and you typed "a" to evaluate the variable a VLS would
interpret Enter:a as a whole legitimate symbol, as it should it
most Lisps. The obvious cure in this example is to use a prompt like
"Enter: " instead with a white-space character at the end.
For VLS, proems however are problematical regardless of white space.
When VLS probes the current Lisp process for values, if a proem appears
in the output stream along with the value VLS has no way of knowing if
the proem is part of the output or not without some extra help. If
there is a proem in a specific Lisp then the specifics files should
specify the v:output-proem-regexp parameter.
VLS was designed to allow a free form scratch pad paradigm for operating
the Lisp shell where there is no prompt or proem, much like the Elisp
*scratch* buffer. We encourage the user to try this kind of paradigm
and there is usually a way to set your prompts to nil or the empty
string so that there are no prompts. It is a lot cleaner and it makes
the Lisp shell buffer almost completely the same as a Lisp file buffer.
Lisp read-eval-print loops do not need a prompt since there is always a
return value printed as feedback to the user that it is ready for
another input. There in one exception to this that the author knows of
which is in Common Lisp if a function ends with a no argument
values expression which means that the function will return no
value. But in this case it is frequently used for making a nice display
without an interfering output value, much like Common Lisp's
pprint. VLS makes it easy to get information that is typically
provided in a prompt string. For example in Lisps that have symbol
package systems, it is easy in VLS to view the current Lisp package at
any time. All this being said the encouraged free form paradigm applies
mostly to Lisp files and the Lisp shell buffer at the top level
listener. In other listeners however, like a stepper or break listener
prompts with information like the break level are useful however.
VLS provides a set of Lisp Type Specifics Files for many Lisp implementations and specifications. You can use these files if they serve your purposes, you can augment those files or you can completely create your own Specifics files using the given ones as examples.
Lets say for example that you want to augment the given Lisp Specifics and just change two Lisp Specifics parameters, one of for a Lisp specification of Common Lisp and another for a Lisp implementation Allegro. Here is an example of how to do this.
First create your own Specifics file in some directory $SOMEDIR for allegro in a file $SOMEDIR/allegro.el as follows
$VLSLIBDIR/types/allegro.el" ;; My Allegro specific stuff examples ;;; Change cl.el c:compile-file option only known to Allegro ((c:compile-file (format "(compile-file \"%s\" :xref nil :verbose t)" arg)) ;;; Change allegro.cl default of debug global variable prefix (v:global-debug-variable-prefix "/*"))
Then if you create a Lisp shell command
; Example Lisp shell command for illustration (defun my-lisp-shell () "My Lisp Shell" (interactive) (vls-shell '(my-allegro "lisp" "$SOMEDIR/allegro.el")))
and after executing my-lisp-shell the following will happen:
First $VLSLIBDIR/types/allegro.el will be interpreted by VLS. At
this point everything would be as if you had just used the given
$VLSLIBDIR/types/allegro.el in the above example Lisp shell
command. Then the following parameters list would override the given
Specifics parameters c:compile-file and c:compile-file
with your versions of those parameters. And finally VLS would execute
this my-allegro Lisp shell that will use these new parameters.
Go to the first, previous, next, last section, table of contents.