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) { func parseDescType(b *bytes.Buffer, arg Arg) (int, error) {
var rn int var rn int
var err error var err error
var selector string var selector string
if arg.Flag != nil { if arg.Flag != nil {
selector = strconv.FormatUint(uint64(*arg.Flag), 10) selector = strconv.FormatUint(uint64(*arg.Flag), 10)
@ -46,13 +47,17 @@ func parseDescType(b *bytes.Buffer, arg Arg) (int, error) {
selector = *arg.Selector selector = *arg.Selector
} }
n, err := writeSym(b, *arg.Sym) var size string
rn += n if arg.Size != nil {
if err != nil { size = strconv.FormatUint(uint64(*arg.Size), 10)
return rn, err n, err := writeSym(b, size)
rn += n
if err != nil {
return rn, err
}
} }
if selector != "" { if arg.Sym != nil {
n, err := writeSym(b, *arg.Sym) n, err := writeSym(b, *arg.Sym)
rn += n rn += n
if err != nil { if err != nil {
@ -60,7 +65,15 @@ func parseDescType(b *bytes.Buffer, arg Arg) (int, error) {
} }
} }
n, err = writeSym(b, *arg.Desc) if selector != "" {
n, err := writeSym(b, *arg.Selector)
rn += n
if err != nil {
return rn, err
}
}
n, err := writeSym(b, *arg.Desc)
rn += n rn += n
if err != nil { if err != nil {
return rn, err 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) { func parseTwoSym(b *bytes.Buffer, arg Arg) (int, error) {
var rn int 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 rn += n
if err != nil { if err != nil {
return rn, err return rn, err
} }
n, err = writeSym(b, *arg.Selector) n, err = writeSym(b, sym)
rn += n rn += n
if err != nil { if err != nil {
return rn, err return rn, err
@ -142,10 +165,7 @@ func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error)
return n_out, err return n_out, err
} }
if a.Sym == nil { // Catch MOUT
return flush(b, w)
}
if a.Desc != nil { if a.Desc != nil {
n, err := parseDescType(b, a) n, err := parseDescType(b, a)
n_buf += n n_buf += n
@ -155,7 +175,9 @@ func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error)
return flush(b, w) return flush(b, w)
} }
// Catch
if a.Selector != nil { if a.Selector != nil {
log.Printf("entering twosym for %v", op)
n, err := parseTwoSym(b, a) n, err := parseTwoSym(b, a)
n_buf += n n_buf += n
if err != nil { if err != nil {
@ -164,6 +186,7 @@ func parseOne(op vm.Opcode, instruction *Instruction, w io.Writer) (int, error)
return flush(b, w) return flush(b, w)
} }
// Catch CATCH, LOAD
if a.Size != nil { if a.Size != nil {
if a.Flag != nil { if a.Flag != nil {
n, err := parseSig(b, a) 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) return flush(b, w)
} }
// Catch HALT
if a.Sym == nil {
return flush(b, w)
}
n, err = writeSym(b, *a.Sym) n, err = writeSym(b, *a.Sym)
n_buf += n n_buf += n
return flush(b, w) return flush(b, w)
@ -236,7 +264,7 @@ var (
func numSize(n uint32) int { func numSize(n uint32) int {
v := math.Log2(float64(n)) 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) { 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) { func(bt *Batcher) MenuExit(w io.Writer) (int, error) {
if !b.inMenu { if !bt.inMenu {
return 0, nil return 0, nil
} }
b.inMenu = false bt.inMenu = false
return w.Write(b.menuProcessor.ToLines()) 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) { func(bt *Batcher) MenuAdd(w io.Writer, code string, arg Arg) (int, error) {
b.inMenu = true bt.inMenu = true
selector := "" var selector string
if arg.Selector != nil { if arg.Size != nil {
selector = strconv.FormatUint(uint64(*arg.Size), 10)
} else if arg.Selector != nil {
selector = *arg.Selector 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 return 0, err
} }
func(b *Batcher) Exit(w io.Writer) (int, error) { func(bt *Batcher) Exit(w io.Writer) (int, error) {
return b.MenuExit(w) return bt.MenuExit(w)
} }
func Parse(s string, w io.Writer) (int, error) { 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 { if err != nil {
return rn, err return rn, err
} }
log.Printf("wrote %v bytes for %v", n, v.OpArg)
} }
} }
n, err := batch.Exit(w) n, err := batch.Exit(w)

View File

@ -73,7 +73,7 @@ func TestParseDisplay(t *testing.T) {
func TestParseDouble(t *testing.T) { func TestParseDouble(t *testing.T) {
var b []byte 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) s, err := vm.ToString(b)
log.Printf("parsing:\n%s\n", s) log.Printf("parsing:\n%s\n", s)
@ -144,8 +144,7 @@ func TestParseSingle(t *testing.T) {
} }
func TestParseSig(t *testing.T) { func TestParseSig(t *testing.T) {
var b []byte b := vm.NewLine(nil, vm.CATCH, []string{"plugh"}, []byte{0x02, 0x9a}, []uint8{0x2a})
b = vm.NewLine(b, vm.CATCH, []string{"plugh"}, []byte{0x02, 0x9a}, []uint8{0x2a})
s, err := vm.ToString(b) s, err := vm.ToString(b)
log.Printf("parsing:\n%s\n", s) log.Printf("parsing:\n%s\n", s)
@ -166,6 +165,28 @@ func TestParseSig(t *testing.T) {
if !bytes.Equal(rb, expect) { if !bytes.Equal(rb, expect) {
t.Fatalf("expected %v, got %x", expect_hex, rb) 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) { func TestParseNoarg(t *testing.T) {
@ -193,7 +214,7 @@ func TestParserWriteMultiple(t *testing.T) {
var b []byte var b []byte
b = vm.NewLine(b, vm.HALT, nil, nil, nil) 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.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.LOAD, []string{"foo"}, []byte{42}, nil)
b = vm.NewLine(b, vm.MOUT, []string{"bar", "bar barb az"}, nil, nil) b = vm.NewLine(b, vm.MOUT, []string{"bar", "bar barb az"}, nil, nil)
s, err := vm.ToString(b) s, err := vm.ToString(b)

9
go/testdata/foo.fst vendored
View File

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