The 3L Project Scheme provides "first-class" source code introspection
and manipulation. This means that the source code of definitions,
whether via a
define form or
let or anything else, is stored and
can be queried via an API.
The only element in the API is the
source special form. Example usage:
;; returns the list:
=> (define (cadr x) (car (cdr x)))
source special form returns the lastest definition of a
variable or "variable like" entity. This means that if
set! is used
to redefine a variable the
source special form will return the
definition resulting from the call to
(define x 10)
=> (define x 10)
(number? (third (source x)))
(set! x "Hi!")
=> (set! x "Hi!")
(string? (third (source x)))
Also note that the
source system tracks macro definitions as well.
The first-class source code part of the introspection API has some major development related implications.
First, it can be used to quickly fix a bug or add a feature to some
part of a running program when used with
eval. It can be hooked in
to the running REPL to "paste" the code into the REPL line for easy
manipulation and redefinition. It can also be hooked in to your
favorite editor to paste the definition in to the a source file.
Combined with other introspection features it could even provide
synchronization between the running program and its source code.
Second, it can be used to build documentation resources. For example, documentation can be automatically generated for function signatures. When working with an introspection API that lists variables and definitions currently in scope documentation could be generated for the entire running program or a program for the sole purpose of generating the documentation for future reference. This also makes it easy to provide a dynamic documentation explorer. (The 3L Project Scheme also provides a first-class documentation API which combined with the introspection API can generate comprehensive documentation easily.)
Third, it can be used to dynamically instrument or uninstrument code for debugging purposes; explicit support within the language runtime is not required for creating a debugger. This also means that it is easy to add new debuggers and test out different debugging methods by simply creating and loading a library.
Fourth, it can similarly be used to instrument or uninstrument code for profiling and again that removes the need to explicitly support profiling in the language runtime itself.
There are almost certainly other development features that can exploit the source API that will be explored in the future. The primary goal of the source API is to provide a simple building block for other development features.