195 lines
5.5 KiB
Plaintext
195 lines
5.5 KiB
Plaintext
ell
|
|
===
|
|
:compact-option:
|
|
|
|
'ell' is a middle ground between Scheme and Tcl. The goal was to conceive
|
|
a programming language implementable with as little code as possible while
|
|
still being reasonably comfortable to use.
|
|
|
|
This package contains two implementations of said language--one in C and
|
|
another in Go--which are meant to be self-contained, portable and reusable.
|
|
Performance is specifically not an intent.
|
|
|
|
The project is currently in a "proof of concept" stage with many useful data
|
|
operations missing but I believe it won't be a problem to implement them as
|
|
needed for anyone interested.
|
|
|
|
Syntax
|
|
------
|
|
Owing to its heritage, 'ell' is homoiconic, that is a program can be directly
|
|
expressed using the language's data types. There are only two of those:
|
|
the list and the string. Any numerical conversions are made on an as-needed
|
|
basis. Similarly, strings act like atoms/symbols when executed.
|
|
|
|
The parser, however, does a bunch of transformations:
|
|
|
|
* `[a b c]` makes a call to `(list a b c)`;
|
|
* `@var` is a shorthand for `(set var)`;
|
|
* `{ code }` is the most complex one. Each line within the curly braces is
|
|
wrapped in parentheses, and the resulting sequence is wrapped in a quoted
|
|
list, so that it doesn't execute immediately.
|
|
|
|
As an example, consider the following snippet:
|
|
|
|
print (if { eq? @var foo } {
|
|
values 'Hello world\n'
|
|
} else {
|
|
values 'Error\n'
|
|
})
|
|
|
|
which gets expanded to the following:
|
|
|
|
((print (if (block (eq? (set var) foo))
|
|
(block (values 'Hello world\n'))
|
|
else
|
|
(block (values 'Error\n')))))
|
|
|
|
Observe that the whole program is enclosed in an implicit pair of `{}` and that
|
|
`block` is all that's left of special forms.
|
|
|
|
For a slightly more realistic example you can have a look at 'greet.ell'.
|
|
|
|
Runtime
|
|
-------
|
|
Variables use per-block dynamic scoping. Arguments to a block (which is a list
|
|
of lists) are assigned to local variables named `1`, `2`, etc., and the full
|
|
list of them is stored in `args`.
|
|
|
|
When evaluating a command, the first argument is typically a string with its
|
|
name and it is resolved as if `set` was called on it. Lists are left for
|
|
execution as they are.
|
|
|
|
The last expression in a block is the return value.
|
|
|
|
Special Forms
|
|
-------------
|
|
`block [<arg>]...`
|
|
|
|
Like `list` but doesn't evaluate arguments. A more appropriate name might be
|
|
`quoted-list`, which is not as descriptive in terms of syntax. If simple
|
|
quoting is desired, the list can be unpacked by an ordinary command.
|
|
|
|
Standard Library
|
|
----------------
|
|
The standard library interprets the empty list and the empty string as false
|
|
values, everything else is considered true. Numbers are floating point with
|
|
double precision, trailing zeroes are truncated.
|
|
|
|
Where a `<body>` is expected, strings retain their value, and block evaluation
|
|
is postponed as necessary.
|
|
|
|
`local <names> [<value>]...`
|
|
|
|
Create local variables in the current block. Names for which there are no
|
|
values left default to `()`.
|
|
|
|
`set <name> [<value>]`
|
|
|
|
Retrieve or set a named variable. The syntax sugar for retrieval is `@`.
|
|
|
|
`list [<item>]...`
|
|
|
|
Return a list made of given arguments. The syntax sugar for lists is `[]`.
|
|
|
|
`values [<item>]...`
|
|
|
|
Return an arbitrary number of values.
|
|
|
|
`if <cond> <body> [elif <cond> <body>]... [else <body>]`
|
|
|
|
Conditional evaluation.
|
|
|
|
`for <list> <body>`
|
|
|
|
Run the body for each element.
|
|
|
|
`break`
|
|
|
|
Abort the running loop.
|
|
|
|
`map <list> <body>`
|
|
|
|
Transform each element with the given function into any number of values.
|
|
|
|
`filter <list> <body>`
|
|
|
|
Return a new list consisting of matching elements only.
|
|
|
|
`.. [<string>]...`
|
|
|
|
Concatenate strings.
|
|
|
|
`print [<item>]...`
|
|
|
|
Print all items in sequence--strings directly, lists as source code.
|
|
|
|
`system <command>`
|
|
|
|
Run a system command and return its return value.
|
|
|
|
`parse <program>`
|
|
|
|
Parse a program into a list of lists.
|
|
|
|
`try <body> <handler>`
|
|
|
|
Execute the body and pass any error to the handler instead of propagating it.
|
|
|
|
`throw <message>`
|
|
|
|
Throw an error. Messages starting on an underscore don't generate backtraces,
|
|
which can be used to catch them.
|
|
|
|
`not <value>`
|
|
|
|
Return a boolean with the opposite truthiness.
|
|
|
|
`and [<body>]...`, `or [<body>]...`
|
|
|
|
Short-circuit evaluation, trying to return whatever the bodies result in.
|
|
|
|
`+`, `-`, `*`, `/`
|
|
|
|
Arithmetic operations on floating point numbers.
|
|
|
|
`=`, `<>`, `<`, `>`, `<=`, `>=`
|
|
|
|
Arithmetic comparisons on floating point numbers.
|
|
|
|
`eq?`, `ne?`, `lt?`, `gt?`, `le?`, `ge?`
|
|
|
|
Simple string comparisons.
|
|
|
|
Building and Running
|
|
--------------------
|
|
By default, running `make' will only build the interpreter:
|
|
|
|
$ make
|
|
$ ./interpreter greet.ell
|
|
|
|
Install development packages for GNU Readline to get a REPL for toying around:
|
|
|
|
$ make repl
|
|
$ ./repl
|
|
|
|
Possible Ways of Complicating
|
|
-----------------------------
|
|
* `local [_a _b _rest] @args` would elegantly solve the problem of varargs,
|
|
that is, unpack a list when names are list, and make the last element a list
|
|
when there are more arguments than names
|
|
* reference counting: currently all values are always copied as needed, which
|
|
is good enough for all imaginable use cases, simpler and less error-prone
|
|
|
|
Contributing and Support
|
|
------------------------
|
|
Use https://git.janouch.name/p/ell to report any bugs, request features,
|
|
or submit pull requests. `git send-email` is tolerated. If you want to discuss
|
|
the project, feel free to join me at ircs://irc.janouch.name, channel #dev.
|
|
|
|
Bitcoin donations are accepted at: 12r5uEWEgcHC46xd64tt3hHt9EUvYYDHe9
|
|
|
|
License
|
|
-------
|
|
This software is released under the terms of the 0BSD license, the text of which
|
|
is included within the package along with the list of authors.
|