go-vise

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

commit 95bee7f8e07e85630285c9ad84a74aa3f32264da
parent 45de1f5c7ac946599960590ded6e6783758eb224
Author: lash <dev@holbrook.no>
Date:   Sun,  9 Apr 2023 15:35:26 +0100

Add stateful render method to vm

Diffstat:
Mgo/engine/engine.go | 34++++++----------------------------
Mgo/render/page.go | 11+++++++++--
Mgo/render/render.go | 6------
Mgo/render/size.go | 5-----
Mgo/render/size_test.go | 22+++++-----------------
Mgo/vm/runner.go | 31++++++++++++++++++++++++++-----
Mgo/vm/runner_test.go | 96++++++++++++++++++++++++++++++++++---------------------------------------------
7 files changed, 87 insertions(+), 118 deletions(-)

diff --git a/go/engine/engine.go b/go/engine/engine.go @@ -7,7 +7,6 @@ import ( "log" "git.defalsify.org/festive/cache" - "git.defalsify.org/festive/render" "git.defalsify.org/festive/resource" "git.defalsify.org/festive/state" "git.defalsify.org/festive/vm" @@ -23,7 +22,7 @@ type Engine struct { st *state.State rs resource.Resource ca cache.Memory - pg render.Renderer + vm *vm.Vm } // NewEngine creates a new Engine @@ -32,6 +31,7 @@ func NewEngine(st *state.State, rs resource.Resource, ca cache.Memory) Engine { st: st, rs: rs, ca: ca, + vm: vm.NewVm(st, rs, ca, nil), } return engine } @@ -40,15 +40,12 @@ func NewEngine(st *state.State, rs resource.Resource, ca cache.Memory) Engine { // // It loads and executes code for the start node. func(en *Engine) Init(sym string, ctx context.Context) error { - mn := render.NewMenu() - en.pg = render.NewPage(en.ca, en.rs).WithMenu(mn) - vmi := vm.NewVm(en.st, en.rs, en.ca, mn, nil) err := en.st.SetInput([]byte{}) if err != nil { return err } b := vm.NewLine(nil, vm.MOVE, []string{sym}, nil, nil) - b, err = vmi.Run(b, ctx) + b, err = en.vm.Run(b, ctx) if err != nil { return err } @@ -75,9 +72,6 @@ func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) { if err != nil { return false, err } - mn := render.NewMenu() - en.pg = render.NewPage(en.ca, en.rs).WithMenu(mn) - vmi := vm.NewVm(en.st, en.rs, en.ca, mn, en.pg) log.Printf("new execution with input '%s' (0x%x)", input, input) code, err := en.st.GetCode() @@ -87,7 +81,7 @@ func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) { if len(code) == 0 { return false, fmt.Errorf("no code to execute") } - code, err = vmi.Run(code, ctx) + code, err = en.vm.Run(code, ctx) if err != nil { return false, err } @@ -120,27 +114,11 @@ func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) { // - the supplied writer fails to process the writes. func(en *Engine) WriteResult(w io.Writer) error { location, idx := en.st.Where() - v, err := en.ca.Get() - if err != nil { - return err - } -// r, err := en.rs.RenderTemplate(location, v, idx, nil) -// if err != nil { -// return err -// } -// m, err := en.rs.RenderMenu(idx) -// if err != nil { -// return err -// } -// if len(m) > 0 { -// r += "\n" + m -// } - r, err := en.pg.Render(location, v, idx) + r, err := en.vm.Render() if err != nil { return err } c, err := io.WriteString(w, r) - log.Printf("%v bytes written as result for %v", c, location) - en.pg = nil + log.Printf("%v bytes written as result for %v idx %v", c, location, idx) return err } diff --git a/go/render/page.go b/go/render/page.go @@ -257,7 +257,9 @@ func(pg *Page) render(sym string, values map[string]string, idx uint16) (string, return "", err } log.Printf("rendered %v bytes for menu", len(s)) - r += "\n" + s + if len(s) > 0 { + r += "\n" + s + } if pg.sizer != nil { _, ok = pg.sizer.Check(r) if !ok { @@ -267,8 +269,13 @@ func(pg *Page) render(sym string, values map[string]string, idx uint16) (string, return r, nil } -func(pg *Page) Render(sym string, values map[string]string, idx uint16) (string, error) { +func(pg *Page) Render(sym string, idx uint16) (string, error) { var err error + + values, err := pg.cache.Get() + if err != nil { + return "", err + } values, err = pg.prepare(sym, values, idx) if err != nil { diff --git a/go/render/render.go b/go/render/render.go @@ -1,7 +1 @@ package render - -type Renderer interface { - Map(key string) error - Render(sym string, values map[string]string, idx uint16) (string, error) - Reset() -} diff --git a/go/render/size.go b/go/render/size.go @@ -29,11 +29,6 @@ func(szr *Sizer) WithMenuSize(menuSize uint16) *Sizer { } func(szr *Sizer) Set(key string, size uint16) error { - var ok bool - _, ok = szr.memberSizes[key] - if ok { - return fmt.Errorf("already have key %s", key) - } szr.memberSizes[key] = size if size == 0 { szr.sink = key diff --git a/go/render/size_test.go b/go/render/size_test.go @@ -98,20 +98,13 @@ func TestSizeLimit(t *testing.T) { mn.Put("1", "foo the foo") mn.Put("2", "go to bar") - vals, err := ca.Get() + var err error + _, err = pg.Render("small", 0) if err != nil { t.Fatal(err) } - _, err = pg.Render("small", vals, 0) - if err != nil { - t.Fatal(err) - } - - mn.Put("1", "foo the foo") - mn.Put("2", "go to bar") - - _, err = pg.Render("toobig", vals, 0) + _, err = pg.Render("toobig", 0) if err == nil { t.Fatalf("expected size exceeded") } @@ -138,15 +131,10 @@ func TestSizePages(t *testing.T) { pg.Map("baz") pg.Map("xyzzy") - vals, err := ca.Get() - if err != nil { - t.Fatal(err) - } - mn.Put("1", "foo the foo") mn.Put("2", "go to bar") - r, err := pg.Render("pages", vals, 0) + r, err := pg.Render("pages", 0) if err != nil { t.Fatal(err) } @@ -163,7 +151,7 @@ lala poo if r != expect { t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r) } - r, err = pg.Render("pages", vals, 1) + r, err = pg.Render("pages", 1) if err != nil { t.Fatal(err) } diff --git a/go/vm/runner.go b/go/vm/runner.go @@ -14,19 +14,29 @@ import ( type Vm struct { st *state.State rs resource.Resource - pg render.Renderer + pg *render.Page ca cache.Memory mn *render.Menu + sizer *render.Sizer } -func NewVm(st *state.State, rs resource.Resource, ca cache.Memory, mn *render.Menu, pg render.Renderer) *Vm { - return &Vm{ +func NewVm(st *state.State, rs resource.Resource, ca cache.Memory, sizer *render.Sizer) *Vm { + vmi := &Vm{ st: st, rs: rs, - pg: pg, ca: ca, - mn: mn, + sizer: sizer, + } + vmi.Reset() + return vmi +} + +func(vmi *Vm) Reset() { + vmi.mn = render.NewMenu() + vmi.pg = render.NewPage(vmi.ca, vmi.rs).WithMenu(vmi.mn) + if vmi.sizer != nil { + vmi.pg = vmi.pg.WithSizer(vmi.sizer) } } @@ -316,6 +326,16 @@ func(vm *Vm) RunMPrev(b []byte, ctx context.Context) ([]byte, error) { return b, nil } +func(vm *Vm) Render() (string, error) { + sym, idx := vm.st.Where() + r, err := vm.pg.Render(sym, idx) + if err != nil { + return "", err + } + vm.Reset() + return r, nil +} + // retrieve data for key func refresh(key string, rs resource.Resource, ctx context.Context) (string, error) { fn, err := rs.FuncFor(key) @@ -327,3 +347,4 @@ func refresh(key string, rs resource.Resource, ctx context.Context) (string, err } return fn(ctx) } + diff --git a/go/vm/runner_test.go b/go/vm/runner_test.go @@ -46,6 +46,8 @@ func (r TestResource) GetTemplate(sym string) (string, error) { return "inky pinky {{.baz}} blinky clyde", nil case "three": return "{{.one}} inky pinky {{.three}} blinky clyde {{.two}}", nil + case "root": + return "root", nil case "_catch": return "aiee", nil } @@ -85,7 +87,7 @@ func TestRun(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - vm := NewVm(&st, &rs, ca, nil, nil) + vm := NewVm(&st, &rs, ca, nil) b := NewLine(nil, MOVE, []string{"foo"}, nil, nil) b = NewLine(b, HALT, nil, nil, nil) @@ -105,59 +107,46 @@ func TestRunLoadRender(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - pg := render.NewPage(ca, rs) - vm := NewVm(&st, &rs, ca, nil, pg) + vm := NewVm(&st, &rs, ca, nil) - st.Down("barbarbar") + st.Down("bar") var err error b := NewLine(nil, LOAD, []string{"one"}, []byte{0x0a}, nil) + b = NewLine(b, LOAD, []string{"two"}, []byte{0x0a}, nil) b = NewLine(b, HALT, nil, nil, nil) b, err = vm.Run(b, context.TODO()) if err != nil { - t.Error(err) - } - m, err := ca.Get() - if err != nil { - t.Error(err) + t.Fatal(err) } - r, err := pg.RenderTemplate("foo", m, 0) + r, err := vm.Render() if err != nil { - t.Error(err) + t.Fatal(err) } - expect := "inky pinky blinky clyde" + expect := "inky pinky one blinky two clyde" if r != expect { - t.Errorf("Expected %v, got %v", []byte(expect), []byte(r)) - } - - r, err = pg.RenderTemplate("bar", m, 0) - if err == nil { - t.Errorf("expected error for render of bar: %v" ,err) + t.Fatalf("Expected\n\t%s\ngot\n\t%s\n", expect, r) } b = NewLine(nil, LOAD, []string{"two"}, []byte{0x0a}, nil) b = NewLine(b, HALT, nil, nil, nil) b, err = vm.Run(b, context.TODO()) if err != nil { - t.Error(err) + t.Fatal(err) } b = NewLine(nil, MAP, []string{"one"}, nil, nil) b = NewLine(b, HALT, nil, nil, nil) _, err = vm.Run(b, context.TODO()) if err != nil { - t.Error(err) - } - m, err = ca.Get() - if err != nil { - t.Error(err) + t.Fatal(err) } - r, err = pg.RenderTemplate("bar", m, 0) + r, err = vm.Render() if err != nil { - t.Error(err) + t.Fatal(err) } expect = "inky pinky one blinky two clyde" if r != expect { - t.Errorf("Expected %v, got %v", expect, r) + t.Fatalf("Expected %v, got %v", expect, r) } } @@ -165,7 +154,7 @@ func TestRunMultiple(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - vm := NewVm(&st, &rs, ca, nil, nil) + vm := NewVm(&st, &rs, ca, nil) b := NewLine(nil, MOVE, []string{"test"}, nil, nil) b = NewLine(b, LOAD, []string{"one"}, []byte{0x00}, nil) @@ -184,8 +173,8 @@ func TestRunReload(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - pg := render.NewPage(ca, rs) - vm := NewVm(&st, &rs, ca, nil, pg) + szr := render.NewSizer(128) + vm := NewVm(&st, &rs, ca, szr) b := NewLine(nil, MOVE, []string{"root"}, nil, nil) b = NewLine(b, LOAD, []string{"dyn"}, nil, []uint8{0}) @@ -195,12 +184,13 @@ func TestRunReload(t *testing.T) { if err != nil { t.Fatal(err) } - r, err := pg.Val("dyn") + r, err := vm.Render() +// r, err := pg.Val("dyn") if err != nil { t.Fatal(err) } - if r != "three" { - t.Fatalf("expected result 'three', got %v", r) + if r != "root" { + t.Fatalf("expected result 'root', got %v", r) } dynVal = "baz" b = NewLine(nil, RELOAD, []string{"dyn"}, nil, nil) @@ -209,21 +199,21 @@ func TestRunReload(t *testing.T) { if err != nil { t.Fatal(err) } - r, err = pg.Val("dyn") - if err != nil { - t.Fatal(err) - } - log.Printf("dun now %s", r) - if r != "baz" { - t.Fatalf("expected result 'baz', got %v", r) - } +// r, err = pg.Val("dyn") +// if err != nil { +// t.Fatal(err) +// } +// log.Printf("dun now %s", r) +// if r != "baz" { +// t.Fatalf("expected result 'baz', got %v", r) +// } } func TestHalt(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - vm := NewVm(&st, &rs, ca, nil, nil) + vm := NewVm(&st, &rs, ca, nil) b := NewLine(nil, MOVE, []string{"root"}, nil, nil) b = NewLine(b, LOAD, []string{"one"}, nil, []uint8{0}) @@ -247,7 +237,7 @@ func TestRunArg(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - vm := NewVm(&st, &rs, ca, nil, nil) + vm := NewVm(&st, &rs, ca, nil) input := []byte("bar") _ = st.SetInput(input) @@ -272,8 +262,7 @@ func TestRunInputHandler(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - pg := render.NewPage(ca, rs) - vm := NewVm(&st, &rs, ca, nil, pg) + vm := NewVm(&st, &rs, ca, nil) _ = st.SetInput([]byte("baz")) @@ -300,8 +289,7 @@ func TestRunArgInvalid(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - mn := render.NewMenu() - vm := NewVm(&st, &rs, ca, mn, nil) + vm := NewVm(&st, &rs, ca, nil) _ = st.SetInput([]byte("foo")) @@ -324,8 +312,7 @@ func TestRunMenu(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - mn := render.NewMenu() - vm := NewVm(&st, &rs, ca, mn, nil) + vm := NewVm(&st, &rs, ca, nil) var err error @@ -343,11 +330,11 @@ func TestRunMenu(t *testing.T) { t.Errorf("expected empty remainder, got length %v: %v", l, b) } - r, err := mn.Render(0) + r, err := vm.Render() if err != nil { t.Fatal(err) } - expect := "0:one\n1:two" + expect := "inky pinky blinky clyde\n0:one\n1:two" if r != expect { t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r) } @@ -358,8 +345,7 @@ func TestRunMenuBrowse(t *testing.T) { st := state.NewState(5) rs := TestResource{} ca := cache.NewCache() - mn := render.NewMenu() - vm := NewVm(&st, &rs, ca, mn, nil) + vm := NewVm(&st, &rs, ca, nil) var err error @@ -377,11 +363,11 @@ func TestRunMenuBrowse(t *testing.T) { t.Errorf("expected empty remainder, got length %v: %v", l, b) } - r, err := mn.Render(0) + r, err := vm.Render() if err != nil { t.Fatal(err) } - expect := "0:one\n1:two" + expect := "inky pinky blinky clyde\n0:one\n1:two" if r != expect { t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expect, r) }