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