summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2022-12-12 23:37:21 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2022-12-21 20:15:47 +0000
commit1e73045da851c3e8bda1250b224fd7ffa2f5dce1 (patch)
tree9388c880fdda2c26bfb27e6fc67b195b80812fd2 /Source
parent9e8a0daf9e48ffa3f9d3552b86bebdf530a45dc7 (diff)
downloadswig-1e73045da851c3e8bda1250b224fd7ffa2f5dce1.tar.gz
Refactor Swig_cparse_template_parms_expand()
Break up functionality in Swig_cparse_template_parms_expand() to make it more readable / maintainable.
Diffstat (limited to 'Source')
-rw-r--r--Source/CParse/cparse.h2
-rw-r--r--Source/CParse/parser.y6
-rw-r--r--Source/CParse/templ.c147
-rw-r--r--Source/Swig/parms.c42
-rw-r--r--Source/Swig/swigparm.h8
5 files changed, 140 insertions, 65 deletions
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);