go-vise

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

commit afb3ff3a36ef84b343b4a4c8e92dc8287386b302
parent 100f7f3b48193f432bb18a6058b6414f78355939
Author: lash <dev@holbrook.no>
Date:   Mon, 17 Apr 2023 06:35:36 +0100

Add hello world example

Diffstat:
MMakefile | 5++++-
MREADME.md | 1+
Mdev/interactive/main.go | 11++++++++++-
Mengine/engine.go | 33++++++++++++++-------------------
Mengine/engine_test.go | 8+++++---
Mengine/loop_test.go | 9++++++---
Aexamples/helloworld/que.txt.orig | 2++
Aexamples/helloworld/root | 1+
Aexamples/helloworld/root.vis | 2++
Mexamples/profile/main.go | 3++-
Mexamples/session/main.go | 3++-
11 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,4 +1,4 @@ -examples: profile session +examples: profile session helloworld .PHONY: examples @@ -7,3 +7,6 @@ profile: session: bash examples/compile.bash examples/session + +helloworld: + bash examples/compile.bash examples/helloworld diff --git a/README.md b/README.md @@ -38,6 +38,7 @@ Original motivation was to create a simple templating renderer for USSD clients, * Breakpoints. * Key/value database reference example. +* Same-page catch with dedicated error string to prepend to template ## Opcodes diff --git a/dev/interactive/main.go b/dev/interactive/main.go @@ -23,11 +23,20 @@ func main() { ctx := context.Background() en := engine.NewSizedEngine(dir, uint32(size)) - err := en.Init(ctx) + cont, err := en.Init(ctx) if err != nil { fmt.Fprintf(os.Stderr, "engine init exited with error: %v\n", err) os.Exit(1) } + if !cont { + _, err = en.WriteResult(os.Stdout, ctx) + 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(&en, os.Stdin, os.Stdout, ctx) if err != nil { fmt.Fprintf(os.Stderr, "loop exited with error: %v\n", err) diff --git a/engine/engine.go b/engine/engine.go @@ -53,37 +53,34 @@ func NewEngine(cfg Config, st *state.State, rs resource.Resource, ca cache.Memor // Init must be explicitly called before using the Engine instance. // // It loads and executes code for the start node. -func(en *Engine) Init(ctx context.Context) error { +func(en *Engine) Init(ctx context.Context) (bool, error) { if en.initd { log.Printf("already initialized") - return nil + return true, nil } sym := en.root if sym == "" { - return fmt.Errorf("start sym empty") + return false, fmt.Errorf("start sym empty") } inSave, _ := en.st.GetInput() err := en.st.SetInput([]byte{}) if err != nil { - return err + return false, 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 - } - if len(b) == 0 { - return fmt.Errorf("no code left after init, that's just useless and sad") + return false, err } + log.Printf("ended init VM run with code %x", b) en.st.SetCode(b) err = en.st.SetInput(inSave) if err != nil { - return err + return false, err } - en.initd = true - return nil + return len(b) > 0, nil } // Exec processes user input against the current state of the virtual machine environment. @@ -99,13 +96,11 @@ func(en *Engine) Init(ctx context.Context) error { func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) { var err error if en.st.Moves == 0 { - err = en.Init(ctx) + cont, err := en.Init(ctx) if err != nil { return false, err } - if len(input) == 0 { - return true, nil - } + return cont, nil } err = vm.ValidInput(input) if err != nil { @@ -146,7 +141,7 @@ func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) { en.st.SetCode(code) if len(code) == 0 { log.Printf("runner finished with no remaining code") - err = en.reset(ctx) + _, err = en.reset(ctx) return false, err } @@ -168,17 +163,17 @@ func(en *Engine) WriteResult(w io.Writer, ctx context.Context) (int, error) { } // start execution over at top node while keeping current state of client error flags. -func(en *Engine) reset(ctx context.Context) error { +func(en *Engine) reset(ctx context.Context) (bool, error) { var err error var isTop bool for !isTop { isTop, err = en.st.Top() if err != nil { - return err + return false, err } _, err = en.st.Up() if err != nil { - return err + return false, err } en.ca.Pop() } diff --git a/engine/engine_test.go b/engine/engine_test.go @@ -85,7 +85,7 @@ func TestEngineInit(t *testing.T) { Root: "root", }, &st, &rs, ca, ctx) - err = en.Init(ctx) + _, err = en.Init(ctx) if err != nil { t.Fatal(err) } @@ -141,7 +141,8 @@ func TestEngineExecInvalidInput(t *testing.T) { en := NewEngine(Config{ Root: "root", }, &st, &rs, ca, ctx) - err := en.Init(ctx) + var err error + _, err = en.Init(ctx) if err != nil { t.Fatal(err) } @@ -161,7 +162,8 @@ func TestEngineResumeTerminated(t *testing.T) { en := NewEngine(Config{ Root: "root", }, &st, &rs, ca, ctx) - err := en.Init(ctx) + var err error + _, err = en.Init(ctx) if err != nil { t.Fatal(err) } diff --git a/engine/loop_test.go b/engine/loop_test.go @@ -24,7 +24,8 @@ func TestLoopTop(t *testing.T) { Root: "root", } en := NewEngine(cfg, &st, &rs, ca, ctx) - err := en.Init(ctx) + var err error + _, err = en.Init(ctx) if err != nil { t.Fatal(err) } @@ -60,7 +61,8 @@ func TestLoopBackForth(t *testing.T) { Root: "root", } en := NewEngine(cfg, &st, &rs, ca, ctx) - err := en.Init(ctx) + var err error + _, err = en.Init(ctx) if err != nil { t.Fatal(err) } @@ -94,7 +96,8 @@ func TestLoopBrowse(t *testing.T) { Root: "root", } en := NewEngine(cfg, &st, &rs, ca, ctx) - err := en.Init(ctx) + var err error + _, err = en.Init(ctx) if err != nil { t.Fatal(err) } diff --git a/examples/helloworld/que.txt.orig b/examples/helloworld/que.txt.orig @@ -0,0 +1 @@ +world +\ No newline at end of file diff --git a/examples/helloworld/root b/examples/helloworld/root @@ -0,0 +1 @@ +hello, {{.que}}! diff --git a/examples/helloworld/root.vis b/examples/helloworld/root.vis @@ -0,0 +1,2 @@ +LOAD que 5 +MAP que diff --git a/examples/profile/main.go b/examples/profile/main.go @@ -124,7 +124,8 @@ func main() { } ctx := context.Background() en := engine.NewEngine(cfg, &st, rs, ca, ctx) - err := en.Init(ctx) + var err error + _, err = en.Init(ctx) if err != nil { fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) os.Exit(1) diff --git a/examples/session/main.go b/examples/session/main.go @@ -72,7 +72,8 @@ func main() { ctx := context.Background() ctx = context.WithValue(ctx, "SessionId", sessionId) en := engine.NewEngine(cfg, &st, rs, ca, ctx) - err := en.Init(ctx) + var err error + _, err = en.Init(ctx) if err != nil { fmt.Fprintf(os.Stderr, "engine init fail: %v\n", err) os.Exit(1)