Merge remote-tracking branch 'vadz/py-args'
* vadz/py-args: Allow using enum elements as default values for Python functions. Don't always use "*args" for all Python wrapper functions. No real changes, just make PYTHON::check_kwargs() const. Refactor: move makeParameterName() to common Language base class. Remove long line wrapping from Python parameter list generation code.
This commit is contained in:
commit
36ae32e941
8 changed files with 127 additions and 207 deletions
|
|
@ -3200,43 +3200,6 @@ public:
|
|||
Delete(replacementname);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* makeParameterName()
|
||||
*
|
||||
* Inputs:
|
||||
* n - Node
|
||||
* p - parameter node
|
||||
* arg_num - parameter argument number
|
||||
* setter - set this flag when wrapping variables
|
||||
* Return:
|
||||
* arg - a unique parameter name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
|
||||
|
||||
String *arg = 0;
|
||||
String *pn = Getattr(p, "name");
|
||||
|
||||
// Use C parameter name unless it is a duplicate or an empty parameter name
|
||||
int count = 0;
|
||||
ParmList *plist = Getattr(n, "parms");
|
||||
while (plist) {
|
||||
if ((Cmp(pn, Getattr(plist, "name")) == 0))
|
||||
count++;
|
||||
plist = nextSibling(plist);
|
||||
}
|
||||
String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
|
||||
arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
|
||||
|
||||
if (setter && Cmp(arg, "self") != 0) {
|
||||
// Note that in C# properties, the input variable name is always called 'value'
|
||||
Delete(arg);
|
||||
arg = NewString("value");
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitTypeWrapperClass()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -4299,40 +4299,8 @@ private:
|
|||
return proxyname;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* D::makeParameterName()
|
||||
*
|
||||
* Inputs:
|
||||
* n - Node
|
||||
* p - parameter node
|
||||
* arg_num - parameter argument number
|
||||
* setter - set this flag when wrapping variables
|
||||
* Return:
|
||||
* arg - a unique parameter name
|
||||
* --------------------------------------------------------------------------- */
|
||||
String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) const {
|
||||
String *arg = 0;
|
||||
String *pn = Getattr(p, "name");
|
||||
|
||||
// Use C parameter name unless it is a duplicate or an empty parameter name
|
||||
int count = 0;
|
||||
ParmList *plist = Getattr(n, "parms");
|
||||
while (plist) {
|
||||
if ((Cmp(pn, Getattr(plist, "name")) == 0))
|
||||
count++;
|
||||
plist = nextSibling(plist);
|
||||
}
|
||||
String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
|
||||
arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
|
||||
|
||||
if (setter && Cmp(arg, "self") != 0) {
|
||||
// In theory, we could use the normal parameter name for setter functions.
|
||||
// Unfortunately, it is set to "Class::VariableName" for static public
|
||||
// members by the parser, which is not legal D syntax. Thus, we just force
|
||||
// it to "value".
|
||||
Delete(arg);
|
||||
arg = NewString("value");
|
||||
}
|
||||
String *arg = Language::makeParameterName(n, p, arg_num, setter);
|
||||
|
||||
if (split_proxy_dmodule && Strncmp(arg, package, Len(arg)) == 0) {
|
||||
// If we are in split proxy mode and the argument is named like the target
|
||||
|
|
|
|||
|
|
@ -3115,44 +3115,6 @@ public:
|
|||
Delete(replacementname);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* makeParameterName()
|
||||
*
|
||||
* Inputs:
|
||||
* n - Node
|
||||
* p - parameter node
|
||||
* arg_num - parameter argument number
|
||||
* setter - set this flag when wrapping variables
|
||||
* Return:
|
||||
* arg - a unique parameter name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
|
||||
|
||||
String *arg = 0;
|
||||
String *pn = Getattr(p, "name");
|
||||
|
||||
// Use C parameter name unless it is a duplicate or an empty parameter name
|
||||
int count = 0;
|
||||
ParmList *plist = Getattr(n, "parms");
|
||||
while (plist) {
|
||||
if ((Cmp(pn, Getattr(plist, "name")) == 0))
|
||||
count++;
|
||||
plist = nextSibling(plist);
|
||||
}
|
||||
String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
|
||||
arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
|
||||
|
||||
if (setter && Cmp(arg, "self") != 0) {
|
||||
// Note that for setters the parameter name is always set but sometimes includes C++
|
||||
// scope resolution, so we need to strip off the scope resolution to make a valid name.
|
||||
Delete(arg);
|
||||
arg = NewString("value"); //Swig_scopename_last(pn);
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitTypeWrapperClass()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -3499,6 +3499,44 @@ int Language::is_smart_pointer() const {
|
|||
return SmartPointer;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Language::makeParameterName()
|
||||
*
|
||||
* Inputs:
|
||||
* n - Node
|
||||
* p - parameter node
|
||||
* arg_num - parameter argument number
|
||||
* setter - set this flag when wrapping variables
|
||||
* Return:
|
||||
* arg - a unique parameter name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
String *Language::makeParameterName(Node *n, Parm *p, int arg_num, bool setter) const {
|
||||
|
||||
String *arg = 0;
|
||||
String *pn = Getattr(p, "name");
|
||||
|
||||
// Use C parameter name unless it is a duplicate or an empty parameter name
|
||||
int count = 0;
|
||||
ParmList *plist = Getattr(n, "parms");
|
||||
while (plist) {
|
||||
if ((Cmp(pn, Getattr(plist, "name")) == 0))
|
||||
count++;
|
||||
plist = nextSibling(plist);
|
||||
}
|
||||
String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
|
||||
arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
|
||||
|
||||
if (setter && Cmp(arg, "self") != 0) {
|
||||
// Some languages (C#) insist on calling the input variable "value" while
|
||||
// others (D, Java) could, in principle, use something different but this
|
||||
// would require more work, and so we just use "value" for them too.
|
||||
Delete(arg);
|
||||
arg = NewString("value");
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Language::()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -3621,35 +3621,6 @@ MODULA3():
|
|||
return substitution_performed;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* makeParameterName()
|
||||
*
|
||||
* Inputs:
|
||||
* n - Node
|
||||
* p - parameter node
|
||||
* arg_num - parameter argument number
|
||||
* Return:
|
||||
* arg - a unique parameter name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *makeParameterName(Node *n, Parm *p, int arg_num) {
|
||||
|
||||
// Use C parameter name unless it is a duplicate or an empty parameter name
|
||||
String *pn = Getattr(p, "name");
|
||||
int count = 0;
|
||||
ParmList *plist = Getattr(n, "parms");
|
||||
while (plist) {
|
||||
if ((Cmp(pn, Getattr(plist, "name")) == 0))
|
||||
count++;
|
||||
plist = nextSibling(plist);
|
||||
}
|
||||
String *arg = (!pn || (count > 1)) ? NewStringf("arg%d",
|
||||
arg_num) : Copy(Getattr(p,
|
||||
"name"));
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* attachParameterNames()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1528,6 +1528,21 @@ public:
|
|||
return ds;
|
||||
}
|
||||
|
||||
virtual String *makeParameterName(Node *n, Parm *p, int arg_num, bool = false) const {
|
||||
// For the keyword arguments, we want to preserve the names as much as possible,
|
||||
// so we only minimally rename them in Swig_name_make(), e.g. replacing "keyword"
|
||||
// with "_keyword" if they have any name at all.
|
||||
if (check_kwargs(n)) {
|
||||
String* name = Getattr(p, "name");
|
||||
if (name)
|
||||
return Swig_name_make(p, 0, name, 0, 0);
|
||||
}
|
||||
|
||||
// For the other cases use the general function which replaces arguments whose
|
||||
// names clash with keywords with (less useful) "argN".
|
||||
return Language::makeParameterName(n, p, arg_num);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* addMissingParameterNames()
|
||||
* For functions that have not had nameless parameters set in the Language class.
|
||||
|
|
@ -1539,13 +1554,14 @@ public:
|
|||
* The "lname" attribute in each parameter in plist will be contain a parameter name
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void addMissingParameterNames(ParmList *plist, int arg_offset) {
|
||||
void addMissingParameterNames(Node* n, ParmList *plist, int arg_offset) {
|
||||
Parm *p = plist;
|
||||
int i = arg_offset;
|
||||
while (p) {
|
||||
if (!Getattr(p, "lname")) {
|
||||
String *pname = Swig_cparm_name(p, i);
|
||||
Delete(pname);
|
||||
String *name = makeParameterName(n, p, i);
|
||||
Setattr(p, "lname", name);
|
||||
Delete(name);
|
||||
}
|
||||
i++;
|
||||
p = nextSibling(p);
|
||||
|
|
@ -1568,14 +1584,18 @@ public:
|
|||
Parm *pnext;
|
||||
|
||||
|
||||
int lines = 0;
|
||||
int start_arg_num = is_wrapping_class() ? 1 : 0;
|
||||
const int maxwidth = 80;
|
||||
// Normally we start counting auto-generated argument names from 1, but we should do it from 2
|
||||
// if the first argument is "self", i.e. if we're handling a non-static member function.
|
||||
int arg_num = 1;
|
||||
if (is_wrapping_class()) {
|
||||
if (Cmp(Getattr(n, "storage"), "static") != 0)
|
||||
arg_num++;
|
||||
}
|
||||
|
||||
if (calling)
|
||||
func_annotation = false;
|
||||
|
||||
addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
|
||||
addMissingParameterNames(n, plist, arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
|
||||
Swig_typemap_attach_parms("in", plist, 0);
|
||||
Swig_typemap_attach_parms("doc", plist, 0);
|
||||
|
||||
|
|
@ -1584,7 +1604,7 @@ public:
|
|||
return doc;
|
||||
}
|
||||
|
||||
for (p = plist; p; p = pnext) {
|
||||
for (p = plist; p; p = pnext, arg_num++) {
|
||||
|
||||
String *tm = Getattr(p, "tmap:in");
|
||||
if (tm) {
|
||||
|
|
@ -1607,25 +1627,22 @@ public:
|
|||
}
|
||||
|
||||
// Note: the generated name should be consistent with that in kwnames[]
|
||||
name = name ? name : Getattr(p, "name");
|
||||
name = name ? name : Getattr(p, "lname");
|
||||
name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword
|
||||
String *made_name = 0;
|
||||
if (!name) {
|
||||
name = made_name = makeParameterName(n, p, arg_num);
|
||||
}
|
||||
|
||||
type = type ? type : Getattr(p, "type");
|
||||
value = value ? value : Getattr(p, "value");
|
||||
|
||||
if (SwigType_isvarargs(type))
|
||||
if (SwigType_isvarargs(type)) {
|
||||
Delete(made_name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Len(doc)) {
|
||||
// add a comma to the previous one if any
|
||||
Append(doc, ", ");
|
||||
|
||||
// Do we need to wrap a long line?
|
||||
if ((Len(doc) - lines * maxwidth) > maxwidth) {
|
||||
Printf(doc, "\n%s", tab4);
|
||||
lines += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the param type too?
|
||||
|
|
@ -1647,17 +1664,11 @@ public:
|
|||
// Write default value
|
||||
if (value && !calling) {
|
||||
String *new_value = convertValue(value, Getattr(p, "type"));
|
||||
if (new_value) {
|
||||
value = new_value;
|
||||
} else {
|
||||
Node *lookup = Swig_symbol_clookup(value, 0);
|
||||
if (lookup)
|
||||
value = Getattr(lookup, "sym:name");
|
||||
}
|
||||
Printf(doc, "=%s", value);
|
||||
if (new_value)
|
||||
Printf(doc, "=%s", new_value);
|
||||
}
|
||||
Delete(type_str);
|
||||
Delete(name);
|
||||
Delete(made_name);
|
||||
}
|
||||
if (pdocs)
|
||||
Setattr(n, "feature:pdocs", pdocs);
|
||||
|
|
@ -1805,40 +1816,50 @@ public:
|
|||
|
||||
/* ------------------------------------------------------------
|
||||
* convertValue()
|
||||
* Check if string v can be a Python value literal,
|
||||
* (eg. number or string), or translate it to a Python literal.
|
||||
* Check if string v can be a Python value literal or a
|
||||
* constant. Return NIL if it isn't.
|
||||
* ------------------------------------------------------------ */
|
||||
String *convertValue(String *v, SwigType *t) {
|
||||
if (v && Len(v) > 0) {
|
||||
char fc = (Char(v))[0];
|
||||
if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
|
||||
/* number or string (or maybe NULL pointer) */
|
||||
if (SwigType_ispointer(t) && Strcmp(v, "0") == 0)
|
||||
return NewString("None");
|
||||
else
|
||||
return v;
|
||||
}
|
||||
if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
|
||||
return NewString("True");
|
||||
if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
|
||||
return NewString("False");
|
||||
if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
|
||||
return SwigType_ispointer(t) ? NewString("None") : NewString("0");
|
||||
char fc = (Char(v))[0];
|
||||
if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
|
||||
/* number or string (or maybe NULL pointer) */
|
||||
if (SwigType_ispointer(t) && Strcmp(v, "0") == 0)
|
||||
return NewString("None");
|
||||
else
|
||||
return v;
|
||||
}
|
||||
return 0;
|
||||
if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
|
||||
return NewString("True");
|
||||
if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
|
||||
return NewString("False");
|
||||
if (Strcmp(v, "NULL") == 0 || Strcmp(v, "nullptr") == 0)
|
||||
return SwigType_ispointer(t) ? NewString("None") : NewString("0");
|
||||
|
||||
// This could also be an enum type, default value of which is perfectly
|
||||
// representable in Python.
|
||||
Node *lookup = Swig_symbol_clookup(v, 0);
|
||||
if (lookup) {
|
||||
if (Cmp(Getattr(lookup, "nodeType"), "enumitem") == 0)
|
||||
return Getattr(lookup, "sym:name");
|
||||
}
|
||||
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------
|
||||
* is_primitive_defaultargs()
|
||||
* Check if all the default args have primitive type.
|
||||
* (So we can generate proper parameter list with default
|
||||
* values..)
|
||||
* is_representable_as_pyargs()
|
||||
* Check if the function parameters default argument values
|
||||
* can be represented in Python.
|
||||
*
|
||||
* If this method returns false, the parameters will be translated
|
||||
* to a generic "*args" which allows us to deal with default values
|
||||
* at C++ code level where they can always be handled.
|
||||
* ------------------------------------------------------------ */
|
||||
bool is_primitive_defaultargs(Node *n) {
|
||||
bool is_representable_as_pyargs(Node *n) {
|
||||
ParmList *plist = CopyParmList(Getattr(n, "parms"));
|
||||
Parm *p;
|
||||
Parm *pnext;
|
||||
|
||||
Swig_typemap_attach_parms("in", plist, 0);
|
||||
for (p = plist; p; p = pnext) {
|
||||
String *tm = Getattr(p, "tmap:in");
|
||||
if (tm) {
|
||||
|
|
@ -1849,10 +1870,11 @@ public:
|
|||
} else {
|
||||
pnext = nextSibling(p);
|
||||
}
|
||||
String *type = Getattr(p, "type");
|
||||
String *value = Getattr(p, "value");
|
||||
if (!convertValue(value, type))
|
||||
return false;
|
||||
if (String *value = Getattr(p, "value")) {
|
||||
String *type = Getattr(p, "type");
|
||||
if (!convertValue(value, type))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1897,7 +1919,7 @@ public:
|
|||
n = nn;
|
||||
|
||||
/* For overloaded function, just use *args */
|
||||
if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || !is_primitive_defaultargs(n)) {
|
||||
if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || !is_representable_as_pyargs(n)) {
|
||||
String *parms = NewString("");
|
||||
if (in_class)
|
||||
Printf(parms, "self, ");
|
||||
|
|
@ -2057,7 +2079,7 @@ public:
|
|||
* check if using kwargs is allowed for this Node
|
||||
* ------------------------------------------------------------ */
|
||||
|
||||
int check_kwargs(Node *n) {
|
||||
int check_kwargs(Node *n) const {
|
||||
return (use_kw || GetFlag(n, "feature:kwargs"))
|
||||
&& !GetFlag(n, "memberset") && !GetFlag(n, "memberget");
|
||||
}
|
||||
|
|
@ -2436,7 +2458,6 @@ public:
|
|||
}
|
||||
|
||||
SwigType *pt = Getattr(p, "type");
|
||||
String *pn = Getattr(p, "name");
|
||||
String *ln = Getattr(p, "lname");
|
||||
bool parse_from_tuple = (i > 0 || !add_self);
|
||||
if (SwigType_type(pt) == T_VARARGS) {
|
||||
|
|
@ -2458,18 +2479,9 @@ public:
|
|||
|
||||
/* Keyword argument handling */
|
||||
if (allow_kwargs && parse_from_tuple) {
|
||||
if (Len(pn)) {
|
||||
String *tmp = 0;
|
||||
String *name = pn;
|
||||
if (!Getattr(p, "hidden")) {
|
||||
name = tmp = Swig_name_make(p, 0, pn, 0, 0); // rename parameter if a keyword
|
||||
}
|
||||
Printf(kwargs, "(char *) \"%s\",", name);
|
||||
if (tmp)
|
||||
Delete(tmp);
|
||||
} else {
|
||||
Printf(kwargs, "(char *)\"arg%d\",", i + 1);
|
||||
}
|
||||
String *name = makeParameterName(n, p, i + 1);
|
||||
Printf(kwargs, "(char *) \"%s\",", name);
|
||||
Delete(name);
|
||||
}
|
||||
|
||||
/* Look for an input typemap */
|
||||
|
|
|
|||
|
|
@ -297,6 +297,9 @@ protected:
|
|||
/* Return true if the current method is part of a smart-pointer */
|
||||
int is_smart_pointer() const;
|
||||
|
||||
/* Return the name to use for the given parameter. */
|
||||
virtual String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter = false) const;
|
||||
|
||||
/* Some language modules require additional wrappers for virtual methods not declared in sub-classes */
|
||||
virtual bool extraDirectorProtectedCPPMethodsRequired() const;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue