func()

in internal/compile/compile.go [1667:1733]


func (fcomp *fcomp) args(call *syntax.CallExpr) (op Opcode, arg uint32) {
	var callmode int
	// Compute the number of each kind of parameter.
	var p, n int // number of  positional, named arguments
	var varargs, kwargs syntax.Expr
	for _, arg := range call.Args {
		if binary, ok := arg.(*syntax.BinaryExpr); ok && binary.Op == syntax.EQ {

			// named argument (name, value)
			fcomp.string(binary.X.(*syntax.Ident).Name)
			fcomp.expr(binary.Y)
			n++
			continue
		}
		if unary, ok := arg.(*syntax.UnaryExpr); ok {
			if unary.Op == syntax.STAR {
				callmode |= 1
				varargs = unary.X
				continue
			} else if unary.Op == syntax.STARSTAR {
				callmode |= 2
				kwargs = unary.X
				continue
			}
		}

		// positional argument
		fcomp.expr(arg)
		p++
	}

	// Python2 and Python3 both permit named arguments
	// to appear both before and after a *args argument:
	//   f(1, 2, x=3, *[4], y=5, **dict(z=6))
	//
	// They also differ in their evaluation order:
	//  Python2: 1 2 3 5 4 6 (*args and **kwargs evaluated last)
	//  Python3: 1 2 4 3 5 6 (positional args evaluated before named args)
	// Starlark-in-Java historically used a third order:
	//  Lexical: 1 2 3 4 5 6 (all args evaluated left-to-right)
	//
	// After discussion in github.com/bazelbuild/starlark#13, the
	// spec now requires Starlark to statically reject named
	// arguments after *args (e.g. y=5), and to use Python2-style
	// evaluation order. This is both easy to implement and
	// consistent with lexical order:
	//
	//   f(1, 2, x=3, *[4], **dict(z=6)) # 1 2 3 4 6

	// *args
	if varargs != nil {
		fcomp.expr(varargs)
	}

	// **kwargs
	if kwargs != nil {
		fcomp.expr(kwargs)
	}

	// TODO(adonovan): avoid this with a more flexible encoding.
	if p >= 256 || n >= 256 {
		// resolve already checked this; should be unreachable
		panic("too many arguments in call")
	}

	return CALL + Opcode(callmode), uint32(p<<8 | n)
}