A Go embedable lisp-like language.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
cmd/gimmick
.gitignore
AUTHORS
LICENSE
README.md
SYNTAX.md
environment.go
errors.go
eval.go
gimmick.go
parse.go
parse_test.go
primitives.go
primitives_test.go
ruse.go

README.md

GIMMICK v0.1.0-development

Gimmick aims to be a lisp language that features static type checking, first class concurrency support and native code generation on top of a classic Scheme-like core.

At present, all of these features are missing and only a basic interpreter exists that can be called from within a Go program.

Requirements

  • readline - a Go library implementing readline features (cmd/gimmick REPL dependency only)
  • echo - a Go http router used for the Ruse server

Installation

The dependency Go libraries can be installed with the following commands.

go get github.com/chzyer/readline
go get github.com/tbogdala/gimmick

Usage

First, build the main tool: gimmick.

cd $GOPATH/src/github.com/tbogdala/gimmick/cmd/gimmick
go build

Once this executable is built, it can be called with a command-line parameter to indicate the operation to perform. At present only the repl command is supported.

REPL

To start the REPL interpreter, run the following:

./gimmick repl <file_to_load.gmk>*

At this point, you can enter in code and evaluate it in a multiline fashion.

The following special commands are supported:

  • .help prints the list of special commands
  • .parse shows the parse message for the current sexp
  • .print displays the current sexp being entered
  • .quit exits the REPL
  • .reset resets the environment currently used for evaluation
  • .type shows the type of the last result value
  • [empty line] erases the current command in a multi-line context

Interpreter Features

  • basic interpreter easily callable from Go
  • uses symbolic expressions (sexp) for code and data like a lisp
  • embedded HTTP server within the REPL for editor integration
  • supports types: int64, float64, boolean, lists, symbols and strings
  • basic math operations: +, -, *, /
  • basic comparisons: <, >, <=, >=, eqv?
  • basic special forms: quote, quasiquote, unquote, unquote-splicing, if, define, begin, lambda, defmacro
  • special syntax for: quasiquote as backquote (`), unquote as a comma (,), and unquote-splicing as comma-ampersand (,@)
  • basic lisp list functions: list, car, cdr
  • function construction: lambda
  • variable number of parameters with the form: (lambda (x y . z) ...)
  • non-hygienic macros (lisp style) with the form: (defmacro name (args) body)
  • basic timing for benchmarks: (timed-apply <proc> <args>*)
  • tail-call optimized

A more verbose guide to the current language features can be found in SYNTAX.md.

To Do

Many major features are yet to come:

  • transition unit tests to gimmick itself
  • module system
  • structures
  • static type checking
  • concurrency support
  • consider possible error handling mechanisms
  • native code generation
  • debugging support
  • consider a 'safe' compilation/interpreter method that will not have functions like set! supported to fully enforce a non-mutable world view

Example Code

A small example would look like this:

(begin
 (define fib (lambda (n) 
    (if (< n 2) 
        1 
        (+ (fib (- n 1)) (fib (- n 2))))))
 (fib 30)        
)

Known Bugs

  • (Windows only) The readline library used doesn't play nice with the terminal from msys2/mingw-w64, mintty, but the executable works fine from the basic command prompt or other terminals such as cmder.

History and Thanks

One major influence on how this projected developed was Peter Norvig's article (How to Write a (Lisp) Interpreter (in Python)). Long before I read that article, I stumbled on Write Yourself a Scheme in 48 Hours back in my Haskell days. I messed around with it and started to believe in my ability to get something of my own up and running.

In the interim, I spent some time working with Lua having embedded it in my C graphics library called Portable Glue. All this time I wanted to use Scheme but things didn't work out despite some early success with my Gambit-C usage.

Now that I've been working on Fizzle and my associated game libraries, I've been looking for a good lisp-like embedded language and found quite a few. However, after some investigation, I felt that it'd be better if I start on my own language to support the features that I'm interested in. I came across this article on scm.go which helped restart me on the language design path. And naturally, I had to read the relevant portions of SICP.

License

Gimmick is released under the BSD license. See the LICENSE file for more details.