diff --git a/go/state/state.go b/go/state/state.go index 118a10c..8404cc4 100644 --- a/go/state/state.go +++ b/go/state/state.go @@ -126,6 +126,11 @@ func(st *State) FlagBitSize() uint32 { return st.bitSize } +// FlagBitSize reports the amount of bits available in the bit field index. +func(st *State) FlagByteSize() uint8 { + return uint8(len(st.Flags)) +} + // GetIndex scans a byte slice in same order as in storage, and returns the index of the first set bit. // // If the given byte slice is too small for the bit field bitsize, the check will terminate at end-of-data without error. diff --git a/go/vm/vm.go b/go/vm/vm.go index a6ea993..3ade799 100644 --- a/go/vm/vm.go +++ b/go/vm/vm.go @@ -120,13 +120,22 @@ func RunCatch(instruction []byte, st state.State, rs resource.Resource, ctx cont if err != nil { return st, instruction, err } - r, err := rs.Get(head) - if err != nil { - return st, instruction, err - } - _ = tail - st.Add(head, r, 0) - return st, []byte{}, nil + // TODO: perhaps check against the registered byte size + //l := st.FlagByteSize() + bitFieldSize := tail[0] + bitField := tail[1:1+bitFieldSize] + tail = tail[1+bitFieldSize:] + if st.GetIndex(bitField) { + log.Printf("catch at flag %v, moving to %v", bitField, head) +// r, err := rs.Get(head) +// if err != nil { +// return st, instruction, err +// } + //st.Add(head, r, 0) + st.Down(head) + tail = []byte{} + } + return st, tail, nil } // RunMap executes the CROAK opcode diff --git a/go/vm/vm_test.go b/go/vm/vm_test.go index d828449..65a0503 100644 --- a/go/vm/vm_test.go +++ b/go/vm/vm_test.go @@ -51,6 +51,7 @@ func (r *TestResource) Get(sym string) (string, error) { case "three": return "{{.one}} inky pinky {{.three}} blinky clyde {{.two}}", nil } + panic(fmt.Sprintf("unknown symbol %s", sym)) return "", fmt.Errorf("unknown symbol %s", sym) } @@ -89,7 +90,7 @@ func (r *TestResource) FuncFor(sym string) (resource.EntryFunc, error) { func TestRun(t *testing.T) { st := state.NewState(5) rs := TestResource{} - b := []byte{0x00, 0x01, 0x03} + b := []byte{0x00, MOVE, 0x03} b = append(b, []byte("foo")...) r, _, err := Run(b, st, &rs, context.TODO()) if err != nil { @@ -339,3 +340,34 @@ func TestRunMoveAndBack(t *testing.T) { t.Errorf("expected where-string 'bar', got %v", loc) } } + +func TestCatchAndBack(t *testing.T) { + st := state.NewState(5) + rs := TestResource{} + rt := router.NewRouter() + rt.Add("foo", "bar") + b := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0}) + b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, nil) + b = NewLine(b, MOVE, []string{"foo"}, nil, nil) + st, _, err := Run(b, st, &rs, context.TODO()) + if err != nil { + t.Error(err) + } + r := st.Where() + if r != "foo" { + t.Errorf("expected where-symbol 'foo', got %v", r) + } + + st.SetFlag(2) + b = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0}) + b = NewLine(b, CATCH, []string{"bar"}, []byte{0x04}, nil) + b = NewLine(b, MOVE, []string{"foo"}, nil, nil) + st, _, err = Run(b, st, &rs, context.TODO()) + if err != nil { + t.Error(err) + } + r = st.Where() + if r != "bar" { + t.Errorf("expected where-symbol 'bar', got %v", r) + } +}