z3s5

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

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

Go to latest
Published: Oct 27, 2023 License: MIT Imports: 41 Imported by: 0

README

Z3S5 Lisp

"I want my 1980s Lisp!"

Z3S5 GoDoc Go Report Card

Usage

Check out the basic lisp interpreter z3.go in folder cmd/z3/ for an example of how to use Z3S5 Lisp in the Go language. You may also use the interpreter from the command line by running the z3 binary.

There is a build tag nosound you may use to leave out sound support. If this option is not specified, then the beep command produces a few basic sounds which are embedded into the executable and do slightly increase its size.

Building

Go 1.18+ is required.

Linux: Alsa sound support development library libasound2 needs to be installed with apt get install libasound2 on Debian-based distributions. For the manuals both pandoc and the Eisvogel Pandoc Template are required. Notice that normal make will attempt to compile these manuals. You may use make lisp in directory cmd/z3 to only compile the z3 sample executable if you want to test it without generating manuals.

Windows: This has not been tested on Windows so far but should work as long as your machine satisfies the compilation requirements for the Beep sound library or if you use build tag nosound.

MacOS: Not tested so far; building should be similar to Linux.

Z3S5 Lisp Reference

A rudimentary user manual can be found in directory docs/usermanual and PDF and HTML can be generated using the accompanying makefile if pandoc is installed on your system. A very large reference manual can be generated by using the makefile in the main directory or make docs in directory cmd/z3 once the z3 executable has been built.

Online help: You may use (dump [prefix]) in the Lisp system to get a list of toplevel bindings, (help symbol) without quote to get information about a function, global symbol, or macro. To get a list of help topics use (help-topics) and (help-about topic) provides a list of symbols for a help topic.

