Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: document call argument evaluation order #118

Merged
merged 1 commit into from
Jan 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,13 @@ same name, such as `f(x=1, x=2)`. A call that provides a `**kwargs`
argument may yet have two values for the same name, such as
`f(x=1, **dict(x=2))`. This results in a dynamic error.

Function arguments are evaluated in the order they appear in the call.
<!-- see https://github.com/bazelbuild/starlark/issues/13 -->

Unlike Python, Starlark does not allow more than one `*args` argument in a
call, and if a `*args` argument is present it must appear after all
positional and named arguments.

A function call completes normally after the execution of either a
`return` statement, or of the last statement in the function body.
The result of the function call is the value of the return statement's
Expand Down
24 changes: 10 additions & 14 deletions internal/compile/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -1567,27 +1567,23 @@ func (fcomp *fcomp) args(call *syntax.CallExpr) (op Opcode, arg uint32) {
p++
}

// Python2, Python3, and Starlark-in-Java all permit named arguments
// 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))
//
// However all three implement different argument evaluation orders:
// 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: 1 2 3 4 5 6 (lexical order)
// Starlark-in-Java historically used a third order:
// Lexical: 1 2 3 4 5 6 (all args evaluated left-to-right)
//
// The Starlark-in-Java semantics are clean but hostile to a
// compiler-based implementation because they require that the
// compiler emit code for positional, named, *args, more named,
// and *kwargs arguments and provide the callee with a map of
// the terrain.
// 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:
//
// For now we implement the Python2 semantics, but
// the spec needs to clarify the correct approach.
// Perhaps it would be best if we statically rejected
// named arguments after *args (e.g. y=5) so that the
// Python2 implementation strategy matches lexical order.
// Discussion in github.com/bazelbuild/starlark#13.
// f(1, 2, x=3, *[4], **dict(z=6)) # 1 2 3 4 6

// *args
if varargs != nil {
Expand Down