git @ Cat's Eye Technologies Decoy / 54df9aa
54df9aa

Tree @54df9aa (Download .tar.gz)

Decoy

It's a simple functional language with a syntax markedly inspired by Scheme and semantics markedly inspired by Scheme.

But it's not Scheme. Thus the name.

It is also very much a work in progress.

How is this not Scheme

Lots of things are missing:

  • Cons cells aren't mutable
  • There's no tail recursion
  • There's no vectors
  • There's no numeric tower
  • There's no quote or quasiquote notation
  • There's no character or boolean constants
  • define can only be used at top-level
  • There's no call-with-current-continuation or dynamic-wind
  • There's no ports
  • There's no support for SRFIs

All the same, the set of programs that are both R5RS Scheme programs and Decoy programs ought to be fairly large.

Some things are added:

  • A module system of sorts
  • Some libraries, supplied as modules in this system

Again, these would not be too difficult to suppoort in Scheme by means of some support functions and/or macros.

Why?

Having pure functions that transform an system state (plus possibly some input parameters) into a "next system state" (plus possibly some output events) is a really spiffy way to define and implement things like programming languages and user interfaces.

In programming languages they call this small-step operational semantics. In JavaScript web development they call these functions reducers. There are a number of other variations on this theme out there.

I wanted a language for writing these state-transformation functions in. Since the functions themselves are pure (have no side effects), the language should support (or even better, enforce) that. (Thus, no set!.)

It should also be simple to implement, and straightforward to compile to (or otherwise interoperate with) other more conventional languages such as JavaScript. (Thus the simplified type system, and lack of tail recursion.)

Finally, it shouldn't innovate too much in the areas of syntax or semantics, to improve learnability and transferrability, if not strict compatibility. (Thus the significant Scheme borrowings, without actually being Scheme.)

Grammar

This is how the parser understands the program text:

Expr  ::= "(" {Expr} ")"
        | Symbol
        | StrLit
        | NumLit
        .

On another level, we don't actually parse these (as of this writing), but we do interpret them as "special forms" while evaluating expressions:

  • (let* ((name expr) ...) expr)
  • (define name expr)
  • (lambda (name ...) expr)
  • (cond (expr expr) ... (else expr))
  • (if expr expr expr)

There is also a standard environment containing symbols which are mainly bound to functions. This is a work in progress, but includes

  • (list ...)
  • (list? expr)
  • (equal? expr)

Pixley is a much earlier project by the same author to define a minimal subset of Scheme in which a self-interpreter could be written. While Decoy has some similarities to Pixley, here is how Decoy is not Pixley:

  • There are numbers
  • There are many more built-ins (list, etc)

Notes

In the Decoy evaluator written in Lua, the following mapping is used for the types:

lambda function        function
empty list             Nil (singleton table)
cons cell              Cons (table)
string                 String (table)
symbol                 Symbol (table)
boolean                Boolean (table)
number                 Number (table)

The first one is not a table like the latter ones so you cannot access .class on it. When splitting into cases, test for it first.

TODO

  • Support floating-point numbers.
  • Arithmetic operations.
  • Comparison operators.
  • and, or, not
  • Refine the "module system".
  • import-from
  • Start on the compiler framework.
  • if
  • Evaluation of forms given on command line.