The Gmnlisp is a small Lisp implementation in Go. The functions are the subset of ISLisp's. It is developed to embbed to the applications for customizing.
package main
import (
"context"
"fmt"
"os"
"github.com/hymkor/gmnlisp"
)
func main() {
lisp := gmnlisp.New()
lisp = lisp.Let(gmnlisp.Variables{
gmnlisp.NewSymbol("a"): gmnlisp.Integer(1),
gmnlisp.NewSymbol("b"): gmnlisp.Integer(2),
})
value, err := lisp.Interpret(context.TODO(), "(+ a b)")
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
return
}
fmt.Println(value.String())
}
$ go run examples/example1.go
3
gmnlisp.New
returns the new Lisp interpretor instance (*gmnlisp.World
).gmnlisp.NewSymbol
is the symbol constructor.gmnlisp.NewSymbol("a")
always returns the same value no matter how many times you call it.gmnlisp.Variables
is the symbol-map type. It is the alias ofmap[gmnlisp.Symbol]gmnlisp.Node
.Node
is the interface-type that all objects in the Lisp have to implement..Let
makes a new instance including the given namespace.
lisp.Let(gmnlisp.Variables{
gmnlisp.NewSymbol("a"): gmnlisp.Integer(1),
gmnlisp.NewSymbol("b"): gmnlisp.Integer(2),
}).Interpret(context.Background(),"(c)")
is same as (let ((a 1) (b 1)) (c))
package main
import (
"context"
"fmt"
"os"
"github.com/hymkor/gmnlisp"
)
func sum(ctx context.Context, w *gmnlisp.World, args []gmnlisp.Node) (gmnlisp.Node, error) {
a, err := gmnlisp.ExpectClass[gmnlisp.Integer](ctx, w, args[0])
if err != nil {
return nil, err
}
b, err := gmnlisp.ExpectClass[gmnlisp.Integer](ctx, w, args[1])
if err != nil {
return nil, err
}
return a + b, nil
}
func main() {
lisp := gmnlisp.New()
lisp = lisp.Flet(
gmnlisp.Functions{
gmnlisp.NewSymbol("sum"): &gmnlisp.Function{C: 2, F: sum},
})
result, err := lisp.Interpret(context.Background(), `(sum 1 2)`)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
return
}
fmt.Printf("(sum 1 2)=%v\n", result)
}
$ go run examples/example2.go
(sum 1 2)=3
a,err := gmnlisp.ExpectClass[gmnlisp.Integer](ctx,w,x)
is similar as
a,ok := x.(gmnlisp.Integer)
but, ExpectClass can call error-handler defined by user when x is not Integer
The user defined normal functions have to get the three parameters.
- The 1st: context.Context that is given to the method .Interpret()
- The 2nd: *gmnlisp.World on which the instance runs.
- The 3rd: []gmnlisp.Node the parameters given by caller. They are already evaluated.
gmnlisp.Function
wraps the normal function as Lisp object.
F
: the function itselfC
: when the number of the parameter is not same as this, the error will be raised. If it does not have to be checked, omit it.
To get unevaluted parameters, the function's definition should be as below.
func FUNCNAME(c context.Context,w *World,args Node)(Node,error){...}
- The parameters are given as a list not an array.
- Use
gmnlisp.SpecialF(FUNCNAME)
instead ofgmnlisp.Function{F:FUNCNAME}
Type(Lisp) | Type(Go) |
---|---|
t | gmnlisp._TrueType |
nil | gmnlisp._NullType |
<integer> | gmnlisp.Integer == int64 |
<float> | gmnlisp.Float == float64 |
<string> | gmnlisp.String == string |
<symbol> | gmnlisp.Symbol == int |
<cons> | *gmnlisp.Cons == struct{ Car,Cdr: gmnlisp.Node } |
<character> | gmnlisp.Rune == rune |
(keyword) | gmnlisp.Keyword |
(array) | *gmnlisp.Array |
(hashtable) | gmnlisp._Hash == map[gmnlisp.Node]gmnlisp.Node |
gmnlisp.Node
is the root interface.
All objects used in Lisp code have to satisfy it.
gmnlisp.Symbol
is the unique number associated to string.
- string to gmnlisp.Symbol
sbl := gmnlisp.NewSymbol("foo")
- Symbol to string
sbl.String()
Gmnlisp's functions are subset of ISLisp.
Items without checkboxes are not standard functions
- block
- dynamic-let
- flet
- for
- labels
- let
- let*
- tagbody
- with-error-output
- with-open-input-file
- with-open-io-file
- with-open-output-file
- with-standard-input
- with-standard-output
- and
- assure
- block
- case
- case-using
- catch
- class
- cond
- convert
- dynamic
- dynamic-let
- flet
- for
- function
- &rest
- #'FUNCTION
- go
- if
- ignore-errors
- labels
- lambda
- let
- let*
- or
- progn
- quote
- return-from
- setf
- setq
- tagbody
- the
- throw
- unwind-protect
- while
- with-error-output
- with-handler
- with-open-input-file
- with-open-io-file
- with-open-output-file
- with-standard-input
- with-standard-output
- defclass
- :initarg
- :initform
- :accessor
- :reader
- :writer
- :boundp
- defconstant (defined same as defglobal for dummy)
- defdynamic
- defgeneric
- defglobal
- defmacro
- defmethod
- defun
- functionp
- function
- lambda
- labels
- flet
- apply
- funcall
- defconstant
- defglobal
- defdynamic
- defun
- t
- nil
- basic-array-p
- basic-array*-p
- basic-vector-p
- characterp
- consp
- floatp
- functionp
- general-array*-p
- general-vector-p
- generic-function-p
- integerp
- listp
- null
- numberp
- streamp
- stringp
- symbolp
- atom OBJ
- evenp OBJ
- minusp OBJ
- oddp OBJ
- plusp OBJ
- zerop OBJ
- eq
- eql
- equal
- equalp
- not
- and
- or
- (quote)
- 'OBJ
- setq
- setf
- let
- let*
- dynamic
- dynamic-let
- if
- cond
- case
- case-using
- when
- unless
- progn
- prog1
- prog2
- while
- for
- dolist
- dotimes
- block
- return-from
- catch
- throw
- tagbody
- go
- return
- unwind-protect
- defclass
- generic-function-p
- defgeneric
- :rest, &rest
- defmethod
- :rest, &rest
- call-next-method
- next-method-p
- create
- :initarg
- :initform
- :accessor
- :reader
- :writer
- :boundp
- initialize-object
- class-of
- instancep
- subclassp
- class
- defmacro
- 'form
- `form
- ,@form
- the
- assure
- convert
- (convert OBJ <float>)
- (convert OBJ <integer>)
- (convert OBJ <list>)
- (convert OBJ <string>)
- (convert OBJ <symbol>)
- symbolp
- property
- set-property , setf
- remove-property
- gensym
- numberp
- parse-number
- =
- /=
- >=
- <=
- >
- <
- +
- *
- -
- reciproca1
- quotient
- max
- min
- abs
- exp
- log
- expt
- sqrt
- sin
- cos
- tan
- atan
- atan2
- sinh
- cosh
- tanh
- atanh
- 1+
- 1-
- incf
- decf
- *pi*
- *most-positive-float*
- *most-negative-float*
- floatp
- float
- floor
- ceiling
- truncate
- round
- integerp
- div
- mod
- gcd
- lcm
- isqrt
- rem
- most-postive-fixnum
- most-negative-fixnum
- characterp
- char=
- char/=
- char<
- char>
- char<=
- char>=
- consp
- cons OBJ
- car
- cdr
- set-car, (setf (car CONS) OBJ)
- set-cdr, (setf (cdr CONS) OBJ)
- null
- listp
- create-list
- list
- reverse
- nreverse
- append
- member
- mapcar
- mapc
- maplist
- mapl
- mapcan
- mapcon
- assoc
- last
- basic-array-p
- basic-array*-p
- general-array*-p
- create-array
- aref
- garef
- set-aref , (setf (aref BASIC-ARRAY Z*) OBJ)
- set-garef , (setf (garef BASIC-ARRAY Z*) OBJ)
- array-dimensions
- #(...) , #2a((...) (...)) , #3a(((.. ..))) ...
- basic-vector-p
- general-vector-p
- create-vector
- vector
- stringp
- create-string
- string=
- string/=
- string<
- string>
- string>=
- string<=
- char-index
- string-index
- string-append
- length
- elt
- set-elt, (setf (elt SEQ Z) OBJ)
- subseq
- map-into
- streamp
- open-stream-p
- input-stream-p
- output-stream-p
- standard-input
- standard-output
- error-output
- with-standard-input
- with-standard-output
- with-error-output
- open-input-file
- open-output-file
- open-io-file
- with-open-input-file
- with-open-output-file
- with-open-io-file
- close
- finish-output
- create-string-input-stream
- create-string-output-stream
- get-output-stream-string
- read
- read-char
- preview-char
- read-line
- stream-ready-p
- format
- format-char
- format-float
- format-fresh-line
- format-integer
- format-object
- format-tab
- read-byte
- write-byte
- probe-file
- file-position
- set-file-position
- file-length
- error
- cerror
- signal-condition
- ignore-error
- report-condition
- condition-continuable
- continue-condition
- with-handler
- arithmetic-error-operation
- arithmetic-error-operands
- domain-error-object
- domain-error-expected-class
- parse-error-string
- parse-error-expected-class
- simple-error-format-string
- simple-error-format-arguments
- stream-error-stream
- undefined-entity-name
- undefined-entity-namespace
- <program-error>
- arity-error
- immutable-binding
- improper-argument-binding
- index-out-of-range
- <storage-exhausted>
- cannot-create-array
- cannot-create-array
- cannot-create-cons
- cannot-create-list
- cannot-create-sequence
- cannot-create-string
- cannot-create-vector
- <parse-error>, cannot-parse-number
- <control-error>, control-error
- <devision-by-zero>, division-by-zero
- <domain-error>
- not-an-input-stream
- not-an-output-stream
- <end-of-stream>, end-of-stream
- <undefined-entity> , undefined-entity
- <unbound-variable> , unbound-variable
- <undefined-function>, undefined-function
- identify
- get-universal-time
- get-internal-real-time
- get-internal-run-time
- internal-time-units-per-second
(let ((h1 (make-hash-table)))
(setf (gethash 'width h1) 600)
(gethash 'width h1)
(hash-table-count h1)
(remhash 'width h1)
(clrhash h1)
)
- (exit)
- (quit)
- (abort)
- ISLISP - Wikipedia
- ISLisp Home Page
- www.islisp.info: Home
- Programming Language ISLISP Working Draft 23.0
Other implementations of ISLisp
Language | Windows | Linux | |
---|---|---|---|
OK!ISLisp | C | Supported | ? |
iris | Go | Supported | Supported |
Easy-ISLisp | C | Supported |