mirror of
https://github.com/hymkor/lispect.git
synced 2026-08-28 04:46:59 -04:00
92 lines
2.8 KiB
Go
92 lines
2.8 KiB
Go
package lispect
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
|
|
"github.com/hymkor/gmnlisp"
|
|
)
|
|
|
|
// RunFile loads and executes a Lisp script from the specified file.
|
|
// - `fname`: the path to the Lisp source file to be executed.
|
|
// - `args`: a slice of arguments typically corresponding to os.Args[1:].
|
|
// - `args[0]` is set to the Lisp variable `*program-name*`.
|
|
// - `args[1:]` is set to the Lisp variable `*argv*`.
|
|
func RunFile(fname string, args []string) error {
|
|
script, err := os.ReadFile(fname)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return RunString(string(script), args)
|
|
}
|
|
|
|
// New creates a new Env instance that embeds a gmnlisp.World and
|
|
// sets up a pseudoterminal session and related communication structures.
|
|
// This allows users to customize and control the Lisp environment flexibly.
|
|
func New() (*Env, error) {
|
|
term, err := NewTerm()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
watcher := NewWatcher(term)
|
|
|
|
env := &Env{
|
|
term: term,
|
|
w: watcher,
|
|
}
|
|
|
|
gmnlisp.NewLineOnFormat = []byte{'\r', '\n'}
|
|
|
|
lisp := gmnlisp.New()
|
|
|
|
env.World = lisp.Flet(
|
|
gmnlisp.Functions{
|
|
gmnlisp.NewSymbol("send"): &gmnlisp.Function{Min: 1, F: env.send},
|
|
gmnlisp.NewSymbol("sendln"): &gmnlisp.Function{Min: 1, F: env.sendln},
|
|
gmnlisp.NewSymbol("spawn"): &gmnlisp.Function{Min: 1, F: env.spawn},
|
|
gmnlisp.NewSymbol("expect*"): gmnlisp.SpecialF(env.expectX),
|
|
gmnlisp.NewSymbol("expect"): gmnlisp.SpecialF(env.expect),
|
|
gmnlisp.NewSymbol("getenv"): gmnlisp.Function1(env.getenv),
|
|
gmnlisp.NewSymbol("setenv"): gmnlisp.Function2(env.setenv),
|
|
gmnlisp.NewSymbol("wait"): gmnlisp.Function1(env.wait),
|
|
})
|
|
|
|
return env, nil
|
|
}
|
|
|
|
// RunString executes a Lisp script given directly as a string.
|
|
// - `script`: the Lisp source code to be executed (equivalent to the contents of a file).
|
|
// - `args`: a slice of arguments typically corresponding to os.Args[1:].
|
|
// - `args[0]` is set to the Lisp variable `*program-name*`.
|
|
// - `args[1:]` is set to the Lisp variable `*argv*`.
|
|
func RunString(script string, args []string) error {
|
|
env, err := New()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer env.Close()
|
|
|
|
posixArgv := []gmnlisp.Node{}
|
|
for _, s := range args[1:] {
|
|
posixArgv = append(posixArgv, gmnlisp.String(s))
|
|
}
|
|
executable := os.Args[0]
|
|
if value, err := os.Executable(); err == nil {
|
|
executable = value
|
|
}
|
|
lisp := env.Let(gmnlisp.Variables{
|
|
gmnlisp.NewSymbol("ARGV"): gmnlisp.List(posixArgv...),
|
|
gmnlisp.NewSymbol("*argv*"): gmnlisp.List(posixArgv...),
|
|
gmnlisp.NewSymbol("PROGRAM-NAME"): gmnlisp.String(args[0]),
|
|
gmnlisp.NewSymbol("*program-name*"): gmnlisp.String(args[0]),
|
|
gmnlisp.NewSymbol("EXECUTABLE-NAME"): gmnlisp.String(executable),
|
|
gmnlisp.NewSymbol("*executable-name*"): gmnlisp.String(executable),
|
|
})
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
_, err = lisp.Interpret(ctx, script)
|
|
cancel()
|
|
return err
|
|
}
|