Tree @master (Download .tar.gz)
Argyle
Argyle is a Lisp-like programming language which is homoiconic at a higher level than Lisp: an Argyle program is represented as an Abstract Binding Tree (ABTs), and ABTs are first-class values. These ABTs are also hygienic in the sense that all defined ABT operations are, quite unlike Lisp's cons-lists, designed to preserve their name-binding structure.
This is an embryonic iteration of the language, aiming only to present a proof-of-concept. The basic ideas are implemented but their exact design and implementation surely can and ideally will be improved upon.
For more details on the language, see "Documentation" below.
Quick Start
Assuming you have a relatively modern version of ghc
installed,
along with cabal
.
cabal update
cabal install --lib HUnit
./build.sh
You can then start the REPL with
./bin/argyle repl
If you wish to run the test suite (recommended), you may run
pip install falderal
./test.sh
Documentation
For the full definition of Argyle, see the Definition of Argyle document, a literal test suite written in Falderal format that aims to serve as the specification for the language.
What follows is a more informal introduction.
Lisp is usualy promoted as being homoiconic, but presentations of its
homoiconicity often gloss over the following detail: not every
valid S-expression is a valid Lisp program. In essence Lisp has
two syntaxes, the "low-level syntax" of S-expressions, and the
"high-level syntax" of special forms. The traditional treatment
is to completely ignore that fact, and allow expressions such as
(quote (let 123))
to be perfectly acceptable quoted form, even though
(let 123)
is not a valid expression -- and to have the argument to
eval
is a list, even though a list need not contain a valid expression.
Argyle regards this as a shortcoming, and intends to address it. Although they are written in an S-expression syntax, Argyle programs are not parsed into cons-lists. More precisely, even if the implementation parses them into cons-lists (as the reference implementation does), those cons-lists are not directly exposed to the interpreter. Rather, the cons-lists go through an extra step of being parsed into Abstract Binding Trees (ABTs), and it is those that are exposed to the interpreter.
And it is ABTs that an Argyle program works with; the argument to
eval
is not a list, it is an ABT, giving a strong guarantee that
it represents a valid program and not some cons-list junk like
(let 123)
.
That said, it is possible to represent cons lists with ABT nodes!
The example source eg/cons-list.argyle
demonstrates how you could define the functions cons
, car
, and
cdr
using the facilities that Argyle provides for creating,
manipulating, and examining ABT values.
Where is this all headed?
Really, Argyle is only part of a grander vision I have; but it is a reasonably well-delimited and independently-implementable part, so, here it is.
In the grander vision, ABT nodes are defined as an abstract data type (ADT), and a program is able to define new ADTs and use them.
Whether Argyle will be extended to allow that, or whether that will appear in a separate language, the idea to have first-class ABTs is aiming to support two things well:
- hygienic macros
- program analysis and program transformation
The currently somewhat crude tools Argyle exposes for working with ABTs will likely need to be improved significantly, to achieve these goals.
But one could expect that, once they are in place, that support would extend to:
- defining constructs such as
letrec
,if
,cond
, etc. as macros - writing static analyzers, such as for flow-typing and binding-time
- writing optimizers, such as constant subexpression eliminators
- installing any of the above as a pre-evaluation step
TODO
- actually use locally nameless style (bound vars in own namespace)
Commit History
@master
git clone https://git.catseye.tc/Argyle/
- Fix the factorial example. And there was much rejoicing. Chris Pressey a day ago
- Count unclosed parentheses, even after a complete expression. Chris Pressey a day ago
- Checkpoint changes to S-expression parser. Chris Pressey a day ago
- Update README and try to implement factorial. Chris Pressey a day ago
- Handle Literal case in alphaEquivalent function. Chris Pressey a day ago
- Add missing Literal cases on ABT functions. Chris Pressey a day ago
- Improve unit tests for alphaEquivalent. Chris Pressey a day ago
- Charge towards alpha-equivalence of ABT values. Chris Pressey a day ago
- Add `equal?` built-in predicate. Chris Pressey a day ago
- Add `if-apply` built-in function. Chris Pressey 2 days ago