diff options
| author | Marc Vertes <mvertes@free.fr> | 2023-08-31 17:53:54 +0200 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2023-08-31 17:53:54 +0200 |
| commit | 851c793da43be9e4d3319afe440d603c85834045 (patch) | |
| tree | fd4b3d3812f5743213b5849858c459c8196dbf7f /codegen/expression.go | |
| parent | 0f4bfe6e70263fbeb580014b62632f403b29b414 (diff) | |
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
Diffstat (limited to 'codegen/expression.go')
| -rw-r--r-- | codegen/expression.go | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/codegen/expression.go b/codegen/expression.go new file mode 100644 index 0000000..b73f4da --- /dev/null +++ b/codegen/expression.go @@ -0,0 +1,41 @@ +package codegen + +import ( + "fmt" + "reflect" + + "github.com/gnolang/parscan/parser" + "github.com/gnolang/parscan/vm1" +) + +func postCallExpr(x extNode) error { + switch x.Child[0].Kind { + case parser.Ident: + var numOut int + s, _, ok := x.getSym(x.Child[0].Content(), "") + if !ok { + return fmt.Errorf("invalid symbol %s", x.Child[0].Content()) + } + if i, ok := x.codeIndex(s); ok { + // Internal call is always relative to instruction pointer. + x.Emit(x.Node, vm1.Call, int64(i-len(x.Code))) + } else { + // External call, using absolute addr in symtable. + x.Emit(x.Node, vm1.CallX, int64(len(x.Child[1].Child))) + numOut = reflect.TypeOf(x.Data[s.index]).NumOut() + } + if !usedRet(x.anc) { + x.Emit(x.Node, vm1.Pop, int64(numOut)) + } + } + return nil +} + +func usedRet(n *parser.Node) bool { + switch n.Kind { + case parser.Undefined, parser.StmtBloc: + return false + default: + return true + } +} |
