From 1e73045da851c3e8bda1250b224fd7ffa2f5dce1 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 12 Dec 2022 23:37:21 +0000 Subject: Refactor Swig_cparse_template_parms_expand() Break up functionality in Swig_cparse_template_parms_expand() to make it more readable / maintainable. --- Source/CParse/cparse.h | 2 +- Source/CParse/parser.y | 6 +- Source/CParse/templ.c | 147 ++++++++++++++++++++++++++++++------------------- Source/Swig/parms.c | 42 +++++++++++++- Source/Swig/swigparm.h | 8 ++- 5 files changed, 140 insertions(+), 65 deletions(-) (limited to 'Source') diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h index 6fe9215f7..039e97de7 100644 --- a/Source/CParse/cparse.h +++ b/Source/CParse/cparse.h @@ -68,7 +68,7 @@ extern "C" { 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 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 } diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y index 5075f8a04..9cdd2d0f6 100644 --- a/Source/CParse/parser.y +++ b/Source/CParse/parser.y @@ -2892,12 +2892,10 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va continue; } else { String *tname = Copy($5); - /* Expand the template */ 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); update_nested_classes(templnode); /* update classes nested within template */ diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c index a9952a623..2317b892f 100644 --- a/Source/CParse/templ.c +++ b/Source/CParse/templ.c @@ -1006,74 +1006,109 @@ Node *Swig_cparse_template_locate(String *name, Parm *tparms, String *symname, S } /* ----------------------------------------------------------------------------- - * Swig_cparse_template_parms_expand() + * merge_parameters() * - * instantiated_parameters: template parameters passed to %template - * temparms_inputs: template parameters to use as starting point - * targs: primary template parameters, default args copied from here - * nn: template node (just used for warning) + * expanded_templateparms are the template parameters passed to %template. + * This function adds missing parameter name and type attributes from the chosen + * template (templateparms). * - * Expand the instantiated_parameters and return a parameter list with default - * arguments filled in where necessary. + * Grab the parameter names from templateparms. + * Non-type template parameters have no type information in expanded_templateparms. + * Grab them from templateparms. * ----------------------------------------------------------------------------- */ -ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, ParmList *temparms_input, Parm *targs, Node *nn) { - Parm *p; - Parm *tp; - int def_supplied = 0; - ParmList *temparms = CopyParmList(temparms_input); +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); + } +} - p = instantiated_parameters; - tp = temparms; +/* ----------------------------------------------------------------------------- + * mark_defaults() + * + * Mark all the template parameters that are expanded from a default value + * ----------------------------------------------------------------------------- */ - if (!p && ParmList_len(p) != ParmList_len(temparms)) { - /* we have no template parameters supplied in %template for a template that has default args*/ - p = tp; - def_supplied = 1; +static void mark_defaults(ParmList *defaults) { + Parm *tp = defaults; + while (tp) { + Setattr(tp, "default", "1"); + tp = nextSibling(tp); } +} - while (p) { - String *value = Getattr(p, "value"); - if (def_supplied) { - Setattr(p, "default", "1"); - } - 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"); +/* ----------------------------------------------------------------------------- + * 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); - pi = nextSibling(pi); - ti = nextSibling(ti); - } + p = nextSibling(p); } - - 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; + } +} + +/* ----------------------------------------------------------------------------- + * Swig_cparse_template_parms_expand() + * + * instantiated_parameters: template parameters passed to %template + * primary: primary template node + * + * Expand the instantiated_parameters and return a parameter list with default + * arguments filled in where necessary. + * ----------------------------------------------------------------------------- */ + +ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary) { + ParmList *expanded_templateparms = 0; + ParmList *templateparms = Getattr(primary, "templateparms"); + + if (Equal(Getattr(primary, "templatetype"), "class")) { + /* Templated class */ + expanded_templateparms = CopyParmList(instantiated_parameters); + merge_parameters(expanded_templateparms, templateparms); + /* Add default arguments from chosen template */ + ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(instantiated_parameters)); + 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); + } + + if (templateparms && (ParmList_len(templateparms) < ParmList_len(expanded_templateparms))) { + 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); } - return temparms; + return expanded_templateparms; } diff --git a/Source/Swig/parms.c b/Source/Swig/parms.c index 11071ce0c..ab767bd76 100644 --- a/Source/Swig/parms.c +++ b/Source/Swig/parms.c @@ -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) { diff --git a/Source/Swig/swigparm.h b/Source/Swig/swigparm.h index 7b63546ec..77d96aef6 100644 --- a/Source/Swig/swigparm.h +++ b/Source/Swig/swigparm.h @@ -19,10 +19,12 @@ extern Parm *NewParmNode(SwigType *type, Node *from_node); extern Parm *CopyParm(Parm *p); /* Parameter lists */ -extern ParmList *CopyParmList(ParmList *); -extern ParmList *CopyParmListMax(ParmList *, int count); -extern int ParmList_len(ParmList *); +extern ParmList *CopyParmList(ParmList *p); +extern ParmList *CopyParmListMax(ParmList *p, int count); +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_len(ParmList *); extern int ParmList_has_defaultargs(ParmList *p); extern int ParmList_has_varargs(ParmList *p); -- cgit v1.2.1