Z3S5 Lisp is an old-fashioned Lisp-1 dialect originally based on Nukata Lisp by SUZUKI Hisao. It uses real cons cells and is reasonably fast for an interpreter. (Depending on your mileage, it's definitely not optimized for speed.) There are some notable differences to other Lisps:

  • Iterators over sequences use the order (iterator sequence function), not sometimes one and sometimes the other. Exception: memq and member ask whether an element is a member of a list and have order (member element list).

  • There is no meaningful eq, equality is generally tested with equal?.

  • Predicate names generally end in a question mark like in Scheme dialects except for = for numeric equality. Example: equal?. There is no p-suffix like in other Lisps.

  • dict data structures are very powerful and multi-threading safe.

  • There is experimental support for concurrency with green threads (aka goroutines).

Please don't complain it's not Common Lisp or R7RS Scheme! Z3S5 Lisp is deliberately a somewhat arcane, old-fashioned language mostly used for experimentation in a forthcoming retro-style virtual Lisp machine and as an extension language for my own software projects.

License

Permissive MIT License. Happy hacking! 😸

Documentation

Overview

Z3S5 Lisp by Erich Rast. A Lisp-1 for Go based on Nukata Lisp 2.0 by SUZUKI Hisao. MIT License, see the accompanying LICENSE file.

Z3S5 Lisp by Erich Rast.
A Lisp-1 for Go based on Nukata Lisp 2.0 by SUZUKI Hisao.
MIT License, see the accompanying LICENSE file.

Index

Constants

View Source
const (
	SourceSortFile = iota
	SourceSortInternal
)
View Source
const DEFAULT_BUFFMAX = 1048576 // default max buffer size
View Source
const DEFAULT_BUFFSIZE = 32768 // default buffer size for reader
View Source
const DrawTextHook = 2 // Z3S5 Machine draw text in vram - unused in Z3S5 Lisp
View Source
const LastHook = 16 // *never used*
View Source
const LoadHook = 4 // Z3S5 Machine editor load hook - unused in Z3S5 Lisp
View Source
const LoadTextHook = 5 // Z3S5 Machine editor load text hook - unused in Z3S5 Lisp
View Source
const PrintHook = 3 // Z3S5 Machine print text in editor - unused in Z3S5 Lisp
View Source
const SND_CLICK = 3
View Source
const SND_CONFIRM = 5
View Source
const SND_ERROR = 0
View Source
const SND_INFO = 6
View Source
const SND_OKAY = 4
View Source
const SND_READY = 2
View Source
const SND_START = 1
View Source
const SaveHook = 6 // Z3S5 Machine editor save hook - unused in Z3S5 Lisp
View Source
const SaveTextHook = 7 // Z3S5 Machine editor save text hook - unused in Z3S5 Lisp
View Source
const ScrollDownPost = 14 // Z3S5 Machine after scrolling down - unused in Z3S5 Lisp
View Source
const ScrollDownPre = 13 // Z3S5 Machine before scrolling down - unused in Z3S5 Lisp
View Source
const ScrollUpPost = 12 // Z3S5 Machine after scrolling up - unused in Z3S5 Lisp
View Source
const ScrollUpPre = 11 // Z3S5 Machine before scrolling up - unused in Z3S5 Lisp
View Source
const SetCursorHook = 1 // Z3S5 Machine set cursor position in vram - unused in Z3S5 Lisp

Constants for hooks. These are used by various modules and introduce a flat global dependency on github.com/rasteric/hooks. They are defined individually in order to prevent insertion errors. Except for LastHook, the numbers are fixed for all future and can never change or be reused.

View Source
const ShutdownHook = 9 // just before the system shuts down
View Source
const SlowIRQHook = 8 // general slow IRQ (ca. 1 sec. intervals)
View Source
const StartupHook = 15 // called after the system has been started (all init files loaded)
View Source
const SuperslowIRQHook = 10 // very slow (only every few minutes)

Variables

View Source
var AppendSym = NewSym("append")
View Source
var ApplySym = NewSym("apply")
View Source
var ArraySym = NewSym("array")
View Source
var BackQuoteSym = NewSym("`")
View Source
var BoxedBlob = NewSym("blob")

Boxed types (mostly handled externally).

View Source
var BoxedDecimal = NewSym("dec.num")
View Source
var ColorBlack = Color{0, 0, 0, 255, true}
View Source
var ColorWhite = Color{255, 255, 255, 255, true}
View Source
var CommaAtSym = NewSym(",@")
View Source
var CommaSym = NewSym(",")
View Source
var CondSym = NewSym2("cond", true)
View Source
var ConsSym = NewSym("cons")
View Source
var DotSym = NewSym(".")
View Source
var EofToken error = io.EOF

EofToken is a token which represents the end of file.

View Source
var ErrNoSuchPermission = errors.New("security violation - missing permission")
View Source
var ErrPermissionManagerFail = errors.New("internal permission manager failure")
View Source
var ErrSecurityViolation = errors.New("security violation")
View Source
var ErrUnknownPermission = errors.New("unknown permission")
View Source
var ErrorHandler = NewSym("*error-handler*")
View Source
var ErrorPrinter = NewSym("*error-printer*")
View Source
var FullPermissions = Permissions{
	AllowUnprotect: true,
	AllowProtect:   true,
	LoadPrelude:    true,
	LoadUserInit:   true,
	Interactive:    true,
	AllowFileRead:  true,
	AllowFileWrite: true,
}

FullPermissions are the default full permissions of a machine, allowing full access to all resources of the machine.

View Source
var FutureSym = NewSym2("future", true)
View Source
var HashSym = NewSym("#")
View Source
var LambdaSym = NewSym2("lambda", true)
View Source
var LeftParenSym = NewSym("(")
View Source
var ListSym = NewSym("list")
View Source
var MacroSym = NewSym2("macro", true)
View Source
var Number0 = goarith.AsNumber(0)
View Source
var Number1 = goarith.AsNumber(1)
View Source
var Prelude = strings.Replace(`
(setq defmacro
      (macro (name args &rest body)
             ~(progn (setq ,name (macro ,args ,@body))
                     ',name)))

(defmacro defun (name args &rest body)
  ~(progn (setq ,name (lambda ,args ,@body))
          ',name))

(defun caar (x) (car (car x)))
(defun cadr (x) (car (cdr x)))
(defun cdar (x) (cdr (car x)))
(defun cddr (x) (cdr (cdr x)))
(defun caaar (x) (car (car (car x))))
(defun caadr (x) (car (car (cdr x))))
(defun cadar (x) (car (cdr (car x))))
(defun caddr (x) (car (cdr (cdr x))))
(defun cdaar (x) (cdr (car (car x))))
(defun cdadr (x) (cdr (car (cdr x))))
(defun cddar (x) (cdr (cdr (car x))))
(defun cdddr (x) (cdr (cdr (cdr x))))
(defun not (x) (eq? x nil))
(defun cons? (x) (not (atom? x)))
(defun print (x) (prin1 x) (terpri) x)
(defun identity (x) x)

(defun feature? (sym)
 (if (member sym *reflect*) t nil))

(setq
 = eql?
 null? not
 setcar rplaca
 setcdr rplacd)

(defun > (x y) (< y x))
(defun >= (x y) (not (< x y)))
(defun <= (x y) (not (< y x)))
(defun /= (x y) (not (= x y)))

(defun equal? (x y)
  (cond ((atom? x) (eql? x y))
        ((atom? y) nil)
        ((equal? (car x) (car y)) (equal? (cdr x) (cdr y)))))

(defmacro if (test then &rest else)
  ~(cond (,test ,then)
         ,@(cond (else ~((t ,@else))))))

(defmacro when (test &rest then)
  ~(cond (,test ,@then)
         ,@(cond (t ~((t (void)))))))

(defmacro unless (test &rest then)
  ~(cond ((not ,test) ,@then)
         ,@(cond (t ~((t (void)))))))

;; original definition returns nil instead of void:
;; (defmacro when (test &rest body)
;;  ~(cond (,test ,@body)))

(defmacro let (args &rest body)
  ((lambda (vars vals)
     (defun vars (x)
       (cond (x (cons (if (atom? (car x))
                          (car x)
                        (caar x))
                      (vars (cdr x))))))
     (defun vals (x)
       (cond (x (cons (if (atom? (car x))
                          nil
                        (cadar x))
                      (vals (cdr x))))))
     ~((lambda ,(vars args) ,@body) ,@(vals args)))
   nil nil))

(defmacro letrec (args &rest body)      ; (letrec ((v e) ...) body...)
  (let (vars setqs)
    (defun vars (x)
      (cond (x (cons (caar x)
                     (vars (cdr x))))))
    (defun sets (x)
      (cond (x (cons ~(setq ,(caar x) ,(cadar x))
                     (sets (cdr x))))))
    ~(let ,(vars args) ,@(sets args) ,@body)))

(defun _append (x y)
  (if (null? x)
      y
    (cons (car x) (_append (cdr x) y))))

(defmacro append (x &rest y)
  (if (null? y)
      x
    ~(_append ,x (append ,@y))))

(defmacro and (x &rest y)
  (if (null? y)
      x
    ~(cond (,x (and ,@y)))))

(defun mapcar (x f)
  (and x (cons (f (car x)) (mapcar (cdr x) f))))

(defmacro or (x &rest y)
  (if (null? y)
      x
    ~(cond (,x)
           ((or ,@y)))))

(defun list? (x)
  (or (null? x) (cons? x)))    ; NB (list? (lambda (x) (+ x 1))) => nil

(defun memq (key x)
  (cond ((null? x) nil)
        ((eq? key (car x)) x)
        (t (memq key (cdr x)))))

(defun member (key x)
  (cond ((null? x) nil)
        ((equal? key (car x)) x)
        (t (member key (cdr x)))))

(defun assq (key alist)
  (cond (alist (let ((e (car alist)))
                 (if (and (cons? e) (eq? key (car e)))
                     e
                   (assq key (cdr alist)))))))

(defun assoc (key alist)
  (cond (alist (let ((e (car alist)))
                 (if (and (cons? e) (equal? key (car e)))
                     e
                   (assoc key (cdr alist)))))))

(defun _nreverse (x prev)
  (let ((next (cdr x)))
    (setcdr x prev)
    (if (null? next)
        x
      (_nreverse next x))))
(defun nreverse (list)            ; (nreverse '(a b c d)) => (d c b a)
  (cond (list (_nreverse list nil))))

(defun list-last (list)
  (if (atom? (cdr list))
      list
    (list-last (cdr list))))

(defun nconc (&rest lists)
  (if (null? (cdr lists))
      (car lists)
    (if (null? (car lists))
        (apply nconc (cdr lists))
      (setcdr (list-last (car lists))
              (apply nconc (cdr lists)))
      (car lists))))

(defmacro while (test &rest body)
  (let ((loop (gensym)))
    ~(letrec ((,loop (lambda () (cond (,test ,@body (,loop))(t (void))))))
       (,loop))))

(defmacro dolist (spec &rest body) ; (dolist (name list [result]) body...)
  (let ((name (car spec))
        (list (gensym)))
    ~(let (,name
           (,list ,(cadr spec)))
       (while ,list
         (setq ,name (car ,list))
         ,@body
         (setq ,list (cdr ,list)))
       ,@(if (cddr spec)
             ~((setq ,name nil)
               ,(caddr spec))))))

(defmacro dotimes (spec &rest body) ; (dotimes (name count [result]) body...)
  (let ((name (car spec))
        (count (gensym)))
    ~(let ((,name 0)
           (,count ,(cadr spec)))
       (while (< ,name ,count)
         ,@body
         (setq ,name (+ ,name 1)))
       ,@(if (cddr spec)
             ~(,(caddr spec))))))

(setq *mutable-toplevel-symbols* (dict))

(defun declare-unprotected (sym)
  (set *mutable-toplevel-symbols* sym t))

(setq *volatile-toplevel-symbols* (dict))

(defun declare-volatile (sym)
  (set *volatile-toplevel-symbols* sym t))

(declare-volatile '*volatile-toplevel-symbols*)
(declare-volatile '*mutable-toplevel-symbols*)
(declare-unprotected 'vars) ; fixes unclean macro definitions using defun 
(declare-unprotected 'vals) ; so these do not get protected later
(declare-unprotected 'sets) ; unbind does not do the job since init sequence uses the macros later

`, "~", "`", -1)

Prelude is an initialization script of Lisp. Each "~" is replaced by "`" at runtime.

View Source
var ProgNSym = NewSym2("progn", true)
View Source
var QuasiquoteSym = NewSym2("quasiquote", true)
View Source
var QuoteSym = NewSym2("quote", true)
View Source
var ReflectSym = NewSym("*reflect*")
View Source
var RestSym = NewSym("&rest")
View Source
var RestrictedPermissions = Permissions{
	AllowUnprotect: false,
	AllowProtect:   false,
	LoadPrelude:    true,
	LoadUserInit:   true,
	Interactive:    false,
	AllowFileRead:  false,
	AllowFileWrite: false,
}

SafeSilentPermissions are minimal permissions without sound, graphics, and file access but with prefs read access and console.

View Source
var RightParenSym = NewSym(")")
View Source
var SetqSym = NewSym2("setq", true)
View Source
var SingleQuoteSym = NewSym("'")
View Source
var TaskSym = NewSym2("systask", true)
View Source
var UnquoteSplicingSym = NewSym("unquote-splicing")
View Source
var UnquoteSym = NewSym("unquote")
View Source
var Void = NewSym("<void>")

Functions

func AsLispBool

func AsLispBool(b bool) any

AsLispBool returns a given Go bool as a Lisp bool, i.e., using Nil for false.

func Btoi

func Btoi(b []byte) uint64

Btoi returns the uint64 from an 8-byte big endian representation.

func ConvertIntsToNumbers

func ConvertIntsToNumbers(a []any)

ConvertIntsToNumbers converts any Int64 integer values in a slice to goarith.Int64 values, modifying the array. The int64 values in the array can afterwards be used in Lisp.

func ConvertNumbersToInts

func ConvertNumbersToInts(a []any)

ConvertNumbersToInts converts any goarith.Int32 and goarith.Int64 values in a slice of interface{} values to Int64, modifying the array. The array can no longer be used for representing Lisp numbers afterwards.

func CopyMap

func CopyMap(m map[any]any) map[any]any

copyMap copies a interface{} map deeply.

func DictToArray

func DictToArray(dict any) []any

dictToArray converts a dict (Go map) to an array.

func GetGID

func GetGID() uint64

GetGID returns the current goroutine's ID. This should not be abused and may break. But who cares! CHECK DANGER UNSAFE

func Itob

func Itob(v uint64) []byte

Itob returns an 8-byte big endian representation of an uint64.

func ListToArray

func ListToArray(li *Cell) []any

ListToArray converts a list into an array (Go slice).

func MaxInt

func MaxInt(a, b int) int

MaxInt returns the larger of two ints, the first argument if they are equal.

func MinInt

func MinInt(a, b int) int

MinInt returns the smaller of two ints, the first argument if they are equal.

func NewClosure

func NewClosure(carity int, args *Cell, body *Cell, env *Cell) any

NewClosure constructs a Closure.

func NewLambda

func NewLambda(carity int, args *Cell, body *Cell, env *Cell) any

NewLambda constructs a Lambda.

func NewMacro

func NewMacro(carity int, args *Cell, body *Cell, env *Cell) any

NewMacro constructs a Macro.

func QqExpand

func QqExpand(x any) any

QqExpand expands x of any quasi-quote `x into the equivalent S-expression.

func QqQuote

func QqQuote(x any) any

QqQuote quotes x so that the result evaluates to x.

func ReverseArray

func ReverseArray(arr []any) []any

reverse array returns an array reversed as copy

func ReverseStr

func ReverseStr(s string) string

reverse a string

func Same

func Same(a, b any) bool

Same is true if two Lisp interface{} have the same values, false otherwise. This is needed because map[interface{}]interface{} cannot be compared!

func SleepHiRes

func SleepHiRes(duration time.Duration, cancel *int32)

SleepNS blocks for duration and then returns. This function busy loops over a high precision timer.

func Str

func Str(x any) string

Str returns a textual representation of any Lisp expression x.

func Str2

func Str2(x any, quoteString bool) string

Str2 returns a textual representation of any Lisp expression x. If quoteString is true, any strings in the expression are represented with enclosing quotes respectively.

func ToBool

func ToBool(a any) bool

ToBool takes a Lisp bool and returns a Go bool. See asLispBool for more information.

func ToFloat64

func ToFloat64(x any) float64

func ToInt64

func ToInt64(caller string, a any) int64

ToInt64 attempts to convert a value to int64

func ToMaybeUInt64

func ToMaybeUInt64(a any) (uint64, bool)

ToMaybeUInt64 attempts to convert a value to uint64

func ToUInt16

func ToUInt16(a any) uint16

ToUint16 converts a value to uint16

func ToUInt32

func ToUInt32(a any) uint32

ToUInt32 converts a value to uint32

func ToUInt8

func ToUInt8(a any) uint8

ToUInt8 convert a value to uint8

Types

type Arg

type Arg struct {
	// Level is a nesting level of the lexical scope.
	// 0 for the innermost scope.
	Level int

	// Offset is an offset of the variable within the frame of the Level.
	// 0 for the first variable within the frame.
	Offset int

	// Sym is a symbol which represented the variable before compilation.
	Symbol *Sym
}

Arg represents a bound variable in a compiled lambda/macro expression. It is constructed with &Arg{level, offset, symbol}.

func (*Arg) Externalize

func (x *Arg) Externalize(interp *Interp, env *Cell) string

Externalize returns the external representation of the argument (assuming it's name has been resolved in higher environments).

func (*Arg) GetValue

func (x *Arg) GetValue(env *Cell) any

GetValue gets a value from the location corresponding to the variable x within an environment env.

func (*Arg) GetValueSafe

func (x *Arg) GetValueSafe(env *Cell) (any, bool)

GetValueSafe gets the value from the location corresponding to the variable x within an environment env and returns true, or it returns nil and false if the value cannot be found in env.

func (*Arg) HasValue

func (x *Arg) HasValue(env *Cell) bool

HasValue returns true if the env has the value of arg, false otherwise.

func (*Arg) SetValue

func (x *Arg) SetValue(y any, env *Cell)

SetValue sets a value y to the location corresponding to the variable x within an environment env.

func (*Arg) String

func (x *Arg) String() string

String returns a textual representation of the Arg.

type Audio

type Audio interface {
	SystemSound(id int)   // play a system sound with given ID
	SetVolume(fl float64) // set the volume of a sound played
}

type BasicAudio

type BasicAudio struct {
}

BasicAudio plays a small number of predefined system sounds.

func NewBasicAudio

func NewBasicAudio() *BasicAudio

func (*BasicAudio) SetVolume

func (audio *BasicAudio) SetVolume(vol float64)

func (*BasicAudio) SystemSound

func (audio *BasicAudio) SystemSound(snd int)

type BasicEditor

type BasicEditor struct {
	// contains filtered or unexported fields
}

BasicEditor provides only basic string entering for a REPL.

func NewBasicEditor

func NewBasicEditor() *BasicEditor

func (*BasicEditor) Color

func (ed *BasicEditor) Color(bg bool) Color

func (*BasicEditor) EndInput

func (ed *BasicEditor) EndInput() (string, bool)

func (*BasicEditor) EndInputCallback

func (ed *BasicEditor) EndInputCallback() func()

func (*BasicEditor) Print

func (ed *BasicEditor) Print(s string) (int, int)

func (*BasicEditor) ResetColor

func (ed *BasicEditor) ResetColor()

func (*BasicEditor) SetColor

func (ed *BasicEditor) SetColor(bg bool, color Color)

func (*BasicEditor) StartInput

func (ed *BasicEditor) StartInput(cb func())

type BasicRuntime

type BasicRuntime struct {
	// contains filtered or unexported fields
}

BasicRuntime is a minimal runtime system that only uses the console and basic sounds. It implements the Runtime interface.

func NewBasicRuntime

func NewBasicRuntime(perm Permissions) *BasicRuntime

func (*BasicRuntime) EditorInterface

func (rt *BasicRuntime) EditorInterface() Editing

func (*BasicRuntime) Enqueue

func (rt *BasicRuntime) Enqueue(f func())

func (*BasicRuntime) Perm

func (rt *BasicRuntime) Perm() Permissions

func (*BasicRuntime) RequestShutdown

func (rt *BasicRuntime) RequestShutdown(errcode int)

func (*BasicRuntime) SetPerm

func (rt *BasicRuntime) SetPerm(p Permissions) error

func (*BasicRuntime) SoundInterface

func (rt *BasicRuntime) SoundInterface() Audio

type Boxed

type Boxed struct {
	Datum    any
	Sort     *Sym
	Template string
	Equal    func(other *Boxed) bool
	Valid    bool
}

Boxed is the type of an opaque, non-writable Lisp object. It holds the actual object as interface{} and manages the Lisp type and printing.

func ExpectBoxed

func ExpectBoxed(a any, sort *Sym) (*Boxed, bool)

ExpectBoxed returns a boxed value of type sort if a is one and true, nil and false otherwise.

func MustGetBoxed

func MustGetBoxed(caller string, a any, sort *Sym) *Boxed

MustGetBoxed returns a boxed value of type sort or panics.

func (*Boxed) Print

func (o *Boxed) Print() string

Print the object into a string.

type BoxedArray

type BoxedArray struct {
	// contains filtered or unexported fields
}

BoxedArray is a synchronized array of boxed items.

func NewBoxedArray

func NewBoxedArray() *BoxedArray

NewBoxedArray returns a new empty array for boxed items.

func (*BoxedArray) Add

func (a *BoxedArray) Add(obj *Boxed)

Add a new boxed item to the array.

func (*BoxedArray) Clear

func (a *BoxedArray) Clear()

Clear the array.

func (*BoxedArray) Range

func (a *BoxedArray) Range(f func(i int, obj *Boxed) bool)

Range is used to traverse a boxed array with a function that takes an index and an object and returns bool. If the function returns false, then the traversal stops. Otherwise it continues until the whole array has been traversed.

func (*BoxedArray) Remove

func (a *BoxedArray) Remove(obj *Boxed)

Remove a boxed item from the array.

type BufferedReader

type BufferedReader struct {
	// contains filtered or unexported fields
}

BufferedReader is a buffered reader.

func NewBufferedReader

func NewBufferedReader(reader io.Reader) *BufferedReader

NewBufferedReader returns a buffered reader based on an io.Reader.

func (*BufferedReader) BuffIOReader

func (r *BufferedReader) BuffIOReader() *bufio.Reader

BuffIOReader returns the bufio.Reader encapsulated in the BufferedReader.

type BuiltInFunc

type BuiltInFunc struct {
	Func
	// contains filtered or unexported fields
}

BuiltInFunc represents a built-in function.

func NewBuiltInFunc

func NewBuiltInFunc(name string, carity int,
	body func([]any) any) *BuiltInFunc

NewBuiltInFunc constructs a BuiltInFunc.

func (*BuiltInFunc) EvalWith

func (x *BuiltInFunc) EvalWith(interp *Interp, arg *Cell,
	interpEnv *Cell) any

EvalWith invokes the built-in function with a list of actual arguments.

func (*BuiltInFunc) Externalize

func (x *BuiltInFunc) Externalize(interp *Interp, env *Cell) string

Externalize returns a textual representation suitable for reading.

func (*BuiltInFunc) String

func (x *BuiltInFunc) String() string

String returns a textual representation of the BuiltInFunc.

type Cell

type Cell struct {
	Car any
	Cdr any
}

Cell represents a cons cell. &Cell{car, cdr} works as the "cons" operation.

var Nil *Cell = nil

Nil is a nil of type *Cell and it represents the empty list.

func ArrayToList

func ArrayToList(arr []any) *Cell

ArrayToList converts an array (Go slice) to a list.

func ConvertTimeToDateList

func ConvertTimeToDateList(t time.Time) *Cell

ConvertTimeToDateList converts a time.Time value into a Lisp datelist.

func StrArrayToList

func StrArrayToList(arr []string) *Cell

StrArrayToList converts an array of strings (not a Lisp object) to a list of strings (an admissible Lisp object).

func (*Cell) CdrCell

func (j *Cell) CdrCell() *Cell

CdrCell returns cdr of the cell as a *Cell or Nil.

func (*Cell) FoldL

func (j *Cell) FoldL(x any,
	fn func(any, any) any) any

(a b c).FoldL(x, fn) returns fn(fn(fn(x, a), b), c)

func (*Cell) Len

func (j *Cell) Len() int

Len returns the length of list j

func (*Cell) MapCar

func (j *Cell) MapCar(fn func(any) any) any

(a b c).MapCar(fn) returns (fn(a) fn(b) fn(c))

func (*Cell) Reverse

func (j *Cell) Reverse() *Cell

Reverse the list non-destructively (creating a copy first).

func (*Cell) String

func (j *Cell) String() string

String returns a raw textual representation of j for debugging.

type Closure

type Closure struct {
	Lambda
	// Env is the closure's own environment.
	Env *Cell
}

Closure represents a compiled lambda expression with its own environment.

func (*Closure) Externalize

func (x *Closure) Externalize(interp *Interp, env *Cell) string

Externalize returns an external representation suitable for reading.

func (*Closure) MakeEnv

func (x *Closure) MakeEnv(interp *Interp, arg *Cell, interpEnv *Cell) *Cell

MakeEnv makes a new environment from a list of actual arguments, which will be used in evaluation of the body of the closure.

func (*Closure) String

func (x *Closure) String() string

String returns a textual representation of the closure.

type Color

type Color struct {
	R    uint8
	G    uint8
	B    uint8
	A    uint8
	Used bool
}

SimpleColor is to simpify 8-bit color handling. It's an ad hoc structure.

func (Color) RGBA

func (c Color) RGBA() (uint32, uint32, uint32, uint32)

func (Color) String

func (c Color) String() string

type Dict

type Dict struct {
	Data      *sync.Map
	Protected bool
}

func CopyDict

func CopyDict(m *Dict) *Dict

copyDict copies a Dict deeply.

type Editing

type Editing interface {
	StartInput(cb func())          // called to start the input, callback is called when input ends
	EndInput() (string, bool)      // called when input ends
	EndInputCallback() func()      // the callback called when the input ends
	Print(s string) (int, int)     // print s in the current color, return number of lines scrolled and number of lines printed
	SetColor(bg bool, color Color) // set the current color
	Color(bg bool) Color           // get the current color
	ResetColor()                   // reset both foreground and background color to default
}

type EvalError

type EvalError struct {
	Message string
	Trace   []string
}

EvalError represents an error in evaluation.

func NewEvalError

func NewEvalError(msg string, x any) *EvalError

NewEvalError constructs an EvalError.

func NewNotVariableError

func NewNotVariableError(x any) *EvalError

NewNotVariableError constructs an EvalError which indicates an absence of variable.

func NewProtectedVariableError

func NewProtectedVariableError(x any) *EvalError

NewProtectedVariableError constructs an EvalError which indicates that the given variable is protected against global mutation.

func (*EvalError) Error

func (err *EvalError) Error() string

Error returns a textual representation of the error. It is defined in compliance with the error type.

type Externalizable

type Externalizable interface {
	Externalize(interp *Interp, env *Cell) string
}

type Func

type Func struct {
	// Carity is a number of arguments, made negative if the func has &rest.
	Carity int
	// Args is the formal argument list of the function when it was originally defined, or nil
	// for a builin function. This is used by Externalize.
	Args *Cell
}

Func is a common base type of Lisp functions.

func (*Func) EvalFrame

func (fn *Func) EvalFrame(frame []any, interp *Interp, env *Cell)

EvalFrame evaluates each expression of frame with interp in env.

func (*Func) MakeFrame

func (fn *Func) MakeFrame(arg *Cell, x any) []any

MakeFrame makes a call-frame from a list of actual arguments. Argument x will be used instead of fn only in error messages.

type Future

type Future struct {
	// Chan is a channel which transmits a pair of result and error.
	// The pair is represented by Cell.
	Chan <-chan Cell

	// Result is a pair of the result (in a narrow meaning) and the error.
	Result Cell

	// Lock is an exclusive lock to receive the result at "force".
	Lock sync.Mutex
}

Future represents a "promise" for future/force.

func (*Future) String

func (fu *Future) String() string

String returns a textual representation of the Future.

type Interp

type Interp struct {
	// contains filtered or unexported fields
}

Interp represents a core of the interpreter.

func NewInterp

func NewInterp(pc any) (*Interp, error)

NewInterp constructs an interpreter and sets built-in functions etc. as the global values of symbols within the interpreter.

func (*Interp) Boot

func (interp *Interp) Boot() error

Boot loads the standard prelude and any other init files and ensures that the interpreter is in a ready state.

func (*Interp) Break

func (interp *Interp) Break()

Break attempts to globally cancel a running process and restart the read-eval-print loop using StartREPL. It is like a soft reset function and would usually be bound to a function (break).

func (*Interp) CanExternalize

func (interp *Interp) CanExternalize(a any) bool

CanExternalize returns true if the value in a can be externalized, false otherwise. Changes must be reflected in Externalize.

func (*Interp) Def

func (interp *Interp) Def(name string, carity int,
	body func([]any) any)

Def defines a built-in function by giving a name, arity, and body.

func (*Interp) DefBoxed

func (interp *Interp) DefBoxed(sort *Sym)

DefBoxed defines the standard functions for a boxed value.

func (*Interp) DefaultPrintError

func (interp *Interp) DefaultPrintError(err any)

DefaultPrintError is the default error printer that simply outputs the error string.

func (*Interp) Define_Base

func (interp *Interp) Define_Base()

Define_Base defines basic Lisp functions that should work on any platform.

func (*Interp) Define_Console

func (interp *Interp) Define_Console()

Define_Console defines console-related commands, where the console is a OS terminal, not an editor console based on the virtual machine in PC.

func (*Interp) Define_DB

func (interp *Interp) Define_DB()

func (*Interp) Define_Decimal

func (interp *Interp) Define_Decimal()

Define_Decimal defines decimal arithmetics primitives with prefix 'dec. These can be used for finance and banking applications that require fixed precision and correct rounding.

func (*Interp) Define_FileIO

func (interp *Interp) Define_FileIO()

func (*Interp) Define_Float

func (interp *Interp) Define_Float()

Define_Float defines floating point related functions with prefix fl.

func (*Interp) Define_Ling

func (interp *Interp) Define_Ling()

func (*Interp) Define_StyledText

func (interp *Interp) Define_StyledText()

func (*Interp) EndLineInput

func (interp *Interp) EndLineInput()

func (*Interp) Eval

func (interp *Interp) Eval(expression any, env *Cell) any

Eval evaluates a Lisp expression in a given environment env.

func (*Interp) EvalFile

func (interp *Interp) EvalFile(path string) bool

EvalFile evaluates a file, returns true if no error has occurred and false if an error has occurred.

func (*Interp) EvalString

func (interp *Interp) EvalString(s string) (any, error)

EvalString evaluates a string and returns the result or an error. If string contains more than one expression, then only the first expression is executed. To prevent this, you may wrap several expressions into (progn expr ...). If the expression is empty, io.EOF error is returned. Use Str(result) to print the result in human-readable form.

func (*Interp) ExpandMacros

func (interp *Interp) ExpandMacros(x any, count int) any

ExpandMacros expands macros and quasi-quotes in x up to count nestings.

func (*Interp) ExpectInts

func (interp *Interp) ExpectInts(caller string, a []any, offset, n int) []int

ExpectInts returns a slice of n ints decoded from a[offset], or panics with an error.

func (*Interp) Externalize

func (interp *Interp) Externalize(env *Cell, a any) string

Return a representation of a that is suitable for reading. Like Str and derived directly from it - see externalize5 and externalizeListBody -, but this procedure creates externalizable representations for all arguments. Changes must be reflected in CanExternalize.

func (*Interp) GetGlobalVar

func (interp *Interp) GetGlobalVar(sym *Sym) (any, bool)

GetGlobalVar gets a global value of symbol sym within the interpreter.

func (*Interp) HandleError

func (interp *Interp) HandleError(err any) (any, bool)

HandleError attempts to handle the error by invoking *error-handler* if it is defined. If there is no error handler or an error occurs in it, then the default error printer is called and Void, false is returned. If the error is handled successfuly, the handler's result and true is returned.

func (*Interp) InputCond

func (interp *Interp) InputCond() *sync.Cond

InputCond returns a pointer to an sync.Cond condition used for waiting for input. This is used for asynchronously signaling EndInput.

func (*Interp) InputLock

func (interp *Interp) InputLock() *sync.Mutex

InputLock returns a pointer to a mutex used for locking on certain input conditions. It is recommended not to use this mutex unless you know what you're doing.

func (*Interp) Lock

func (interp *Interp) Lock()

Lock locks the interpreter's internal RWMutex. Be careful not to create deadlocks using this mechanism and bear in mind that some calls internally use this mutex.

func (*Interp) MaybeLoadUserInit

func (interp *Interp) MaybeLoadUserInit() error

MaybeLoadUserInit attempts to load the user init file if it exists in the local directory and if the permission is available.

func (*Interp) MustParseBlobArgs

func (interp *Interp) MustParseBlobArgs(caller string, a []any) ([]byte, int, int)

MustParseBlobArgs parses the Lisp arguments for a blob and optional lower and upper bound. If the offset and upper bound are not provided, 0 and the length of the blob are used.

func (*Interp) Print

func (interp *Interp) Print(s string)

Print outputs a string according using the runtime EditorInterface Print function. This is equivalent to using (out datum) on the Lisp side.

func (*Interp) PrintError

func (interp *Interp) PrintError(err any)

PrintError prints the given error using the *error-printer* global variable if it has been set. The variable *error-printer* must contain a closure that takes an error or string as argument. If *error-printer* is unbound, then the built-in error printer is called.

func (*Interp) RLock

func (interp *Interp) RLock()

RLock read-locks the interpreter's internal RWMutex. Be careful not to create deadlocks using this mechanism and bear in mind that some calls internally use this mutex.

func (*Interp) RUnlock

func (interp *Interp) RUnlock()

RUnlock unlocks a read-lock of the interpreter's internal RWMutex.

func (*Interp) Run

func (interp *Interp) Run(input io.Reader, source *Source) bool

Run executes REPL (Read-Eval-Print Loop). It returns false if REPL was ceased by an error. It returns true if REPL was finished normally.

func (*Interp) Runtime

func (interp *Interp) Runtime() any

Runtime returns the runtime support system provided when a new interpreter was created, as an unrestricted any interface, so the client can type cast it to whatever runtime structure they use.

func (*Interp) SafeEval

func (interp *Interp) SafeEval(expression any, env *Cell) (
	result any, err any)

SafeEval evaluates a Lisp expression in a given environment env and returns the result and nil. If an error happens, it returns Nil and the error

func (*Interp) SetGlobalVar

func (interp *Interp) SetGlobalVar(sym *Sym, val any)

SetGlobalVar sets a global value of symbol sym within the interpreter.

func (*Interp) SetInteractive

func (interp *Interp) SetInteractive(on bool)

SetInteractive sets the Lisp *interactive-session* global variable to indicate a session is interactive or not.

func (*Interp) StartREPL

func (interp *Interp) StartREPL()

StartREPL marks the start of the line input in the current editor. The line can then be retrieved with EndLineInput for use in the Repl loop.

func (*Interp) Streams

func (interp *Interp) Streams() *sync.Map

Streams returns a pointer to a sync.Map containing the i/o streams managed by the interpreter.

func (*Interp) UnbindGlobalVar

func (interp *Interp) UnbindGlobalVar(sym *Sym)

UnbindGlobalVar removes the value of symbol, making the symbol unbound (not defined).

func (*Interp) Unlock

func (interp *Interp) Unlock()

Unlock unlocks the interpreter's internal RWMutex.

type Lambda

type Lambda struct {
	Func
	// Body is a list which will be used as the function body.
	Body *Cell
}

Lambda represents a compiled lambda expression (within another function).

func (*Lambda) Externalize

func (x *Lambda) Externalize(interp *Interp, env *Cell) string

Externalize returns a readable external representation of the lambda term.

func (*Lambda) String

func (x *Lambda) String() string

String returns a textual representation of the lambda.

type Macro

type Macro struct {
	Func
	// contains filtered or unexported fields
}

Macro represents a compiled macro expression.

func (*Macro) ExpandWith

func (x *Macro) ExpandWith(interp *Interp, arg *Cell) any

ExpandWith expands the macro with a list of actual arguments.

func (*Macro) Externalize

func (x *Macro) Externalize(interp *Interp, env *Cell) string

Externalize returns a readable external representation of the macro.

func (*Macro) String

func (x *Macro) String() string

String returns a textual representation of the macro.

type Permissions

type Permissions struct {
	AllowUnprotect bool
	AllowProtect   bool
	LoadPrelude    bool
	LoadUserInit   bool
	Interactive    bool
	AllowFileRead  bool
	AllowFileWrite bool
}

func NewPermissions

func NewPermissions(current Permissions, perms []string) (Permissions, error)

NewPermissions creates a set of permissions from an array of symbolic strings. The permissions must be as restrictive or more restictive as the current permissions, or ErrSecurityViolation is returned.

func (*Permissions) Get

func (p *Permissions) Get(s string) (any, error)

func (Permissions) Set

func (p Permissions) Set(perm string, v any) (Permissions, error)

Set sets a permission to the given value, returns an error if the permission cannot be changed. Permissions can only be changed from less secure to more secure, not vice versa, where the security hierarchy is hardcoded.

func (*Permissions) Strings

func (p *Permissions) Strings() []string

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader represents a reader of Lisp expressions.

func NewReader

func NewReader(r io.Reader, source *Source) *Reader

NewReader constructs a reader which will read Lisp expressions from r.

func (*Reader) IOReader

func (rr *Reader) IOReader() io.Reader

IOReader returns the underlying Go io.Reader for direct use. This is used by binary operations that don't use the *bufio.scanner.

func (*Reader) Read

func (rr *Reader) Read() (result any, err any)

Read reads a Lisp expression and returns the expression and nil. If the input runs out, it returns EofToken and nil. If an error happens, it returns Nil and the error.

type Runtime

type Runtime interface {
	EditorInterface() Editing    // return the editor interface
	SoundInterface() Audio       // return the audio interface
	Perm() Permissions           // return the current permissions of the interpreter
	SetPerm(Permissions) error   // set the current permissions, may return an error if not allowed
	RequestShutdown(errcode int) // request a shutdown of the interpreter - but it is not guaranteed
	Enqueue(func())              // enqueue an arbitrary function in a sequential queue - supposed to be GUI safe
}

type Seeker

type Seeker struct {
	// contains filtered or unexported fields
}

Seeker is a minor abstraction wrapper for io.Seeker.

func NewSeeker

func NewSeeker(seeker io.Seeker) *Seeker

NewSeeker returns a new Seeker based on given io.Seeker.

func (*Seeker) IOSeeker

func (s *Seeker) IOSeeker() io.Seeker

IOSeeker returns the underlying io.Seeker for the seekable port.

type Source

type Source struct {
	Sort   int    // the type of the source
	Path   string // path to the source file, URL, etc.
	LineNo int    // line number (if applicable)
	Line   string // the current line (used sometimes by the reader)
}

func NewFileSource

func NewFileSource(path string) *Source

func NewInternalSource

func NewInternalSource(path, line string) *Source

func (Source) Clone

func (s Source) Clone(newLine int, line string) *Source

Clone returns a new Source with the given line number, all other data remaining the same.

type Stream

type Stream struct {
	LispReader   *Reader
	LispWriter   *Writer
	LispSeeker   *Seeker
	LispWriterAt *WriterAt
	BuffReader   *BufferedReader
}

Stream is a Lisp wrapper for a lisp stream, reader and writer. It is used in combination with the FileManager to manage i/o streams.

func NewStream

func NewStream(source *Source, ioreader io.Reader, iowriter io.Writer, ioseeker io.Seeker, iowriterat io.WriterAt) *Stream

type Sym

type Sym struct {
	Name      string
	IsKeyword bool
}

Sym represents a symbol (or an expression keyword) in Lisp. &Sym{name, false} constructs a symbol which is not interned yet.

func NewSym

func NewSym(name string) *Sym

NewSym constructs an interned symbol for name.

func NewSym2

func NewSym2(name string, isKeyword bool) *Sym

NewSym2 constructs an interned symbol (or an expression keyword if isKeyword is true on its first construction) for name.

func (*Sym) IsInterned

func (sym *Sym) IsInterned() bool

IsInterned returns true if sym is interned.

func (*Sym) String

func (sym *Sym) String() string

String returns a textual representation of sym.

type ValueHolder

type ValueHolder struct {
	Value     any
	Protected bool
}

ValueHolder is a miscellaneous structure to hold interface{} values with symbols as keys. The additional indirection is tolerated to avoid having to use two map lookups, one for the value and one for the Protected feature. Performance: The performance impact should be analyzed.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer is the counterpart to Reader for writing lisp expressions to streams.

func NewWriter

func NewWriter(writer io.Writer) *Writer

NewWriter returns a new lisp writer.

func (*Writer) IOWriter

func (w *Writer) IOWriter() io.Writer

IOWriter retrieves the underlying io.Writer from Go for direct use.

func (*Writer) Write

func (w *Writer) Write(x any) (int, error)

Write a lisp expression to this stream.

type WriterAt

type WriterAt struct {
	// contains filtered or unexported fields
}

WriterAt is a writer that can write to particular positions.

func NewWriterAt

func NewWriterAt(writer io.WriterAt) *WriterAt

NewWriterAt creates a new WriterAt for writing to particular positions.

func (*WriterAt) IOWriterAt

func (w *WriterAt) IOWriterAt() io.WriterAt

IOWriterAt returns the wrapped io.writerat in this stream.

Directories

Path Synopsis
Package actions contains helper functions for implementing actions (plugins) in a program using Z3S5 Lisp.
Package actions contains helper functions for implementing actions (plugins) in a program using Z3S5 Lisp.
cmd
z3
z3g

Jump to

Keyboard shortcuts

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