lisp

package module
v0.0.0-...-1e26f15 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2023 License: AGPL-3.0 Imports: 6 Imported by: 0

README

Go Lisp Interpreter

This repository contains a small Lisp-like language interpreter implemented in Golang.

(fmt.Println "Hello, World!")

Features

This Go Lisp Interpreter offers the following features:

  • Easy Interoperability with Golang: You can easily call Go code from within this Lisp language. Simply use interp.Use(lisp.Symbols.All) or interp.Use(lisp.Symbols.Fmt) to add symbols to the root scope. These example symbols are collections of stdlib functions exported as a map of functions. To mix Lisp and Go code, use interp.EvalWithMap("(+ x 1)", lisp.ScopeMap{ "x": 1 }), which evaluates to int64(2). Alternatively, the method Interpreter.EvalWithValues(string, any...) allows you to provide a series of values that will be bound to _0, _1, and so on. It's important to note that these bindings do not override globals with the same name, as a new scope is created.

  • Lists: The language supports lists represented as [1 2 3].

  • Maps: Maps can be created using the syntax { #name "John" #surname "Smith" }.

  • Property Chaining: Property chaining is supported using the dot notation. For example, you can compute the length of a vector with (math.Sqrt (+ (^ v.x 2) (^ v.y 2) (^ v.z 2))).

  • Quasi-quotes: Quasi-quotes are denoted by the symbols # for quoting and $ for interpolation. For instance, #(a b 1.0 [3 $(+ 3 1) 5] $(+ 1 2 3)) evaluates to #(a b 1 [3 4 5] 6). This feature allows for convenient construction of data structures or DSLs. As an example, an HTML DSL could be defined as follows:

    #(div { #class "card" }
        (img { #src $author.profile-image-url #alt "example image" })
        (div { #class "title" } $author.full-name)
        (div { #class "description" } $author.bio)  
    
  • Lexical Scoping: Lexical scoping is not yet implemented in the current version.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseExpression

func ParseExpression(tokens []Token) (any, error)

func Show

func Show(v any) string

Types

type Apply

type Apply struct{ Values []any }

func (Apply) String

func (e Apply) String() string

type Drill

type Drill struct{ Chain []any }

func (Drill) String

func (e Drill) String() string

type Interpreter

type Interpreter struct {
	Root *Scope
}

func NewInterpreter

func NewInterpreter() *Interpreter

func (*Interpreter) Eval

func (i *Interpreter) Eval(program string) (any, error)
Example (Plus)
interp := lisp.NewInterpreter()
v, err := interp.Eval(`(+ 1 2 3)`)
if err != nil {
	log.Fatal(err)
}

fmt.Println(lisp.Show(v))
Output:

6
Example (Println)
interp := lisp.NewInterpreter()
v, err := interp.Eval(`(fmt.Println "Hello, World!")`)
if err != nil {
	log.Fatal(err)
}

fmt.Println(lisp.Show(v))
Output:

Hello, World!
(14 ())
Example (Quasiquote)
interp := lisp.NewInterpreter()
v, err := interp.Eval(`#(a b 1.0 [3 $(+ 3 1) 5] $(+ 1 2 3))`)
if err != nil {
	log.Fatal(err)
}

fmt.Println(lisp.Show(v))
Output:

#(a b 1 [3 4 5] 6)
Example (Quote1)
interp := lisp.NewInterpreter()
v, err := interp.Eval(`#"example"`)
if err != nil {
	log.Fatal(err)
}

fmt.Println(lisp.Show(v))
Output:

#"example"
Example (Quote2)
interp := lisp.NewInterpreter()
v, err := interp.Eval(`#(+ 1 2 3)`)
if err != nil {
	log.Fatal(err)
}

fmt.Println(lisp.Show(v))
Output:

#(+ 1 2 3)
Example (String)
interp := lisp.NewInterpreter()
v, err := interp.Eval(`"example"`)
if err != nil {
	log.Fatal(err)
}

fmt.Println(lisp.Show(v))
Output:

"example"

func (*Interpreter) Execute

func (i *Interpreter) Execute(program string) error
Example (List)
interp := lisp.NewInterpreter()
err := interp.Execute(`
		(set! a [1 2 3])
		(fmt.Println a)
		(fmt.Println a.0)
		(fmt.Println a.1)
		(fmt.Println a.2)
	`)
if err != nil {
	log.Fatal(err)
}
Output:

[1 2 3]
1
2
3
Example (Map)
interp := lisp.NewInterpreter()
err := interp.Execute(`
		(set! v {#a 1 #b 2 #c (+ 1 2)})
		(fmt.Println v)
		(fmt.Println v.0)
		(fmt.Println v.1)
		(fmt.Println v.2)
	`)
if err != nil {
	log.Fatal(err)
}
Output:

{#a 1 #b 2 #c 3}
(#a 1)
(#b 2)
(#c 3)

type List

type List struct{ Values []any }

func (List) String

func (e List) String() string

type Map

type Map struct{ Entries []Apply }

func (Map) String

func (e Map) String() string

type Quote

type Quote struct{ Value any }

func (Quote) String

func (e Quote) String() string

type Scope

type Scope struct {
	Parent   *Scope
	Bindings map[string]any
}

type Symbol

type Symbol struct{ Name string }

func (Symbol) String

func (e Symbol) String() string

type Token

type Token struct {
	Type     TokenType
	Value    string
	Location int
}

func Tokenize

func Tokenize(source string) ([]Token, error)

type TokenType

type TokenType string
var (
	CommentToken     TokenType = "Comment"
	FloatToken       TokenType = "Float"
	IntegerToken     TokenType = "Integer"
	StringToken      TokenType = "String"
	PunctuationToken TokenType = "Punctuation"
	WhitespaceToken  TokenType = "Whitespace"
	IdentifierToken  TokenType = "Identifier"
)

type TokenizeError

type TokenizeError struct {
	Source   *string
	Location int
	Message  string
}

func (TokenizeError) Error

func (e TokenizeError) Error() string

type Unquote

type Unquote struct{ Value any }

func (Unquote) String

func (e Unquote) String() string

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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