[Numpy-svn] r5066 - trunk/numpy/distutils

numpy-svn at scipy.org numpy-svn at scipy.org
Wed Apr 23 00:57:02 EDT 2008


Author: charris
Date: 2008-04-22 23:57:00 -0500 (Tue, 22 Apr 2008)
New Revision: 5066

Modified:
   trunk/numpy/distutils/conv_template.py
Log:
Add nested loops to the template processor.
The syntax is to separate the nested loops with lines containing strings
like

#repeat = 1#
#repeat = 2#
...

The number doesn't really matter, but it helps document the depth.

Example:

The file containing

/**begin repeat
 * # a = 1,2,3#
 * # b = 1,2,3#
 * # repeat = 1#
 * # c = 1,2#
 * # d = 1,2#
 */
@a@@b@@c@@d@
/**end repeat**/

produces


#line 1 "template.c.src"

/*
 *****************************************************************************
 **       This file was autogenerated from a template  DO NOT EDIT!!!!      **
 **       Changes should be made to the original source (.src) file         **
 *****************************************************************************
 */

#line 8
1111

#line 8
1122

#line 8
2211

#line 8
2222

#line 8
3311

#line 8
3322




Modified: trunk/numpy/distutils/conv_template.py
===================================================================
--- trunk/numpy/distutils/conv_template.py	2008-04-23 00:20:57 UTC (rev 5065)
+++ trunk/numpy/distutils/conv_template.py	2008-04-23 04:57:00 UTC (rev 5066)
@@ -46,7 +46,7 @@
 _special_names = {}
 
 template_re = re.compile(r"@([\w]+)@")
-named_re = re.compile(r"#([\w]*)=([^#]*?)#")
+named_re = re.compile(r"#\s*([\w]*)\s*=\s*([^#]*)#")
 
 parenrep = re.compile(r"[(]([^)]*?)[)]\*(\d+)")
 def paren_repl(obj):
@@ -55,15 +55,15 @@
     return ','.join([torep]*int(numrep))
 
 plainrep = re.compile(r"([^*]+)\*(\d+)")
-
 def conv(astr):
     # replaces all occurrences of '(a,b,c)*4' in astr
-    #  with 'a,b,c,a,b,c,a,b,c,a,b,c'
+    #  with 'a,b,c,a,b,c,a,b,c,a,b,c'. The result is
+    # split at ',' and a list of values returned.
     astr = parenrep.sub(paren_repl,astr)
     # replaces occurences of xxx*3 with xxx, xxx, xxx
     astr = ','.join([plainrep.sub(paren_repl,x.strip())
                      for x in astr.split(',')])
-    return astr
+    return astr.split(',')
 
 def unique_key(adict):
     # this obtains a unique key given a dictionary
@@ -82,52 +82,75 @@
     return newkey
 
 def expand_sub(substr, namestr, line):
-    # find all named replacements
+    # find all named replacements in the various loops.
     reps = named_re.findall(namestr)
+    nsubs = None
+    loops = []
     names = {}
     names.update(_special_names)
-    numsubs = None
     for rep in reps:
         name = rep[0].strip()
-        thelist = conv(rep[1])
-        names[name] = thelist
-
-    # make lists out of string entries in name dictionary
-    for name in names.keys():
-        entry = names[name]
-        entrylist = entry.split(',')
-        names[name] = entrylist
-        num = len(entrylist)
-        if numsubs is None:
-            numsubs = num
-        elif numsubs != num:
-            print namestr
-            print substr
+        vals = conv(rep[1])
+        size = len(vals)
+        if name == "repeat" :
+            names[None] = nsubs
+            loops.append(names)
+            nsubs = None
+            names = {}
+            continue
+        if nsubs is None :
+            nsubs = size
+        elif nsubs != size :
+            print name
+            print vals
             raise ValueError, "Mismatch in number to replace"
+        names[name] = vals
+    names[None] = nsubs
+    loops.append(names)
 
-    # now replace all keys for each of the lists
-    mystr = ''
-    thissub = [None]
+    # generate list of dictionaries, one for each template iteration
+    def merge(d1,d2) :
+        tmp = d1.copy()
+        tmp.update(d2)
+        return tmp
+
+    dlist = [{}]
+    for d in loops :
+        nsubs = d.pop(None)
+        tmp = [{} for i in range(nsubs)]
+        for name, item in d.items() :
+            for i in range(nsubs) :
+                tmp[i][name] = item[i]
+        dlist = [merge(d1,d2) for d1 in dlist for d2 in tmp]
+
+    # now replace all keys for each of the dictionaries
     def namerepl(match):
         name = match.group(1)
-        return names[name][thissub[0]]
-    for k in range(numsubs):
-        thissub[0] = k
-        mystr += ("#line %d\n%s\n\n"
-                  % (line, template_re.sub(namerepl, substr)))
+        return d[name]
+
+    mystr = []
+    header = "#line %d\n"%line
+    for d in dlist :
+        code = ''.join((header, template_re.sub(namerepl, substr), '\n'))
+        mystr.append(code)
+
     return mystr
 
 
-_head = \
-"""/*  This file was autogenerated from a template  DO NOT EDIT!!!!
-       Changes should be made to the original source (.src) file
-*/
+header =\
+"""
+/*
+ *****************************************************************************
+ **       This file was autogenerated from a template  DO NOT EDIT!!!!      **
+ **       Changes should be made to the original source (.src) file         **
+ *****************************************************************************
+ */
 
 """
 
 def get_line_header(str,beg):
     extra = []
-    ind = beg-1
+    ind = beg - 1
     char = str[ind]
     while (ind > 0) and (char != '\n'):
         extra.insert(0,char)
@@ -136,25 +159,24 @@
     return ''.join(extra)
 
 def process_str(allstr):
-    newstr = allstr
-    writestr = _head
+    code = [header]
+    struct = parse_structure(allstr)
 
-    struct = parse_structure(newstr)
     #  return a (sorted) list of tuples for each begin repeat section
     #  each tuple is the start and end of a region to be template repeated
-
     oldend = 0
     for sub in struct:
-        writestr += newstr[oldend:sub[0]]
-        expanded = expand_sub(newstr[sub[1]:sub[2]],
-                              newstr[sub[0]:sub[1]], sub[4])
-        writestr += expanded
+        pref = allstr[oldend:sub[0]]
+        head = allstr[sub[0]:sub[1]]
+        text = allstr[sub[1]:sub[2]]
+        line = sub[4]
         oldend =  sub[3]
+        code.append(pref)
+        code.extend(expand_sub(text,head,line))
+    code.append(allstr[oldend:])
+    return ''.join(code)
 
 
-    writestr += newstr[oldend:]
-    return writestr
-
 include_src_re = re.compile(r"(\n|\A)#include\s*['\"]"
                             r"(?P<name>[\w\d./\\]+[.]src)['\"]", re.I)
 
@@ -184,6 +206,7 @@
     return ('#line 1 "%s"\n%s'
             % (sourcefile, process_str(''.join(lines))))
 
+
 if __name__ == "__main__":
 
     try:
@@ -200,3 +223,4 @@
     allstr = fid.read()
     writestr = process_str(allstr)
     outfile.write(writestr)
+




More information about the Numpy-svn mailing list