summaryrefslogtreecommitdiff
path: root/codegen/expression.go
blob: b73f4da87bba7628049000b17d8ba43a72c5d05d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
	}
}