diff options
| author | Marc Vertes <mvertes@free.fr> | 2023-09-04 16:58:15 +0200 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2023-09-04 16:58:15 +0200 |
| commit | 4241593b42bffac2f8fcb63f1e88621fe025e360 (patch) | |
| tree | 48680879982947524e1b028e179608bb5cbcda23 /codegen/compiler.go | |
| parent | 8feddd9b3eefb920c4a0c7a5b4c3b8ae160f3c71 (diff) | |
codegen: add interpreter tests
Also simplify project structure. The executable is now produced in
the root directory. Work in progress.
Diffstat (limited to 'codegen/compiler.go')
| -rw-r--r-- | codegen/compiler.go | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/codegen/compiler.go b/codegen/compiler.go index 3952166..30fc070 100644 --- a/codegen/compiler.go +++ b/codegen/compiler.go @@ -2,6 +2,7 @@ package codegen import ( "fmt" + "log" "strings" "github.com/gnolang/parscan/parser" @@ -84,8 +85,14 @@ func (c *Compiler) CodeGen(node *parser.Node) (err error) { c.Emit(n, vm1.Assign, int64(l)) case parser.DeclFunc: + fun := frameNode[len(frameNode)-1] + if len(fun.Child) == 3 { // no return values + if c.Code[len(c.Code)-1][1] != vm1.Return { + c.Emit(n, vm1.Return, 0, int64(len(fun.Child[1].Child))) + } + } scope = popScope(scope) - fnote = notes[frameNode[len(frameNode)-1]] + fnote = notes[fun] case parser.Ident: ident := n.Content() @@ -121,7 +128,15 @@ func (c *Compiler) CodeGen(node *parser.Node) (err error) { case parser.StmtReturn: fun := frameNode[len(frameNode)-1] - c.Emit(n, vm1.Return, int64(len(n.Child)), int64(len(fun.Child[1].Child))) + nret := 0 + if len(fun.Child) > 3 { + if ret := fun.Child[2]; ret.Kind == parser.BlockParen { + nret = len(ret.Child) + } else { + nret = 1 + } + } + c.Emit(n, vm1.Return, int64(nret), int64(len(fun.Child[1].Child))) case parser.BlockStmt: nd.ipend = len(c.Code) @@ -151,6 +166,17 @@ func (c *Compiler) CodeGen(node *parser.Node) (err error) { } return true }) + + log.Println("main:", c.symbols["main"]) + if s, _, ok := c.getSym("main", ""); ok { + if i, ok := c.codeIndex(s); ok { + // Internal call is always relative to instruction pointer. + c.Emit(nil, vm1.Call, int64(i-len(c.Code))) + c.Entry = len(c.Code) - 1 + } + log.Println(vm1.Disassemble(c.Code)) + } + return } @@ -168,7 +194,11 @@ func (c *Compiler) addSym(v any, name string, local bool, n *parser.Node) int { } func (c *Compiler) Emit(n *parser.Node, op ...int64) int { - op = append([]int64{int64(n.Pos())}, op...) + var pos int64 + if n != nil { + pos = int64(n.Pos()) + } + op = append([]int64{pos}, op...) l := len(c.Code) c.Code = append(c.Code, op) return l |
