Experimental Little Language
Go to file
Přemysl Janouch 3e68a09ae1
Remove suck
struct context::arguments stank, the "arg" special form stank.

The amount of lines this adds can be counted on one hand.
2017-05-26 20:15:43 +02:00
.gitignore Add a REPL for toying around 2017-05-21 13:19:50 +02:00
ell.c Remove suck 2017-05-26 20:15:43 +02:00
greet.ell Remove suck 2017-05-26 20:15:43 +02:00
interpreter.c Remove suck 2017-05-26 20:15:43 +02:00
LICENSE Make this look like a project 2017-05-21 13:19:44 +02:00
Makefile Add a REPL for toying around 2017-05-21 13:19:50 +02:00
README.adoc Remove suck 2017-05-26 20:15:43 +02:00
repl.c Remove suck 2017-05-26 20:15:43 +02:00

ell

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.

The project is currently in a "proof of concept" stage with many useful data operations missing but I believe it wont be a problem to implement them as needed for anyone interested.

Syntax

Owing to its Scheme heritage, ell is homoiconic, that is a program can be directly expressed using the languages 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 doesnt 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 (quote ((eq? (set var) foo)
            (quote values 'Hello world\n')
            else
            (quote values 'Error\n'))))

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.

For a slightly more realistic example 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 *.

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.

Special Forms

quote [<arg>]…​

Like values but returns the arguments without any evaluation.

Standard library

The standard library interprets the empty list and the empty string as false values, everything else is taken as true.

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, strings evaluate to themselves.

for <list> <body>

Run the body for each element.

break

Abort the running loop.

map <list> <body>

Transform each element with the given function.

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 dont 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.

+, -, *, /

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] @* would elegantly solve the problem of varargs

  • 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 this projects 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.

Bitcoin donations: 12r5uEWEgcHC46xd64tt3hHt9EUvYYDHe9

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: