commit 602ca92b6a412f8e10d8f191a1d3c8ef7be3d658
parent da45ee783b8afaff461638549de67b39bed180b8
Author: lash <dev@holbrook.no>
Date: Mon, 10 Apr 2023 09:05:48 +0100
Add cache push and pop in vm target processingC
Diffstat:
5 files changed, 55 insertions(+), 12 deletions(-)
diff --git a/go/state/flag.go b/go/state/flag.go
@@ -3,4 +3,5 @@ package state
const (
FLAG_INMATCH = 1
FLAG_TERMINATE = 2
+ FLAG_DIRTY = 4
)
diff --git a/go/state/state.go b/go/state/state.go
@@ -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, "/"))
+}
diff --git a/go/testdata/testdata.go b/go/testdata/testdata.go
@@ -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"
diff --git a/go/vm/input.go b/go/vm/input.go
@@ -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
diff --git a/go/vm/runner.go b/go/vm/runner.go
@@ -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
}
- if sym != string(input) {
- return b, nil
+ 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)
}
- log.Printf("input match for '%s', target '%s'", input, target)
_, 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 {
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 {