From 4ffb196563f39f4ad524e890594bcb889b6a3ee3 Mon Sep 17 00:00:00 2001 From: HAYAMA_Kaoru Date: Sat, 30 Nov 2024 02:01:52 +0900 Subject: [PATCH] Implement `(expect)` like `(case)` --- example.lsp | 8 ++++---- global.go | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++- main.go | 3 ++- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/example.lsp b/example.lsp index 28bd4b9..f1d5431 100644 --- a/example.lsp +++ b/example.lsp @@ -2,17 +2,17 @@ (let ((ctrlc (format nil "~A" (convert 3 )))) (block main (while t - (case (expect* 'timeout 10 "xxx" "yyy") - ((0) + (expect + ("xxx" (send ctrlc) (sendln "exit") (return-from main nil) ) - ((1) + (("yyy" "zzz") (send ctrlc) (sendln "rem") ) - ((-1) + (10 ; timeout second (send ctrlc) (sendln "exit") (return-from main nil) diff --git a/global.go b/global.go index 43b36d8..38b8505 100644 --- a/global.go +++ b/global.go @@ -49,7 +49,7 @@ func (g *Global) spawn(ctx context.Context, w *gmnlisp.World, args []gmnlisp.Nod var symTimeout = gmnlisp.NewSymbol("timeout") -func (g *Global) expect(ctx context.Context, w *gmnlisp.World, node gmnlisp.Node) (gmnlisp.Node, error) { +func (g *Global) expectX(ctx context.Context, w *gmnlisp.World, node gmnlisp.Node) (gmnlisp.Node, error) { patterns := []string{} timeOut := 0 @@ -83,3 +83,58 @@ func (g *Global) expect(ctx context.Context, w *gmnlisp.World, node gmnlisp.Node } return gmnlisp.Integer(result), nil } + +func (g *Global) expect(ctx context.Context, w *gmnlisp.World, node gmnlisp.Node) (gmnlisp.Node, error) { + + patterns := []string{} + actions := []gmnlisp.Node{} + + timeoutSec := 0 + var timeoutAct gmnlisp.Node + + for gmnlisp.IsSome(node) { + var err error + var _patAndAct gmnlisp.Node + _patAndAct, node, err = gmnlisp.Shift(node) + if err != nil { + return nil, err + } + patAndAct, err := gmnlisp.ExpectClass[*gmnlisp.Cons](ctx, w, _patAndAct) + if err != nil { + return nil, err + } + pat := patAndAct.Car + act := patAndAct.Cdr + + if patInt, ok := pat.(gmnlisp.Integer); ok { + timeoutSec = int(patInt) + timeoutAct = act + } else if _, ok := pat.(*gmnlisp.Cons); ok { + for gmnlisp.IsSome(pat) { + var pat1 gmnlisp.Node + + pat1, pat, err = gmnlisp.Shift(pat) + if err != nil { + return nil, err + } + actions = append(actions, act) + patterns = append(patterns, pat1.String()) + } + } else { + actions = append(actions, act) + patterns = append(patterns, pat.String()) + } + } + + var result int + if timeoutSec == 0 { + result = g.w.Expect(patterns...) + } else { + result = g.w.ExpectWithTimeout(time.Second*time.Duration(timeoutSec), patterns...) + } + if result >= 0 { + return gmnlisp.Progn(ctx, w, actions[result]) + } else { + return gmnlisp.Progn(ctx, w, timeoutAct) + } +} diff --git a/main.go b/main.go index 88d64fa..d406fa5 100644 --- a/main.go +++ b/main.go @@ -31,7 +31,8 @@ func mains(args []string) error { gmnlisp.NewSymbol("send"): gmnlisp.Function1(g.send), gmnlisp.NewSymbol("sendln"): gmnlisp.Function1(g.sendln), gmnlisp.NewSymbol("spawn"): &gmnlisp.Function{Min: 1, F: g.spawn}, - gmnlisp.NewSymbol("expect*"): gmnlisp.SpecialF(g.expect), + gmnlisp.NewSymbol("expect*"): gmnlisp.SpecialF(g.expectX), + gmnlisp.NewSymbol("expect"): gmnlisp.SpecialF(g.expect), }) if len(args) <= 0 {