Refactor Swig_cparse_template_parms_expand()

Break up functionality in Swig_cparse_template_parms_expand() to make it
more readable / maintainable.
This commit is contained in:
William S Fulton 2022-12-12 23:37:21 +00:00
commit 1e73045da8
5 changed files with 141 additions and 66 deletions

View file

@ -68,7 +68,7 @@ extern "C" {
extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope); extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope); extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope);
extern void Swig_cparse_debug_templates(int); extern void Swig_cparse_debug_templates(int);
extern ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, ParmList *temparms_input, Parm *targs, Node *nn); extern ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -2892,12 +2892,10 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
continue; continue;
} else { } else {
String *tname = Copy($5); String *tname = Copy($5);
/* Expand the template */
Node *primary_template = Swig_symbol_clookup(tname, 0); Node *primary_template = Swig_symbol_clookup(tname, 0);
ParmList *targs = primary_template ? Getattr(primary_template, "templateparms") : 0;
ParmList *temparms_input = specialized ? $7 : tparms;
ParmList *temparms = Swig_cparse_template_parms_expand($7, temparms_input, targs, nn); /* Expand the template */
ParmList *temparms = Swig_cparse_template_parms_expand($7, primary_template);
templnode = copy_node(nn); templnode = copy_node(nn);
update_nested_classes(templnode); /* update classes nested within template */ update_nested_classes(templnode); /* update classes nested within template */

View file

@ -1005,75 +1005,110 @@ Node *Swig_cparse_template_locate(String *name, Parm *tparms, String *symname, S
return n; return n;
} }
/* -----------------------------------------------------------------------------
* merge_parameters()
*
* expanded_templateparms are the template parameters passed to %template.
* This function adds missing parameter name and type attributes from the chosen
* template (templateparms).
*
* Grab the parameter names from templateparms.
* Non-type template parameters have no type information in expanded_templateparms.
* Grab them from templateparms.
* ----------------------------------------------------------------------------- */
static void merge_parameters(ParmList *expanded_templateparms, ParmList *templateparms) {
Parm *p = expanded_templateparms;
Parm *tp = templateparms;
while (p && tp) {
Setattr(p, "name", Getattr(tp, "name"));
if (!Getattr(p, "type"))
Setattr(p, "type", Getattr(tp, "type"));
p = nextSibling(p);
tp = nextSibling(tp);
}
}
/* -----------------------------------------------------------------------------
* mark_defaults()
*
* Mark all the template parameters that are expanded from a default value
* ----------------------------------------------------------------------------- */
static void mark_defaults(ParmList *defaults) {
Parm *tp = defaults;
while (tp) {
Setattr(tp, "default", "1");
tp = nextSibling(tp);
}
}
/* -----------------------------------------------------------------------------
* expand_defaults()
*
* Replace parameter types in default argument values, example:
* input: int K,int T,class C=Less<(K)>
* output: int K,int T,class C=Less<(int)>
* ----------------------------------------------------------------------------- */
static void expand_defaults(ParmList *expanded_templateparms) {
Parm *tp = expanded_templateparms;
while (tp) {
Parm *p = expanded_templateparms;
String *tv = Getattr(tp, "value");
if (!tv)
tv = Getattr(tp, "type");
while(p) {
String *name = Getattr(p, "name");
String *value = Getattr(p, "value");
if (!value)
value = Getattr(p, "type");
if (name)
Replaceid(tv, name, value);
p = nextSibling(p);
}
tp = nextSibling(tp);
}
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Swig_cparse_template_parms_expand() * Swig_cparse_template_parms_expand()
* *
* instantiated_parameters: template parameters passed to %template * instantiated_parameters: template parameters passed to %template
* temparms_inputs: template parameters to use as starting point * primary: primary template node
* targs: primary template parameters, default args copied from here
* nn: template node (just used for warning)
* *
* Expand the instantiated_parameters and return a parameter list with default * Expand the instantiated_parameters and return a parameter list with default
* arguments filled in where necessary. * arguments filled in where necessary.
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, ParmList *temparms_input, Parm *targs, Node *nn) { ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary) {
Parm *p; ParmList *expanded_templateparms = 0;
Parm *tp; ParmList *templateparms = Getattr(primary, "templateparms");
int def_supplied = 0;
ParmList *temparms = CopyParmList(temparms_input);
p = instantiated_parameters; if (Equal(Getattr(primary, "templatetype"), "class")) {
tp = temparms; /* Templated class */
expanded_templateparms = CopyParmList(instantiated_parameters);
if (!p && ParmList_len(p) != ParmList_len(temparms)) { merge_parameters(expanded_templateparms, templateparms);
/* we have no template parameters supplied in %template for a template that has default args*/ /* Add default arguments from chosen template */
p = tp; ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(instantiated_parameters));
def_supplied = 1; if (defaults_start) {
ParmList *defaults = CopyParmList(defaults_start);
mark_defaults(defaults);
expanded_templateparms = ParmList_join(expanded_templateparms, defaults);
expand_defaults(expanded_templateparms);
}
} else {
/* Templated function */
/* TODO: Default template parameters support was only added in C++11 */
expanded_templateparms = CopyParmList(instantiated_parameters);
merge_parameters(expanded_templateparms, templateparms);
} }
while (p) { if (templateparms && (ParmList_len(templateparms) < ParmList_len(expanded_templateparms))) {
String *value = Getattr(p, "value"); SWIG_WARN_NODE_BEGIN(nn);
if (def_supplied) { Swig_warning(WARN_CPP11_VARIADIC_TEMPLATE, cparse_file, cparse_line, "Only the first variadic template argument is currently supported.\n");
Setattr(p, "default", "1"); SWIG_WARN_NODE_END(nn);
}
if (value) {
Setattr(tp, "value", value);
} else {
SwigType *ty = Getattr(p, "type");
if (ty) {
Setattr(tp, "type", ty);
}
Delattr(tp, "value");
}
/* fix default arg values */
if (targs) {
Parm *pi = temparms;
Parm *ti = targs;
String *tv = Getattr(tp, "value");
if (!tv) tv = Getattr(tp, "type");
while(pi != tp && ti && pi) {
String *name = Getattr(ti, "name");
String *value = Getattr(pi, "value");
if (!value) value = Getattr(pi, "type");
Replaceid(tv, name, value);
pi = nextSibling(pi);
ti = nextSibling(ti);
}
}
p = nextSibling(p);
tp = nextSibling(tp);
if (!p && tp) {
p = tp;
def_supplied = 1;
} else if (p && !tp) { /* Variadic template - tp < p */
SWIG_WARN_NODE_BEGIN(nn);
Swig_warning(WARN_CPP11_VARIADIC_TEMPLATE, cparse_file, cparse_line, "Only the first variadic template argument is currently supported.\n");
SWIG_WARN_NODE_END(nn);
break;
}
} }
return temparms; return expanded_templateparms;
} }

