ell/README.adoc

196 lines
5.6 KiB
Plaintext
Raw Normal View History

2017-05-06 14:12:46 +02:00
ell
===
:compact-option:
'ell' is a modified subset of Scheme with added syntax sugar, incorporating
ideas from Perl, Tcl and Bourne shell. The goal was to conceive a programming
language implementable with as little code as possible while still being
reasonably comfortable to use.
This package is an implementation of said language, meant to be self-contained,
portable and reusable. Performance is specifically not an intent.
2017-05-25 14:38:43 +02:00
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.
2017-05-20 21:24:11 +02:00
2017-05-06 14:12:46 +02:00
Syntax
------
Owing to its Scheme 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 list is quoted, so that it doesn't
execute immediately.
As an example, consider the following snippet:
2017-05-21 11:26:59 +02:00
print (if { eq? @var foo } {
values 'Hello world\n'
2017-05-06 14:12:46 +02:00
} else {
values 'Error\n'
2017-05-06 14:12:46 +02:00
})
which gets expanded to the following:
2017-05-21 11:26:59 +02:00
((print (if (quote ((eq? (set var) foo)))
(quote ((values 'Hello world\n')))
2017-05-06 14:12:46 +02:00
else
(quote ((values 'Error\n'))))))
2017-05-06 14:12:46 +02:00
Observe that the whole program is enclosed in an implicit pair of `{}` and that
`quote` is a very powerful special form which can replace many others if needed.
2017-05-25 14:38:43 +02:00
For a slightly more realistic example have a look at 'greet.ell'.
2017-05-06 14:12:46 +02:00
Runtime
-------
All variables are put in a single global namespace with no further scoping.
2017-05-21 17:47:19 +02:00
Arguments to a block (which is a list of lists) must be assigned to variables
first using the `arg` special form, and that must happen before they get
overriden by execution of a different block.
2017-05-06 14:12:46 +02:00
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.
The last expression in a block is the return value.
2017-05-21 13:37:43 +02:00
Special Forms
2017-05-06 14:12:46 +02:00
-------------
2017-05-25 14:38:43 +02:00
`quote [<arg>]...`
2017-05-06 14:12:46 +02:00
2017-05-25 14:38:43 +02:00
Returns the arguments without any evaluation.
2017-05-06 14:12:46 +02:00
2017-05-25 14:38:43 +02:00
`arg [<name>]...`
2017-05-06 14:12:46 +02:00
2017-05-21 18:20:12 +02:00
Assigns arguments to the current call in order to given names.
2017-05-25 14:38:43 +02:00
Names for which there are no values left are set to `[]`.
2017-05-06 14:12:46 +02:00
Standard library
----------------
2017-05-21 12:24:04 +02:00
The standard library interprets the empty list and the empty string as false
values, everything else is taken as true.
2017-05-20 21:24:11 +02:00
`set <name> [<value>]`
2017-05-21 13:37:43 +02:00
Retrieve or set a named variable. The syntax sugar for retrieval is `@`.
2017-05-20 21:24:11 +02:00
2017-05-21 18:20:12 +02:00
`list [<item>]...`
2017-05-20 21:24:11 +02:00
2017-05-21 13:37:43 +02:00
Return a list made of given arguments. The syntax sugar for lists is `[]`.
2017-05-20 21:24:11 +02:00
`values [<item>]...`
Return an arbitrary number of values.
2017-05-06 14:12:46 +02:00
`if <cond> <body> [elif <cond> <body>]... [else <body>]`
Conditional evaluation, strings evaluate to themselves.
2017-05-20 21:24:11 +02:00
`for <list> <body>`
2017-05-06 14:12:46 +02:00
2017-05-20 21:24:11 +02:00
Run the body for each element.
2017-05-06 14:12:46 +02:00
2017-05-21 12:24:04 +02:00
`break`
Abort the running loop.
2017-05-20 21:24:11 +02:00
`map <list> <body>`
2017-05-18 18:13:33 +02:00
2017-05-20 21:24:11 +02:00
Transform each element with the given function.
`filter <list> <body>`
Return a new list consisting of matching elements only.
`.. [<string>]...`
2017-05-21 12:24:04 +02:00
Concatenate strings.
2017-05-20 21:24:11 +02:00
`print [<item>]...`
2017-05-21 12:24:04 +02:00
Print all items in sequence--strings directly, lists as source code.
`system <command>`
Run a system command and return its return value.
2017-05-25 14:38:43 +02:00
`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.
`not <value>`
Return a boolean with the opposite truthiness.
`and [<body>]...`, `or [<body>]...`
Short-circuit evaluation, trying to return whatever the bodies result in.
2017-05-21 12:24:04 +02:00
`+`, `-`, `*`, `/`
Arithmetic operations on floating point numbers.
`=`, `<>`, `<`, `>`, `<=`, `>=`
Arithmetic comparisons on floating point numbers.
`eq?`, `ne?`, `lt?`, `gt?`, `le?`, `ge?`
Simple string comparisons.
2017-05-18 18:13:33 +02:00
2017-05-21 13:37:43 +02:00
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
2017-05-25 14:38:43 +02:00
Possible Ways of Complicating
-----------------------------
2017-05-26 12:49:15 +02:00
* variable scoping: lexical scoping is deemed too complex. The simplest is to
look up and set values in the nearest dynamic scope they can be found in,
or globally if not found, and have `arg` create the scopes, which also makes
AWK-style local variables work. A convention of starting locally bound names
with an underscore can keep the global namespace always accessible, and even
overridable if needed.
2017-05-25 14:38:43 +02:00
* reference counting: currently all values are always copied as needed, which
is good enough for all imaginable use cases, simpler and less error-prone
2017-05-06 14:12:46 +02:00
Contributing and Support
------------------------
Use this project's GitHub to report any bugs, request features, or submit pull
requests. If you want to discuss this project, or maybe just hang out with
the developer, feel free to join me at irc://irc.janouch.name, channel #dev.
2017-05-18 18:13:33 +02:00
Bitcoin donations: 12r5uEWEgcHC46xd64tt3hHt9EUvYYDHe9
2017-05-06 14:12:46 +02:00
License
-------
'ell' is written by Přemysl Janouch <p.janouch@gmail.com>.
You may use the software under the terms of the ISC license, the text of which
is included within the package, or, at your option, you may relicense the work
under the MIT or the Modified BSD License, as listed at the following site:
http://www.gnu.org/licenses/license-list.html