Changeset c01ed3e in sasmodels
- Timestamp:
- Dec 22, 2017 6:48:12 PM (7 years ago)
- Children:
- 15be191
- Parents:
- 2694cb8
- git-author:
- Paul Kienzle <pkienzle@…> (12/22/17 18:46:46)
- git-committer:
- Paul Kienzle <pkienzle@…> (12/22/17 18:48:12)
- Location:
- sasmodels
- Files:
-
- 1 deleted
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/autoc.py
r67cc0ff rc01ed3e 4 4 from __future__ import print_function 5 5 6 import ast7 6 import inspect 8 from functools import reduce9 7 10 8 import numpy as np … … 96 94 # Claim all constants are declared on line 1 97 95 snippets.append('#line 1 "%s"'%escaped_filename) 98 snippets.append( define_constant(name, obj))96 snippets.append(py2c.define_constant(name, obj)) 99 97 elif isinstance(obj, special.Gauss): 100 98 for var, value in zip(("N", "Z", "W"), (obj.n, obj.z, obj.w)): … … 102 100 constants[var] = value 103 101 snippets.append('#line 1 "%s"'%escaped_filename) 104 snippets.append( define_constant(var, value))102 snippets.append(py2c.define_constant(var, value)) 105 103 #libs.append('lib/gauss%d.c'%obj.n) 106 104 source = (source.replace(name+'.n', 'GAUSS_N') … … 121 119 122 120 # translate source 123 ordered_code = [code[name] for name in ordered_dag(depends) if name in code]121 ordered_code = [code[name] for name in py2c.ordered_dag(depends) if name in code] 124 122 functions = py2c.translate(ordered_code, constants) 125 123 snippets.extend(functions) … … 129 127 info.c_code = "\n".join(snippets) 130 128 info.Iq = info.Iqac = info.Iqabc = info.Iqxy = info.form_volume = None 131 132 def define_constant(name, value):133 if isinstance(value, int):134 parts = ["int ", name, " = ", "%d"%value, ";"]135 elif isinstance(value, float):136 parts = ["double ", name, " = ", "%.15g"%value, ";"]137 else:138 # extend constant arrays to a multiple of 4; not sure if this139 # is necessary, but some OpenCL targets broke if the number140 # of parameters in the parameter table was not a multiple of 4,141 # so do it for all constant arrays to be safe.142 if len(value)%4 != 0:143 value = list(value) + [0.]*(4 - len(value)%4)144 elements = ["%.15g"%v for v in value]145 parts = ["double ", name, "[]", " = ",146 "{\n ", ", ".join(elements), "\n};"]147 return "".join(parts)148 149 150 # Modified from the following:151 #152 # http://code.activestate.com/recipes/578272-topological-sort/153 # Copyright (C) 2012 Sam Denton154 # License: MIT155 def ordered_dag(dag):156 # type: (Dict[T, Set[T]]) -> Iterator[T]157 dag = dag.copy()158 159 # make leaves depend on the empty set160 leaves = reduce(set.union, dag.values()) - set(dag.keys())161 dag.update({node: set() for node in leaves})162 while True:163 leaves = set(node for node, links in dag.items() if not links)164 if not leaves:165 break166 for node in leaves:167 yield node168 dag = {node: (links-leaves)169 for node, links in dag.items() if node not in leaves}170 if dag:171 raise ValueError("Cyclic dependes exists amongst these items:\n%s"172 % ", ".join(str(node) for node in dag.keys())) -
sasmodels/modelinfo.py
r67cc0ff rc01ed3e 810 810 info.sesans = getattr(kernel_module, 'sesans', None) # type: ignore 811 811 # Default single and opencl to True for C models. Python models have callable Iq. 812 info.opencl = getattr(kernel_module, 'opencl', not callable(info.Iq))813 info.single = getattr(kernel_module, 'single', not callable(info.Iq))814 812 info.random = getattr(kernel_module, 'random', None) 815 813 … … 827 825 except Exception as exc: 828 826 logger.warn(str(exc) + " while converting %s from C to python"%name) 827 828 # Needs to come after autoc.convert since the Iq symbol may have been 829 # converted from python to C 830 info.opencl = getattr(kernel_module, 'opencl', not callable(info.Iq)) 831 info.single = getattr(kernel_module, 'single', not callable(info.Iq)) 829 832 830 833 if callable(info.Iq) and parameters.has_2d: -
sasmodels/models/_cylpy.py
r67cc0ff rc01ed3e 140 140 py2c = True 141 141 142 # TODO: "#define INVALID (expr)" is not supported 142 143 def invalid(v): 143 144 return v.radius < 0 or v.length < 0 … … 206 207 phi_pd=10, phi_pd_n=5) 207 208 208 qx, qy = 0.2 * np.cos(2.5), 0.2 * np.sin(2.5)209 qx, qy = 0.2 * cos(2.5), 0.2 * sin(2.5) 209 210 # After redefinition of angles, find new tests values. Was 10 10 in old coords 210 211 tests = [ -
sasmodels/py2c.py
r7b1dcf9 rc01ed3e 1 2 1 """ 3 codegen 4 ~~~~~~~ 5 6 Extension to ast that allow ast -> python code generation. 7 8 :copyright: Copyright 2008 by Armin Ronacher. 9 :license: BSD. 10 """ 11 """ 2 py2c 3 ~~~~ 4 5 Convert simple numeric python code into C code. 6 7 The translate() function works on 8 12 9 Variables definition in C 13 10 ------------------------- 14 Defining variables within the Translate function is a bit of a guess work,15 using following rules .11 Defining variables within the translate function is a bit of a guess work, 12 using following rules: 16 13 * By default, a variable is a 'double'. 17 14 * Variable in a for loop is an int. … … 19 16 variable within the brackets is integer. For example, in the 20 17 reference 'var1[var2]', var1 is a double array, and var2 is an integer. 21 * Assignment to an argument makes that argument an array, and the index in22 that assignment is 0.23 For example, the following python code 18 * Assignment to an argument makes that argument an array, and the index 19 in that assignment is 0. 20 For example, the following python code:: 24 21 def func(arg1, arg2): 25 22 arg2 = 17. 26 is translated to the following C code 23 is translated to the following C code:: 27 24 double func(double arg1) 28 25 { 29 26 arg2[0] = 17.0; 30 27 } 31 For example, the following python code is translated to the following C code 28 For example, the following python code is translated to the 29 following C code:: 30 32 31 def func(arg1, arg2): double func(double arg1) { 33 32 arg2 = 17. arg2[0] = 17.0; 34 33 } 35 * All functions are defined as double, even if there is no return statement. 36 37 34 * All functions are defined as double, even if there is no 35 return statement. 36 37 Based on codegen.py: 38 39 :copyright: Copyright 2008 by Armin Ronacher. 40 :license: BSD. 41 """ 42 """ 38 43 Update Notes 39 44 ============ 40 11/22 14:15, O.E. Each 'visit_*' method is to build a C statement string. It45 11/22/2017, O.E. Each 'visit_*' method is to build a C statement string. It 41 46 shold insert 4 blanks per indentation level. 42 47 The 'body' method will combine all the strings, by adding … … 52 57 12/07/2017, OE: Translation of integer division, '\\' in python, implemented 53 58 in translate_integer_divide, called from visit_BinOp 54 12/07/2017, OE: C variable definition handled in 'define_ C_Vars'59 12/07/2017, OE: C variable definition handled in 'define_c_vars' 55 60 : Python integer division, '//', translated to C in 56 61 'translate_integer_divide' … … 102 107 103 108 104 def to_source(node, func_name, constants=None): 105 """This function can convert a node tree back into python sourcecode. 106 This is useful for debugging purposes, especially if you're dealing with 107 custom asts not generated by python itself. 108 109 It could be that the sourcecode is evaluable when the AST itself is not 110 compilable / evaluable. The reason for this is that the AST contains some 111 more data than regular sourcecode does, which is dropped during 112 conversion. 113 114 Each level of indentation is replaced with `indent_with`. Per default this 115 parameter is equal to four spaces as suggested by PEP 8, but it might be 116 adjusted to match the application's styleguide. 117 118 If `add_line_information` is set to `True` comments for the line numbers 119 of the nodes are added to the output. This can be used to spot wrong line 120 number information of statement nodes. 109 def to_source(tree, constants=None, fname=None, lineno=0): 121 110 """ 122 generator = SourceGenerator(' ' * 4, False, constants) 123 generator.visit(node) 124 125 return ''.join(generator.c_proc) 111 This function can convert a syntax tree into C sourcecode. 112 """ 113 generator = SourceGenerator(constants=constants, fname=fname, lineno=lineno) 114 generator.visit(tree) 115 c_code = "\n".join(generator.c_proc) 116 return c_code 126 117 127 118 def isevaluable(s): … … 129 120 eval(s) 130 121 return True 131 except :122 except Exception: 132 123 return False 133 124 … … 138 129 """ 139 130 140 def __init__(self, indent_with, add_line_information=False, constants=None): 131 def __init__(self, indent_with=" ", add_line_information=False, 132 constants=None, fname=None, lineno=0): 141 133 self.result = [] 142 134 self.indent_with = indent_with … … 144 136 self.indentation = 0 145 137 self.new_lines = 0 138 139 # for C 146 140 self.c_proc = [] 147 # for C148 141 self.signature_line = 0 149 142 self.arguments = [] 150 self.name = "" 143 self.current_function = "" 144 self.fname = fname 145 self.lineno_offset = lineno 151 146 self.warnings = [] 152 self. Statements = []147 self.statements = [] 153 148 self.current_statement = "" 154 self.strMethodSignature = "" 155 self.C_Vars = [] 156 self.C_IntVars = [] 157 self.MathIncludeed = False 158 self.C_Pointers = [] 159 self.C_DclPointers = [] 160 self.C_Functions = [] 161 self.C_Vectors = [] 162 self.C_Constants = constants 163 self.SubRef = False 164 self.InSubscript = False 165 self.Tuples = [] 149 # TODO: use set rather than list for c_vars, ... 150 self.c_vars = [] 151 self.c_int_vars = [] 152 self.c_pointers = [] 153 self.c_dcl_pointers = [] 154 self.c_functions = [] 155 self.c_vectors = [] 156 self.c_constants = constants if constants is not None else {} 157 self.in_subref = False 158 self.in_subscript = False 159 self.tuples = [] 166 160 self.required_functions = [] 167 161 self.is_sequence = False … … 176 170 self.result.append(x) 177 171 178 def write_c(self, x): 179 self.current_statement += x 180 181 def add_c_line(self, x): 182 string = '' 183 for _ in range(self.indentation): 184 string += (" ") 185 string += str(x) 186 self.c_proc.append(str(string + "\n")) 187 x = '' 172 def write_c(self, statement): 173 # TODO: build up as a list rather than adding to string 174 self.current_statement += statement 175 176 def add_c_line(self, line): 177 indentation = self.indent_with * self.indentation 178 self.c_proc.append("".join((indentation, line, "\n"))) 188 179 189 180 def add_current_line(self): … … 192 183 self.current_statement = '' 193 184 194 def AddUniqueVar(self, new_var):195 if new_var not in self. C_Vars:196 self. C_Vars.append(str(new_var))197 198 def WriteSincos(self, node):185 def add_unique_var(self, new_var): 186 if new_var not in self.c_vars: 187 self.c_vars.append(str(new_var)) 188 189 def write_sincos(self, node): 199 190 angle = str(node.args[0].id) 200 191 self.write_c(node.args[1].id + " = sin(" + angle + ");") … … 203 194 self.add_current_line() 204 195 for arg in node.args: 205 self. AddUniqueVar(arg.id)196 self.add_unique_var(arg.id) 206 197 207 198 def newline(self, node=None, extra=0): … … 211 202 self.new_lines = 1 212 203 if self.current_statement: 213 self. Statements.append(self.current_statement)204 self.statements.append(self.current_statement) 214 205 self.current_statement = '' 215 206 … … 278 269 self.visit(node.msg) 279 270 280 def define_ C_Vars(self, target):271 def define_c_vars(self, target): 281 272 if hasattr(target, 'id'): 282 273 # a variable is considered an array if it apears in the agrument list … … 287 278 # return 288 279 # 289 if target.id not in self. C_Vars:280 if target.id not in self.c_vars: 290 281 if target.id in self.arguments: 291 282 idx = self.arguments.index(target.id) 292 283 new_target = self.arguments[idx] + "[0]" 293 if new_target not in self. C_Pointers:284 if new_target not in self.c_pointers: 294 285 target.id = new_target 295 self. C_Pointers.append(self.arguments[idx])286 self.c_pointers.append(self.arguments[idx]) 296 287 else: 297 self. C_Vars.append(target.id)288 self.c_vars.append(target.id) 298 289 299 290 def add_semi_colon(self): … … 308 299 if idx: 309 300 self.write_c(' = ') 310 self.define_ C_Vars(target)301 self.define_c_vars(target) 311 302 self.visit(target) 312 if self.Tuples:313 tplTargets = list(self.Tuples)314 del self.Tuples[:]303 # Capture assigned tuple names, if any 304 targets = self.tuples[:] 305 del self.tuples[:] 315 306 self.write_c(' = ') 316 307 self.is_sequence = False … … 319 310 self.add_semi_colon() 320 311 self.add_current_line() 321 for n, item in enumerate(self.Tuples): 322 self.visit(tplTargets[n]) 312 # Assign tuples to tuples, if any 313 # TODO: doesn't handle swap: a,b = b,a 314 for target, item in zip(targets, self.tuples): 315 self.visit(target) 323 316 self.write_c(' = ') 324 317 self.visit(item) … … 328 321 for target in node.targets: 329 322 if hasattr(target, 'id'): 330 if target.id in self. C_Vars and target.id not in self.C_DclPointers:331 if target.id not in self. C_DclPointers:332 self. C_DclPointers.append(target.id)333 if target.id in self. C_Vars:334 self. C_Vars.remove(target.id)323 if target.id in self.c_vars and target.id not in self.c_dcl_pointers: 324 if target.id not in self.c_dcl_pointers: 325 self.c_dcl_pointers.append(target.id) 326 if target.id in self.c_vars: 327 self.c_vars.remove(target.id) 335 328 self.current_statement = '' 336 329 337 330 def visit_AugAssign(self, node): 338 if node.target.id not in self. C_Vars:331 if node.target.id not in self.c_vars: 339 332 if node.target.id not in self.arguments: 340 self. C_Vars.append(node.target.id)333 self.c_vars.append(node.target.id) 341 334 self.visit(node.target) 342 335 self.write_c(' ' + BINOP_SYMBOLS[type(node.op)] + '= ') … … 346 339 347 340 def visit_ImportFrom(self, node): 341 return # import ignored 348 342 self.newline(node) 349 343 self.write_python('from %s%s import ' %('.' * node.level, node.module)) … … 354 348 355 349 def visit_Import(self, node): 350 return # import ignored 356 351 self.newline(node) 357 352 for item in node.names: … … 363 358 self.generic_visit(node) 364 359 365 def listToDeclare(self, vars): 366 return ", ".join(vars) 367 368 def write_C_Pointers(self, start_var): 369 if self.C_DclPointers: 360 def write_c_pointers(self, start_var): 361 if self.c_dcl_pointers: 370 362 var_list = [] 371 for c_ptr in self.C_DclPointers: 372 if(len(vars) > 0): 373 vars += ", " 363 for c_ptr in self.c_dcl_pointers: 374 364 if c_ptr not in self.arguments: 375 365 var_list.append("*" + c_ptr) 376 if c_ptr in self. C_Vars:377 self. C_Vars.remove(c_ptr)366 if c_ptr in self.c_vars: 367 self.c_vars.remove(c_ptr) 378 368 if var_list: 379 369 c_dcl = " double " + ", ".join(var_list) + ";\n" … … 382 372 return start_var 383 373 384 def insert_ C_Vars(self, start_var):385 fLine= False386 start_var = self.write_ C_Pointers(start_var)387 if self. C_IntVars:388 for var in self. C_IntVars:389 if var in self. C_Vars:390 self. C_Vars.remove(var)391 s = self.listToDeclare(self.C_IntVars)392 self.c_proc.insert(start_var, " int " + s + ";\n")393 fLine= True374 def insert_c_vars(self, start_var): 375 have_decls = False 376 start_var = self.write_c_pointers(start_var) 377 if self.c_int_vars: 378 for var in self.c_int_vars: 379 if var in self.c_vars: 380 self.c_vars.remove(var) 381 decls = ", ".join(self.c_int_vars) 382 self.c_proc.insert(start_var, " int " + decls + ";\n") 383 have_decls = True 394 384 start_var += 1 395 385 396 if self. C_Vars:397 s = self.listToDeclare(self.C_Vars)398 self.c_proc.insert(start_var, " double " + s + ";\n")399 fLine= True386 if self.c_vars: 387 decls = ", ".join(self.c_vars) 388 self.c_proc.insert(start_var, " double " + decls + ";\n") 389 have_decls = True 400 390 start_var += 1 401 391 402 if self.C_Vectors: 403 s = self.listToDeclare(self.C_Vectors) 404 for n in range(len(self.C_Vectors)): 405 name = "vec" + str(n+1) 406 c_dcl = " double " + name + "[] = {" + self.C_Vectors[n] + "};" 407 self.c_proc.insert(start_var, c_dcl + "\n") 392 if self.c_vectors: 393 for vec_number, vec_value in enumerate(self.c_vectors): 394 name = "vec" + str(vec_number + 1) 395 decl = " double " + name + "[] = {" + vec_value + "};" 396 self.c_proc.insert(start_var, decl + "\n") 408 397 start_var += 1 409 398 410 del self. C_Vars[:]411 del self. C_IntVars[:]412 del self. C_Vectors[:]413 del self. C_Pointers[:]414 self.C_DclPointers415 if fLine:399 del self.c_vars[:] 400 del self.c_int_vars[:] 401 del self.c_vectors[:] 402 del self.c_pointers[:] 403 del self.c_dcl_pointers[:] 404 if have_decls: 416 405 self.c_proc.insert(start_var, "\n") 417 406 418 def InsertSignature(self):407 def insert_signature(self): 419 408 arg_decls = [] 420 409 for arg in self.arguments: 421 410 decl = "double " + arg 422 if arg in self. C_Pointers:411 if arg in self.c_pointers: 423 412 decl += "[]" 424 413 arg_decls.append(decl) 425 414 args_str = ", ".join(arg_decls) 426 self.strMethodSignature = 'double ' + self.name+ '(' + args_str + ")"415 method_sig = 'double ' + self.current_function + '(' + args_str + ")" 427 416 if self.signature_line >= 0: 428 self.c_proc.insert(self.signature_line, self.strMethodSignature)417 self.c_proc.insert(self.signature_line, method_sig) 429 418 430 419 def visit_FunctionDef(self, node): 420 if self.current_function: 421 self.unsupported(node, "function within a function") 422 self.current_function = node.name 423 431 424 self.newline(extra=1) 432 425 self.decorators(node) 433 426 self.newline(node) 434 427 self.arguments = [] 435 self.name = node.name436 #if self.name not in self.required_functions[0]:437 # return438 #print("Parsing '" + self.name + "'")439 440 428 self.visit(node.args) 441 429 # for C 442 430 self.signature_line = len(self.c_proc) 443 #self.add_c_line(self.strMethodSignature)444 431 self.add_c_line("\n{") 445 432 start_vars = len(self.c_proc) + 1 446 433 self.body(node.body) 447 434 self.add_c_line("}\n") 448 self.InsertSignature() 449 self.insert_C_Vars(start_vars) 450 self.C_Pointers = [] 435 self.insert_signature() 436 self.insert_c_vars(start_vars) 437 self.c_pointers = [] 438 self.current_function = "" 451 439 452 440 def visit_ClassDef(self, node): … … 511 499 break 512 500 513 def getNodeLineNo(self, node): 514 line_number = -1 515 if hasattr(node, 'value'): 516 line_number = node.value.lineno 517 elif hasattr(node, 'iter'): 518 if hasattr(node.iter, 'lineno'): 519 line_number = node.iter.lineno 520 return line_number 521 522 def GetNodeAsString(self, node): 523 res = '' 524 if hasattr(node, 'n'): 525 res = str(node.n) 526 elif hasattr(node, 'id'): 527 res = node.id 528 return res 529 530 def GetForRange(self, node): 501 def get_for_range(self, node): 531 502 stop = "" 532 503 start = '0' … … 565 536 iterator = self.current_statement 566 537 self.current_statement = '' 567 if iterator not in self. C_IntVars:568 self. C_IntVars.append(iterator)569 start, stop, step = self. GetForRange(node)538 if iterator not in self.c_int_vars: 539 self.c_int_vars.append(iterator) 540 start, stop, step = self.get_for_range(node) 570 541 self.write_c("for(" + iterator + "=" + str(start) + 571 542 " ; " + iterator + " < " + str(stop) + … … 575 546 fForDone = True 576 547 if not fForDone: 577 line_number = self.getNodeLineNo(node)548 # Generate the statement that is causing the error 578 549 self.current_statement = '' 579 550 self.write_c('for ') … … 582 553 self.visit(node.iter) 583 554 self.write_c(':') 584 errStr = "Conversion Error in function " + self.name + ", Line #" + str(line_number) 585 errStr += "\nPython for expression not supported: '" + self.current_statement + "'" 586 raise Exception(errStr) 555 # report the error 556 self.unsupported("unsupported " + self.current_statement) 587 557 588 558 def visit_While(self, node): … … 594 564 595 565 def visit_With(self, node): 566 self.unsupported(node) 596 567 self.newline(node) 597 568 self.write_python('with ') … … 605 576 def visit_Pass(self, node): 606 577 self.newline(node) 607 self.write_python('pass')578 #self.write_python('pass') 608 579 609 580 def visit_Print(self, node): 581 # TODO: print support would be nice, though hard to do 582 self.unsupported(node) 610 583 # CRUFT: python 2.6 only 611 584 self.newline(node) … … 625 598 626 599 def visit_Delete(self, node): 600 self.unsupported(node) 627 601 self.newline(node) 628 602 self.write_python('del ') … … 633 607 634 608 def visit_TryExcept(self, node): 609 self.unsupported(node) 635 610 self.newline(node) 636 611 self.write_python('try:') … … 640 615 641 616 def visit_TryFinally(self, node): 617 self.unsupported(node) 642 618 self.newline(node) 643 619 self.write_python('try:') … … 648 624 649 625 def visit_Global(self, node): 626 self.unsupported(node) 650 627 self.newline(node) 651 628 self.write_python('global ' + ', '.join(node.names)) … … 676 653 677 654 def visit_Raise(self, node): 655 self.unsupported(node) 678 656 # CRUFT: Python 2.6 / 3.0 compatibility 679 657 self.newline(node) … … 697 675 698 676 def visit_Attribute(self, node): 699 errStr = "Conversion Error in function " + self.name + ", Line #" + str(node.value.lineno) 700 errStr += "\nPython expression not supported: '" + node.value.id + "." + node.attr + "'" 701 raise Exception(errStr) 677 self.unsupported(node, "attribute reference a.b not supported") 702 678 self.visit(node.value) 703 679 self.write_python('.' + node.attr) … … 711 687 want_comma.append(True) 712 688 if hasattr(node.func, 'id'): 713 if node.func.id not in self. C_Functions:714 self. C_Functions.append(node.func.id)689 if node.func.id not in self.c_functions: 690 self.c_functions.append(node.func.id) 715 691 if node.func.id == 'abs': 716 692 self.write_c("fabs ") … … 718 694 self.write_c('(int) ') 719 695 elif node.func.id == "SINCOS": 720 self. WriteSincos(node)696 self.write_sincos(node) 721 697 return 722 698 else: … … 724 700 else: 725 701 self.visit(node.func) 726 #self.C_Functions727 702 self.write_c('(') 728 703 for arg in node.args: … … 748 723 def visit_Name(self, node): 749 724 self.write_c(node.id) 750 if node.id in self. C_Pointers and not self.SubRef:725 if node.id in self.c_pointers and not self.in_subref: 751 726 self.write_c("[0]") 752 727 name = "" … … 756 731 else: 757 732 name = node.id 758 # add variable to C_Vars if it ins't there yet, not an argument and not a number759 if (name not in self. C_Functions and name not in self.C_Vars and760 name not in self. C_IntVars and name not in self.arguments and761 name not in self. C_Constants and not name.isdigit()):762 if self. InSubscript:763 self. C_IntVars.append(node.id)733 # add variable to c_vars if it ins't there yet, not an argument and not a number 734 if (name not in self.c_functions and name not in self.c_vars and 735 name not in self.c_int_vars and name not in self.arguments and 736 name not in self.c_constants and not name.isdigit()): 737 if self.in_subscript: 738 self.c_int_vars.append(node.id) 764 739 else: 765 self. C_Vars.append(node.id)740 self.c_vars.append(node.id) 766 741 767 742 def visit_Str(self, node): … … 777 752 for idx, item in enumerate(node.elts): 778 753 if idx: 779 self. Tuples.append(item)754 self.tuples.append(item) 780 755 else: 781 756 self.visit(item) … … 793 768 s += str(item.n) 794 769 if s: 795 self. C_Vectors.append(s)796 vec_name = "vec" + str(len(self. C_Vectors))770 self.c_vectors.append(s) 771 vec_name = "vec" + str(len(self.c_vectors)) 797 772 self.write_c(vec_name) 798 773 return visit … … 803 778 804 779 def visit_Dict(self, node): 780 self.unsupported(node) 805 781 self.write_python('{') 806 782 for idx, (key, value) in enumerate(zip(node.keys, node.values)): … … 901 877 902 878 def visit_Subscript(self, node): 903 if node.value.id not in self. C_Constants:904 if node.value.id not in self. C_Pointers:905 self. C_Pointers.append(node.value.id)906 self. SubRef = True879 if node.value.id not in self.c_constants: 880 if node.value.id not in self.c_pointers: 881 self.c_pointers.append(node.value.id) 882 self.in_subref = True 907 883 self.visit(node.value) 908 self. SubRef = False884 self.in_subref = False 909 885 self.write_c('[') 910 self. InSubscript = True886 self.in_subscript = True 911 887 self.visit(node.slice) 912 self. InSubscript = False888 self.in_subscript = False 913 889 self.write_c(']') 914 890 … … 931 907 932 908 def visit_Yield(self, node): 909 self.unsupported(node) 933 910 self.write_python('yield ') 934 911 self.visit(node.value) 935 912 936 913 def visit_Lambda(self, node): 914 self.unsupported(node) 937 915 self.write_python('lambda ') 938 916 self.visit(node.args) … … 941 919 942 920 def visit_Ellipsis(self, node): 921 self.unsupported(node) 943 922 self.write_python('Ellipsis') 944 923 … … 960 939 961 940 def visit_DictComp(self, node): 941 self.unsupported(node) 962 942 self.write_python('{') 963 943 self.visit(node.key) … … 988 968 989 969 def visit_alias(self, node): 970 self.unsupported(node) 990 971 self.write_python(node.name) 991 972 if node.asname is not None: … … 1005 986 def visit_arguments(self, node): 1006 987 self.signature(node) 988 989 def unsupported(self, node, message=None): 990 if hasattr(node, "value"): 991 lineno = node.value.lineno 992 elif hasattr(node, "iter"): 993 lineno = node.iter.lineno 994 else: 995 #print(dir(node)) 996 lineno = 0 997 998 lineno += self.lineno_offset 999 if self.fname: 1000 location = "%s(%d)" % (self.fname, lineno) 1001 else: 1002 location = "%d" % (self.fname, lineno) 1003 if self.current_function: 1004 location += ", function %s" % self.current_function 1005 if message is None: 1006 message = node.__class__.__name__ + " syntax not supported" 1007 raise SyntaxError("[%s] %s" % (location, message)) 1007 1008 1008 1009 def print_function(f=None): … … 1018 1019 print(tree_source) 1019 1020 1020 def translate(functions, constants=0): 1021 def define_constant(name, value, block_size=1): 1022 # type: (str, any, int) -> str 1023 """ 1024 Convert a python constant into a C constant of the same name. 1025 1026 Returns the C declaration of the constant as a string, possibly containing 1027 line feeds. The string will not be indented. 1028 1029 Supports int, double and sequences of double. 1030 """ 1031 const = "constant " # OpenCL needs globals to be constant 1032 if isinstance(value, int): 1033 parts = [const + "int ", name, " = ", "%d"%value, ";"] 1034 elif isinstance(value, float): 1035 parts = [const + "double ", name, " = ", "%.15g"%value, ";"] 1036 else: 1037 try: 1038 len(value) 1039 except TypeError: 1040 raise TypeError("constant %s must be int, float or [float, ...]"%name) 1041 # extend constant arrays to a multiple of 4; not sure if this 1042 # is necessary, but some OpenCL targets broke if the number 1043 # of parameters in the parameter table was not a multiple of 4, 1044 # so do it for all constant arrays to be safe. 1045 if len(value)%block_size != 0: 1046 value = list(value) + [0.]*(block_size - len(value)%block_size) 1047 elements = ["%.15g"%v for v in value] 1048 parts = [const + "double ", name, "[]", " = ", 1049 "{\n ", ", ".join(elements), "\n};"] 1050 1051 return "".join(parts) 1052 1053 1054 # Modified from the following: 1055 # 1056 # http://code.activestate.com/recipes/578272-topological-sort/ 1057 # Copyright (C) 2012 Sam Denton 1058 # License: MIT 1059 def ordered_dag(dag): 1060 # type: (Dict[T, Set[T]]) -> Iterator[T] 1061 """ 1062 Given a dag defined by a dictionary of {k1: [k2, ...]} yield keys 1063 in order such that every key occurs after the keys it depends upon. 1064 1065 This is an iterator not a sequence. To reverse it use:: 1066 1067 reversed(tuple(ordered_dag(dag))) 1068 1069 Raise an error if there are any cycles. 1070 1071 Keys are arbitrary hashable values. 1072 """ 1073 # Local import to make the function stand-alone, and easier to borrow 1074 from functools import reduce 1075 1076 dag = dag.copy() 1077 1078 # make leaves depend on the empty set 1079 leaves = reduce(set.union, dag.values()) - set(dag.keys()) 1080 dag.update({node: set() for node in leaves}) 1081 while True: 1082 leaves = set(node for node, links in dag.items() if not links) 1083 if not leaves: 1084 break 1085 for node in leaves: 1086 yield node 1087 dag = {node: (links-leaves) 1088 for node, links in dag.items() if node not in leaves} 1089 if dag: 1090 raise ValueError("Cyclic dependes exists amongst these items:\n%s" 1091 % ", ".join(str(node) for node in dag.keys())) 1092 1093 def translate(functions, constants=None): 1094 # type: (List[(str, str, int)], Dict[str, any]) -> List[str] 1095 """ 1096 Convert a set of functions 1097 """ 1021 1098 snippets = [] 1022 1099 #snippets.append("#include <math.h>") 1023 1100 #snippets.append("") 1024 for source, fname, line _no in functions:1025 line_directive = '#line %d "%s"'%(line _no, fname.replace('\\', '\\\\'))1101 for source, fname, lineno in functions: 1102 line_directive = '#line %d "%s"'%(lineno, fname.replace('\\', '\\\\')) 1026 1103 snippets.append(line_directive) 1027 1104 tree = ast.parse(source) 1028 # in the future add filename, offset, constants 1029 c_code = to_source(tree, functions, constants) 1105 c_code = to_source(tree, constants=constants, fname=fname, lineno=lineno) 1030 1106 snippets.append(c_code) 1031 1107 return snippets … … 1051 1127 with open(fname_in, "r") as python_file: 1052 1128 code = python_file.read() 1053 1054 translation = translate([code, fname_in, 1])[0] 1129 name = "gauss" 1130 code = (code 1131 .replace(name+'.n', 'GAUSS_N') 1132 .replace(name+'.z', 'GAUSS_Z') 1133 .replace(name+'.w', 'GAUSS_W')) 1134 1135 translation = translate([(code, fname_in, 1)])[0] 1055 1136 1056 1137 with open(fname_out, "w") as file_out:
Note: See TracChangeset
for help on using the changeset viewer.