View file

@ -113,7 +113,47 @@ ParmList *CopyParmList(ParmList *p) {
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* int ParmList_numrequired(). Return number of required arguments * ParmList_join()
*
* Join two parameter lists. Appends p2 to the end of p.
* No copies are made.
* Returns start of joined parameter list.
* ----------------------------------------------------------------------------- */
ParmList *ParmList_join(ParmList *p, ParmList *p2) {
Parm *firstparm = p ? p : p2;
Parm *lastparm = p;
while (p) {
p = nextSibling(p);
if (p)
lastparm = p;
}
if (lastparm)
set_nextSibling(lastparm, p2);
return firstparm;
}
/* -----------------------------------------------------------------------------
* ParmList_nth_parm()
*
* return the nth parameter (0 based) in the parameter list
* ----------------------------------------------------------------------------- */
Parm *ParmList_nth_parm(ParmList *p, unsigned int n) {
while (p) {
if (n == 0)
break;
n--;
p = nextSibling(p);
}
return p;
}
/* -----------------------------------------------------------------------------
* ParmList_numrequired()
*
* Return number of required arguments
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
int ParmList_numrequired(ParmList *p) { int ParmList_numrequired(ParmList *p) {

View file

@ -19,10 +19,12 @@ extern Parm *NewParmNode(SwigType *type, Node *from_node);
extern Parm *CopyParm(Parm *p); extern Parm *CopyParm(Parm *p);
/* Parameter lists */ /* Parameter lists */
extern ParmList *CopyParmList(ParmList *); extern ParmList *CopyParmList(ParmList *p);
extern ParmList *CopyParmListMax(ParmList *, int count); extern ParmList *CopyParmListMax(ParmList *p, int count);
extern int ParmList_len(ParmList *); extern ParmList *ParmList_join(ParmList *p, ParmList *p2);
extern Parm *ParmList_nth_parm(ParmList *p, unsigned int n);
extern int ParmList_numrequired(ParmList *); extern int ParmList_numrequired(ParmList *);
extern int ParmList_len(ParmList *);
extern int ParmList_has_defaultargs(ParmList *p); extern int ParmList_has_defaultargs(ParmList *p);
extern int ParmList_has_varargs(ParmList *p); extern int ParmList_has_varargs(ParmList *p);