go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit fb9a6b5642ee67dcc4971464af2149c6864bea00
parent 2d1e44d44050356121b62b6d3ba91f9326227fc2
Author: lash <dev@holbrook.no>
Date:   Fri, 20 Sep 2024 15:37:17 +0100

Remove need for initial Exec before loop

Diffstat:
Mengine/db.go | 9++++++++-
Mengine/loop.go | 16++++++++++++++--
Mengine/loop_test.go | 6+++---
Mexamples/db/main.go | 8+-------
Mexamples/gdbm/main.go | 8+-------
Mexamples/intro/main.go | 9+--------
Mexamples/languages/main.go | 9+--------
Mexamples/longmenu/main.go | 17+----------------
Mexamples/pincheck/main.go | 8+-------
Mexamples/preprocessor/main.go | 9+--------
Mexamples/profile/main.go | 8+-------
Mexamples/quit/main.go | 10+---------
Mexamples/reuse/main.go | 9+--------
Mexamples/session/main.go | 8+-------
Mexamples/state/main.go | 9+--------
Mexamples/state_passive/main.go | 26+++-----------------------
Mexamples/validate/main.go | 9+--------
17 files changed, 41 insertions(+), 137 deletions(-)

diff --git a/engine/db.go b/engine/db.go @@ -16,6 +16,10 @@ import ( "git.defalsify.org/vise.git/vm" ) +var ( + ErrFlushNoExec = errors.New("Attempted flush on unexecuted engine") +) + type DefaultEngine struct { st *state.State ca cache.Memory @@ -356,6 +360,9 @@ func(en *DefaultEngine) runFirst(ctx context.Context) (bool, error) { // * resource backend did not close cleanly. func(en *DefaultEngine) Finish() error { var perr error + if !en.initd { + return nil + } if en.pe != nil { perr = en.pe.Save(en.cfg.SessionId) } @@ -557,7 +564,7 @@ func(en *DefaultEngine) exec(ctx context.Context, input []byte) (bool, error) { func(en *DefaultEngine) Flush(ctx context.Context, w io.Writer) (int, error) { var l int if !en.execd { - return 0, errors.New("Attempted flush on unexecuted engine") + return 0, ErrFlushNoExec } if en.st.Language != nil { ctx = context.WithValue(ctx, "Language", *en.st.Language) diff --git a/engine/loop.go b/engine/loop.go @@ -17,15 +17,27 @@ import ( // Any error not handled by the engine will terminate the oop and return an error. // // Rendered output is written to the provided writer. -func Loop(ctx context.Context, en Engine, reader io.Reader, writer io.Writer) error { +func Loop(ctx context.Context, en Engine, reader io.Reader, writer io.Writer, initial []byte) error { defer en.Finish() - l, err := en.Flush(ctx, writer) + if initial == nil { + initial = []byte{} + } + cont, err := en.Exec(ctx, initial) if err != nil { return err } + l, err := en.Flush(ctx, writer) + if err != nil { + if err != ErrFlushNoExec { + return err + } + } if l > 0 { writer.Write([]byte{0x0a}) } + if !cont { + return nil + } running := true bufReader := bufio.NewReader(reader) diff --git a/engine/loop_test.go b/engine/loop_test.go @@ -43,7 +43,7 @@ func TestLoopTop(t *testing.T) { outputBuf := bytes.NewBuffer(nil) log.Printf("running with input: %s", inputBuf.Bytes()) - err = Loop(ctx, en, inputBuf, outputBuf) + err = Loop(ctx, en, inputBuf, outputBuf, nil) if err != nil { t.Fatal(err) } @@ -84,7 +84,7 @@ func TestLoopBackForth(t *testing.T) { outputBuf := bytes.NewBuffer(nil) log.Printf("running with input: %s", inputBuf.Bytes()) - err = Loop(ctx, en, inputBuf, outputBuf) + err = Loop(ctx, en, inputBuf, outputBuf, nil) if err != nil { t.Fatal(err) } @@ -123,7 +123,7 @@ func TestLoopBrowse(t *testing.T) { outputBuf := bytes.NewBuffer(nil) log.Printf("running with input: %s", inputBuf.Bytes()) - err = Loop(ctx, en, inputBuf, outputBuf) + err = Loop(ctx, en, inputBuf, outputBuf, nil) if err != nil { t.Fatal(err) } diff --git a/examples/db/main.go b/examples/db/main.go @@ -141,13 +141,7 @@ func main() { en := engine.NewEngine(cfg, rs) en = en.WithPersister(pr) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/gdbm/main.go b/examples/gdbm/main.go @@ -59,13 +59,7 @@ func main() { } en := engine.NewEngine(cfg, rs) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/intro/main.go b/examples/intro/main.go @@ -97,14 +97,7 @@ func main() { en = en.WithState(st) en = en.WithMemory(ca) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/languages/main.go b/examples/languages/main.go @@ -121,14 +121,7 @@ func main() { rs.AddLocalFunc("momsg", aux.moMsg) rs.AddLocalFunc("empty", empty) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/longmenu/main.go b/examples/longmenu/main.go @@ -37,22 +37,7 @@ func main() { OutputSize: uint32(size), } en := engine.NewEngine(cfg, rs) - //cont, err := en.Init(ctx) - cont, err := en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init exited with error: %v\n", err) - os.Exit(1) - } - if !cont { - _, err = en.Flush(ctx, os.Stdout) - if err != nil { - fmt.Fprintf(os.Stderr, "dead init write error: %v\n", err) - os.Exit(1) - } - os.Stdout.Write([]byte{0x0a}) - os.Exit(0) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/pincheck/main.go b/examples/pincheck/main.go @@ -94,14 +94,8 @@ func main() { en := engine.NewEngine(cfg, rs) en = en.WithState(st) en = en.WithMemory(ca) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/preprocessor/main.go b/examples/preprocessor/main.go @@ -95,15 +95,8 @@ func main() { en := engine.NewEngine(cfg, rsf) en = en.WithState(st) en = en.WithMemory(ca) - - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/profile/main.go b/examples/profile/main.go @@ -123,14 +123,8 @@ func main() { en := engine.NewEngine(cfg, rs) en = en.WithState(st) en = en.WithMemory(ca) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/quit/main.go b/examples/quit/main.go @@ -39,15 +39,7 @@ func main() { rs.AddLocalFunc("quitcontent", quit) en := engine.NewEngine(cfg, rs) - - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/reuse/main.go b/examples/reuse/main.go @@ -44,14 +44,7 @@ func main() { Root: "root", } en := engine.NewEngine(cfg, rs) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/session/main.go b/examples/session/main.go @@ -77,13 +77,7 @@ func main() { } ctx = context.WithValue(ctx, "SessionId", sessionId) en := engine.NewEngine(cfg, rs) - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/state/main.go b/examples/state/main.go @@ -96,14 +96,7 @@ func main() { en := engine.NewEngine(cfg, rs) en = en.WithState(st) en = en.WithDebug(nil) - - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/state_passive/main.go b/examples/state_passive/main.go @@ -1,4 +1,6 @@ // Example: Asynchronous state persistence. +// +// TODO: this example is broken after change to loop package main import ( @@ -120,29 +122,7 @@ func main() { rs.AddLocalFunc("poke", aux.poke) rs.AddLocalFunc("peek", aux.peek) - cont, err := en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init exited with error: %v\n", err) - os.Exit(1) - } - if !cont { - _, err = en.Flush(ctx, os.Stdout) - if err != nil { - fmt.Fprintf(os.Stderr, "dead init write error: %v\n", err) - os.Exit(1) - } - stnew := pr.GetState() - stnew.ResetFlag(state.FLAG_TERMINATE) - stnew.Up() - err = en.Finish() - if err != nil { - fmt.Fprintf(os.Stderr, "engine finish error: %v\n", err) - os.Exit(1) - } - os.Stdout.Write([]byte{0x0a}) - os.Exit(0) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1) diff --git a/examples/validate/main.go b/examples/validate/main.go @@ -77,14 +77,7 @@ func main() { en := engine.NewEngine(cfg, rs) en = en.WithState(st) - - //_, err = en.Init(ctx) - _, err = en.Exec(ctx, []byte{}) - if err != nil { - fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) - os.Exit(1) - } - err = engine.Loop(ctx, en, os.Stdin, os.Stdout) + err = engine.Loop(ctx, en, os.Stdin, os.Stdout, nil) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) os.Exit(1)