Embbed gmnlisp interpreter

This commit is contained in:
HAYAMA_Kaoru
2024-11-29 17:57:13 +09:00
parent 022810feee
commit 6906ab0c4d
3 changed files with 82 additions and 15 deletions
+3 -2
View File
@@ -4,13 +4,14 @@ go 1.23.3
require ( require (
github.com/aymanbagabas/go-pty v0.2.2 github.com/aymanbagabas/go-pty v0.2.2
github.com/hymkor/gmnlisp v0.7.3
github.com/hymkor/go-windows1x-virtualterminal v0.5.0 github.com/hymkor/go-windows1x-virtualterminal v0.5.0
golang.org/x/term v0.15.0 golang.org/x/term v0.26.0
) )
require ( require (
github.com/creack/pty v1.1.21 // indirect github.com/creack/pty v1.1.21 // indirect
github.com/u-root/u-root v0.11.0 // indirect github.com/u-root/u-root v0.11.0 // indirect
golang.org/x/crypto v0.17.0 // indirect golang.org/x/crypto v0.17.0 // indirect
golang.org/x/sys v0.16.0 // indirect golang.org/x/sys v0.27.0 // indirect
) )
+6 -4
View File
@@ -2,6 +2,8 @@ github.com/aymanbagabas/go-pty v0.2.2 h1:YZREB4eSj+1xdbbItIokX0ekjjeifgJOA+ZvxU4
github.com/aymanbagabas/go-pty v0.2.2/go.mod h1:gfvlwH+0U66BCwxJREjJaAOEs9H1OFf3YFjI9WSiZ04= github.com/aymanbagabas/go-pty v0.2.2/go.mod h1:gfvlwH+0U66BCwxJREjJaAOEs9H1OFf3YFjI9WSiZ04=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/hymkor/gmnlisp v0.7.3 h1:LDolAFXisJvY4j/8VrJvC12J2NL5KXLKilTLG47l0RI=
github.com/hymkor/gmnlisp v0.7.3/go.mod h1:5GY1Nxnu68pufvGdhrk9Kyp9XSNkYLfNpXznLk+eS74=
github.com/hymkor/go-windows1x-virtualterminal v0.5.0 h1:UIMMK09QSLCdM9Up4ny6qmBOrrn3rozxIRPfEUhxmTo= github.com/hymkor/go-windows1x-virtualterminal v0.5.0 h1:UIMMK09QSLCdM9Up4ny6qmBOrrn3rozxIRPfEUhxmTo=
github.com/hymkor/go-windows1x-virtualterminal v0.5.0/go.mod h1:M/X0FJL+4wQtrm03JnL9gVyvhyscJk3t+ItZ29sla2g= github.com/hymkor/go-windows1x-virtualterminal v0.5.0/go.mod h1:M/X0FJL+4wQtrm03JnL9gVyvhyscJk3t+ItZ29sla2g=
github.com/u-root/gobusybox/src v0.0.0-20221229083637-46b2883a7f90 h1:zTk5683I9K62wtZ6eUa6vu6IWwVHXPnoKK5n2unAwv0= github.com/u-root/gobusybox/src v0.0.0-20221229083637-46b2883a7f90 h1:zTk5683I9K62wtZ6eUa6vu6IWwVHXPnoKK5n2unAwv0=
@@ -10,7 +12,7 @@ github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8=
github.com/u-root/u-root v0.11.0/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY= github.com/u-root/u-root v0.11.0/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
+73 -9
View File
@@ -1,12 +1,57 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"io" "io"
"os" "os"
"time"
"github.com/hymkor/gmnlisp"
) )
type Global struct {
w *Watcher
term *Term
closer []func()
}
func (g *Global) Close() {
for i := len(g.closer) - 1; i >= 0; i-- {
g.closer[i]()
}
g.closer = nil
}
func (g *Global) sendln(ctx context.Context, w *gmnlisp.World, arg gmnlisp.Node) (gmnlisp.Node, error) {
io.WriteString(g.term, arg.String())
g.term.Write([]byte{'\r'})
return gmnlisp.Null, nil
}
func (g *Global) spawn(ctx context.Context, w *gmnlisp.World, args []gmnlisp.Node) (gmnlisp.Node, error) {
argStrings := make([]string, 0, len(args))
for _, s := range args {
argStrings = append(argStrings, s.String())
}
sh := g.term.Command(argStrings[0], argStrings[1:]...)
if err := sh.Start(); err != nil {
return nil, err
}
g.closer = append(g.closer, func() { sh.Wait() })
return gmnlisp.Null, nil
}
func (g *Global) expect(ctx context.Context, w *gmnlisp.World, args []gmnlisp.Node) (gmnlisp.Node, error) {
patterns := make([]string, 0, len(args))
for _, arg := range args {
patterns = append(patterns, arg.String())
}
result := g.w.Expect(patterns...)
return gmnlisp.Integer(result), nil
}
func mains() error { func mains() error {
term, err := NewTerm() term, err := NewTerm()
if err != nil { if err != nil {
@@ -16,16 +61,35 @@ func mains() error {
watcher := NewWatcher(term) watcher := NewWatcher(term)
sh := term.Command("cmd.exe") g := &Global{
if err := sh.Start(); err != nil { term: term,
return err w: watcher,
} }
defer g.Close()
i := watcher.ExpectWithTimeout(time.Duration(10*time.Second), "100") lisp := gmnlisp.New()
// i := watcher.Expect("100")
io.WriteString(term, "\x03exit\r") lisp = lisp.Flet(
println(i) gmnlisp.Functions{
return sh.Wait() gmnlisp.NewSymbol("sendln"): gmnlisp.Function1(g.sendln),
gmnlisp.NewSymbol("spawn"): &gmnlisp.Function{Min: 1, F: g.spawn},
gmnlisp.NewSymbol("expect*"): &gmnlisp.Function{Min: 1, F: g.expect},
})
_, err = lisp.Interpret(context.Background(), `
(spawn "cmd.exe")
(block main
(while t
(case (expect* "xxx" "yyy")
((0)
(sendln (format nil "~Aexit" (convert 3 <character>)))
(return-from main nil)
)
((1)
(sendln (format nil "~Arem" (convert 3 <character>)))
)
)))`)
return err
} }
func main() { func main() {