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 ( const (
FLAG_INMATCH = 1 FLAG_INMATCH = 1
FLAG_TERMINATE = 2 FLAG_TERMINATE = 2
FLAG_DIRTY = 4
) )

View File

@ -3,6 +3,7 @@ package state
import ( import (
"fmt" "fmt"
"log" "log"
"strings"
) )
// State holds the command stack, error condition of a unique execution session. // 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 { if l == 0 {
return "", fmt.Errorf("exit called beyond top frame") return "", fmt.Errorf("exit called beyond top frame")
} }
log.Printf("execpath before %v", st.execPath)
st.execPath = st.execPath[:l-1] st.execPath = st.execPath[:l-1]
sym := "" sym := ""
if len(st.execPath) > 0 { if len(st.execPath) > 0 {
sym = st.execPath[len(st.execPath)-1] sym = st.execPath[len(st.execPath)-1]
} }
st.sizeIdx = 0 st.sizeIdx = 0
log.Printf("execpath after %v", st.execPath)
return sym, nil return sym, nil
} }
@ -316,3 +319,7 @@ func(st *State) SetInput(input []byte) error {
// Reset to initial state (start navigation over). // Reset to initial state (start navigation over).
func(st *State) Reset() { 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.HALT, nil, nil, nil)
b = vm.NewLine(b, vm.INCMP, []string{"0", "_"}, 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.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 := make(map[string]string)
data["inky"] = "one" data["inky"] = "one"
@ -86,7 +86,7 @@ func bar() error {
b := []byte{} b := []byte{}
b = vm.NewLine(b, vm.LOAD, []string{"pinky"}, []byte{0}, nil) 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.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" tpl := "this is bar - an end node"
@ -110,7 +110,7 @@ func defaultCatch() error {
b := []byte{} b := []byte{}
b = vm.NewLine(b, vm.MOUT, []string{"0", "back"}, nil, nil) 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.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" tpl := "invalid input"

View File

@ -5,13 +5,14 @@ import (
"fmt" "fmt"
"regexp" "regexp"
"git.defalsify.org/festive/cache"
"git.defalsify.org/festive/state" "git.defalsify.org/festive/state"
) )
var ( var (
inputRegexStr = "^[a-zA-Z0-9].*$" inputRegexStr = "^[a-zA-Z0-9].*$"
inputRegex = regexp.MustCompile(inputRegexStr) inputRegex = regexp.MustCompile(inputRegexStr)
ctrlRegexStr = "^[><_]$" ctrlRegexStr = "^[><_^]$"
ctrlRegex = regexp.MustCompile(ctrlRegexStr) ctrlRegex = regexp.MustCompile(ctrlRegexStr)
symRegexStr = "^[a-zA-Z0-9][a-zA-Z0-9_]+$" symRegexStr = "^[a-zA-Z0-9][a-zA-Z0-9_]+$"
symRegex = regexp.MustCompile(symRegexStr) 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, // 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 var err error
sym, idx := st.Where() sym, idx := st.Where()
@ -102,6 +103,7 @@ func applyTarget(target []byte, st *state.State, ctx context.Context) (string, u
switch target[0] { switch target[0] {
case '_': case '_':
sym, err = st.Up() sym, err = st.Up()
ca.Pop()
if err != nil { if err != nil {
return sym, idx, err return sym, idx, err
} }
@ -115,9 +117,15 @@ func applyTarget(target []byte, st *state.State, ctx context.Context) (string, u
if err != nil { if err != nil {
return sym, idx, err return sym, idx, err
} }
case '^':
_, err := st.SetFlag(state.FLAG_TERMINATE)
if err != nil {
return sym, idx, err
}
default: default:
sym = string(target) sym = string(target)
st.Down(sym) st.Down(sym)
ca.Push()
idx = 0 idx = 0
} }
return sym, idx, nil 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) { func(vm *Vm) Run(b []byte, ctx context.Context) ([]byte, error) {
running := true running := true
for running { 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) op, bb, err := opSplit(b)
if err != nil { if err != nil {
return b, err return b, err
} }
b = bb b = bb
log.Printf("execute code %x (%s) %x", op, OpcodeString[op], b) log.Printf("execute code %x (%s) %x", op, OpcodeString[op], b)
log.Printf("state: %v", vm.st)
switch op { switch op {
case CATCH: case CATCH:
b, err = vm.RunCatch(b, ctx) 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 { if len(b) > 0 {
return b, nil return b, nil
} }
log.Printf("no code remaining, let's check if we terminate")
r, err := vm.st.MatchFlag(state.FLAG_TERMINATE, false) r, err := vm.st.MatchFlag(state.FLAG_TERMINATE, false)
if err != nil { if err != nil {
panic(err) panic(err)
} }
if r { if r {
log.Printf("Terminate found!!")
return b, nil return b, nil
} }
log.Printf("no code remaining but not terminating")
location, _ := vm.st.Where() location, _ := vm.st.Where()
if location == "" { if location == "" {
return b, fmt.Errorf("dead runner with no current location") return b, fmt.Errorf("dead runner with no current location")
} }
b = NewLine(nil, MOVE, []string{"_catch"}, nil, nil) b = NewLine(nil, MOVE, []string{"_catch"}, nil, nil)
log.Printf("code is now %x", b)
return b, nil return b, nil
} }
@ -138,7 +151,6 @@ func(vm *Vm) RunMap(b []byte, ctx context.Context) ([]byte, error) {
// RunMap executes the CATCH opcode // RunMap executes the CATCH opcode
func(vm *Vm) RunCatch(b []byte, ctx context.Context) ([]byte, error) { func(vm *Vm) RunCatch(b []byte, ctx context.Context) ([]byte, error) {
log.Printf("zzz %x", b)
sym, sig, mode, b, err := ParseCatch(b) sym, sig, mode, b, err := ParseCatch(b)
if err != nil { if err != nil {
return b, err return b, err
@ -251,14 +263,22 @@ func(vm *Vm) RunInCmp(b []byte, ctx context.Context) ([]byte, error) {
if err != nil { if err != nil {
return b, err return b, err
} }
if sym != string(input) { log.Printf("sym is %s", sym)
return b, nil 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)
} }
log.Printf("input match for '%s', target '%s'", input, target)
_, err = vm.st.SetFlag(state.FLAG_INMATCH) _, err = vm.st.SetFlag(state.FLAG_INMATCH)
if err != nil {
return b, err
}
target, _, err = applyTarget([]byte(target), vm.st, ctx) target, _, err = applyTarget([]byte(target), vm.st, vm.ca, ctx)
if err != nil { if err != nil {
return b, err return b, err
} }
@ -330,6 +350,13 @@ func(vm *Vm) RunMPrev(b []byte, ctx context.Context) ([]byte, error) {
} }
func(vm *Vm) Render() (string, 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() sym, idx := vm.st.Where()
r, err := vm.pg.Render(sym, idx) r, err := vm.pg.Render(sym, idx)
if err != nil { if err != nil {