spy16 / sabre

Sabre is highly customisable, embeddable LISP engine for Go. :computer:
GNU General Public License v3.0
28 stars 5 forks source link
embeddable go golang lisp lisp-interpreter parser reflection scripting-engine

Sabre

GoDoc Go Report Card Build Status

DEPRECATED: This repository is deprecated in favour much better slurp project and will be archived/removed soon.

Sabre is highly customizable, embeddable LISP engine for Go.

Check out Slang for a tiny LISP written using Sabre.

Features

Please note that Sabre is NOT an implementation of a particular LISP dialect. It provides pieces that can be used to build a LISP dialect or can be used as a scripting layer.

Usage

What can you use it for?

  1. Embedded script engine to provide dynamic behavior without requiring re-compilation of your application.
  2. Business rule engine by exposing very specific & composable rule functions.
  3. To build your own LISP dialect.

Sabre requires Go 1.13 or higher.

As Embedded Script Engine

Sabre has concept of Scope which is responsible for maintaining bindings. You can bind any Go value and access it using LISP code, which makes it possible to expose parts of your API and make it scriptable or build your own LISP dialect. Also, See Extending for more information on customizing the reader or eval.

package main

import "github.com/spy16/sabre"

func main() {
    scope := sabre.NewScope(nil)
    _ = scope.BindGo("inc", func(v int) int { return v+1 })

    result, _ := sabre.ReadEvalStr(scope, "(inc 10)")
    fmt.Printf("Result: %v\n", result) // should print "Result: 11"
}

Expose through a REPL

Sabre comes with a tiny repl package that is very flexible and easy to setup to expose your LISP through a read-eval-print-loop.

package main

import (
  "context"

  "github.com/spy16/sabre"
  "github.com/spy16/sabre/repl"
)

func main() {
  scope := sabre.NewScope(nil)
  scope.BindGo("inc", func(v int) int { return v+1 })

  repl.New(scope,
    repl.WithBanner("Welcome to my own LISP!"),
    repl.WithPrompts("=>", "|"),
    // many more options available
  ).Loop(context.Background())
}

Standalone

Sabre has a small reference LISP dialect named Slang (short for Sabre Lang) for which a standalone binary is available. Check out Slang for instructions on installing Slang.

Extending

Reader

Sabre reader is inspired by Clojure reader and uses a read table. Reader supports following forms:

Reader can be extended to add new syntactical features by adding reader macros to the read table. Reader Macros are implementations of sabre.ReaderMacro function type. Except numbers and symbols, everything else supported by the reader is implemented using reader macros.

Evaluation