vise/asm/menu.go

95 lines
2.5 KiB
Go
Raw Normal View History

2023-04-04 11:32:39 +02:00
package asm
2023-04-03 09:22:01 +02:00
import (
"fmt"
2023-04-04 11:32:39 +02:00
"git.defalsify.org/festive/vm"
2023-04-03 09:22:01 +02:00
)
2023-04-12 19:04:36 +02:00
// BatchCode defines quasi-opcodes that expand to mulitple individual vm instructions.
2023-04-03 09:22:01 +02:00
type BatchCode uint16
const (
2023-04-03 10:14:45 +02:00
_MENU_OFFSET = 256
MENU_DOWN = _MENU_OFFSET
MENU_UP = _MENU_OFFSET + 1
MENU_NEXT = _MENU_OFFSET + 2
MENU_PREVIOUS = _MENU_OFFSET + 3
2023-04-03 09:22:01 +02:00
)
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
}
2023-04-12 19:04:36 +02:00
// MenuProcessor handles code lines with BatchCode quasi-opcodes that control menu generation.
//
// It creates vm instructions for display of menu and handling of input on either size of a vm.HALT instruction.
2023-04-03 09:22:01 +02:00
type MenuProcessor struct {
items []menuItem
size uint32
}
2023-04-12 19:04:36 +02:00
// NewMenuProcessor creates a new MenuProcessor object.
2023-04-03 09:22:01 +02:00
func NewMenuProcessor() MenuProcessor {
return MenuProcessor{}
}
2023-04-12 19:04:36 +02:00
// Add a menu batch instruction to be processed.
//
// Instructions will be rendered in the order in which they have been added.
2023-04-03 09:22:01 +02:00
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)
}
if len(target) > 0 && bopCode != MENU_DOWN {
return fmt.Errorf("target is only valid for DOWN")
}
2023-04-03 09:22:01 +02:00
m := menuItem{
code: bopCode,
choice: choice,
display: display,
target: target,
}
mp.items = append(mp.items, m)
return nil
}
2023-04-12 19:04:36 +02:00
// ToLines returns the generated bytecode from the added menu batch instructions.
2023-04-03 09:22:01 +02:00
func (mp *MenuProcessor) ToLines() []byte {
preLines := []byte{}
postLines := []byte{}
for _, v := range mp.items {
switch v.code {
case MENU_UP:
2023-04-08 10:31:32 +02:00
preLines = vm.NewLine(preLines, vm.MOUT, []string{v.choice, v.display}, nil, nil)
2023-04-04 11:32:39 +02:00
postLines = vm.NewLine(postLines, vm.INCMP, []string{v.choice, "_"}, nil, nil)
2023-04-03 09:22:01 +02:00
case MENU_NEXT:
preLines = vm.NewLine(preLines, vm.MNEXT, []string{v.choice, v.display}, nil, nil)
postLines = vm.NewLine(postLines, vm.INCMP, []string{v.choice, ">"}, nil, nil)
2023-04-03 09:22:01 +02:00
case MENU_PREVIOUS:
preLines = vm.NewLine(preLines, vm.MPREV, []string{v.choice, v.display}, nil, nil)
postLines = vm.NewLine(postLines, vm.INCMP, []string{v.choice, "<"}, nil, nil)
2023-04-03 09:22:01 +02:00
default:
2023-04-08 10:31:32 +02:00
preLines = vm.NewLine(preLines, vm.MOUT, []string{v.choice, v.display}, nil, nil)
2023-04-04 11:32:39 +02:00
postLines = vm.NewLine(postLines, vm.INCMP, []string{v.choice, v.target}, nil, nil)
2023-04-03 09:22:01 +02:00
}
}
2023-04-04 11:32:39 +02:00
preLines = vm.NewLine(preLines, vm.HALT, nil, nil, nil)
2023-04-03 09:22:01 +02:00
return append(preLines, postLines...)
}