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:
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)