Package instant :: Module codegeneration
[hide private]
[frames] | no frames]

Source Code for Module instant.codegeneration

  1  """This module contains helper functions for code generation.""" 
  2   
  3  import re 
  4  from output import instant_assert, instant_warning, instant_debug, write_file 
  5   
  6   
7 -def mapstrings(format, sequence):
8 return "\n".join(format % i for i in sequence)
9 10
11 -def reindent(code):
12 '''Reindent a multiline string to allow easier to read syntax. 13 14 Each line will be indented relative to the first non-empty line. 15 Start the first line without text like shown in this example:: 16 17 code = reindent(""" 18 Foo 19 Bar 20 Blatti 21 Ping 22 """) 23 24 makes all indentation relative to Foo. 25 ''' 26 lines = code.split("\n") 27 space = "" 28 # Get initial spaces from first non-empty line: 29 for l in lines: 30 if l: 31 r = re.search(r"^( [ ]*)", l) 32 if r is not None: 33 space = r.groups()[0] 34 break 35 if not space: 36 return code 37 n = len(space) 38 instant_assert(space == " "*n, "Logic breach in reindent.") 39 return "\n".join(re.sub(r"^%s" % space, "", l) for l in lines)
40 41
42 -def write_interfacefile(filename, modulename, code, init_code, 43 additional_definitions, additional_declarations, 44 system_headers, local_headers, wrap_headers, arrays):
45 """Generate a SWIG interface file. Intended for internal library use. 46 47 The input arguments are as follows: 48 - modulename (Name of the module) 49 - code (Code to be wrapped) 50 - init_code (Code to put in the init section of the interface file) 51 - additional_definitions (FIXME: comment) 52 - additional_declarations (FIXME: comment) 53 - system_headers (A list of system headers with declarations needed by the wrapped code) 54 - local_headers (A list of local headers with declarations needed by the wrapped code) 55 - wrap_headers (A list of local headers that will be included in the code and wrapped by SWIG) 56 - arrays (FIXME: comment) 57 58 The result of this function is that a SWIG interface with 59 the name modulename.i is written to the current directory. 60 """ 61 instant_debug("Generating SWIG interface file '%s'." % filename) 62 63 # create typemaps 64 typemaps = "" 65 for a in arrays: 66 # 1 dimentional arrays, ie. vectors 67 if (len(a) == 2): 68 typemaps += reindent(""" 69 %%typemap(in) (int %(n)s,double* %(array)s){ 70 if (!PyArray_Check($input)) { 71 PyErr_SetString(PyExc_TypeError, "Not a NumPy array"); 72 return NULL; ; 73 } 74 PyArrayObject* pyarray; 75 pyarray = (PyArrayObject*)$input; 76 $1 = int(pyarray->dimensions[0]); 77 $2 = (double*)pyarray->data; 78 } 79 """ % { 'n' : a[0] , 'array' : a[1] }) 80 # n dimentional arrays, ie. matrices and tensors 81 elif (len(a) == 3): 82 typemaps += reindent(""" 83 %%typemap(in) (int %(n)s,int* %(ptv)s,double* %(array)s){ 84 if (!PyArray_Check($input)) { 85 PyErr_SetString(PyExc_TypeError, "Not a NumPy array"); 86 return NULL; ; 87 } 88 PyArrayObject* pyarray; 89 pyarray = (PyArrayObject*)$input; 90 $1 = int(pyarray->nd); 91 int* dims = new int($1); 92 for (int d=0; d<$1; d++) { 93 dims[d] = int(pyarray->dimensions[d]); 94 } 95 96 $2 = dims; 97 $3 = (double*)pyarray->data; 98 } 99 %%typemap(freearg) (int %(n)s,int* %(ptv)s,double* %(array)s){ 100 // deleting dims 101 delete $2; 102 } 103 """ % { 'n' : a[0] , 'ptv' : a[1], 'array' : a[2] }) 104 # end if 105 # end for 106 107 system_headers_code = mapstrings('#include <%s>', system_headers) 108 local_headers_code = mapstrings('#include "%s"', local_headers) 109 wrap_headers_code1 = mapstrings('#include "%s"', wrap_headers) 110 wrap_headers_code2 = mapstrings('%%include "%s"', wrap_headers) 111 112 interface_string = reindent(""" 113 %%module %(modulename)s 114 //%%module (directors="1") %(modulename)s 115 116 //%%feature("director"); 117 118 %%{ 119 #include <iostream> 120 %(additional_definitions)s 121 %(system_headers_code)s 122 %(local_headers_code)s 123 %(wrap_headers_code1)s 124 %(code)s 125 %%} 126 127 //%%feature("autodoc", "1"); 128 %%init%%{ 129 %(init_code)s 130 %%} 131 132 %(additional_definitions)s 133 %(additional_declarations)s 134 %(wrap_headers_code2)s 135 //%(typemaps)s 136 %(code)s; 137 138 """ % locals()) 139 140 write_file(filename, interface_string) 141 instant_debug("Done generating interface file.")
142 143
144 -def write_setup(filename, modulename, csrcs, cppsrcs, local_headers, include_dirs, library_dirs, libraries, swigargs, cppargs, lddargs):
145 """Generate a setup.py file. Intended for internal library use.""" 146 instant_debug("Generating %s." % filename) 147 #instant_warning("FIXME: Not using csrcs in write_setupfile().") 148 149 # Handle arguments 150 swigfilename = "%s.i" % modulename 151 wrapperfilename = "%s_wrap.cxx" % modulename 152 153 cppsrcs = cppsrcs + [wrapperfilename] 154 155 swig_args = "" 156 if swigargs: 157 swig_args = " ".join(swigargs) 158 159 compile_args = "" 160 if cppargs: 161 compile_args = ", extra_compile_args=%r" % cppargs 162 163 link_args = "" 164 if lddargs: 165 link_args = ", extra_link_args=%r" % lddargs 166 167 inc_dir = "" 168 if len(local_headers) > 0: 169 inc_dir = "-I.." 170 171 # Generate code 172 code = reindent(""" 173 import os 174 from distutils.core import setup, Extension 175 name = '%s' 176 swig_cmd ='swig -python %s %s %s' 177 os.system(swig_cmd) 178 sources = %s 179 setup(name = '%s', 180 ext_modules = [Extension('_' + '%s', 181 sources, 182 include_dirs=%s, 183 library_dirs=%s, 184 libraries=%s %s %s)]) 185 """ % (modulename, inc_dir, swig_args, swigfilename, cppsrcs, 186 modulename, modulename, include_dirs, library_dirs, libraries, compile_args, link_args)) 187 188 write_file(filename, code) 189 instant_debug("Done writing setup.py file.")
190 191
192 -def _test_write_interfacefile():
193 modulename = "testmodule" 194 code = "void foo() {}" 195 init_code = "/* custom init code */" 196 additional_definitions = "/* custom definitions */" 197 additional_declarations = "/* custom declarations */" 198 system_headers = ["system_header1.h", "system_header2.h"] 199 local_headers = ["local_header1.h", "local_header2.h"] 200 wrap_headers = ["wrap_header1.h", "wrap_header2.h"] 201 arrays = [] # FIXME: Example input here 202 203 write_interfacefile("%s.i" % modulename, modulename, code, init_code, additional_definitions, additional_declarations, system_headers, local_headers, wrap_headers, arrays) 204 print "".join(open("%s.i" % modulename).readlines())
205 206
207 -def _test_write_setup():
208 modulename = "testmodule" 209 csrcs = ["csrc1.c", "csrc2.c"] 210 cppsrcs = ["cppsrc1.cpp", "cppsrc2.cpp"] 211 local_headers = ["local_header1.h", "local_header2.h"] 212 include_dirs = ["includedir1", "includedir2"] 213 library_dirs = ["librarydir1", "librarydir2"] 214 libraries = ["lib1", "lib2"] 215 swigargs = ["-Swigarg1", "-Swigarg2"] 216 cppargs = ["-cpparg1", "-cpparg2"] 217 lddargs = ["-Lddarg1", "-Lddarg2"] 218 219 write_setup("setup.py", modulename, csrcs, cppsrcs, local_headers, include_dirs, library_dirs, libraries, swigargs, cppargs, lddargs) 220 print "".join(open("setup.py").readlines())
221 222 223 if __name__ == "__main__": 224 _test_write_interfacefile() 225 print "\n"*3 226 _test_write_setup() 227