func createMock(fn *ssa.Function, t types.Type, s string) store.Key {
	return mockValue{
		parent: fn,
		typ:    t,
		desc:   s,
	}
}
createMock returns a new mockValue.
package funcs
import (
	"bytes"
	"fmt"
	"go/token"
	"go/types"
	"log"
	"github.com/nickng/gospal/store"
	"golang.org/x/tools/go/ssa"
)
type Call struct {
	def        *Definition  
	Parameters []store.Key  
	Args       []store.Key  
	Returns    []store.Key  
}
func MakeCall(d *Definition, call *ssa.CallCommon, ret ssa.Value) *Call {
	c := Call{def: d}
	if call != nil {
		c.Args = getArgs(call)
		if len(c.Args) != d.NParam {
			log.Fatalf("Mismatched argument(%d)/parameter(%d)\n\t%s\n\t%s",
				len(c.Args), d.NParam,
				d.Function.Prog.Fset.Position(call.Pos()).String(),
				d.Function.Prog.Fset.Position(d.Function.Pos()).String())
		}
		if len(d.bindings) != d.NFreeVar {
			log.Printf("Mismatched capture(%d)/binding(%d)\n\t%s\n\t%s",
				len(d.bindings), d.NFreeVar,
				d.Function.Prog.Fset.Position(call.Pos()).String(),
				d.Function.Prog.Fset.Position(d.Function.Pos()).String())
			return nil
		}
	} else {
		c.Args = getFakeArgs(d.Function)
	}
	c.Parameters = make([]store.Key, d.NParam+d.NFreeVar+d.NReturn)
	for i, arg := range c.Args {
		c.Parameters[i] = arg
	}
	for i, binding := range d.bindings {
		c.Parameters[d.NParam+i] = store.Key(binding)
	}
	switch d.NReturn {
	case 0:
	case 1:
		if ret != nil {
			c.Parameters[d.NParam+d.NFreeVar] = ret
		} else {
			c.Parameters[d.NParam+d.NFreeVar] = store.Unused{store.MockKey{
				Description: "Unused_RetVal",
				Typ:         d.Function.Signature.Results().At(0).Type(),
				SrcPos:      d.Function.Pos(),
			}}
		}
	default:
		retvals := make([]store.Key, d.NReturn)
		if ret != nil {
			for _, instr := range *ret.Referrers() {
				switch instr := instr.(type) {
				case *ssa.Extract:
					if instr.Tuple != ret {
						log.Fatal("Return values:", ret.Name(), "is not a tuple")
					}
					c.Parameters[d.NParam+d.NFreeVar+instr.Index] = instr
					retvals[instr.Index] = instr
				case *ssa.DebugRef:
				}
			}
		}
		for i, retval := range retvals {
			if retval == nil {
				c.Parameters[d.NParam+d.NFreeVar+i] = store.Unused{store.MockKey{
					Description: "Unused_RetVal",
					Typ:         d.Function.Signature.Results().At(i).Type(),
					SrcPos:      d.Function.Pos(),
				}}
			}
		}
	}
	return &c
}
func (c *Call) Definition() *Definition {
	return c.def
}
func (c *Call) Param(i int) store.Key   { return c.Parameters[i] }
func (c *Call) Bind(i int) store.Key    { return c.Parameters[c.NParam()+i] }
func (c *Call) Return(i int) store.Key  { return c.Parameters[c.NParam()+c.NBind()+i] }
func (c *Call) Function() *ssa.Function { return c.def.Function }
func (c *Call) NParam() int             { return c.def.NParam }
func (c *Call) NBind() int              { return c.def.NFreeVar }
func (c *Call) NReturn() int            { return c.def.NReturn }
func (c *Call) UniqName() string {
	return c.def.UniqName()
}
func (c *Call) String() string {
	var buf bytes.Buffer
	buf.WriteString(fmt.Sprintf("funccall(%d): ", len(c.Parameters)))
	buf.Write(c.Definition().getName())
	buf.WriteRune(' ')
	for i := 0; i < c.NParam(); i++ {  
		if i > 0 {
			buf.WriteString(", ")
		}
		p := c.Parameters[i]
		buf.WriteString(fmt.Sprintf("%s:%v", p.Name(), p.Type()))
	}
	if c.def.IsVararg {
		buf.WriteRune('…')
	}
	for i := 0; i < c.NBind(); i++ {  
		if i > 0 || c.NParam() > 0 {
			buf.WriteString(", ")
		}
		b := c.Bind(i)
		buf.WriteString(fmt.Sprintf("%s:%v", b.Name(), b.Type()))
	}
	if c.NReturn() > 0 {
		buf.WriteString(" ⇒ {")
		for i := 0; i < c.NReturn(); i++ {
			if i > 0 {
				buf.WriteString(", ")
			}
			retval := c.Return(i)
			buf.WriteString(fmt.Sprintf("%s:%v", retval.Name(), retval.Type()))
		}
		buf.WriteRune('}')
	}
	return buf.String()
}
func getArgs(call *ssa.CallCommon) []store.Key {
	if !call.IsInvoke() {  
		switch call.Value.(type) {
		case *ssa.Function, *ssa.MakeClosure:
		case *ssa.Builtin:
		default:
		}
		nArg := len(call.Args)
		args := make([]store.Key, nArg)
		for i, arg := range call.Args {
			args[i] = store.Key(arg)
		}
		return args
	}
	nArg := len(call.Args) + 1
	args := make([]store.Key, nArg)
	args[0] = call.Value
	for i, arg := range call.Args {
		args[i+1] = arg
	}
	return args
}
func getFakeArgs(fn *ssa.Function) []store.Key {
	if sigParam := fn.Signature.Params(); sigParam != nil {
		nArg := sigParam.Len()
		args := make([]store.Key, nArg)
		for i, arg := range fn.Params {
			args[i] = createMock(fn, arg.Type(), "arg")
		}
		return args
	}
	return []store.Key{}
}
type mockValue struct {
	parent *ssa.Function  
	typ    types.Type     
	desc   string         
}