elpsutil

package
v1.74.0 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2026 License: BSD-3-Clause Imports: 9 Imported by: 2

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExtendPackage added in v1.73.0

func ExtendPackage(env *lisp.LEnv, name string) *lisp.LVal

ExtendPackage makes the package named name env's current package, exactly as the Lisp form (in-package 'name) does: the package is created if it does not exist, and a package this call creates uses the language package (when the registry has one), while an existing package is entered unchanged. The name is validated as in-package validates it, with the same error.

It is the first step of a loader that adds Go builtins to a package that Lisp code may also define or extend (luthersystems/elps#745); follow it with LEnv.BindBuiltins. Like in-package it does not restore the previous package -- the Load helpers in this package do that for a loader.

It charges no evaluation step. A PackageLoader package does not use the language package; use ExtendPackage only where in-package semantics are what the package had before.

func Load

func Load(env *lisp.LEnv, fn Loader) *lisp.LVal

Load loads an elps package implemented in Go. Load restores the package that was active when it was called, whether or not fn succeeds, so that further defined symbols end up in that package by default.

A loader that returns a Go nil *LVal, rather than lisp.Nil(), is reported as an error naming the loader instead of panicking.

func Validate added in v1.50.0

func Validate(p Package) error

Validate reports mistakes in an elps package implemented in Go that the Go type system cannot catch. It is intended to be called from an embedder's test:

func TestPackage(t *testing.T) {
	if err := elpsutil.Validate(&MyPackage{}); err != nil {
		t.Fatal(err)
	}
}

Validate reports every problem it finds, joined into a single error. A nil return means PackageLoader will not reject the package.

Validate performs one check that PackageLoader deliberately does not: it reports a package that contributes no builtins, no special operators, no macros and has no PackageInit. Such a package is almost certainly a mistake, but "almost" is not enough to fail a load -- a namespace-only package is unusual, not illegal.

Types

type Builtin

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

Builtin captures Go functions that are callable from elps.

func Function

func Function(name string, formals *lisp.LVal, fun lisp.LBuiltin) *Builtin

Function is a helper to construct builtins.

formals must be a list of symbols, as returned by lisp.Formals. A function that takes no arguments is declared with lisp.Formals(), the empty list; a nil formals list is not a valid spelling of that and is rejected by PackageLoader and Validate.

A function constructed with Function has no documentation. Use FunctionDoc to give it a docstring.

func FunctionDoc added in v1.58.0

func FunctionDoc(name string, formals *lisp.LVal, fun lisp.LBuiltin, docs string) *Builtin

FunctionDoc is a helper to construct documented builtins. It is Function plus the docstring the function is registered with, which is what `elps doc` prints, what the language server shows on hover, and what the linter reads.

The docstring follows the same conventions as the interpreter's own builtins. In particular a paragraph beginning "Deprecated:" (or "DEPRECATED:") marks the function deprecated, exactly as it does in a Go doc comment: the `deprecated` lint check then reports every use of the function and quotes the rest of that paragraph as the reason. For example

elpsutil.FunctionDoc("blend-paths", lisp.Formals("a", "b"), blendPaths,
	"Blend two paths.\n\nDeprecated: use join-paths instead.")

func (*Builtin) Docstring added in v1.58.0

func (fun *Builtin) Docstring() string

Docstring returns the documentation for a function, which is empty for a function constructed with Function. It satisfies the interface lisp checks for when registering a definition, so the string reaches the registered value and everything that reads documentation from it.

func (*Builtin) Eval

func (fun *Builtin) Eval(env *lisp.LEnv, args *lisp.LVal) *lisp.LVal

Eval evaluates a function on an environment.

func (*Builtin) Formals

func (fun *Builtin) Formals() *lisp.LVal

Formals returns the formal arguments of a function.

func (*Builtin) Name

func (fun *Builtin) Name() string

Name returns the name of a function.

type Loader

type Loader = lisp.Loader

Loader is a generic function to initialize/load an LEnv. A Loader should first define and switch into the package(s) it loads. The helpers in this package (Load, LoadAll, LibraryLoader and PackageLoader) restore the package that was active when they were called, whether the load succeeds or fails, so that symbols defined after a load end up where the caller expects them. A load performed from the user package -- the conventional top-level usage -- therefore ends in the user package, as it always has.

A chain of loaders may be formed to load a library.

func LibraryLoader

func LibraryLoader(ps ...Package) Loader

LibraryLoader loads multiple elps packages implemented in Go.

func LoadAll

func LoadAll(fns ...Loader) Loader

LoadAll loads multiple elps files implemented in Go. Like Load, LoadAll restores the package that was active when it was called, whether or not the loaders succeed, and runs each loader from that package.

A loader that returns a Go nil *LVal, rather than lisp.Nil(), is reported as an error naming the loader and its position in the chain instead of panicking.

func PackageLoader

func PackageLoader(p Package) Loader

PackageLoader loads an elps package implemented in Go.

PackageLoader restores the package that was active when it was called, whether or not the load succeeds, the same invariant the stdlib LoadPackage functions honor (https://github.com/luthersystems/elps/issues/99). It also re-establishes the loaded package after PackageInit returns, so that a PackageInit which switches packages -- directly, or indirectly through a nested Load -- does not cause the package's builtins, special operators and macros to be registered and exported somewhere else (https://github.com/luthersystems/elps/issues/352).

PackageLoader validates the package definition before registering anything, and returns an *LVal error identifying the package and the offending definition rather than letting lisp panic or deferring a nil dereference to call time. A definition lisp accepts today is still accepted.

type Package

type Package interface {
	PackageName() string
}

Package is an elps package implemented in Go.

type PackageBuiltins

type PackageBuiltins interface {
	Package
	Builtins() []lisp.LBuiltinDef
}

PackageBuiltins retrieves the exposed builtins for an elps package implemented in Go.

type PackageDocumented added in v1.16.12

type PackageDocumented interface {
	Package
	PackageDoc() string
}

PackageDocumented allows an elps package to provide a documentation string.

type PackageInit

type PackageInit interface {
	Package
	PackageInit(env *lisp.LEnv) *lisp.LVal
}

PackageInit allows initialization of an elps package implemented in Go.

type PackageMacros

type PackageMacros interface {
	Package
	Macros() []lisp.LBuiltinDef
}

PackageMacros returns the macros for an elps package implemented in Go.

type PackageSpecialOps

type PackageSpecialOps interface {
	Package
	SpecialOps() []lisp.LBuiltinDef
}

PackageSpecialOps returns the special operators for an elps package implemented in Go.

type Template added in v1.73.0

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

Template is a quasiquote-style form, read once by the elps reader and expanded by Go macros into fresh syntax.

The source is one ordinary elps form: symbols, lists, (), strings, numbers and 'form are copied as written. Placeholders use the forms elps quasiquote uses, naming a declared parameter:

(unquote name)           the argument, inserted by pointer
(unquote-splicing name)  the argument's cells, spliced into the enclosing list

A placeholder is recognised anywhere in the form, including under a quote, so '(unquote name) quotes the argument. unquote-splicing must appear directly inside a list, not at the top level or directly under a quote. Because every unquote form is a placeholder, a template cannot contain a literal unquote form or a nested quasiquote: in (quasiquote (a (unquote x))) the inner unquote is substituted. Build such a form in Go and pass it as an argument.

A template stores no LVals. Each Expand constructs fresh, unsealed, unlocated syntax, as the Go macro contract in lisp.LEnv.AddMacros requires: the evaluator locates it at the macro call site. Arguments are inserted by pointer, and () uses the immutable lisp.Nil singleton. Expansion neither reads nor evaluates anything, and templates may be expanded concurrently.

func MustTemplate added in v1.73.0

func MustTemplate(src string, params ...string) *Template

MustTemplate reads src with the elps reader and compiles it, with params declaring placeholder names in argument order. It is meant for package initialization and panics if src is not exactly one form, fails to parse, or contains a value the reader produces that a template cannot copy; on an undeclared placeholder, a duplicate or unused parameter, a malformed unquote, or a misplaced unquote-splicing.

func (*Template) Expand added in v1.73.0

func (t *Template) Expand(args ...*lisp.LVal) *lisp.LVal

Expand returns a fresh expansion, inserting args by pointer without copying or evaluating them. Quoted forms use lisp.Quote, as the reader does; Quote may copy an argument's header to add a quote without changing the argument. Expand panics if the argument count differs from the declared parameter count or a spliced argument is not an unquoted list (nil is accepted).

Jump to

Keyboard shortcuts

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