MethodHandle
with an array of
values, corresponding in order and number to its parameters
(formal arguments).
This parser transforms several argument presentations that occur
in a Python implementation, and arranges them into an array. This
array is either created by the parser, or designated by the
caller. The parser may therefore be used to prepare arguments for
a pure a Java method (or MethodHandle
) that accepts an
array, or to insert arguments as initial values of local
variables in an an optimised interpreter frame (PyFrame
).
The fields of the parser that determine the acceptable numbers of
positional arguments and their names are essentially those of a
code
object (PyCode
). Defaults are provided
values that mirror the defaults built into a function
object (PyFunction
).
Consider for example a function that in Python would have the function definition:
def func(a, b, c=3, d=4, /, e=5, f=6, *aa, g=7, h, i=9, **kk): passThis could be described by a constructor call and modifiers:
String[] names = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "aa", "kk"}; ArgParser ap = new ArgParser("func", names, names.length - 2, 4, 3, true, true) // .defaults(3, 4, 5, 6) // .kwdefaults(7, null, 9);Note that "aa" and "kk" are at the end of the parameter names. (This is how a CPython frame is laid out.)
Defaults are provided, after the parser has been constructed, as
values corresponding to parameter names, when right-justified in
the space to which they apply. (See diagram below.) Both the
positional and keyword defaults are given by position in this
formulation. The kwdefaults(Object.
call is allowed
to supply null
values at positions it does not define.
When parsed to an array, the layout of the argument values, in relation to fields of the parser will be as follows.
names | a | b | c | d | e | f | g | h | i | aa | kk |
layout | posOnly | kwOnly | |||||||||
defaults | kwdefaults |
The most readable way of specifying a parser (although one that
is a little costly to construct) is to list the parameters as
they would be declared in Python, including the furniture that
marks up the positional-only, keyword-only, positional varargs,
and keyword varargs. This is the API offered by
fromSignature(String, String.
. In practice we only
use this in unit tests. For serious applications we construct the
ArgParser
with a complex of arguments derived by
inspection of the Java or Python signature.
Modifier and Type | Class and Description |
---|---|
pack-priv class | ArgParser.ArrayFrameWrapper
Wrap an array provided by a client so that the enclosing argument parser may fill it from the arguments to a Python call. |
pack-priv abstract class | ArgParser.FrameWrapper
Abstract wrapper for storage that the enclosing argument parser should be able to fill from the arguments to a Python call. |
Modifier and Type | Field and Description |
---|---|
pack-priv final int | argcount
The number of positional parameters. |
pack-priv final String[] | argnames
Names of parameters that could be satisfied by position or keyword, including the collector parameters. |
private Object[] | defaults
The (positional) default parameters or |
pack-priv String | doc
The documentation string of the method. |
private Map | kwdefaults
The keyword defaults, may be a |
pack-priv final int | kwonlyargcount
The number of keyword-only parameters. |
pack-priv final MethodKind | methodKind
The kind of method (instance, static or class) that this parser works for. |
pack-priv final String | name
The name of the function, mainly for error messages. |
private static final Object[] | NO_OBJECTS
Empty object array. |
private static final String[] | NO_STRINGS
Empty names array. |
pack-priv final int | posonlyargcount
The number of parameters that can only be satisfied by arguments given by position. |
pack-priv final int | regargcount
The number of positional or keyword parameters, excluding the
"collector" ( |
pack-priv final ScopeKind | scopeKind
The kind of object (type or module) in which the method is found. |
private static final String | |
private static final String | |
pack-priv final int | varArgsIndex
The frame has a collector ( |
pack-priv final int | varKeywordsIndex
The frame has a collector ( |
Access | Constructor and Description |
---|---|
pack-priv | ArgParser(String
of the function name, String[] of the parameters including any collectors (varargs) names, int number of regular (non-collector) parameters regargcount, int number of positional-only parameters posOnly, int number of keyword-only parameters kwOnly, boolean whether there is positional collector varargs, boolean whether there is a keywords collector varkw)Construct a parser for a named function, with defined numbers of positional-only and keyword-only parameters, and parameter names in an array prepared by client code. |
pack-priv | ArgParser(String
of the function name, ScopeKind whether module, etc. scopeKind, MethodKind whether static, etc. methodKind, String[] of the parameters including any collectors (varargs) names, int number of regular (non-collector) parameters regargcount, int number of positional-only parameters posOnly, int number of keyword-only parameters kwOnly, boolean whether there is positional collector varargs, boolean whether there is a keywords collector varkw)Construct a parser from descriptive parameters that may be
derived from a the annotated declarations ( |
Modifier and Type | Method and Description |
---|---|
private void | checkShape()
The number of keyword-only parameters and positional-only parameters must not together exceed the number of parameters named in the constructor. |
pack-priv ArgParser | |
pack-priv static ArgParser | Returns: the constructed parserof function name, String... names of parameters and indicators "/", "*", "**" decl)Create a parser, for a named function, with defined numbers of positional-only and keyword-only parameters, and naming the parameters. |
pack-priv Object[] | |
pack-priv boolean | |
pack-priv boolean | |
pack-priv boolean | |
pack-priv boolean | |
pack-priv ArgParser | Returns: this keyword values aligned to the parameter names values)Provide the keyword-only defaults as values. |
pack-priv ArgParser | Returns: this replacement keyword defaults (or kwd)null )Provide the keyword-only defaults, perhaps as a |
private String | |
private String | |
private String | |
pack-priv Object[] | |
pack-priv Object[] | Returns: array of parsed argumentspositional and keyword arguments s, int position of arguments in the array p, int number of positional and keyword arguments n, String[] of keyword arguments or names)null Parse CPython-style vector call arguments and create an array, using the arguments supplied and the defaults held in the parser. |
pack-priv Object[] | |
pack-priv void | parseToFrame(ArgParser.
to populate with argument values frame,positional arguments given args, PyDict keyword arguments given kwargs)Parse when an args tuple and keyword dictionary are supplied, that is, for a classic call. |
pack-priv void | parseToFrame(ArgParser.
to populate with argument values frame,array containing all arguments stack, int of the slice in the stack start, int number of arguments in the slice, whether position
or keyword nargs, String[] (implying number) of keyword arguments kwnames)Parse when an args array and keyword array are supplied, that is, for a vector call on a stack slice. |
pack-priv void | parseToFrame(ArgParser.
to populate with argument values frame,all arguments, positional then keyword args, String[] of keyword arguments (or kwnames)null )Parse when an args array and keyword array are supplied, that is,
for a standard |
private static String | |
pack-priv String | Returns: the signature of the argumentsReturn a string representing the argument list of the method. |
public String | toString()
Overrides java. ArgParser is based on the
__text_signature__ attribute of built-in methods (see
textSignature() ) and the specifications found in CPython
Argument Clinic.
|
argcount | back to summary |
---|---|
pack-priv final int argcount The number of positional parameters. |
argnames | back to summary |
---|---|
pack-priv final String[] argnames Names of parameters that could be satisfied by position or
keyword, including the collector parameters. Elements are
guaranteed to be interned, and not It is often is longer since it suits us to re-use an array that names all the local variables of a frame. |
defaults | back to summary |
---|---|
private Object[] defaults The (positional) default parameters or |
doc | back to summary |
---|---|
pack-priv String doc The documentation string of the method. |
kwdefaults | back to summary |
---|---|
private Map<Object, Object> kwdefaults The keyword defaults, may be a |
kwonlyargcount | back to summary |
---|---|
pack-priv final int kwonlyargcount The number of keyword-only parameters. |
methodKind | back to summary |
---|---|
pack-priv final MethodKind methodKind The kind of method (instance, static or class) that this parser works for. |
name | back to summary |
---|---|
pack-priv final String name The name of the function, mainly for error messages. |
NO_OBJECTS | back to summary |
---|---|
private static final Object[] NO_OBJECTS Empty object array. |
NO_STRINGS | back to summary |
---|---|
private static final String[] NO_STRINGS Empty names array. |
posonlyargcount | back to summary |
---|---|
pack-priv final int posonlyargcount The number of parameters that can only be satisfied by arguments
given by position. This differs from |
regargcount | back to summary |
---|---|
pack-priv final int regargcount The number of positional or keyword parameters, excluding the
"collector" ( |
scopeKind | back to summary |
---|---|
pack-priv final ScopeKind scopeKind The kind of object (type or module) in which the method is found. This makes a difference to the signature reported for an instance method. |
TOO_MANY_DEFAULTS | back to summary |
---|---|
private static final String TOO_MANY_DEFAULTS |
TOO_MANY_KWDEFAULTS | back to summary |
---|---|
private static final String TOO_MANY_KWDEFAULTS |
varArgsIndex | back to summary |
---|---|
pack-priv final int varArgsIndex The frame has a collector ( |
varKeywordsIndex | back to summary |
---|---|
pack-priv final int varKeywordsIndex The frame has a collector ( |
ArgParser | back to summary |
---|---|
pack-priv ArgParser(String name, String[] names, int regargcount, int posOnly, int kwOnly, boolean varargs, boolean varkw) Construct a parser for a named function, with defined numbers of positional-only and keyword-only parameters, and parameter names in an array prepared by client code. The array of names is used in-place (not copied). The client code must therefore ensure that it cannot be modified after the parser has been constructed.
The array of names may be longer than is necessary: the caller
specifies how much of the array should be treated as regular
parameter names, and whether zero, one or two further elements
will name collectors for excess positional or keyword arguments.
The rest of the elements will not be examined by the parser. The
motivation for this design is to permit efficient construction
when the the array of names is the local variable names in a
Python
|
ArgParser | back to summary | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
pack-priv ArgParser(String name, ScopeKind scopeKind, MethodKind methodKind, String[] names, int regargcount, int posOnly, int kwOnly, boolean varargs, boolean varkw) Construct a parser from descriptive parameters that may be
derived from a the annotated declarations ( def func(a, b, c=3, d=4, /, e=5, f=6, *aa, g=7, h, i=9, **kk): passThe constructor arguments should specify this layout:
|
checkShape | back to summary |
---|---|
private void checkShape() The number of keyword-only parameters and positional-only parameters must not together exceed the number of parameters named in the constructor. (The last two are defined in the constructor.) Nor must there be excess default values for the number of parameters. |
defaults | back to summary |
---|---|
pack-priv ArgParser defaults(Object... values) Provide the positional defaults. * The
If L values are provided, they correspond to
|
fromSignature | back to summary |
---|---|
pack-priv static ArgParser fromSignature(String name, String... decl) Create a parser, for a named function, with defined numbers of positional-only and keyword-only parameters, and naming the parameters. Parameters that may only be given by position need not be named. ("" is acceptable in the names array.) This is a convenient way to construct a reference result in unit tests. |
getDefaults | back to summary |
---|---|
pack-priv Object[] getDefaults()
|
hasDefaults | back to summary |
---|---|
pack-priv boolean hasDefaults()
|
hasKwdefaults | back to summary |
---|---|
pack-priv boolean hasKwdefaults()
|
hasVarArgs | back to summary |
---|---|
pack-priv boolean hasVarArgs()
|
hasVarKeywords | back to summary |
---|---|
pack-priv boolean hasVarKeywords()
|
kwdefaults | back to summary |
---|---|
pack-priv ArgParser kwdefaults(Object... values) Provide the keyword-only defaults as values. If K values are
provided, they correspond to |
kwdefaults | back to summary |
---|---|
pack-priv ArgParser kwdefaults(Map<Object, Object> kwd) Provide the keyword-only defaults, perhaps as a |
nameArg | back to summary |
---|---|
private String nameArg(int i) Get the name of arg i or make one up. |
parameterToString | back to summary |
---|---|
private String parameterToString(int i, int d) Return ith positional parameter name and default value if
available. Helper to |
parameterToString | back to summary |
---|---|
private String parameterToString(int i) Return ith parameter name and keyword default value if
available. Helper to |
parse | back to summary |
---|---|
pack-priv Object[] parse(Object[] args, String[] names) Parse |
parse | back to summary |
---|---|
pack-priv Object[] parse(Object[] s, int p, int n, String[] names) Parse CPython-style vector call arguments and create an array, using the arguments supplied and the defaults held in the parser. |
parse | back to summary |
---|---|
pack-priv Object[] parse(PyTuple args, PyDict kwargs) Parse classic arguments and create an array, using the arguments supplied and the defaults held in the parser. |
parseToFrame | back to summary |
---|---|
pack-priv void parseToFrame(ArgParser. Parse when an args tuple and keyword dictionary are supplied, that is, for a classic call.
|
parseToFrame | back to summary |
---|---|
pack-priv void parseToFrame(ArgParser. Parse when an args array and keyword array are supplied, that is, for a vector call on a stack slice.
|
parseToFrame | back to summary |
---|---|
pack-priv void parseToFrame(ArgParser. Parse when an args array and keyword array are supplied, that is,
for a standard
|
repr | back to summary |
---|---|
private static String repr(Object o) Weak substitute for |
textSignature | back to summary |
---|---|
pack-priv String textSignature() Return a string representing the argument list of the method. The
string is like that found in the
|
toString | back to summary |
---|---|
public String toString() Overrides java. The representation of an
|
ArgParser#parseToFrame(FrameWrapper, PyTuple, PyDict)
.
Modifier and Type | Field and Description |
---|---|
pack-priv final int | |
private final Object[] |
Access | Constructor and Description |
---|---|
pack-priv | ArrayFrameWrapper(Object[]
destination array vars, int at which to place first parsed argument start)Wrap a slice of an existing array. |
pack-priv |
Modifier and Type | Method and Description |
---|---|
pack-priv Object | getLocal(int
index of variable name in i)argnames Implements abstract org. argnames[i]
|
pack-priv void | setLocal(int
index of variable name in i, Object argnames to assign to variable named v)argnames[i] Implements abstract org. argnames[i]
|
pack-priv void | setPositionalArguments(PyTuple
positional arguments argsTuple)Overrides org. |
pack-priv void | setPositionalArguments(Object[]
positional and keyword arguments stack, int position of arguments in the array pos, int number of positional arguments nargs)Overrides org. |
start | back to summary |
---|---|
pack-priv final int start |
vars | back to summary |
---|---|
private final Object[] vars |
ArrayFrameWrapper | back to summary |
---|---|
pack-priv ArrayFrameWrapper(Object[] vars, int start) Wrap a slice of an existing array. The elements to fill are a
slice of the destination array with specified starting index. The
intended use is that
|
ArrayFrameWrapper | back to summary |
---|---|
pack-priv ArrayFrameWrapper(Object[] vars) Wrap an existing array. The capacity of the array must be sufficient to hold the parse result.
|
getLocal | back to summary |
---|---|
pack-priv Object getLocal(int i) Implements abstract org. Doc from org. Get the local variable named by |
setLocal | back to summary |
---|---|
pack-priv void setLocal(int i, Object v) Implements abstract org. Doc from org. Set the local variable named by |
setPositionalArguments | back to summary |
---|---|
pack-priv void setPositionalArguments(PyTuple argsTuple) Overrides org. Doc from org. Copy positional arguments into local variables, making sure we don't copy more than have been allowed for in the frame. Providing too many or too few is not an error at this stage, as there may be a collector to catch the excess arguments or positional or keyword defaults to make up the shortfall. |
setPositionalArguments | back to summary |
---|---|
pack-priv void setPositionalArguments(Object[] stack, int pos, int nargs) Overrides org. Doc from org. Copy positional arguments into local variables, making sure we don't copy more than have been allowed for in the frame. Providing too many or too few is not an error at this stage, as there may be a collector to catch the excess arguments or positional or keyword defaults to make up the shortfall. |
PyFrame
) that the run-time is in
the process of initialising during a call.
Modifier and Type | Field and Description |
---|---|
pack-priv static final String | |
pack-priv static final String | |
pack-priv static final String | |
pack-priv static final String | |
pack-priv static final String |
Access | Constructor and Description |
---|---|
pack-priv |
Modifier and Type | Method and Description |
---|---|
pack-priv void | applyDefaults(int
number of positional arguments given in call nargs, Object[] default values by position or defs)null Fill in missing positional parameters from a from |
pack-priv void | applyKWDefaults(Map<Object, Object>
default values by keyword or kwdefs)null Deal with missing keyword arguments, attempting to fill them from
|
private int | Returns: index ofname in argnames or -1parameter name given as keyword name)Find the given name in |
pack-priv abstract Object | Returns: value of variable namedargnames[i] index of variable name in i)argnames Get the local variable named by |
protected TypeError | Returns: TypeError listing names of the missing argumentsnumber of missing arguments missing, int number of positional defaults available (or -1) defcount)Diagnose which positional or keywords arguments are missing, and
throw |
private TypeError | missingNamesTypeError(String kind, ArrayList<String> names)
Compose a |
pack-priv void | setKeywordArguments(PyDict
keyword arguments given in call kwargs)For each of the names used as keywords in the call, match it with an allowable parameter name, and assign that frame-local variable the keyword argument given in the call. |
pack-priv void | setKeywordArguments(Object[]
[kwstart:kwstart+len(kwnames)] values
corresponding to kwnames in orderstart position in kwstart, String[] kwvalues keywords used in the call (or kwnames)**kwargs )For each of the names used as keywords in the call, match it with an allowable parameter name, and assign that frame-local variable the keyword argument given in the call. |
pack-priv abstract void | |
pack-priv void | setPositionalArguments(PyTuple
positional arguments args)Copy positional arguments into local variables, making sure we don't copy more than have been allowed for in the frame. |
pack-priv void | setPositionalArguments(Object[]
positional and keyword arguments stack, int position of arguments in the array pos, int number of positional arguments nargs)Copy positional arguments into local variables, making sure we don't copy more than have been allowed for in the frame. |
protected TypeError | |
protected < type of element in keyword collection K> TypeError | Returns: TypeError diagnosing the problemthe unexpected keyword encountered in the call kw, Collection<? extends K> all the keywords used in the call kwnames)Diagnose an unexpected keyword occurring in a call and represent the problem as an exception. |
KEYWORD_NOT_COMPARABLE | back to summary |
---|---|
pack-priv static final String KEYWORD_NOT_COMPARABLE |
KEYWORD_NOT_STRING | back to summary |
---|---|
pack-priv static final String KEYWORD_NOT_STRING |
MULTIPLE_VALUES | back to summary |
---|---|
pack-priv static final String MULTIPLE_VALUES |
POSITIONAL_ONLY | back to summary |
---|---|
pack-priv static final String POSITIONAL_ONLY |
UNEXPECTED_KEYWORD | back to summary |
---|---|
pack-priv static final String UNEXPECTED_KEYWORD |
FrameWrapper | back to summary |
---|---|
pack-priv FrameWrapper() |
applyDefaults | back to summary |
---|---|
pack-priv void applyDefaults(int nargs, Object[] defs) throws TypeError Fill in missing positional parameters from a from
It is harmless (but a waste) to call this when
|
applyKWDefaults | back to summary |
---|---|
pack-priv void applyKWDefaults(Map<Object, Object> kwdefs) throws TypeError Deal with missing keyword arguments, attempting to fill them from
|
argnamesIndexOf | back to summary |
---|---|
private int argnamesIndexOf(Object name) Find the given name in
|
getLocal | back to summary |
---|---|
pack-priv abstract Object getLocal(int i) Get the local variable named by
|
missingArguments | back to summary |
---|---|
protected TypeError missingArguments(int missing, int defcount) Diagnose which positional or keywords arguments are missing, and
throw
|
missingNamesTypeError | back to summary |
---|---|
private TypeError missingNamesTypeError(String kind, ArrayList<String> names) Compose a |
setKeywordArguments | back to summary |
---|---|
pack-priv void setKeywordArguments(PyDict kwargs) For each of the names used as keywords in the call, match it with an allowable parameter name, and assign that frame-local variable the keyword argument given in the call. If the variable is not null, this is an error.
"Allowable parameter name" here means the names in
In this version, accept the keyword arguments passed as a
dictionary, as in the "classic"
|
setKeywordArguments | back to summary |
---|---|
pack-priv void setKeywordArguments(Object[] stack, int kwstart, String[] kwnames) For each of the names used as keywords in the call, match it with an allowable parameter name, and assign that frame-local variable the keyword argument given in the call. If the variable is not null, this is an error.
"Allowable parameter name" here means the names in
In this version, accept the keyword arguments passed as a
dictionary, as in the "classic" |
setLocal | back to summary |
---|---|
pack-priv abstract void setLocal(int i, Object v) Set the local variable named by
|
setPositionalArguments | back to summary |
---|---|
pack-priv void setPositionalArguments(PyTuple args) Copy positional arguments into local variables, making sure we don't copy more than have been allowed for in the frame. Providing too many or too few is not an error at this stage, as there may be a collector to catch the excess arguments or positional or keyword defaults to make up the shortfall.
|
setPositionalArguments | back to summary |
---|---|
pack-priv void setPositionalArguments(Object[] stack, int pos, int nargs) Copy positional arguments into local variables, making sure we don't copy more than have been allowed for in the frame. Providing too many or too few is not an error at this stage, as there may be a collector to catch the excess arguments or positional or keyword defaults to make up the shortfall.
|
tooManyPositional | back to summary |
---|---|
protected TypeError tooManyPositional(int posGiven) |
unexpectedKeyword | back to summary |
---|---|
protected <K> TypeError unexpectedKeyword(Object kw, Collection<? extends K> kwnames) Diagnose an unexpected keyword occurring in a call and represent the problem as an exception. The particular keyword may incorrectly name a positional parameter, or it may be entirely unexpected (not be a parameter at all). In any case, since this error is going to be fatal to the call, this method looks at all the keywords to see if any are positional-only parameters, and if that's not the problem, reports just the originally-offending keyword as unexpected.
We call this method when any keyword has been encountered that
does not match a legitimate parameter, and there is no
|