WIP Add termination handler in engine
This commit is contained in:
parent
6325ef4afd
commit
a3073f6189
@ -321,7 +321,6 @@ func(bt *Batcher) MenuExit(w io.Writer) (int, error) {
|
||||
}
|
||||
bt.inMenu = false
|
||||
b := bt.menuProcessor.ToLines()
|
||||
log.Printf("tolines %v", b)
|
||||
return w.Write(b)
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
in = strings.TrimSpace(in)
|
||||
err = en.Exec([]byte(in), ctx)
|
||||
running, err = en.Exec([]byte(in), ctx)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "execution terminated: %v\n", err)
|
||||
os.Exit(1)
|
||||
@ -50,4 +50,5 @@ func main() {
|
||||
en.WriteResult(b)
|
||||
fmt.Println(b.String())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -59,22 +59,38 @@ func(en *Engine) Init(sym string, ctx context.Context) error {
|
||||
// - input is objectively invalid (too long etc)
|
||||
// - no current bytecode is available
|
||||
// - input processing against bytcode failed
|
||||
func (en *Engine) Exec(input []byte, ctx context.Context) error {
|
||||
func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) {
|
||||
err := en.st.SetInput(input)
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
log.Printf("new execution with input '%s' (0x%x)", input, input)
|
||||
code, err := en.st.GetCode()
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
if len(code) == 0 {
|
||||
return fmt.Errorf("no code to execute")
|
||||
return false, fmt.Errorf("no code to execute")
|
||||
}
|
||||
code, err = vm.Run(code, en.st, en.rs, ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
v, err := en.st.MatchFlag(state.FLAG_TERMINATE, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if v {
|
||||
if len(code) > 0 {
|
||||
log.Printf("terminated with code remaining: %x", code)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
en.st.SetCode(code)
|
||||
return err
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// WriteResult writes the output of the last vm execution to the given writer.
|
||||
|
@ -97,7 +97,7 @@ func TestEngineInit(t *testing.T) {
|
||||
}
|
||||
|
||||
input := []byte("1")
|
||||
err = en.Exec(input, ctx)
|
||||
_, err = en.Exec(input, ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -135,6 +135,26 @@ func(st *State) FlagByteSize() uint8 {
|
||||
return uint8(len(st.Flags))
|
||||
}
|
||||
|
||||
// MatchFlag matches the current state of the given flag.
|
||||
//
|
||||
// The flag is specified given its bit index in the bit field.
|
||||
//
|
||||
// If invertMatch is set, a positive result will be returned if the flag is not set.
|
||||
func(st *State) MatchFlag(sig uint32, invertMatch bool) (bool, error) {
|
||||
r, err := st.GetFlag(sig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if invertMatch {
|
||||
if !r {
|
||||
return true, nil
|
||||
}
|
||||
} else if r {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// GetIndex scans a byte slice in same order as in storage, and returns the index of the first set bit.
|
||||
//
|
||||
// If the given byte slice is too small for the bit field bitsize, the check will terminate at end-of-data without error.
|
||||
|
@ -82,7 +82,7 @@ func RunDeadCheck(b []byte, st *state.State, rs resource.Resource, ctx context.C
|
||||
return b, nil
|
||||
}
|
||||
log.Printf("no code remaining, let's check if we terminate")
|
||||
r, err := matchFlag(st, state.FLAG_TERMINATE, false)
|
||||
r, err := st.MatchFlag(state.FLAG_TERMINATE, false)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -114,7 +114,7 @@ func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
r, err := matchFlag(st, sig, mode)
|
||||
r, err := st.MatchFlag(sig, mode)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
@ -132,7 +132,7 @@ func RunCroak(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
r, err := matchFlag(st, sig, mode)
|
||||
r, err := st.MatchFlag(sig, mode)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
|
17
go/vm/vm.go
17
go/vm/vm.go
@ -3,8 +3,6 @@ package vm
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"git.defalsify.org/festive/state"
|
||||
)
|
||||
|
||||
// NewLine creates a new instruction line for the VM.
|
||||
@ -177,21 +175,6 @@ func parseSig(b []byte) (uint32, bool, []byte, error) {
|
||||
return sig, matchmode, b, nil
|
||||
}
|
||||
|
||||
// TODO: move to state
|
||||
func matchFlag(st *state.State, sig uint32, invertMatch bool) (bool, error) {
|
||||
r, err := st.GetFlag(sig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if invertMatch {
|
||||
if !r {
|
||||
return true, nil
|
||||
}
|
||||
} else if r {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// split bytecode into head and b using length-prefixed bitfield
|
||||
func byteSplit(b []byte) ([]byte, []byte, error) {
|
||||
|
Loading…
Reference in New Issue
Block a user