WIP Add batch menu handler for asm
This commit is contained in:
parent
b8c8802421
commit
13bf7309e7
@ -69,7 +69,7 @@ A menu has both a display and a input processing part. They are on either side o
|
|||||||
|
|
||||||
To assist with menu creation, a few batch operation symbols have been made available for use with the assembly language.
|
To assist with menu creation, a few batch operation symbols have been made available for use with the assembly language.
|
||||||
|
|
||||||
* `DOWN <choice> <display> <symbol>` descend to next frame
|
* `DOWN <symbol> <choice> <display>` descend to next frame and move to `symbol`
|
||||||
* `UP <choice> <display>` return to the previous frame
|
* `UP <choice> <display>` return to the previous frame
|
||||||
* `NEXT <choice> <display>` include pagination advance
|
* `NEXT <choice> <display>` include pagination advance
|
||||||
* `PREVIOUS <choice> <display>` include pagination return. If `NEXT` has not been defined this will not be rendered.
|
* `PREVIOUS <choice> <display>` include pagination return. If `NEXT` has not been defined this will not be rendered.
|
||||||
|
489
go/asm/asm.go
489
go/asm/asm.go
@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/participle/v2"
|
"github.com/alecthomas/participle/v2"
|
||||||
@ -20,73 +21,197 @@ type Asm struct {
|
|||||||
Instructions []*Instruction `@@*`
|
Instructions []*Instruction `@@*`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Display struct {
|
|
||||||
Sym string `@Sym Whitespace`
|
|
||||||
Val string `Quote (@Sym @Whitespace?)+ Quote`
|
|
||||||
}
|
|
||||||
|
|
||||||
func(d Display) String() string {
|
|
||||||
return fmt.Sprintf("Display: %v %v", d.Sym, d.Val)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Single struct {
|
|
||||||
One string `@Sym`
|
|
||||||
}
|
|
||||||
|
|
||||||
func(s Single) String() string {
|
|
||||||
return fmt.Sprintf("Single: %v", s.One)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Double struct {
|
|
||||||
One string `@Sym Whitespace`
|
|
||||||
Two string `@Sym`
|
|
||||||
}
|
|
||||||
|
|
||||||
func(d Double) String() string {
|
|
||||||
return fmt.Sprintf("Double: %v %v", d.One, d.Two)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sized struct {
|
|
||||||
Sym string `@Sym Whitespace`
|
|
||||||
Size uint32 `@Size`
|
|
||||||
}
|
|
||||||
|
|
||||||
func(s Sized) String() string {
|
|
||||||
return fmt.Sprintf("Sized: %v %v", s.Sym, s.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Arg struct {
|
type Arg struct {
|
||||||
ArgDisplay *Display `@@?`
|
Sym *string `(@Sym Whitespace?)?`
|
||||||
ArgSized *Sized `@@?`
|
Size *uint32 `(@Size Whitespace?)?`
|
||||||
ArgFlag *uint8 `@Size?`
|
Flag *uint8 `(@Size Whitespace?)?`
|
||||||
ArgDouble *Double `@@?`
|
Selector *string `(@Sym Whitespace?)?`
|
||||||
ArgSingle *Single `@@?`
|
Desc *string `(Quote ((@Sym | @Size) @Whitespace?)+ Quote Whitespace?)?`
|
||||||
ArgNone string `Whitespace? EOL`
|
}
|
||||||
|
|
||||||
|
func flush(b *bytes.Buffer, w io.Writer) (int, error) {
|
||||||
|
if w != nil {
|
||||||
|
return w.Write(b.Bytes())
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDescType(b *bytes.Buffer, arg Arg) (int, error) {
|
||||||
|
var rn int
|
||||||
|
var err error
|
||||||
|
var selector string
|
||||||
|
if arg.Flag != nil {
|
||||||
|
selector = strconv.FormatUint(uint64(*arg.Flag), 10)
|
||||||
|
} else if arg.Selector != nil {
|
||||||
|
selector = *arg.Selector
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := writeSym(b, *arg.Sym)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if selector != "" {
|
||||||
|
n, err := writeSym(b, *arg.Sym)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = writeSym(b, *arg.Desc)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseTwoSym(b *bytes.Buffer, arg Arg) (int, error) {
|
||||||
|
var rn int
|
||||||
|
|
||||||
|
n, err := writeSym(b, *arg.Sym)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = writeSym(b, *arg.Selector)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSig(b *bytes.Buffer, arg Arg) (int, error) {
|
||||||
|
var rn int
|
||||||
|
|
||||||
|
n, err := writeSym(b, *arg.Sym)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = writeSize(b, *arg.Size)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = b.Write([]byte{uint8(*arg.Flag)})
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSized(b *bytes.Buffer, arg Arg) (int, error) {
|
||||||
|
var rn int
|
||||||
|
|
||||||
|
n, err := writeSym(b, *arg.Sym)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = writeSize(b, *arg.Size)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error) {
|
||||||
|
a := instruction.OpArg
|
||||||
|
var n_buf int
|
||||||
|
var n_out int
|
||||||
|
|
||||||
|
b := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
|
n, err := writeOpcode(b, op)
|
||||||
|
n_buf += n
|
||||||
|
if err != nil {
|
||||||
|
return n_out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Sym == nil {
|
||||||
|
return flush(b, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Desc != nil {
|
||||||
|
n, err := parseDescType(b, a)
|
||||||
|
n_buf += n
|
||||||
|
if err != nil {
|
||||||
|
return n_out, err
|
||||||
|
}
|
||||||
|
return flush(b, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Selector != nil {
|
||||||
|
n, err := parseTwoSym(b, a)
|
||||||
|
n_buf += n
|
||||||
|
if err != nil {
|
||||||
|
return n_out, err
|
||||||
|
}
|
||||||
|
return flush(b, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Size != nil {
|
||||||
|
if a.Flag != nil {
|
||||||
|
n, err := parseSig(b, a)
|
||||||
|
n_buf += n
|
||||||
|
if err != nil {
|
||||||
|
return n_out, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n, err := parseSized(b, a)
|
||||||
|
n_buf += n
|
||||||
|
if err != nil {
|
||||||
|
return n_out, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flush(b, w)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err = writeSym(b, *a.Sym)
|
||||||
|
n_buf += n
|
||||||
|
return flush(b, w)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Arg) String() string {
|
func (a Arg) String() string {
|
||||||
if a.ArgDisplay != nil {
|
s := "[Arg]"
|
||||||
return fmt.Sprintf("%s", a.ArgDisplay)
|
if a.Sym != nil {
|
||||||
|
s += " Sym: " + *a.Sym
|
||||||
}
|
}
|
||||||
if a.ArgFlag != nil {
|
if a.Size != nil {
|
||||||
return fmt.Sprintf("Flag: %v", *a.ArgFlag)
|
s += fmt.Sprintf(" Size: %v", *a.Size)
|
||||||
}
|
}
|
||||||
if a.ArgSized != nil {
|
if a.Flag != nil {
|
||||||
return fmt.Sprintf("%s", a.ArgSized)
|
s += fmt.Sprintf(" Flag: %v", *a.Flag)
|
||||||
}
|
}
|
||||||
if a.ArgSingle != nil {
|
if a.Selector != nil {
|
||||||
return fmt.Sprintf("%s", a.ArgSingle)
|
s += " Selector: " + *a.Selector
|
||||||
}
|
}
|
||||||
if a.ArgDouble != nil {
|
if a.Desc != nil {
|
||||||
return fmt.Sprintf("%s", a.ArgDouble)
|
s += " Description: " + *a.Desc
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
|
return fmt.Sprintf(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Instruction struct {
|
type Instruction struct {
|
||||||
OpCode string `@Ident`
|
OpCode string `@Ident`
|
||||||
OpArg Arg `@@`
|
OpArg Arg `(Whitespace @@)?`
|
||||||
Comment string `Comment?`
|
Comment string `Comment? EOL`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Instruction) String() string {
|
func (i Instruction) String() string {
|
||||||
@ -95,13 +220,11 @@ func (i Instruction) String() string {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
asmLexer = lexer.MustSimple([]lexer.SimpleRule{
|
asmLexer = lexer.MustSimple([]lexer.SimpleRule{
|
||||||
{"Comment", `(?:#)[^\n]*\n?`},
|
{"Comment", `(?:#)[^\n]*`},
|
||||||
{"Ident", `^[A-Z]+`},
|
{"Ident", `^[A-Z]+`},
|
||||||
{"SizeSig", `[0-9]+\s+{?:[0-9]}`},
|
|
||||||
{"Size", `[0-9]+`},
|
{"Size", `[0-9]+`},
|
||||||
{"Sym", `[a-zA-Z_][a-zA-Z0-9_]+`},
|
{"Sym", `[a-zA-Z_][a-zA-Z0-9_]*`},
|
||||||
{"Whitespace", `[ \t]+`},
|
{"Whitespace", `[ \t]+`},
|
||||||
{"Discard", `^\s+[\n\r]+$`},
|
|
||||||
{"EOL", `[\n\r]+`},
|
{"EOL", `[\n\r]+`},
|
||||||
{"Quote", `["']`},
|
{"Quote", `["']`},
|
||||||
})
|
})
|
||||||
@ -116,14 +239,14 @@ func numSize(n uint32) int {
|
|||||||
return int(((v - 1) / 8) + 1)
|
return int(((v - 1) / 8) + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeOpcode(op vm.Opcode, w *bytes.Buffer) (int, error) {
|
func writeOpcode(w *bytes.Buffer, op vm.Opcode) (int, error) {
|
||||||
bn := [2]byte{}
|
bn := [2]byte{}
|
||||||
binary.BigEndian.PutUint16(bn[:], uint16(op))
|
binary.BigEndian.PutUint16(bn[:], uint16(op))
|
||||||
n, err := w.Write(bn[:])
|
n, err := w.Write(bn[:])
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeSym(s string, w *bytes.Buffer) (int, error) {
|
func writeSym(w *bytes.Buffer, s string) (int, error) {
|
||||||
sz := len(s)
|
sz := len(s)
|
||||||
if sz > 255 {
|
if sz > 255 {
|
||||||
return 0, fmt.Errorf("string size %v too big", sz)
|
return 0, fmt.Errorf("string size %v too big", sz)
|
||||||
@ -132,7 +255,7 @@ func writeSym(s string, w *bytes.Buffer) (int, error) {
|
|||||||
return w.WriteString(s)
|
return w.WriteString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeDisplay(s string, w *bytes.Buffer) (int, error) {
|
func writeDisplay(w *bytes.Buffer, s string) (int, error) {
|
||||||
s = strings.Trim(s, "\"'")
|
s = strings.Trim(s, "\"'")
|
||||||
sz := len(s)
|
sz := len(s)
|
||||||
if sz > 255 {
|
if sz > 255 {
|
||||||
@ -141,8 +264,7 @@ func writeDisplay(s string, w *bytes.Buffer) (int, error) {
|
|||||||
w.Write([]byte{byte(sz)})
|
w.Write([]byte{byte(sz)})
|
||||||
return w.WriteString(s)
|
return w.WriteString(s)
|
||||||
}
|
}
|
||||||
|
func writeSize(w *bytes.Buffer, n uint32) (int, error) {
|
||||||
func writeSize(n uint32, w *bytes.Buffer) (int, error) {
|
|
||||||
bn := [4]byte{}
|
bn := [4]byte{}
|
||||||
sz := numSize(n)
|
sz := numSize(n)
|
||||||
if sz > 4 {
|
if sz > 4 {
|
||||||
@ -154,175 +276,37 @@ func writeSize(n uint32, w *bytes.Buffer) (int, error) {
|
|||||||
return w.Write(bn[c:])
|
return w.Write(bn[c:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSingle(op vm.Opcode, arg Arg, w io.Writer) (int, error) {
|
type Batcher struct {
|
||||||
var rn int
|
menuProcessor MenuProcessor
|
||||||
|
inMenu bool
|
||||||
v := arg.ArgSingle
|
|
||||||
if v == nil {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
n, err := writeOpcode(op, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = writeSym(v.One, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if w != nil {
|
|
||||||
rn, err = w.Write(b.Bytes())
|
|
||||||
} else {
|
|
||||||
rn = 0
|
|
||||||
}
|
|
||||||
return rn, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDisplay(op vm.Opcode, arg Arg, w io.Writer) (int, error) {
|
func NewBatcher(mp MenuProcessor) Batcher {
|
||||||
var rn int
|
return Batcher{
|
||||||
|
menuProcessor: NewMenuProcessor(),
|
||||||
v := arg.ArgDisplay
|
|
||||||
if v == nil {
|
|
||||||
return 0, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
n, err := writeOpcode(op, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = writeSym(v.Sym, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = writeDisplay(v.Val, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
if w != nil {
|
|
||||||
rn, err = w.Write(b.Bytes())
|
|
||||||
} else {
|
|
||||||
rn = 0
|
|
||||||
}
|
|
||||||
return rn, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDouble(op vm.Opcode, arg Arg, w io.Writer) (int, error) {
|
func(b *Batcher) MenuExit(w io.Writer) (int, error) {
|
||||||
var rn int
|
if !b.inMenu {
|
||||||
|
|
||||||
v := arg.ArgDouble
|
|
||||||
if v == nil {
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
b.inMenu = false
|
||||||
b := bytes.NewBuffer(nil)
|
return w.Write(b.menuProcessor.ToLines())
|
||||||
|
|
||||||
n, err := writeOpcode(op, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = writeSym(v.One, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = writeSym(v.Two, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if w != nil {
|
|
||||||
rn, err = w.Write(b.Bytes())
|
|
||||||
} else {
|
|
||||||
rn = 0
|
|
||||||
}
|
|
||||||
return rn, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSized(op vm.Opcode, arg Arg, w io.Writer) (int, error) {
|
func(b *Batcher) MenuAdd(w io.Writer, code string, arg Arg) (int, error) {
|
||||||
var rn int
|
b.inMenu = true
|
||||||
|
selector := ""
|
||||||
v := arg.ArgSized
|
if arg.Selector != nil {
|
||||||
if v == nil {
|
selector = *arg.Selector
|
||||||
return 0, nil
|
|
||||||
}
|
}
|
||||||
|
err := b.menuProcessor.Add(code, *arg.Sym, selector, *arg.Desc)
|
||||||
b := bytes.NewBuffer(nil)
|
return 0, err
|
||||||
|
|
||||||
n, err := writeOpcode(op, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = writeSym(v.Sym, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = writeSize(v.Size, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
if w != nil {
|
|
||||||
rn, err = w.Write(b.Bytes())
|
|
||||||
} else {
|
|
||||||
rn = 0
|
|
||||||
}
|
|
||||||
return rn, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseNoarg(op vm.Opcode, arg Arg, w io.Writer) (int, error) {
|
func(b *Batcher) Exit(w io.Writer) (int, error) {
|
||||||
var rn int
|
return b.MenuExit(w)
|
||||||
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
|
|
||||||
n, err := writeOpcode(op, b)
|
|
||||||
rn += n
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
if w != nil {
|
|
||||||
rn, err = w.Write(b.Bytes())
|
|
||||||
} else {
|
|
||||||
rn = 0
|
|
||||||
}
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseFlag(op vm.Opcode, arg Arg, w io.Writer) (int, error) {
|
|
||||||
var rn int
|
|
||||||
var err error
|
|
||||||
|
|
||||||
v := arg.ArgFlag
|
|
||||||
if v == nil {
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
if w != nil {
|
|
||||||
rn, err = w.Write([]byte{*v})
|
|
||||||
} else {
|
|
||||||
rn = 0
|
|
||||||
}
|
|
||||||
return rn, err
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(s string, w io.Writer) (int, error) {
|
func Parse(s string, w io.Writer) (int, error) {
|
||||||
@ -332,56 +316,39 @@ func Parse(s string, w io.Writer) (int, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batch := Batcher{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var rn int
|
var rn int
|
||||||
for _, v := range ast.Instructions {
|
for _, v := range ast.Instructions {
|
||||||
log.Printf("parsing line %v: %v", v.OpCode, v.OpArg)
|
log.Printf("parsing line %v: %v", v.OpCode, v.OpArg)
|
||||||
op := vm.OpcodeIndex[v.OpCode]
|
op, ok := vm.OpcodeIndex[v.OpCode]
|
||||||
n, err := parseSized(op, v.OpArg, w)
|
if !ok {
|
||||||
if err != nil {
|
n, err := batch.MenuAdd(w, v.OpCode, v.OpArg)
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
rn += n
|
rn += n
|
||||||
n, err = parseFlag(op, v.OpArg, w)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return rn, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
n, err := batch.MenuExit(w)
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
}
|
}
|
||||||
rn += n
|
rn += n
|
||||||
continue
|
n, err = parseOne(op, v, w)
|
||||||
}
|
|
||||||
n, err = parseDisplay(op, v.OpArg, w)
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
rn += n
|
rn += n
|
||||||
continue
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n, err = parseDouble(op, v.OpArg, w)
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
rn += n
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
n, err = parseSingle(op, v.OpArg, w)
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
rn += n
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
n, err = parseNoarg(op, v.OpArg, w)
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
if n > 0 {
|
|
||||||
rn += n
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
n, err := batch.Exit(w)
|
||||||
|
rn += n
|
||||||
|
if err != nil {
|
||||||
|
return rn, err
|
||||||
|
}
|
||||||
|
rn += n
|
||||||
|
|
||||||
return rn, err
|
return rn, err
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package asm
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -91,6 +92,36 @@ func TestParseDouble(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseMenu(t *testing.T) {
|
||||||
|
s := `DOWN foobar 00 "inky pinky"
|
||||||
|
UP bazbar s1 "tinkywinky"
|
||||||
|
`
|
||||||
|
r := bytes.NewBuffer(nil)
|
||||||
|
n, err := Parse(s, r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Printf("wrote %v bytes", n)
|
||||||
|
|
||||||
|
s = `MOUT foobar 00 "inky pinky"
|
||||||
|
MOUT bazbar s1 "tinky winky"
|
||||||
|
HALT
|
||||||
|
INCMP 00 foobar
|
||||||
|
INCMP s1 bazbar
|
||||||
|
`
|
||||||
|
r_check := bytes.NewBuffer(nil)
|
||||||
|
n, err = Parse(s, r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Printf("wrote %v bytes", n)
|
||||||
|
|
||||||
|
if !bytes.Equal(r_check.Bytes(), r.Bytes()) {
|
||||||
|
fmt.Errorf("expected:\n\t%xgot:\n\t%x\n", r_check, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseSingle(t *testing.T) {
|
func TestParseSingle(t *testing.T) {
|
||||||
var b []byte
|
var b []byte
|
||||||
b = vm.NewLine(b, vm.MAP, []string{"xyzzy"}, nil, nil)
|
b = vm.NewLine(b, vm.MAP, []string{"xyzzy"}, nil, nil)
|
||||||
@ -173,23 +204,21 @@ func TestParserWriteMultiple(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
n_expect := 2 // halt
|
|
||||||
n_expect += 2 + 6 + 3 + 1 // catch
|
|
||||||
n_expect += 2 + 5 + 6 // incmp
|
|
||||||
n_expect += 2 + 4 + 2 // load
|
|
||||||
n_expect += 2 + 4 + 12 // mout
|
|
||||||
log.Printf("result %x", r.Bytes())
|
log.Printf("result %x", r.Bytes())
|
||||||
if n != n_expect {
|
|
||||||
t.Fatalf("expected total %v bytes output, got %v", n_expect, n)
|
|
||||||
}
|
|
||||||
r_expect_hex := "000700010578797a7a7902029a01000804696e6b790570696e6b79000303666f6f012a000a036261720b626172206261726220617a"
|
r_expect_hex := "000700010578797a7a7902029a01000804696e6b790570696e6b79000303666f6f012a000a036261720b626172206261726220617a"
|
||||||
r_expect, err := hex.DecodeString(r_expect_hex)
|
r_expect, err := hex.DecodeString(r_expect_hex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
n_expect := len(r_expect)
|
||||||
|
if n != n_expect {
|
||||||
|
t.Fatalf("expected total %v bytes output, got %v", n_expect, n)
|
||||||
|
}
|
||||||
|
|
||||||
rb := r.Bytes()
|
rb := r.Bytes()
|
||||||
if !bytes.Equal(rb, r_expect) {
|
if !bytes.Equal(rb, r_expect) {
|
||||||
t.Fatalf("expected result %v, got %x", r_expect_hex, rb)
|
t.Fatalf("expected result:\n\t%v, got:\n\t%x", r_expect_hex, rb)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = vm.ParseAll(rb, nil)
|
_, err = vm.ParseAll(rb, nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user