diff --git a/README.md b/README.md index 2afd306..430f272 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ The VM defines the following opcode symbols: * `MAP ` - Expose a code symbol previously loaded by `LOAD` to the rendering client. Roughly corresponds to the `global` directive in Python. * `MOVE ` - Create a new execution frame, invalidating all previous `MAP` calls. More detailed: After a `MOVE` call, a `BACK` call will return to the same execution frame, with the same symbols available, but all `MAP` calls will have to be repeated. * `HALT` - Stop execution. The remaining bytecode (typically, the routing code for the node) is returned to the invoking function. +* `INCMP ` - Compare registered input to `arg` and and move to `symbol` node on match. Any consecutive matches will be ignored until `HALT` is called. ### External code diff --git a/go/engine/engine_test.go b/go/engine/engine_test.go index a94de99..7d6936a 100644 --- a/go/engine/engine_test.go +++ b/go/engine/engine_test.go @@ -85,7 +85,7 @@ func TestEngineInit(t *testing.T) { if !bytes.Equal(b, []byte("hello world")) { t.Fatalf("expected result 'hello world', got %v", b) } - input := []byte("bar") + input := []byte("ooo") err = en.Exec(input, ctx) if err != nil { t.Fatal(err) diff --git a/go/testdata/bar.bin b/go/testdata/bar.bin index 703a92b..be35b15 100644 Binary files a/go/testdata/bar.bin and b/go/testdata/bar.bin differ diff --git a/go/testdata/root.bin b/go/testdata/root.bin index a3b7f0b..35a110e 100644 Binary files a/go/testdata/root.bin and b/go/testdata/root.bin differ diff --git a/go/vm/vm.go b/go/vm/vm.go index 85b536d..6853bab 100644 --- a/go/vm/vm.go +++ b/go/vm/vm.go @@ -169,12 +169,16 @@ func RunIncmp(instruction []byte, st *state.State, rs resource.Resource, ctx con if err != nil { return instruction, err } + sym, tail, err := instructionSplit(tail) + if err != nil { + return instruction, err + } v, err := st.GetFlag(state.FLAG_INMATCH) if err != nil { return tail, err } if v { - return tail, nil + return tail, nil } input, err := st.GetInput() if err != nil { @@ -184,7 +188,7 @@ func RunIncmp(instruction []byte, st *state.State, rs resource.Resource, ctx con if head == string(input) { log.Printf("input match for '%s'", input) _, err = st.SetFlag(state.FLAG_INMATCH) - st.Down(head) + st.Down(sym) } return tail, err } diff --git a/go/vm/vm_test.go b/go/vm/vm_test.go index 42b3420..e2c60eb 100644 --- a/go/vm/vm_test.go +++ b/go/vm/vm_test.go @@ -232,10 +232,10 @@ func TestRunArg(t *testing.T) { st := state.NewState(5) rs := TestResource{} - input := []byte("baz") + input := []byte("bar") _ = st.SetInput(input) - bi := NewLine([]byte{}, INCMP, []string{"baz"}, nil, nil) + bi := NewLine([]byte{}, INCMP, []string{"bar", "baz"}, nil, nil) b, err := Run(bi, &st, &rs, context.TODO()) if err != nil { t.Error(err) @@ -254,10 +254,10 @@ func TestRunInputHandler(t *testing.T) { st := state.NewState(5) rs := TestResource{} - _ = st.SetInput([]byte("foo")) + _ = st.SetInput([]byte("baz")) - bi := NewLine([]byte{}, INCMP, []string{"bar"}, nil, nil) - bi = NewLine(bi, INCMP, []string{"foo"}, nil, nil) + bi := NewLine([]byte{}, INCMP, []string{"bar", "aiee"}, nil, nil) + bi = NewLine(bi, INCMP, []string{"baz", "foo"}, nil, nil) bi = NewLine(bi, LOAD, []string{"one"}, nil, []uint8{0}) bi = NewLine(bi, LOAD, []string{"two"}, nil, []uint8{3}) bi = NewLine(bi, MAP, []string{"one"}, nil, nil) @@ -282,7 +282,7 @@ func TestRunArgInvalid(t *testing.T) { var err error - b := NewLine([]byte{}, INCMP, []string{"bar"}, nil, nil) + b := NewLine([]byte{}, INCMP, []string{"bar", "baz"}, nil, nil) b = NewLine(b, CATCH, []string{"_catch"}, []byte{state.FLAG_INMATCH}, []uint8{1}) b, err = Run(b, &st, &rs, context.TODO())