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 (
|
const (
|
||||||
FLAG_INMATCH = 1
|
FLAG_INMATCH = 1
|
||||||
FLAG_TERMINATE = 2
|
FLAG_TERMINATE = 2
|
||||||
|
FLAG_DIRTY = 4
|
||||||
)
|
)
|
||||||
|
@ -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, "/"))
|
||||||
|
}
|
||||||
|
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.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"
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user