gimmick

package module
v0.0.0-...-af96495 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2017 License: BSD-2-Clause Imports: 14 Imported by: 0

README

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.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetTypeString

func GetTypeString(v Value) string

GetTypeString returns the name of the type for the Value object.

Types

type Bool

type Bool bool

Bool is a boolean true or false value

type Environment

type Environment struct {
	// Vars are the symbol mappings for the environment context
	Vars map[Symbol]Value

	// Macros is the collection of syntax extension procedures that can
	// expand incoming symbolic expressions before executing them.
	Macros map[Symbol]Procedure

	// Parent is the enclosing environment object
	Parent *Environment
	// contains filtered or unexported fields
}

Environment represents the symbol mappings for a given context; can be nested.

func NewEnvironment

func NewEnvironment(parent *Environment) *Environment

NewEnvironment creates a new environment context with an optional parent context.

func (*Environment) Copy

func (env *Environment) Copy() *Environment

Copy returns a new copy of the Environment with a separate Vars map so that changes to the copy do not affect the Vars of the original Environment.

func (*Environment) Find

func (env *Environment) Find(s Symbol) (Value, bool)

Find attempts to find the symbol in the current environment mapping or it's parent environment. Returns a bool indicating if the Value was found.

func (*Environment) FindMacro

func (env *Environment) FindMacro(s Symbol) (p Procedure, success bool)

FindMacro attempts to find the symbol in the current environment macros or it's parent environment. Returns a bool indicating if the macro Procedure was found.

func (*Environment) SetupPrimitives

func (env *Environment) SetupPrimitives()

SetupPrimitives will add in the primitive functions to the given environment.

type Float

type Float float64

Float is the type for floating point values

type Integer

type Integer int64

Integer is the type for integer values

type List

type List []Value

List is the list datatype that contains multiple values

type Primitive

type Primitive func(Value, *Environment) Value

Primitive is a built in function

type Procedure

type Procedure struct {
	//ParentEnv is the environment the procedure was defined in
	ParentEnv *Environment

	// Body is sexp that will be evaluated when the procedure is called
	Body Value

	// Args is the list of procedure arguments accepted
	Args List

	VariableParameters bool
}

Procedure is a user defined function

type RuseCommand

type RuseCommand int

RuseCommand aliases the int type for commands to send to the Ruse server

type String

type String string

String is the string type value

type Symbol

type Symbol string

Symbol is the type for the symbol values

type SyntaxError

type SyntaxError struct {
	// Message is the error message for the syntax error
	Message string

	// Filename is the name of the file associated with the error
	Filename string

	// LineNumber is the line number where the error occurred
	LineNumber int
}

SyntaxError is an error type for syntax problems in the source code.

func NewSyntaxError

func NewSyntaxError(msg string, fn string, ln int) *SyntaxError

NewSyntaxError creates a new error value for syntax problems.

func (*SyntaxError) Error

func (err *SyntaxError) Error() string

Error prints the syntax error message out to a string.

type Value

type Value interface{}

Value is the common interface between scheme data types (e.g. number, symbol, lists)

func Eval

func Eval(v Value, env *Environment) Value

Eval evalutes a sexp value in a given environment and returns the result.

func ParseString

func ParseString(source string) (Value, error)

ParseString takes a source code chunk in string form and parses it returning the resulting Value or an error.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL