From 7b3aad4436b8cbd25fda2bd658ed44b3dc2c6dcc Mon Sep 17 00:00:00 2001 From: alandonovan Date: Fri, 18 Jan 2019 12:54:00 -0500 Subject: [PATCH] doc: document call argument evaluation order (#118) ..now that the spec is resolved. --- doc/spec.md | 7 +++++++ internal/compile/compile.go | 24 ++++++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/doc/spec.md b/doc/spec.md index e256b249..c9cb1d49 100644 --- a/doc/spec.md +++ b/doc/spec.md @@ -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. + + +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 diff --git a/internal/compile/compile.go b/internal/compile/compile.go index 67f3ae80..6b43fbe3 100644 --- a/internal/compile/compile.go +++ b/internal/compile/compile.go @@ -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 {