commit 856bbdeb6317e8c28b46b828f2357c50f5d0f785
parent 5a63b24ec1c59d83779daa3adf870de620e63f63
Author: lash <dev@holbrook.no>
Date: Mon, 3 Apr 2023 08:22:01 +0100
Add menu interpreter
Diffstat:
2 files changed, 122 insertions(+), 0 deletions(-)
diff --git a/go/vm/interpreter.go b/go/vm/interpreter.go
@@ -0,0 +1,76 @@
+package vm
+
+import (
+ "fmt"
+)
+
+type BatchCode uint16
+
+const (
+ MENU_DOWN = 256
+ MENU_UP = 257
+ MENU_NEXT = 258
+ MENU_PREVIOUS = 259
+)
+
+var (
+ batchCode = map[string]BatchCode{
+ "DOWN": MENU_DOWN,
+ "UP": MENU_UP,
+ "NEXT": MENU_NEXT,
+ "PREVIOUS": MENU_PREVIOUS,
+ }
+)
+
+type menuItem struct {
+ code BatchCode
+ choice string
+ display string
+ target string
+}
+
+type MenuProcessor struct {
+ items []menuItem
+ size uint32
+}
+
+func NewMenuProcessor() MenuProcessor {
+ return MenuProcessor{}
+}
+
+func(mp *MenuProcessor) Add(bop string, choice string, display string, target string) error {
+ bopCode := batchCode[bop]
+ if bopCode == 0 {
+ return fmt.Errorf("unknown menu instruction: %v", bop)
+ }
+ m := menuItem{
+ code: bopCode,
+ choice: choice,
+ display: display,
+ target: target,
+ }
+ mp.items = append(mp.items, m)
+ return nil
+}
+
+func (mp *MenuProcessor) ToLines() []byte {
+ preLines := []byte{}
+ postLines := []byte{}
+
+ for _, v := range mp.items {
+ preLines = NewLine(preLines, MOUT, []string{v.choice, v.display}, nil, nil)
+ switch v.code {
+ case MENU_UP:
+ postLines = NewLine(postLines, INCMP, []string{v.choice, "_"}, nil, nil)
+ case MENU_NEXT:
+ _ = postLines
+ case MENU_PREVIOUS:
+ _ = postLines
+ default:
+ postLines = NewLine(postLines, INCMP, []string{v.choice, v.target}, nil, nil)
+ }
+ }
+
+ preLines = NewLine(preLines, HALT, nil, nil, nil)
+ return append(preLines, postLines...)
+}
diff --git a/go/vm/interpreter_test.go b/go/vm/interpreter_test.go
@@ -0,0 +1,46 @@
+package vm
+
+import (
+ "testing"
+)
+
+
+func TestMenuInterpreter(t *testing.T) {
+ m := NewMenuProcessor()
+ err := m.Add("DOWN", "0", "inky", "foo")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = m.Add("NEXT", "1", "pinky", "bar")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = m.Add("PREVIOUS", "2", "blinky clyde", "baz")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = m.Add("UP", "99", "tinky-winky", "xyzzy")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = m.Add("BOGUS", "42", "lala poo", "plugh")
+ if err == nil {
+ t.Errorf("expected error on invalid menu item 'BOGUS'")
+ }
+ b := m.ToLines()
+ r, err := ToString(b)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expect := `MOUT 0 "inky"
+MOUT 1 "pinky"
+MOUT 2 "blinky clyde"
+MOUT 99 "tinky-winky"
+HALT
+INCMP 0 foo
+INCMP 99 _
+`
+ if r != expect {
+ t.Errorf("expected:\n\t%v\ngot:\n\t%v\n", expect, r)
+ }
+}