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 } {
|
2017-05-26 01:36:43 +02:00
|
|
|
values 'Hello world\n'
|
2017-05-06 14:12:46 +02:00
|
|
|
} else {
|
2017-05-26 01:36:43 +02:00
|
|
|
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)))
|
2017-05-26 01:36:43 +02:00
|
|
|
(quote ((values 'Hello world\n')))
|
2017-05-06 14:12:46 +02:00
|
|
|
else
|
2017-05-26 01:36:43 +02:00
|
|
|
(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
|
|
|
|
2017-05-26 01:36:43 +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.
|
|
|
|
|
2017-05-26 01:27:30 +02:00
|
|
|
`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
|