From 725ee335ec2d0247bf1959bb9e38ca94d572a672 Mon Sep 17 00:00:00 2001 From: lash Date: Fri, 31 Mar 2023 20:05:57 +0100 Subject: [PATCH] Add back handler --- go/vm/vm.go | 10 +++++++++ go/vm/vm_test.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/go/vm/vm.go b/go/vm/vm.go index 19b1779..dff702f 100644 --- a/go/vm/vm.go +++ b/go/vm/vm.go @@ -38,6 +38,8 @@ func Apply(input []byte, instruction []byte, st state.State, rs resource.Fetcher } if sym == "" { instruction = NewLine([]byte{}, MOVE, []string{"_catch"}, nil, nil) + } else if sym == "_" { + instruction = NewLine([]byte{}, BACK, nil, nil, nil) } else { new_instruction := NewLine([]byte{}, MOVE, []string{sym}, nil, nil) instruction = append(new_instruction, instruction...) @@ -80,6 +82,9 @@ func Run(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Co case MOVE: st, instruction, err = RunMove(instruction[2:], st, rs, ctx) break + case BACK: + st, instruction, err = RunBack(instruction[2:], st, rs, ctx) + break default: err = fmt.Errorf("Unhandled state: %v", op) } @@ -169,6 +174,11 @@ func RunMove(instruction []byte, st state.State, rs resource.Fetcher, ctx contex return st, tail, nil } +func RunBack(instruction []byte, st state.State, rs resource.Fetcher, ctx context.Context) (state.State, []byte, error) { + st.Up() + return st, instruction, nil +} + func refresh(key string, sym []byte, rs resource.Fetcher, ctx context.Context) (string, error) { fn, err := rs.FuncFor(key) if err != nil { diff --git a/go/vm/vm_test.go b/go/vm/vm_test.go index 7f5afa3..4dab858 100644 --- a/go/vm/vm_test.go +++ b/go/vm/vm_test.go @@ -250,9 +250,10 @@ func TestRunArgInvalid(t *testing.T) { func TestRunArgInstructions(t *testing.T) { st := state.NewState(5) + rs := TestResource{} + rt := router.NewRouter() rt.Add("foo", "bar") - rs := TestResource{} b := []byte{0x03} b = append(b, []byte("foo")...) b = append(b, rt.ToBytes()...) @@ -284,3 +285,57 @@ func TestRunArgInstructions(t *testing.T) { } _ = r } + +func TestRunMoveAndBack(t *testing.T) { + st := state.NewState(5) + rs := TestResource{} + rt := router.NewRouter() + rt.Add("foo", "bar") + b := []byte{0x03} + b = append(b, []byte("foo")...) + b = append(b, rt.ToBytes()...) + bi := NewLine([]byte{}, LOAD, []string{"one"}, nil, []uint8{0}) + + var err error + st, b, err = Apply(b, bi, st, &rs, context.TODO()) + if err != nil { + t.Error(err) + } + l := len(b) + if l != 0 { + t.Errorf("expected empty remainder, got length %v: %v", l, b) + } + + rt = router.NewRouter() + rt.Add("foo", "baz") + b = []byte{0x03} + b = append(b, []byte("foo")...) + b = append(b, rt.ToBytes()...) + bi = NewLine([]byte{}, LOAD, []string{"two"}, nil, []uint8{0}) + st, b, err = Apply(b, bi, st, &rs, context.TODO()) + if err != nil { + t.Error(err) + } + l = len(b) + if l != 0 { + t.Errorf("expected empty remainder, got length %v: %v", l, b) + } + + rt = router.NewRouter() + rt.Add("foo", "_") + b = []byte{0x03} + b = append(b, []byte("foo")...) + b = append(b, rt.ToBytes()...) + st, b, err = Apply(b, []byte{}, st, &rs, context.TODO()) + if err != nil { + t.Error(err) + } + l = len(b) + if l != 0 { + t.Errorf("expected empty remainder, got length %v: %v", l, b) + } + loc := st.Where() + if loc != "bar" { + t.Errorf("expected where-string 'bar', got %v", loc) + } +}