Proper catch of CATCH and INCMP

This commit is contained in:
lash 2023-04-06 08:38:30 +01:00
parent 13bf7309e7
commit d6a0314132
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
3 changed files with 88 additions and 32 deletions

View File

@ -39,6 +39,7 @@ func flush(b *bytes.Buffer, w io.Writer) (int, error) {
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)
@ -46,21 +47,33 @@ func parseDescType(b *bytes.Buffer, arg Arg) (int, error) {
selector = *arg.Selector
}
var size string
if arg.Size != nil {
size = strconv.FormatUint(uint64(*arg.Size), 10)
n, err := writeSym(b, size)
rn += n
if err != nil {
return rn, err
}
}
if arg.Sym != nil {
n, err := writeSym(b, *arg.Sym)
rn += n
if err != nil {
return rn, err
}
}
if selector != "" {
n, err := writeSym(b, *arg.Sym)
n, err := writeSym(b, *arg.Selector)
rn += n
if err != nil {
return rn, err
}
}
n, err = writeSym(b, *arg.Desc)
n, err := writeSym(b, *arg.Desc)
rn += n
if err != nil {
return rn, err
@ -72,13 +85,23 @@ func parseDescType(b *bytes.Buffer, arg Arg) (int, error) {
func parseTwoSym(b *bytes.Buffer, arg Arg) (int, error) {
var rn int
n, err := writeSym(b, *arg.Sym)
var selector string
var sym string
if arg.Size != nil {
selector = strconv.FormatUint(uint64(*arg.Size), 10)
sym = *arg.Selector
} else if arg.Selector != nil {
sym = *arg.Sym
selector = *arg.Selector
}
n, err := writeSym(b, selector)
rn += n
if err != nil {
return rn, err
}
n, err = writeSym(b, *arg.Selector)
n, err = writeSym(b, sym)
rn += n
if err != nil {
return rn, err
@ -142,10 +165,7 @@ func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error)
return n_out, err
}
if a.Sym == nil {
return flush(b, w)
}
// Catch MOUT
if a.Desc != nil {
n, err := parseDescType(b, a)
n_buf += n
@ -155,7 +175,9 @@ func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error)
return flush(b, w)
}
// Catch
if a.Selector != nil {
log.Printf("entering twosym for %v", op)
n, err := parseTwoSym(b, a)
n_buf += n
if err != nil {
@ -164,6 +186,7 @@ func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error)
return flush(b, w)
}
// Catch CATCH, LOAD
if a.Size != nil {
if a.Flag != nil {
n, err := parseSig(b, a)
@ -181,6 +204,11 @@ func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error)
return flush(b, w)
}
// Catch HALT
if a.Sym == nil {
return flush(b, w)
}
n, err = writeSym(b, *a.Sym)
n_buf += n
return flush(b, w)
@ -236,7 +264,7 @@ var (
func numSize(n uint32) int {
v := math.Log2(float64(n))
return int(((v - 1) / 8) + 1)
return int((v / 8) + 1)
}
func writeOpcode(w *bytes.Buffer, op vm.Opcode) (int, error) {
@ -287,26 +315,31 @@ func NewBatcher(mp MenuProcessor) Batcher {
}
}
func(b *Batcher) MenuExit(w io.Writer) (int, error) {
if !b.inMenu {
func(bt *Batcher) MenuExit(w io.Writer) (int, error) {
if !bt.inMenu {
return 0, nil
}
b.inMenu = false
return w.Write(b.menuProcessor.ToLines())
bt.inMenu = false
b := bt.menuProcessor.ToLines()
log.Printf("tolines %v", b)
return w.Write(b)
}
func(b *Batcher) MenuAdd(w io.Writer, code string, arg Arg) (int, error) {
b.inMenu = true
selector := ""
if arg.Selector != nil {
func(bt *Batcher) MenuAdd(w io.Writer, code string, arg Arg) (int, error) {
bt.inMenu = true
var selector string
if arg.Size != nil {
selector = strconv.FormatUint(uint64(*arg.Size), 10)
} else if arg.Selector != nil {
selector = *arg.Selector
}
err := b.menuProcessor.Add(code, *arg.Sym, selector, *arg.Desc)
log.Printf("menu processor add %v '%v' '%v' '%v'", code, *arg.Sym, selector, *arg.Desc)
err := bt.menuProcessor.Add(code, *arg.Sym, selector, *arg.Desc)
return 0, err
}
func(b *Batcher) Exit(w io.Writer) (int, error) {
return b.MenuExit(w)
func(bt *Batcher) Exit(w io.Writer) (int, error) {
return bt.MenuExit(w)
}
func Parse(s string, w io.Writer) (int, error) {
@ -341,6 +374,7 @@ func Parse(s string, w io.Writer) (int, error) {
if err != nil {
return rn, err
}
log.Printf("wrote %v bytes for %v", n, v.OpArg)
}
}
n, err := batch.Exit(w)

View File

@ -73,7 +73,7 @@ func TestParseDisplay(t *testing.T) {
func TestParseDouble(t *testing.T) {
var b []byte
b = vm.NewLine(b, vm.INCMP, []string{"foo", "bar"}, nil, nil)
b = vm.NewLine(b, vm.INCMP, []string{"bar", "foo"}, nil, nil)
s, err := vm.ToString(b)
log.Printf("parsing:\n%s\n", s)
@ -144,8 +144,7 @@ func TestParseSingle(t *testing.T) {
}
func TestParseSig(t *testing.T) {
var b []byte
b = vm.NewLine(b, vm.CATCH, []string{"plugh"}, []byte{0x02, 0x9a}, []uint8{0x2a})
b := vm.NewLine(nil, vm.CATCH, []string{"plugh"}, []byte{0x02, 0x9a}, []uint8{0x2a})
s, err := vm.ToString(b)
log.Printf("parsing:\n%s\n", s)
@ -166,6 +165,28 @@ func TestParseSig(t *testing.T) {
if !bytes.Equal(rb, expect) {
t.Fatalf("expected %v, got %x", expect_hex, rb)
}
b = vm.NewLine(nil, vm.CATCH, []string{"plugh"}, []byte{0x01}, []uint8{0x0})
s, err = vm.ToString(b)
log.Printf("parsing:\n%s\n", s)
r = bytes.NewBuffer(nil)
n, err = Parse(s, r)
if err != nil {
t.Fatal(err)
}
if n != 11 {
t.Fatalf("expected 11 byte write count, got %v", n)
}
rb = r.Bytes()
expect_hex = "000105706c756768010100"
expect, err = hex.DecodeString(expect_hex)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(rb, expect) {
t.Fatalf("expected %v, got %x", expect_hex, rb)
}
}
func TestParseNoarg(t *testing.T) {
@ -193,7 +214,7 @@ func TestParserWriteMultiple(t *testing.T) {
var b []byte
b = vm.NewLine(b, vm.HALT, nil, nil, nil)
b = vm.NewLine(b, vm.CATCH, []string{"xyzzy"}, []byte{0x02, 0x9a}, []uint8{1})
b = vm.NewLine(b, vm.INCMP, []string{"inky", "pinky"}, nil, nil)
b = vm.NewLine(b, vm.INCMP, []string{"pinky", "inky"}, nil, nil)
b = vm.NewLine(b, vm.LOAD, []string{"foo"}, []byte{42}, nil)
b = vm.NewLine(b, vm.MOUT, []string{"bar", "bar barb az"}, nil, nil)
s, err := vm.ToString(b)

9
go/testdata/foo.fst vendored
View File

@ -1,7 +1,8 @@
MOUT 0 "to foo"
MOUT 1 "go bar"
MOUT 1 "to foo"
MOUT 2 "go bar"
LOAD inky 20
HALT
INCMP 0 _
INCMP 1 baz
INCMP 1 _
INCMP 2 baz
CATCH _catch 1 1
DOWN foofoo 1 "go to foo"