commit 59dcb7875db2a92718c8d049e8526e68012398f3
parent 28cbe308d430557c6d312d7ed481303ba2887944
Author: lash <dev@holbrook.no>
Date: Thu, 13 Apr 2023 10:33:24 +0100
WIP correct entry point in persisted runner
Diffstat:
9 files changed, 106 insertions(+), 60 deletions(-)
diff --git a/engine/engine.go b/engine/engine.go
@@ -43,7 +43,8 @@ func NewEngine(cfg Config, st *state.State, rs resource.Resource, ca cache.Memor
ca: ca,
vm: vm.NewVm(st, rs, ca, szr),
}
- if cfg.Root != "" {
+ //if cfg.Root != "" {
+ if st.Moves == 0 {
engine.Init(cfg.Root, ctx)
}
return engine
@@ -65,10 +66,12 @@ func(en *Engine) Init(sym string, ctx context.Context) error {
return err
}
b := vm.NewLine(nil, vm.MOVE, []string{sym}, nil, nil)
+ log.Printf("start new init VM run with code %x", b)
b, err = en.vm.Run(b, ctx)
if err != nil {
return err
}
+ log.Printf("ended init VM run with code %x", b)
en.st.SetCode(b)
en.initd = true
return nil
@@ -102,10 +105,12 @@ func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) {
if len(code) == 0 {
return false, fmt.Errorf("no code to execute")
}
+ log.Printf("start new VM run with code %x", code)
code, err = en.vm.Run(code, ctx)
if err != nil {
return false, err
}
+ log.Printf("ended VM run with code %x", code)
v, err := en.st.MatchFlag(state.FLAG_TERMINATE, false)
if err != nil {
@@ -133,11 +138,10 @@ func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) {
// - required data inputs to the template are not available.
// - the template for the given node point is note available for retrieval using the resource.Resource implementer.
// - the supplied writer fails to process the writes.
-func(en *Engine) WriteResult(w io.Writer, ctx context.Context) error {
+func(en *Engine) WriteResult(w io.Writer, ctx context.Context) (int, error) {
r, err := en.vm.Render(ctx)
if err != nil {
- return err
+ return 0, err
}
- _, err = io.WriteString(w, r)
- return err
+ return io.WriteString(w, r)
}
diff --git a/engine/engine_test.go b/engine/engine_test.go
@@ -26,10 +26,14 @@ type FsWrapper struct {
func NewFsWrapper(path string, st *state.State) FsWrapper {
rs := resource.NewFsResource(path)
- return FsWrapper {
+ wr := FsWrapper {
&rs,
st,
}
+ wr.AddLocalFunc("one", wr.one)
+ wr.AddLocalFunc("inky", wr.inky)
+ wr.AddLocalFunc("pinky", wr.pinky)
+ return wr
}
func(fs FsWrapper) one(sym string, input []byte, ctx context.Context) (resource.Result, error) {
@@ -51,18 +55,6 @@ func(fs FsWrapper) pinky(sym string, input []byte, ctx context.Context) (resourc
}, nil
}
-func(fs FsWrapper) FuncFor(sym string) (resource.EntryFunc, error) {
- switch sym {
- case "one":
- return fs.one, nil
- case "inky":
- return fs.inky, nil
- case "pinky":
- return fs.pinky, nil
- }
- return nil, fmt.Errorf("function for %v not found", sym)
-}
-
func(fs FsWrapper) GetCode(sym string) ([]byte, error) {
sym += ".bin"
fp := path.Join(fs.Path, sym)
@@ -82,20 +74,19 @@ func generateTestData(t *testing.T) {
}
func TestEngineInit(t *testing.T) {
+ var err error
generateTestData(t)
ctx := context.TODO()
st := state.NewState(17)
rs := NewFsWrapper(dataDir, &st)
ca := cache.NewCache().WithCacheSize(1024)
- en := NewEngine(Config{}, &st, &rs, ca, ctx)
- err := en.Init("root", ctx)
- if err != nil {
- t.Fatal(err)
- }
-
+ en := NewEngine(Config{
+ Root: "root",
+ }, &st, &rs, ca, ctx)
+//
w := bytes.NewBuffer(nil)
- err = en.WriteResult(w, ctx)
+ _, err = en.WriteResult(w, ctx)
if err != nil {
t.Fatal(err)
}
@@ -118,7 +109,7 @@ func TestEngineInit(t *testing.T) {
t.Fatalf("expected where-string 'foo', got %s", r)
}
w = bytes.NewBuffer(nil)
- err = en.WriteResult(w, ctx)
+ _, err = en.WriteResult(w, ctx)
if err != nil {
t.Fatal(err)
}
diff --git a/engine/loop.go b/engine/loop.go
@@ -19,7 +19,8 @@ import (
//
// Rendered output is written to the provided writer.
func Loop(en *Engine, reader io.Reader, writer io.Writer, ctx context.Context) error {
- err := en.WriteResult(writer, ctx)
+ var err error
+ _, err = en.WriteResult(writer, ctx)
if err != nil {
return err
}
@@ -41,7 +42,7 @@ func Loop(en *Engine, reader io.Reader, writer io.Writer, ctx context.Context) e
if err != nil {
return fmt.Errorf("unexpected termination: %v\n", err)
}
- err = en.WriteResult(writer, ctx)
+ _, err = en.WriteResult(writer, ctx)
if err != nil {
return err
}
diff --git a/engine/persist.go b/engine/persist.go
@@ -25,14 +25,43 @@ func RunPersisted(cfg Config, rs resource.Resource, pr persist.Persister, input
return err
}
st := pr.GetState()
- log.Printf("st %v", st)
+ location, idx := st.Where()
+ if location != "" {
+ cfg.Root = location
+ }
+
+ log.Printf("run persisted with state %v %x input %s", st, st.Code, input)
en := NewEngine(cfg, pr.GetState(), rs, pr.GetMemory(), ctx)
- if len(input) > 0 {
- _, err = en.Exec(input, ctx)
- if err != nil {
- return err
- }
+ log.Printf("location %s", location)
+
+// if len(input) == 0 {
+// log.Printf("init")
+// err = en.Init(location, ctx)
+// if err != nil {
+// return err
+// }
+ c, err := en.WriteResult(w, ctx)
+ if err != nil {
+ return err
+ }
+ err = pr.Save(cfg.SessionId)
+ if err != nil {
+ return err
+ }
+ log.Printf("engine init write %v flags %v", c, st.Flags)
+ if c > 0 {
+ return err
+ }
+ _ = idx
+
+ _, err = en.Exec(input, ctx)
+ if err != nil {
+ return err
+ }
+ _, err = en.WriteResult(w, ctx)
+ if err != nil {
+ return err
}
- return en.WriteResult(w, ctx)
+ return pr.Save(cfg.SessionId)
}
diff --git a/engine/persist_test.go b/engine/persist_test.go
@@ -1,9 +1,9 @@
package engine
import (
- "bytes"
+// "bytes"
"context"
- "errors"
+// "errors"
"io/ioutil"
"os"
"testing"
@@ -16,7 +16,7 @@ import (
func TestPersist(t *testing.T) {
generateTestData(t)
cfg := Config{
- OutputSize: 128,
+ OutputSize: 83,
SessionId: "xyzzy",
Root: "root",
}
@@ -31,27 +31,19 @@ func TestPersist(t *testing.T) {
ca := cache.NewCache().WithCacheSize(1024)
pr := persist.NewFsPersister(persistDir).WithContent(&st, ca)
- w := bytes.NewBuffer(nil)
+ //w := bytes.NewBuffer(nil)
+ w := os.Stdout
ctx := context.TODO()
-
- err = RunPersisted(cfg, rs, pr, []byte{}, w, ctx)
+ st = state.NewState(cfg.FlagCount)
+ ca = cache.NewCache()
+ ca = ca.WithCacheSize(cfg.CacheSize)
+ pr = persist.NewFsPersister(persistDir).WithContent(&st, ca)
+ err = pr.Save(cfg.SessionId)
if err != nil {
- if !errors.Is(err, os.ErrNotExist) {
- t.Fatal(err)
- }
- st := state.NewState(cfg.FlagCount)
- ca := cache.NewCache()
- if cfg.CacheSize > 0 {
- ca = ca.WithCacheSize(cfg.CacheSize)
- }
- pr = persist.NewFsPersister(persistDir).WithContent(&st, ca)
- err = pr.Save(cfg.SessionId)
- if err != nil {
- t.Fatal(err)
- }
+ t.Fatal(err)
}
-
+
pr = persist.NewFsPersister(persistDir)
inputs := []string{
"",
@@ -65,4 +57,20 @@ func TestPersist(t *testing.T) {
t.Fatal(err)
}
}
+
+ pr = persist.NewFsPersister(persistDir)
+ err = pr.Load(cfg.SessionId)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ stAfter := pr.GetState()
+ location, idx := stAfter.Where()
+ if location != "long" {
+ t.Fatalf("expected 'long', got %s", location)
+ }
+ if idx != 1 {
+ t.Fatalf("expected '1', got %v", idx)
+ }
+
}
diff --git a/persist/fs.go b/persist/fs.go
@@ -68,7 +68,7 @@ func(p *FsPersister) Save(key string) error {
return err
}
fp := path.Join(p.dir, key)
- log.Printf("saved key %v", key)
+ log.Printf("saved key %v state %x", key, p.State.Code)
return ioutil.WriteFile(fp, b, 0600)
}
@@ -80,6 +80,6 @@ func(p *FsPersister) Load(key string) error {
return err
}
err = p.Deserialize(b)
- log.Printf("loaded key %v", key)
+ log.Printf("loaded key %v state %x", key, p.State.Code)
return err
}
diff --git a/resource/fs.go b/resource/fs.go
@@ -39,6 +39,13 @@ func(fs FsResource) GetCode(sym string) ([]byte, error) {
return ioutil.ReadFile(fp)
}
+func(fs *FsResource) AddLocalFunc(sym string, fn EntryFunc) {
+ if fs.fns == nil {
+ fs.fns = make(map[string]EntryFunc)
+ }
+ fs.fns[sym] = fn
+}
+
func(fs FsResource) FuncFor(sym string) (EntryFunc, error) {
fn, ok := fs.fns[sym]
if ok {
diff --git a/state/state.go b/state/state.go
@@ -34,6 +34,7 @@ type State struct {
BitSize uint32 // size of (32-bit capacity) bit flag byte array
SizeIdx uint16
Flags []byte // Error state
+ Moves uint32 // Number of times navigation has been performed
input []byte // Last input
}
@@ -208,6 +209,7 @@ func(st *State) Next() (uint16, error) {
st.SizeIdx += 1
s, idx := st.Where()
log.Printf("next page for %s: %v", s, idx)
+ st.Moves += 1
return st.SizeIdx, nil
}
@@ -224,6 +226,7 @@ func(st *State) Previous() (uint16, error) {
st.SizeIdx -= 1
s, idx := st.Where()
log.Printf("previous page for %s: %v", s, idx)
+ st.Moves += 1
return st.SizeIdx, nil
}
@@ -258,6 +261,7 @@ func(st *State) Top() (bool, error) {
func(st *State) Down(input string) error {
st.ExecPath = append(st.ExecPath, input)
st.SizeIdx = 0
+ st.Moves += 1
return nil
}
@@ -281,6 +285,7 @@ func(st *State) Up() (string, error) {
}
st.SizeIdx = 0
log.Printf("execpath after %v", st.ExecPath)
+ st.Moves += 1
return sym, nil
}
@@ -332,5 +337,5 @@ func(st *State) Reset() error {
}
func(st State) String() string {
- return fmt.Sprintf("idx %v path: %s", st.SizeIdx, strings.Join(st.ExecPath, "/"))
+ return fmt.Sprintf("moves %v idx %v path: %s", st.Moves, st.SizeIdx, strings.Join(st.ExecPath, "/"))
}
diff --git a/vm/runner.go b/vm/runner.go
@@ -182,10 +182,10 @@ func(vm *Vm) RunCatch(b []byte, ctx context.Context) ([]byte, error) {
if err != nil {
return b, err
}
+ b = append(bh, b...)
vm.st.Down(sym)
vm.ca.Push()
vm.Reset()
- b = append(bh, b...)
}
return b, nil
}
@@ -292,6 +292,7 @@ func(vm *Vm) RunInCmp(b []byte, ctx context.Context) ([]byte, error) {
panic(err)
}
} else {
+ log.Printf("ignoring input %s, already have match", sym)
return b, nil
}
}
@@ -407,7 +408,7 @@ func(vm *Vm) Render(ctx context.Context) (string, error) {
panic(err)
}
if !changed {
- log.Printf("Render called when not dirty, please investigate.")
+ return "", nil
}
sym, idx := vm.st.Where()
r, err := vm.pg.Render(sym, idx)