Proper catch of CATCH and INCMP
This commit is contained in:
parent
13bf7309e7
commit
d6a0314132
@ -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)
|
||||||
|
@ -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
9
go/testdata/foo.fst
vendored
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user