diff options
| author | Marc Vertes <marc.vertes@tendermint.com> | 2023-08-24 09:32:36 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-24 09:32:36 +0200 |
| commit | 00cd63b47c0c32be821f80e006ed08ce57020e15 (patch) | |
| tree | f8952b26e6dd301dfc35df9e0537fb4f92856deb /codegen | |
| parent | c83cdc374f8d50189c2da3460a6db94a4527c1fc (diff) | |
vm1: improve function calling (#6)
The "Enter" instruction has been removed and the frame pointer is
now saved by the "Call" instruction.
The "Return" instruction now takes the number of function input
parameters as the second operand. It's used to return the output
values at the correct place in the caller frame, no matter the
number of input parameters.
The tests and the code generator have been updated accordingly.
Diffstat (limited to 'codegen')
| -rw-r--r-- | codegen/codegen.go | 8 | ||||
| -rw-r--r-- | codegen/codegen_test.go | 13 |
2 files changed, 14 insertions, 7 deletions
diff --git a/codegen/codegen.go b/codegen/codegen.go index 048b20f..d7702cd 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -41,8 +41,7 @@ func (c *Compiler) CodeGen(node *parser.Node) (err error) { switch n.Kind { case parser.FuncDecl: fname := n.Child[0].Content() - i := c.Emit(n, vm1.Enter) - c.AddSym(i, scope+fname, false) + c.AddSym(len(c.Code), scope+fname, false) scope = pushScope(scope, fname) frameNode = append(frameNode, n) fnote = notes[n] @@ -124,7 +123,8 @@ func (c *Compiler) CodeGen(node *parser.Node) (err error) { } case parser.ReturnStmt: - c.Emit(n, vm1.Return, int64(len(n.Child))) + fun := frameNode[len(frameNode)-1] + c.Emit(n, vm1.Return, int64(len(n.Child)), int64(len(fun.Child[1].Child))) case parser.StmtBloc: nd.ipend = len(c.Code) @@ -144,7 +144,7 @@ func (c *Compiler) CodeGen(node *parser.Node) (err error) { // TODO: Fix this temporary hack to compute an entry point if c.Entry < 0 && len(scope) == 0 && n.Kind != parser.FuncDecl { c.Entry = len(c.Code) - 1 - if c.Code[c.Entry][1] == vm1.Return { + if c.Entry >= 0 && len(c.Code) > c.Entry && c.Code[c.Entry][1] == vm1.Return { c.Entry++ } } diff --git a/codegen/codegen_test.go b/codegen/codegen_test.go index d2f8033..7262ddc 100644 --- a/codegen/codegen_test.go +++ b/codegen/codegen_test.go @@ -16,7 +16,7 @@ func TestCodeGen(t *testing.T) { test := test t.Run("", func(t *testing.T) { c := New() - c.AddSym(fmt.Println, "println") + c.AddSym(fmt.Println, "println", false) n := &parser.Node{} var err error if n.Child, err = golang.GoParser.Parse(test.src); err != nil { @@ -31,6 +31,9 @@ func TestCodeGen(t *testing.T) { } t.Log("data:", c.Data) t.Log("code:", vm1.Disassemble(c.Code)) + if s := vm1.Disassemble(c.Code); s != test.asm { + t.Errorf("got error %#v, want error %#v", s, test.asm) + } }) } } @@ -45,7 +48,11 @@ var tests = []struct { asm: "Dup 0\nDup 1\nCallX 1\n", }, { // #02 src: `a := 2; println(a)`, - asm: "Push 2\nAssign 1\nDup 0\nDup 1\nCallX 1", + asm: "Push 2\nAssign 1\nDup 0\nDup 1\nCallX 1\n", }, { // #03 src: `a := 2; if a < 3 {println(a)}; println("bye")`, -}} + asm: "Push 2\nAssign 1\nDup 1\nPush 3\nLower\nJumpFalse 4\nDup 0\nDup 1\nCallX 1\nDup 0\nDup 2\nCallX 1\n", +}, { // #04 + src: "func add(a int, b int) int { return a + b }", + asm: "Fdup -2\nFdup -3\nAdd\nReturn 1 2\n", +}, {}} |
