go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

commit 8d7e8de76bed4a06c122ca79269d460b9bb5dc99
parent 683015d4df80721a2f209979338f383ee3678db9
Author: lash <dev@holbrook.no>
Date:   Wed, 18 Dec 2024 18:21:35 +0000

Prepare VM parser for pluggable handler functions

Diffstat:
Adebug/node.go | 34++++++++++++++++++++++++++++++++++
Adev/walk/main.go | 47+++++++++++++++++++++++++++++++++++++++++++++++
Mvm/debug.go | 245+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
3 files changed, 252 insertions(+), 74 deletions(-)

diff --git a/debug/node.go b/debug/node.go @@ -0,0 +1,34 @@ +package debug + +type Node struct { + Name string + Description string + conn []string +} + +var ( + NodeIndex = make(map[string]Node) +) + +func (n *Node) haveConn(peer string) bool { + var v string + for _, v = range(n.conn) { + if peer == v { + return true + } + } + return false +} + +func (n *Node) Connect(peer Node) bool { + var ok bool + _, ok = NodeIndex[peer.Name] + if !ok { + NodeIndex[peer.Name] = peer + } + if n.haveConn(peer.Name) { + return false + } + n.conn = append(n.conn, peer.Name) + return true +} diff --git a/dev/walk/main.go b/dev/walk/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + + "git.defalsify.org/vise.git/vm" + "git.defalsify.org/vise.git/resource" + fsdb "git.defalsify.org/vise.git/db/fs" + +) + +func main() { + var dir string + var root string + + flag.StringVar(&dir, "d", ".", "resource dir to read from") + flag.StringVar(&root, "root", "root", "entry point symbol") + flag.Parse() + fmt.Fprintf(os.Stderr, "starting session at symbol '%s' using resource dir: %s\n", root, dir) + + ctx := context.Background() + rsStore := fsdb.NewFsDb() + err := rsStore.Connect(ctx, dir) + if err != nil { + fmt.Fprintf(os.Stderr, "resource db connect error: %v", err) + os.Exit(1) + } + + rs := resource.NewDbResource(rsStore) + //rs = rs.With(db.DATATYPE_STATICLOAD) + + ph := vm.NewParseHandler().WithDefaultHandlers().WithWriter(os.Stdout) + + b, err := rs.GetCode(ctx, root) + if err != nil { + panic(err) + } + + n, err := ph.ParseAll(b) + if err != nil { + panic(err) + } + _ = n +} diff --git a/vm/debug.go b/vm/debug.go @@ -6,10 +6,141 @@ import ( "io" ) +type ParseHandler struct { + Catch func(string, uint32, bool) error + Croak func(uint32, bool) error + Load func(string, uint32) error + Reload func(string) error + Map func(string) error + Move func(string) error + Halt func() error + InCmp func(string, string) error + MOut func(string, string) error + MSink func() error + MNext func(string, string) error + MPrev func(string, string) error + cur string + n int + w io.Writer +} + +func NewParseHandler() *ParseHandler { + return &ParseHandler{} +} + +func (ph *ParseHandler) Length() int { + return ph.n +} + +func (ph *ParseHandler) WithDefaultHandlers() *ParseHandler { + ph.Catch = ph.catch + ph.Croak = ph.croak + ph.Load = ph.load + ph.Reload = ph.reload + ph.Map = ph.maph + ph.Move = ph.move + ph.Halt = ph.halt + ph.InCmp = ph.incmp + ph.MOut = ph.mout + ph.MSink = ph.msink +// ph.MNext = ph.mnext +// ph.MPrev = ph.mprev + return ph +} + +func (ph *ParseHandler) WithWriter(w io.Writer) *ParseHandler { + ph.w = w + return ph +} + +// TODO: output op sym +func (ph *ParseHandler) flush() error { + if ph.w != nil { + n, err := io.WriteString(ph.w, ph.cur) + if err != nil { + return err + } + ph.n += n + ph.cur = "" + //logg.Tracef("instruction debug write", "bytes", n, "instruction", s) + logg.Tracef("instruction debug write", "bytes", n) + } + return nil +} + +func (ph *ParseHandler) catch(sym string, flag uint32, inv bool) error { + s := OpcodeString[CATCH] + vv := 0 + if inv { + vv = 1 + } + ph.cur = fmt.Sprintf("%s %s %v %v\n", s, sym, flag, vv) + return nil +} + +func (ph *ParseHandler) croak(flag uint32, inv bool) error { + s := OpcodeString[CROAK] + vv := 0 + if inv { + vv = 1 + } + ph.cur = fmt.Sprintf("%s %v %v\n", s, flag, vv) + return nil +} + +func (ph *ParseHandler) load(sym string, length uint32) error { + s := OpcodeString[LOAD] + ph.cur = fmt.Sprintf("%s %s %v\n", s, sym, length) + return nil +} + +func (ph *ParseHandler) reload(sym string) error { + s := OpcodeString[RELOAD] + ph.cur = fmt.Sprintf("%s %s\n", s, sym) + return nil +} + +func (ph *ParseHandler) maph(sym string) error { + s := OpcodeString[MAP] + ph.cur = fmt.Sprintf("%s %s\n", s, sym) + return nil +} + +func (ph *ParseHandler) move(sym string) error { + s := OpcodeString[MOVE] + ph.cur = fmt.Sprintf("%s %s\n", s, sym) + return nil +} + +func (ph *ParseHandler) incmp(sym string, sel string) error { + s := OpcodeString[INCMP] + ph.cur = fmt.Sprintf("%s %s %v\n", s, sym, sel) + return nil +} + +func (ph *ParseHandler) halt() error { + s := OpcodeString[HALT] + ph.cur = fmt.Sprintf("%s\n", s) + return nil +} + +func (ph *ParseHandler) msink() error { + s := OpcodeString[MSINK] + ph.cur = fmt.Sprintf("%s\n", s) + return nil +} + +func (ph *ParseHandler) mout(sym string, sel string) error { + s := OpcodeString[MOUT] + ph.cur = fmt.Sprintf("%s %s %v\n", s, sym, sel) + return nil +} + // ToString verifies all instructions in bytecode and returns an assmebly code instruction for it. -func ToString(b []byte) (string, error) { +func (ph *ParseHandler) ToString(b []byte) (string, error) { buf := bytes.NewBuffer(nil) - n, err := ParseAll(b, buf) + ph = ph.WithWriter(buf) + n, err := ph.ParseAll(b) if err != nil { return "", err } @@ -24,20 +155,18 @@ func ToString(b []byte) (string, error) { // Bytecode is consumed (and written) one instruction at a time. // // It fails on any parse error encountered before the bytecode EOF is reached. -func ParseAll(b []byte, w io.Writer) (int, error) { +func (ph *ParseHandler) ParseAll(b []byte) (int, error) { var s string - var rs string - var rn int running := true for running { op, bb, err := opSplit(b) b = bb if err != nil { - return rn, err + return ph.Length(), err } s = OpcodeString[op] if s == "" { - return rn, fmt.Errorf("unknown opcode: %v", op) + return ph.Length(), fmt.Errorf("unknown opcode: %v", op) } switch op { @@ -45,120 +174,88 @@ func ParseAll(b []byte, w io.Writer) (int, error) { r, n, m, bb, err := ParseCatch(b) b = bb if err == nil { - if w != nil { - vv := 0 - if m { - vv = 1 - } - if w != nil { - //rs = fmt.Sprintf("%s %s %v %v # invertmatch=%v\n", s, r, n, vv, m) - rs = fmt.Sprintf("%s %s %v %v\n", s, r, n, vv) - } - } + err = ph.Catch(r, n, m) } case CROAK: n, m, bb, err := ParseCroak(b) b = bb if err == nil { - if w != nil { - vv := 0 - if m { - vv = 1 - } - //rs = fmt.Sprintf("%s %v %v # invertmatch=%v\n", s, n, vv, m) - rs = fmt.Sprintf("%s %v %v\n", s, n, vv) - } + err = ph.Croak(n, m) } case LOAD: r, n, bb, err := ParseLoad(b) b = bb if err == nil { - if w != nil { - rs = fmt.Sprintf("%s %s %v\n", s, r, n) - } + err = ph.Load(r, n) } case RELOAD: r, bb, err := ParseReload(b) b = bb if err == nil { - if w != nil { - rs = fmt.Sprintf("%s %s\n", s, r) - } + err = ph.Reload(r) } case MAP: r, bb, err := ParseMap(b) b = bb if err == nil { - if w != nil { - rs = fmt.Sprintf("%s %s\n", s, r) - } + err = ph.Map(r) } case MOVE: r, bb, err := ParseMove(b) b = bb if err == nil { - if w != nil { - rs = fmt.Sprintf("%s %s\n", s, r) - } + err = ph.Move(r) } case INCMP: r, v, bb, err := ParseInCmp(b) b = bb if err == nil { - if w != nil { - rs = fmt.Sprintf("%s %s %s\n", s, r, v) - } + err = ph.InCmp(r, v) } case HALT: b, err = ParseHalt(b) - rs = "HALT\n" + if err != nil { + err = ph.Halt() + } case MSINK: b, err = ParseMSink(b) - rs = "MSINK\n" + if err != nil { + err = ph.MSink() + } case MOUT: r, v, bb, err := ParseMOut(b) b = bb if err == nil { - if w != nil { - //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) - rs = fmt.Sprintf("%s %s %s\n", s, r, v) - } - } - case MNEXT: - r, v, bb, err := ParseMNext(b) - b = bb - if err == nil { - if w != nil { - //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) - rs = fmt.Sprintf("%s %s %s\n", s, r, v) - } - } - case MPREV: - r, v, bb, err := ParseMPrev(b) - b = bb - if err == nil { - if w != nil { - //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) - rs = fmt.Sprintf("%s %s %s\n", s, r, v) - } + err = ph.MOut(r, v) } +// case MNEXT: +// r, v, bb, err := ParseMNext(b) +// b = bb +// if err == nil { +// if w != nil { +// //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) +// rs = fmt.Sprintf("%s %s %s\n", s, r, v) +// } +// } +// case MPREV: +// r, v, bb, err := ParseMPrev(b) +// b = bb +// if err == nil { +// if w != nil { +// //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) +// rs = fmt.Sprintf("%s %s %s\n", s, r, v) +// } +// } } if err != nil { - return rn, err - } - if w != nil { - n, err := io.WriteString(w, rs) - if err != nil { - return rn, err - } - rn += n - logg.Tracef("instruction debug write", "bytes", n, "instruction", s) + return ph.Length(), err } + ph.flush() //rs += "\n" if len(b) == 0 { running = false } } - return rn, nil + return ph.Length(), nil }