Add cache push and pop in vm target processingC
This commit is contained in:
parent
da45ee783b
commit
602ca92b6a
@ -3,4 +3,5 @@ package state
|
||||
const (
|
||||
FLAG_INMATCH = 1
|
||||
FLAG_TERMINATE = 2
|
||||
FLAG_DIRTY = 4
|
||||
)
|
||||
|
@ -3,6 +3,7 @@ package state
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// State holds the command stack, error condition of a unique execution session.
|
||||
@ -261,12 +262,14 @@ func(st *State) Up() (string, error) {
|
||||
if l == 0 {
|
||||
return "", fmt.Errorf("exit called beyond top frame")
|
||||
}
|
||||
log.Printf("execpath before %v", st.execPath)
|
||||
st.execPath = st.execPath[:l-1]
|
||||
sym := ""
|
||||
if len(st.execPath) > 0 {
|
||||
sym = st.execPath[len(st.execPath)-1]
|
||||
}
|
||||
st.sizeIdx = 0
|
||||
log.Printf("execpath after %v", st.execPath)
|
||||
return sym, nil
|
||||
}
|
||||
|
||||
@ -316,3 +319,7 @@ func(st *State) SetInput(input []byte) error {
|
||||
// Reset to initial state (start navigation over).
|
||||
func(st *State) Reset() {
|
||||
}
|
||||
|
||||
func(st State) String() string {
|
||||
return fmt.Sprintf("path: %s", strings.Join(st.execPath, "/"))
|
||||
}
|
||||
|
6
go/testdata/testdata.go
vendored
6
go/testdata/testdata.go
vendored
@ -70,7 +70,7 @@ func foo() error {
|
||||
b = vm.NewLine(b, vm.HALT, nil, nil, nil)
|
||||
b = vm.NewLine(b, vm.INCMP, []string{"0", "_"}, nil, nil)
|
||||
b = vm.NewLine(b, vm.INCMP, []string{"1", "baz"}, nil, nil)
|
||||
b = vm.NewLine(b, vm.CATCH, []string{"_catch"}, []byte{1}, []uint8{1})
|
||||
//b = vm.NewLine(b, vm.CATCH, []string{"_catch"}, []byte{1}, []uint8{1})
|
||||
|
||||
data := make(map[string]string)
|
||||
data["inky"] = "one"
|
||||
@ -86,7 +86,7 @@ func bar() error {
|
||||
b := []byte{}
|
||||
b = vm.NewLine(b, vm.LOAD, []string{"pinky"}, []byte{0}, nil)
|
||||
b = vm.NewLine(b, vm.HALT, nil, nil, nil)
|
||||
b = vm.NewLine(b, vm.INCMP, []string{"0", "_home"}, nil, nil)
|
||||
b = vm.NewLine(b, vm.INCMP, []string{"*", "^"}, nil, nil)
|
||||
|
||||
tpl := "this is bar - an end node"
|
||||
|
||||
@ -110,7 +110,7 @@ func defaultCatch() error {
|
||||
b := []byte{}
|
||||
b = vm.NewLine(b, vm.MOUT, []string{"0", "back"}, nil, nil)
|
||||
b = vm.NewLine(b, vm.HALT, nil, nil, nil)
|
||||
b = vm.NewLine(b, vm.MOVE, []string{"_"}, nil, nil)
|
||||
b = vm.NewLine(b, vm.INCMP, []string{"*", "_"}, nil, nil)
|
||||
|
||||
tpl := "invalid input"
|
||||
|
||||
|
@ -5,13 +5,14 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"git.defalsify.org/festive/cache"
|
||||
"git.defalsify.org/festive/state"
|
||||
)
|
||||
|
||||
var (
|
||||
inputRegexStr = "^[a-zA-Z0-9].*$"
|
||||
inputRegex = regexp.MustCompile(inputRegexStr)
|
||||
ctrlRegexStr = "^[><_]$"
|
||||
ctrlRegexStr = "^[><_^]$"
|
||||
ctrlRegex = regexp.MustCompile(ctrlRegexStr)
|
||||
symRegexStr = "^[a-zA-Z0-9][a-zA-Z0-9_]+$"
|
||||
symRegex = regexp.MustCompile(symRegexStr)
|
||||
@ -90,7 +91,7 @@ func CheckTarget(target []byte, st *state.State) (bool, error) {
|
||||
}
|
||||
|
||||
// route parsed target symbol to navigation state change method,
|
||||
func applyTarget(target []byte, st *state.State, ctx context.Context) (string, uint16, error) {
|
||||
func applyTarget(target []byte, st *state.State, ca cache.Memory, ctx context.Context) (string, uint16, error) {
|
||||
var err error
|
||||
sym, idx := st.Where()
|
||||
|
||||
@ -102,6 +103,7 @@ func applyTarget(target []byte, st *state.State, ctx context.Context) (string, u
|
||||
switch target[0] {
|
||||
case '_':
|
||||
sym, err = st.Up()
|
||||
ca.Pop()
|
||||
if err != nil {
|
||||
return sym, idx, err
|
||||
}
|
||||
@ -115,9 +117,15 @@ func applyTarget(target []byte, st *state.State, ctx context.Context) (string, u
|
||||
if err != nil {
|
||||
return sym, idx, err
|
||||
}
|
||||
case '^':
|
||||
_, err := st.SetFlag(state.FLAG_TERMINATE)
|
||||
if err != nil {
|
||||
return sym, idx, err
|
||||
}
|
||||
default:
|
||||
sym = string(target)
|
||||
st.Down(sym)
|
||||
ca.Push()
|
||||
idx = 0
|
||||
}
|
||||
return sym, idx, nil
|
||||
|
@ -50,12 +50,25 @@ func(vmi *Vm) Reset() {
|
||||
func(vm *Vm) Run(b []byte, ctx context.Context) ([]byte, error) {
|
||||
running := true
|
||||
for running {
|
||||
r, err := vm.st.MatchFlag(state.FLAG_TERMINATE, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if r {
|
||||
log.Printf("terminate set! bailing!")
|
||||
return []byte{}, nil
|
||||
}
|
||||
_, err = vm.st.SetFlag(state.FLAG_DIRTY)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
op, bb, err := opSplit(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
b = bb
|
||||
log.Printf("execute code %x (%s) %x", op, OpcodeString[op], b)
|
||||
log.Printf("state: %v", vm.st)
|
||||
switch op {
|
||||
case CATCH:
|
||||
b, err = vm.RunCatch(b, ctx)
|
||||
@ -112,20 +125,20 @@ func(vm *Vm) RunDeadCheck(b []byte, ctx context.Context) ([]byte, error) {
|
||||
if len(b) > 0 {
|
||||
return b, nil
|
||||
}
|
||||
log.Printf("no code remaining, let's check if we terminate")
|
||||
r, err := vm.st.MatchFlag(state.FLAG_TERMINATE, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if r {
|
||||
log.Printf("Terminate found!!")
|
||||
return b, nil
|
||||
}
|
||||
log.Printf("no code remaining but not terminating")
|
||||
location, _ := vm.st.Where()
|
||||
if location == "" {
|
||||
return b, fmt.Errorf("dead runner with no current location")
|
||||
}
|
||||
b = NewLine(nil, MOVE, []string{"_catch"}, nil, nil)
|
||||
log.Printf("code is now %x", b)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@ -138,7 +151,6 @@ func(vm *Vm) RunMap(b []byte, ctx context.Context) ([]byte, error) {
|
||||
|
||||
// RunMap executes the CATCH opcode
|
||||
func(vm *Vm) RunCatch(b []byte, ctx context.Context) ([]byte, error) {
|
||||
log.Printf("zzz %x", b)
|
||||
sym, sig, mode, b, err := ParseCatch(b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
@ -251,14 +263,22 @@ func(vm *Vm) RunInCmp(b []byte, ctx context.Context) ([]byte, error) {
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
log.Printf("sym is %s", sym)
|
||||
if sym == "*" {
|
||||
log.Printf("input wildcard match ('%s'), target '%s'", input, target)
|
||||
} else {
|
||||
if sym != string(input) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
log.Printf("input match for '%s', target '%s'", input, target)
|
||||
_, err = vm.st.SetFlag(state.FLAG_INMATCH)
|
||||
}
|
||||
|
||||
target, _, err = applyTarget([]byte(target), vm.st, ctx)
|
||||
_, err = vm.st.SetFlag(state.FLAG_INMATCH)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
|
||||
target, _, err = applyTarget([]byte(target), vm.st, vm.ca, ctx)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
@ -330,6 +350,13 @@ func(vm *Vm) RunMPrev(b []byte, ctx context.Context) ([]byte, error) {
|
||||
}
|
||||
|
||||
func(vm *Vm) Render() (string, error) {
|
||||
changed, err := vm.st.ResetFlag(state.FLAG_DIRTY)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !changed {
|
||||
log.Printf("Render called when not dirty, please investigate.")
|
||||
}
|
||||
sym, idx := vm.st.Where()
|
||||
r, err := vm.pg.Render(sym, idx)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user