From 851c793da43be9e4d3319afe440d603c85834045 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Thu, 31 Aug 2023 17:53:54 +0200 Subject: codegen: fix interpreter re-entrance So multiple successive incremental Evals function correctly. Also improve the following: - Apply the same Eval API to vm0 and vm1 - parser: dot diagram display is now synchronous - codegen: outsource complex code generation for readability - vm1: Pop take the number of values to pop as operand --- codegen/interpreter.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'codegen/interpreter.go') diff --git a/codegen/interpreter.go b/codegen/interpreter.go index b26b403..a3268d9 100644 --- a/codegen/interpreter.go +++ b/codegen/interpreter.go @@ -19,24 +19,30 @@ func NewInterpreter(p *parser.Parser) *Interpreter { return &Interpreter{p, NewCompiler(), &vm1.Machine{}} } -func (i *Interpreter) Eval(src string) (err error) { +func (i *Interpreter) Eval(src string) (res any, err error) { n := &parser.Node{} if n.Child, err = i.Parse(src); err != nil { - return err + return res, err } if debug { n.Dot(os.Getenv("DOT"), "") } - offset := len(i.Code) - i.PopExit() // Remove last exit from previous run. + codeOffset := len(i.Code) + dataOffset := 0 + if codeOffset > 0 { + // All data must be copied to the VM the first time only (re-entrance). + dataOffset = len(i.Data) + } + i.PopExit() // Remove last exit from previous run (re-entrance). if err = i.CodeGen(n); err != nil { - return err + return res, err } - i.Push(i.Data...) - i.PushCode(i.Code[offset:]...) + i.Push(i.Data[dataOffset:]...) + i.PushCode(i.Code[codeOffset:]...) i.PushCode([]int64{0, vm1.Exit}) - i.SetIP(max(offset, i.Entry)) - return i.Run() + i.SetIP(max(codeOffset, i.Entry)) + err = i.Run() + return i.Top(), err } func max(a, b int) int { -- cgit v1.2.3