(node *ast.CallNode)
| 776 | } |
| 777 | |
| 778 | func (c *compiler) CallNode(node *ast.CallNode) { |
| 779 | fn := node.Callee.Type() |
| 780 | if fn.Kind() == reflect.Func { |
| 781 | fnInOffset := 0 |
| 782 | fnNumIn := fn.NumIn() |
| 783 | switch callee := node.Callee.(type) { |
| 784 | case *ast.MemberNode: |
| 785 | if prop, ok := callee.Property.(*ast.StringNode); ok { |
| 786 | if _, ok = callee.Node.Type().MethodByName(prop.Value); ok && callee.Node.Type().Kind() != reflect.Interface { |
| 787 | fnInOffset = 1 |
| 788 | fnNumIn-- |
| 789 | } |
| 790 | } |
| 791 | case *ast.IdentifierNode: |
| 792 | if t, ok := c.config.Env.MethodByName(c.ntCache, callee.Value); ok && t.Method { |
| 793 | fnInOffset = 1 |
| 794 | fnNumIn-- |
| 795 | } |
| 796 | } |
| 797 | for i, arg := range node.Arguments { |
| 798 | c.compile(arg) |
| 799 | |
| 800 | var in reflect.Type |
| 801 | if fn.IsVariadic() && i >= fnNumIn-1 { |
| 802 | in = fn.In(fn.NumIn() - 1).Elem() |
| 803 | } else { |
| 804 | in = fn.In(i + fnInOffset) |
| 805 | } |
| 806 | |
| 807 | c.derefParam(in, arg) |
| 808 | } |
| 809 | } else { |
| 810 | for _, arg := range node.Arguments { |
| 811 | c.compile(arg) |
| 812 | } |
| 813 | } |
| 814 | |
| 815 | if ident, ok := node.Callee.(*ast.IdentifierNode); ok { |
| 816 | if c.config != nil { |
| 817 | if fn, ok := c.config.Functions[ident.Value]; ok { |
| 818 | c.emitFunction(fn, len(node.Arguments)) |
| 819 | return |
| 820 | } |
| 821 | } |
| 822 | } |
| 823 | c.compile(node.Callee) |
| 824 | |
| 825 | if c.config != nil { |
| 826 | isMethod, _, _ := checker.MethodIndex(c.ntCache, c.config.Env, node.Callee) |
| 827 | if index, ok := checker.TypedFuncIndex(node.Callee.Type(), isMethod); ok { |
| 828 | c.emit(OpCallTyped, index) |
| 829 | return |
| 830 | } else if checker.IsFastFunc(node.Callee.Type(), isMethod) { |
| 831 | c.emit(OpCallFast, len(node.Arguments)) |
| 832 | } else { |
| 833 | c.emit(OpCall, len(node.Arguments)) |
| 834 | } |
| 835 | } else { |
no test coverage detected