Add cache push and pop in vm target processingC

This commit is contained in:
lash 2023-04-10 09:05:48 +01:00
parent da45ee783b
commit 602ca92b6a
Signed by untrusted user who does not match committer: lash
GPG Key ID: 21D2E7BB88C2A746
5 changed files with 55 additions and 12 deletions

View File

@ -3,4 +3,5 @@ package state
const (
FLAG_INMATCH = 1
FLAG_TERMINATE = 2
FLAG_DIRTY = 4
)

View File

@ -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, "/"))
}

View File

@ -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"

View File

@ -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

View File

@ -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 {