source: sasmodels/sasmodels/Py2C.py @ 6257070

Last change on this file since 6257070 was 6257070, checked in by Omer Eisenberg <omereis@…>, 6 years ago

'Py2C.y' translating python to C

  • Property mode set to 100644
File size: 32.1 KB
Line 
1
2"""
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"""
12Update Notes
13============
1411/22 14:15, O.E.   Each 'visit_*' method is to build a C statement string. It shold insert 4 blanks per indentation level.
15                    The 'body' method will combine all the strings, by adding the 'current_statement' to the c_proc string list
1611/27 17:29, OE: 'if', 'pow' basicly working
17"""
18import ast
19import sys
20from ast import NodeVisitor
21
22BINOP_SYMBOLS = {}
23BINOP_SYMBOLS[ast.Add] = '+'
24BINOP_SYMBOLS[ast.Sub] = '-'
25BINOP_SYMBOLS[ast.Mult] = '*'
26BINOP_SYMBOLS[ast.Div] = '/'
27BINOP_SYMBOLS[ast.Mod] = '%'
28BINOP_SYMBOLS[ast.Pow] = '**'
29BINOP_SYMBOLS[ast.LShift] = '<<'
30BINOP_SYMBOLS[ast.RShift] = '>>'
31BINOP_SYMBOLS[ast.BitOr] = '|'
32BINOP_SYMBOLS[ast.BitXor] = '^'
33BINOP_SYMBOLS[ast.BitAnd] = '&'
34BINOP_SYMBOLS[ast.FloorDiv] = '//'
35
36BOOLOP_SYMBOLS = {}
37BOOLOP_SYMBOLS[ast.And] = '&&'
38BOOLOP_SYMBOLS[ast.Or]  = '||'
39
40CMPOP_SYMBOLS = {}
41CMPOP_SYMBOLS[ast.Eq] = '=='
42CMPOP_SYMBOLS[ast.NotEq] = '!='
43CMPOP_SYMBOLS[ast.Lt] = '<'
44CMPOP_SYMBOLS[ast.LtE] = '<='
45CMPOP_SYMBOLS[ast.Gt] = '>'
46CMPOP_SYMBOLS[ast.GtE] = '>='
47CMPOP_SYMBOLS[ast.Is] = 'is'
48CMPOP_SYMBOLS[ast.IsNot] = 'is not'
49CMPOP_SYMBOLS[ast.In] = 'in'
50CMPOP_SYMBOLS[ast.NotIn] = 'not in'
51
52UNARYOP_SYMBOLS = {}
53UNARYOP_SYMBOLS[ast.Invert] = '~'
54UNARYOP_SYMBOLS[ast.Not] = 'not'
55UNARYOP_SYMBOLS[ast.UAdd] = '+'
56UNARYOP_SYMBOLS[ast.USub] = '-'
57
58
59#def to_source(node, indent_with=' ' * 4, add_line_information=False):
60def to_source(node, func_name):
61    """This function can convert a node tree back into python sourcecode.
62    This is useful for debugging purposes, especially if you're dealing with
63    custom asts not generated by python itself.
64
65    It could be that the sourcecode is evaluable when the AST itself is not
66    compilable / evaluable.  The reason for this is that the AST contains some
67    more data than regular sourcecode does, which is dropped during
68    conversion.
69
70    Each level of indentation is replaced with `indent_with`.  Per default this
71    parameter is equal to four spaces as suggested by PEP 8, but it might be
72    adjusted to match the application's styleguide.
73
74    If `add_line_information` is set to `True` comments for the line numbers
75    of the nodes are added to the output.  This can be used to spot wrong line
76    number information of statement nodes.
77    """
78    generator = SourceGenerator(' ' * 4, False)
79    generator.required_functions = func_name
80    generator.visit(node)
81
82#    return ''.join(generator.result)
83    return ''.join(generator.c_proc)
84
85class SourceGenerator(NodeVisitor):
86    """This visitor is able to transform a well formed syntax tree into python
87    sourcecode.  For more details have a look at the docstring of the
88    `node_to_source` function.
89    """
90
91    def __init__(self, indent_with, add_line_information=False):
92        self.result = []
93        self.indent_with = indent_with
94        self.add_line_information = add_line_information
95        self.indentation = 0
96        self.new_lines = 0
97        self.c_proc = []
98# for C
99        self.signature_line = 0
100        self.arguments = []
101        self.name = ""
102        self.warnings = []
103        self.Statements = []
104        self.current_statement = ""
105        self.strMethodSignature = ""
106        self.C_Vars = []
107        self.C_IntVars = []
108        self.MathIncludeed = False
109        self.C_Pointers = []
110        self.C_Functions = []
111        self.C_Vectors = []
112        self.SubRef = False
113        self.InSubscript = False
114        self.Tuples = []
115        self.required_functions = []
116
117    def write_python(self, x):
118        if self.new_lines:
119            if self.result:
120                self.result.append('\n' * self.new_lines)
121            self.result.append(self.indent_with * self.indentation)
122            self.new_lines = 0
123        self.result.append(x)
124
125    def write_c(self, x):
126        self.current_statement += x
127       
128    def add_c_line(self, x):
129        string = ''
130        for i in range (self.indentation):
131            string += ("    ")
132        string += str(x)
133        self.c_proc.append (str(string + "\n"))
134        x = ''
135
136    def add_current_line (self):
137        if (len(self.current_statement) > 0):
138            self.add_c_line (self.current_statement)
139            self.current_statement = ''
140
141    def AddUniqueVar (self, new_var):
142        if ((new_var not in self.C_Vars)):
143            self.C_Vars.append (str (new_var))
144
145    def WriteSincos (self, node):
146        angle = str(node.args[0].id)
147        self.write_c (node.args[1].id + " = sin (" + angle + ");")
148        self.add_current_line()
149        self.write_c (node.args[2].id + " = cos (" + angle + ");")
150        self.add_current_line()
151        for arg in node.args:
152            self.AddUniqueVar (arg.id)
153
154    def newline(self, node=None, extra=0):
155        self.new_lines = max(self.new_lines, 1 + extra)
156        if node is not None and self.add_line_information:
157            self.write_c('# line: %s' % node.lineno)
158            self.new_lines = 1
159        if (len(self.current_statement)):
160            self.Statements.append (self.current_statement)
161            self.current_statement = ''
162
163    def body(self, statements):
164        if (len(self.current_statement)):
165            self.add_current_line ()
166        self.new_line = True
167        self.indentation += 1
168        for stmt in statements:
169            target_name = ''
170            if (hasattr (stmt, 'targets')):
171                if (hasattr(stmt.targets[0],'id')):
172                    target_name = stmt.targets[0].id # target name needed for debug only
173            self.visit(stmt)
174        self.add_current_line ()
175        self.indentation -= 1
176
177    def body_or_else(self, node):
178        self.body(node.body)
179        if node.orelse:
180            self.newline()
181            self.write_c('else:')
182            self.body(node.orelse)
183
184    def signature(self, node):
185        want_comma = []
186        def write_comma():
187            if want_comma:
188                self.write_c(', ')
189            else:
190                want_comma.append(True)
191# for C
192        for arg in node.args:
193            self.arguments.append (arg.arg)
194
195        padding = [None] * (len(node.args) - len(node.defaults))
196        for arg, default in zip(node.args, padding + node.defaults):
197            if default is not None:
198                self.warnings.append ("Default Parameter unknown to C")
199                w_str = "Default Parameters are unknown to C: '" + arg.arg + " = " + str(default.n) + "'"
200                self.warnings.append (w_str)
201#                self.write_python('=')
202#                self.visit(default)
203
204    def decorators(self, node):
205        for decorator in node.decorator_list:
206            self.newline(decorator)
207            self.write_python('@')
208            self.visit(decorator)
209
210    # Statements
211
212    def visit_Assert(self, node):
213        self.newline(node)
214        self.write_c('assert ')
215        self.visit(node.test)
216        if node.msg is not None:
217           self.write_python(', ')
218           self.visit(node.msg)
219
220    def visit_Assign(self, node):
221        for idx, target in enumerate(node.targets):
222            if idx:
223                self.write_c(' = ')
224            if (hasattr (target, 'id')):
225# a variable is considered an array if it apears in the agrument list
226# and being assigned to. For example, the variable p in the following
227# sniplet is a pointer, while q is not
228# def somefunc (p, q):
229#  p = q + 1
230#  return
231#
232                if (target.id not in self.C_Vars):
233                    if (target.id in self.arguments):
234                        idx = self.arguments.index (target.id)
235                        new_target = self.arguments[idx] + "[0]"
236                        if (new_target not in self.C_Pointers):
237                            target.id = new_target
238                            self.C_Pointers.append (self.arguments[idx])
239                    else:
240                        self.C_Vars.append (target.id)
241            self.visit(target)
242        if (len(self.Tuples) > 0):
243            tplTargets = list (self.Tuples)
244            self.Tuples.clear()
245        self.write_c(' = ')
246        self.visit(node.value)
247        self.write_c(';')
248        self.add_c_line(self.current_statement)
249        self.current_statement = ''
250        for n,item in enumerate (self.Tuples):
251            self.visit(tplTargets[n])
252            self.write_c(' = ')
253            self.visit(item)
254            self.write_c(';')
255            self.add_c_line(self.current_statement)
256            self.current_statement = ''
257
258    def visit_AugAssign(self, node):
259        if (node.target.id not in self.C_Vars):
260            if (node.target.id not in self.arguments):
261                self.C_Vars.append (node.target.id)
262        self.visit(node.target)
263        self.write_c(' ' + BINOP_SYMBOLS[type(node.op)] + '= ')
264        self.visit(node.value)
265        self.write_c(';')
266        self.add_current_line ()
267
268    def visit_ImportFrom(self, node):
269        self.newline(node)
270        self.write_python('from %s%s import ' % ('.' * node.level, node.module))
271        for idx, item in enumerate(node.names):
272            if idx:
273                self.write_python(', ')
274            self.write_python(item)
275
276    def visit_Import(self, node):
277        self.newline(node)
278        for item in node.names:
279            self.write_python('import ')
280            self.visit(item)
281
282    def visit_Expr(self, node):
283        self.newline(node)
284        self.generic_visit(node)
285
286    def listToDeclare(self, Vars):
287        s = ''
288        for n in range(len(Vars)):
289            s += str(Vars[n])
290            if n < (len(Vars) - 1):
291                s += ", "
292        return (s)
293
294    def insert_C_Vars (self, start_var):
295        fLine = False
296       
297        if (len(self.C_Vars) > 0):
298            s = self.listToDeclare(self.C_Vars)
299            self.c_proc.insert (start_var, "    double " + s + ";\n")
300            fLine = True
301            start_var += 1
302        if (len(self.C_IntVars) > 0):
303            s = self.listToDeclare(self.C_IntVars)
304            self.c_proc.insert (start_var, "    int " + s + ";\n")
305            fLine = True
306            start_var += 1
307        if (len (self.C_Vectors) > 0):
308            for n in range(len(self.C_Vectors)):
309                name = "vec" + str(n+1)
310                c_dcl = "    double " + name + "[] = {" + self.C_Vectors[n] + "};"
311                self.c_proc.insert (start_var, c_dcl + "\n")
312                start_var += 1
313        self.C_Vars = []
314        self.C_IntVars = []
315        self.C_Vectors = []
316        if (fLine == True):
317            self.c_proc.insert (start_var, "\n")
318        return
319        s = ''
320        for n in range(len(self.C_Vars)):
321            s += str(self.C_Vars[n])
322            if n < len(self.C_Vars) - 1:
323                s += ", "
324        if (len(s) > 0):
325            self.c_proc.insert (start_var, "    double " + s + ";\n")
326            self.c_proc.insert (start_var + 1, "\n")
327
328    def writeInclude (self):
329        if (self.MathIncludeed == False):
330            self.add_c_line("#include <math.h>\n")
331            self.add_c_line("static double pi = 3.14159265359;\n")
332            self.MathIncludeed = True
333
334    def ListToString (self, strings):
335        s = ''
336        for n in range(len(strings)):
337            s += strings[n]
338            if (n < (len(strings) - 1)):
339                s += ", "
340        return (s)
341
342    def getMethodSignature (self):
343#        args_str = ListToString (self.arguments)
344        args_str = ''
345        for n in range(len(self.arguments)):
346            args_str += "double " + self.arguments[n]
347            if (n < (len(self.arguments) - 1)):
348                args_str += ", "
349        return (args_str)
350#        self.strMethodSignature = 'double ' + self.name + ' (' + args_str + ")"
351
352    def InsertSignature (self):
353        args_str = ''
354        for n in range(len(self.arguments)):
355            args_str += "double " + self.arguments[n]
356            if (self.arguments[n] in self.C_Pointers):
357                args_str += "[]"
358            if (n < (len(self.arguments) - 1)):
359                args_str += ", "
360        self.strMethodSignature = 'double ' + self.name + ' (' + args_str + ")"
361        if (self.signature_line > 0):
362            self.c_proc.insert (self.signature_line, self.strMethodSignature)
363
364    def visit_FunctionDef(self, node):
365        self.newline(extra=1)
366        self.decorators(node)
367        self.newline(node)
368        self.arguments = []
369        self.name = node.name
370        if self.name not in self.required_functions[0]:
371            return
372        print("Parsing '" + self.name + "'")
373        args_str = ""
374
375        self.visit(node.args)
376# for C
377        self.writeInclude()
378        self.getMethodSignature ()
379# for C
380        self.signature_line = len(self.c_proc)
381#        self.add_c_line(self.strMethodSignature)
382        self.add_c_line("\n{")
383        start_vars = len(self.c_proc) + 1
384        self.body(node.body)
385        self.add_c_line("}\n")
386        self.InsertSignature ()
387        self.insert_C_Vars (start_vars)
388        self.C_Pointers = []
389
390    def visit_ClassDef(self, node):
391        have_args = []
392        def paren_or_comma():
393            if have_args:
394                self.write_python(', ')
395            else:
396                have_args.append(True)
397                self.write_python('(')
398
399        self.newline(extra=2)
400        self.decorators(node)
401        self.newline(node)
402        self.write_python('class %s' % node.name)
403        for base in node.bases:
404            paren_or_comma()
405            self.visit(base)
406        # XXX: the if here is used to keep this module compatible
407        #      with python 2.6.
408        if hasattr(node, 'keywords'):
409            for keyword in node.keywords:
410                paren_or_comma()
411                self.write_python(keyword.arg + '=')
412                self.visit(keyword.value)
413            if node.starargs is not None:
414                paren_or_comma()
415                self.write_python('*')
416                self.visit(node.starargs)
417            if node.kwargs is not None:
418                paren_or_comma()
419                self.write_python('**')
420                self.visit(node.kwargs)
421        self.write_python(have_args and '):' or ':')
422        self.body(node.body)
423
424    def visit_If(self, node):
425        self.write_c('if ')
426        self.visit(node.test)
427        self.write_c(' {')
428        self.body(node.body)
429        self.add_c_line('}')
430        while True:
431            else_ = node.orelse
432            if len(else_) == 0:
433                break
434#            elif hasattr (else_, 'orelse'):
435            elif len(else_) == 1 and isinstance(else_[0], ast.If):
436                node = else_[0]
437#                self.newline()
438                self.write_c('else if ')
439                self.visit(node.test)
440                self.write_c(' {')
441                self.body(node.body)
442                self.add_current_line ()
443                self.add_c_line('}')
444#                break
445            else:
446                self.newline()
447                self.write_c('else {')
448                self.body(node.body)
449                self.add_c_line('}')
450                break
451
452    def getNodeLineNo (self, node):
453        line_number = -1
454        if (hasattr (node,'value')):
455            line_number = node.value.lineno
456        elif hasattr(node,'iter'):
457            if hasattr(node.iter,'lineno'):
458                line_number = node.iter.lineno
459        return (line_number)
460
461    def visit_For(self, node):
462        if (len(self.current_statement) > 0):
463            self.add_c_line(self.current_statement)
464            self.current_statement = ''
465        fForDone = False
466        if (hasattr(node.iter,'func')):
467            if (hasattr (node.iter.func,'id')):
468                if (node.iter.func.id == 'range'):
469                    if ('n' not in self.C_IntVars):
470                        self.C_IntVars.append ('n')
471                    self.write_c ("for (n=0 ; n < len(")
472                    for arg in node.iter.args:
473                        self.visit(arg)
474                    self.write_c (") ; n++) {")
475                    self.body_or_else(node)
476                    self.write_c ("}")
477                    fForDone = True
478        if (fForDone == False):
479            line_number = self.getNodeLineNo (node)
480            self.current_statement = ''
481            self.write_c('for ')
482            self.visit(node.target)
483            self.write_c(' in ')
484            self.visit(node.iter)
485            self.write_c(':')
486            errStr = "Conversion Error in function " + self.name + ", Line #" + str (line_number)
487            errStr += "\nPython for expression not supported: '" + self.current_statement + "'"
488            raise Exception(errStr)
489
490    def visit_While(self, node):
491        self.newline(node)
492        self.write_c('while ')
493        self.visit(node.test)
494        self.write_c(':')
495        self.body_or_else(node)
496
497    def visit_With(self, node):
498        self.newline(node)
499        self.write_python('with ')
500        self.visit(node.context_expr)
501        if node.optional_vars is not None:
502            self.write_python(' as ')
503            self.visit(node.optional_vars)
504        self.write_python(':')
505        self.body(node.body)
506
507    def visit_Pass(self, node):
508        self.newline(node)
509        self.write_python('pass')
510
511    def visit_Print(self, node):
512# XXX: python 2.6 only
513        self.newline(node)
514        self.write_c('print ')
515        want_comma = False
516        if node.dest is not None:
517            self.write_c(' >> ')
518            self.visit(node.dest)
519            want_comma = True
520        for value in node.values:
521            if want_comma:
522                self.write_c(', ')
523            self.visit(value)
524            want_comma = True
525        if not node.nl:
526            self.write_c(',')
527
528    def visit_Delete(self, node):
529        self.newline(node)
530        self.write_python('del ')
531        for idx, target in enumerate(node):
532            if idx:
533                self.write_python(', ')
534            self.visit(target)
535
536    def visit_TryExcept(self, node):
537        self.newline(node)
538        self.write_python('try:')
539        self.body(node.body)
540        for handler in node.handlers:
541            self.visit(handler)
542
543    def visit_TryFinally(self, node):
544        self.newline(node)
545        self.write_python('try:')
546        self.body(node.body)
547        self.newline(node)
548        self.write_python('finally:')
549        self.body(node.finalbody)
550
551    def visit_Global(self, node):
552        self.newline(node)
553        self.write_python('global ' + ', '.join(node.names))
554
555    def visit_Nonlocal(self, node):
556        self.newline(node)
557        self.write_python('nonlocal ' + ', '.join(node.names))
558
559    def visit_Return(self, node):
560        self.newline(node)
561        if node.value is None:
562            self.write_c('return')
563        else:
564            self.write_c('return (')
565            self.visit(node.value)
566        self.write_c(');')
567#      self.add_current_statement (self)
568        self.add_c_line (self.current_statement)
569        self.current_statement = ''
570
571    def visit_Break(self, node):
572        self.newline(node)
573        self.write_c('break')
574
575    def visit_Continue(self, node):
576        self.newline(node)
577        self.write_c('continue')
578
579    def visit_Raise(self, node):
580        # XXX: Python 2.6 / 3.0 compatibility
581        self.newline(node)
582        self.write_python('raise')
583        if hasattr(node, 'exc') and node.exc is not None:
584            self.write_python(' ')
585            self.visit(node.exc)
586            if node.cause is not None:
587                self.write_python(' from ')
588                self.visit(node.cause)
589        elif hasattr(node, 'type') and node.type is not None:
590            self.visit(node.type)
591            if node.inst is not None:
592                self.write_python(', ')
593                self.visit(node.inst)
594            if node.tback is not None:
595                self.write_python(', ')
596                self.visit(node.tback)
597
598    # Expressions
599
600    def visit_Attribute(self, node):
601        errStr = "Conversion Error in function " + self.name + ", Line #" + str (node.value.lineno)
602        errStr += "\nPython expression not supported: '" + node.value.id + "." + node.attr + "'"
603        raise Exception(errStr)
604        self.visit(node.value)
605        self.write_python('.' + node.attr)
606
607    def visit_Call(self, node):
608        want_comma = []
609        def write_comma():
610            if want_comma:
611                self.write_c(', ')
612            else:
613                want_comma.append(True)
614        if (hasattr (node.func, 'id')):
615            if (node.func.id not in self.C_Functions):
616                self.C_Functions.append (node.func.id)
617            if (node.func.id == 'abs'):
618                self.write_c ("fabs ")
619            elif (node.func.id == 'int'):
620                self.write_c('(int) ')
621            elif (node.func.id == "SINCOS"):
622                self.WriteSincos (node)
623                return
624            else:
625                self.visit(node.func)
626        else:
627            self.visit(node.func)
628#self.C_Functions
629        self.write_c('(')
630        for arg in node.args:
631            write_comma()
632            self.visit(arg)
633        for keyword in node.keywords:
634            write_comma()
635            self.write_c(keyword.arg + '=')
636            self.visit(keyword.value)
637        if hasattr (node, 'starargs'):
638            if node.starargs is not None:
639                write_comma()
640                self.write_c('*')
641                self.visit(node.starargs)
642        if hasattr (node, 'kwargs'):
643            if node.kwargs is not None:
644                write_comma()
645                self.write_c('**')
646                self.visit(node.kwargs)
647        self.write_c(')')
648
649    def visit_Name(self, node):
650        self.write_c(node.id)
651        if ((node.id in self.C_Pointers) and (not self.SubRef)):
652            self.write_c("[0]")
653        name = ""
654        sub = node.id.find("[")
655        if (sub > 0):
656            name = node.id[0:sub].strip()
657        else:
658            name = node.id
659#       add variable to C_Vars if it ins't there yet, not an argument and not a number
660        if ((name not in self.C_Functions) and (name not in self.C_Vars) and (name not in self.C_IntVars) and (name not in self.arguments) and (name.isnumeric () == False)):
661            if (self.InSubscript):
662                self.C_IntVars.append (node.id)
663            else:
664                self.C_Vars.append (node.id)
665
666    def visit_Str(self, node):
667        self.write_c(repr(node.s))
668
669    def visit_Bytes(self, node):
670        self.write_c(repr(node.s))
671
672    def visit_Num(self, node):
673        self.write_c(repr(node.n))
674
675    def visit_Tuple(self, node):
676#        self.write_c('(')
677#        idx = -1
678        for idx, item in enumerate(node.elts):
679            if idx:
680                self.Tuples.append(item)
681            else:
682#                self.write_c(', ')
683                self.visit(item)
684#        self.write_c(idx and ')' or ',)')
685
686    def sequence_visit(left, right):
687        def visit(self, node):
688            s = ""
689            for idx, item in enumerate(node.elts):
690                if idx:
691                    s += ', '
692                s += item.id
693            self.C_Vectors.append (s)
694            vec_name = "vec"  + str(len(self.C_Vectors))
695            self.write_c(vec_name)
696            vec_name += "#"
697#
698#            self.write_c(left)
699#            for idx, item in enumerate(node.elts):
700#                if idx:
701#                    self.write_c(', ')
702#                self.visit(item)
703#            self.write_c(right)
704#
705        return visit
706
707    visit_List = sequence_visit('[', ']')
708    visit_Set = sequence_visit('{', '}')
709    del sequence_visit
710
711    def visit_Dict(self, node):
712        self.write_python('{')
713        for idx, (key, value) in enumerate(zip(node.keys, node.values)):
714            if idx:
715                self.write_python(', ')
716            self.visit(key)
717            self.write_python(': ')
718            self.visit(value)
719        self.write_python('}')
720
721    def translate_power (self, node):
722# get exponent by visiting the right hand argument.
723        function_name = "pow"
724        temp_statement = self.current_statement
725        self.current_statement = ''
726        self.visit(node.right)
727        exponent = self.current_statement.replace(' ','')
728        exponent = exponent.replace('(','')
729        exponent = exponent.replace(')','')
730        self.current_statement = temp_statement
731# is the right hand argument, the exponent, a number?
732        if (hasattr(node.right, 'n')): # power of constand
733            exponent = node.right.n
734            if (exponent == 2):
735                function_name = "square"
736            elif (exponent == 3):
737                function_name = "cube"
738            elif (exponent == 0.5):
739                function_name = "sqrt"
740        elif (exponent == "1/2"):
741                function_name = "sqrt"
742        self.write_c (function_name + " (")
743        self.visit(node.left)
744        if (function_name == "pow"):
745            self.write_c(", ")
746            self.visit(node.right)
747        self.write_c(")")
748
749    def integer_divide (self, node):
750        self.write_c ("(int) (")
751        self.visit(node.left)
752        self.write_c (") / (int) (")
753        self.visit(node.right)
754        self.write_c (")")
755
756    def visit_BinOp(self, node):
757        if ('%s' % BINOP_SYMBOLS[type(node.op)] == BINOP_SYMBOLS[ast.Pow]):
758            self.translate_power (node)
759        elif ('%s' % BINOP_SYMBOLS[type(node.op)] == BINOP_SYMBOLS[ast.FloorDiv]):
760            self.integer_divide (node)
761        else:
762            self.visit(node.left)
763            self.write_c(' %s ' % BINOP_SYMBOLS[type(node.op)])
764            self.visit(node.right)
765#       for C
766    def visit_BoolOp(self, node):
767        self.write_c('(')
768        for idx, value in enumerate(node.values):
769            if idx:
770                self.write_c(' %s ' % BOOLOP_SYMBOLS[type(node.op)])
771            self.visit(value)
772        self.write_c(')')
773
774    def visit_Compare(self, node):
775        self.write_c('(')
776        self.visit(node.left)
777        for op, right in zip(node.ops, node.comparators):
778            self.write_c(' %s ' % CMPOP_SYMBOLS[type(op)])
779            self.visit(right)
780        self.write_c(')')
781
782    def visit_UnaryOp(self, node):
783        self.write_c('(')
784        op = UNARYOP_SYMBOLS[type(node.op)]
785        self.write_c(op)
786        if op == 'not':
787            self.write_c(' ')
788        self.visit(node.operand)
789        self.write_c(')')
790
791    def visit_Subscript(self, node):
792        if (node.value.id not in self.C_Pointers):
793            self.C_Pointers.append (node.value.id)
794        self.SubRef = True
795        self.visit(node.value)
796        self.SubRef = False
797        self.write_c('[')
798        self.InSubscript = True
799        self.visit(node.slice)
800        self.InSubscript = False
801        self.write_c(']')
802
803    def visit_Slice(self, node):
804        if node.lower is not None:
805            self.visit(node.lower)
806        self.write_python(':')
807        if node.upper is not None:
808            self.visit(node.upper)
809        if node.step is not None:
810            self.write_python(':')
811            if not (isinstance(node.step, Name) and node.step.id == 'None'):
812                self.visit(node.step)
813
814    def visit_ExtSlice(self, node):
815        for idx, item in node.dims:
816            if idx:
817                self.write_python(', ')
818            self.visit(item)
819
820    def visit_Yield(self, node):
821        self.write_python('yield ')
822        self.visit(node.value)
823
824    def visit_Lambda(self, node):
825        self.write_python('lambda ')
826        self.visit(node.args)
827        self.write_python(': ')
828        self.visit(node.body)
829
830    def visit_Ellipsis(self, node):
831        self.write_python('Ellipsis')
832
833    def generator_visit(left, right):
834        def visit(self, node):
835            self.write_python(left)
836            self.visit(node.elt)
837            for comprehension in node.generators:
838                self.visit(comprehension)
839            self.write_python(right)
840        return visit
841
842    visit_ListComp = generator_visit('[', ']')
843    visit_GeneratorExp = generator_visit('(', ')')
844    visit_SetComp = generator_visit('{', '}')
845    del generator_visit
846
847    def visit_DictComp(self, node):
848        self.write_python('{')
849        self.visit(node.key)
850        self.write_python(': ')
851        self.visit(node.value)
852        for comprehension in node.generators:
853            self.visit(comprehension)
854        self.write_python('}')
855
856    def visit_IfExp(self, node):
857        self.visit(node.body)
858        self.write_c(' if ')
859        self.visit(node.test)
860        self.write_c(' else ')
861        self.visit(node.orelse)
862
863    def visit_Starred(self, node):
864        self.write_c('*')
865        self.visit(node.value)
866
867    def visit_Repr(self, node):
868        # XXX: python 2.6 only
869        self.write_c('`')
870        self.visit(node.value)
871        self.write_python('`')
872
873    # Helper Nodes
874
875    def visit_alias(self, node):
876        self.write_python(node.name)
877        if node.asname is not None:
878            self.write_python(' as ' + node.asname)
879
880    def visit_comprehension(self, node):
881        self.write_c(' for ')
882        self.visit(node.target)
883        self.write_python(' in ')
884        self.visit(node.iter)
885        if node.ifs:
886            for if_ in node.ifs:
887                self.write_python(' if ')
888                self.visit(if_)
889
890#    def visit_excepthandler(self, node):
891#        self.newline(node)
892#        self.write_python('except')
893#        if node.type is not None:
894#            self.write_python(' ')
895#            self.visit(node.type)
896#            if node.name is not None:
897#                self.write_python(' as ')
898#                self.visit(node.name)
899#        self.body(node.body)
900
901    def visit_arguments(self, node):
902        self.signature(node)
903
904def Iq1(q, porod_scale, porod_exp, lorentz_scale, lorentz_length, peak_pos, lorentz_exp=17):
905    z1 = z2 = z = abs (q - peak_pos) * lorentz_length
906    if (q > p):
907        q = p + 17
908        p = q - 5
909    z3 = -8
910    inten = (porod_scale / q ** porod_exp
911                + lorentz_scale / (1 + z ** lorentz_exp))
912    return inten
913
914def Iq(q, porod_scale, porod_exp, lorentz_scale, lorentz_length, peak_pos, lorentz_exp=17):
915    z1 = z2 = z = abs (q - peak_pos) * lorentz_length
916    if (q > p):
917        q = p + 17
918        p = q - 5
919    elif (q == p):
920        q = p * q
921        q *= z1
922        p = z1
923    elif (q == 17):
924        q = p * q - 17
925    else:
926        q += 7
927    z3 = -8
928    inten = (porod_scale / q ** porod_exp
929                + lorentz_scale / (1 + z ** lorentz_exp))
930    return inten
931
932def print_function(f=None):
933    """
934    Print out the code for the function
935    """
936    # Include some comments to see if they get printed
937    import ast
938    import inspect
939    if f is not None:
940        tree = ast.parse(inspect.getsource(f))
941        tree_source = to_source (tree)
942        print(tree_source)
943
944def translate (functions, constants=0):
945    sniplets = []
946    fname = functions[1]
947    python_file = open (fname, "r")
948    source = python_file.read()
949    python_file.close()
950    tree = ast.parse (source)
951    sniplet = to_source (tree, functions) # in the future add filename, offset, constants
952    sniplets.append(sniplet)
953    return ("\n".join(sniplets))
954
955def get_file_names ():
956    fname_in = ""
957    fname_out = ""
958    if (len(sys.argv) > 1):
959        fname_in = sys.argv[1]
960        fname_base = os.path.splitext (fname_in)
961        if (len (sys.argv) == 2):
962            fname_out = str (fname_base[0]) + '.c'
963        else:
964            fname_out = sys.argv[2]
965        if (len (fname_in) > 0):
966            python_file = open (sys.argv[1], "r")
967            if (len (fname_out) > 0):
968                file_out = open (fname_out, "w+")
969    return len(sys.argv), fname_in, fname_out
970
971if __name__ == "__main__":
972    import os
973    print("Parsing...using Python" + sys.version)
974    try:
975        fname_in = ""
976        fname_out = ""
977        if (len (sys.argv) == 1):
978            print ("Usage:\npython parse01.py <infile> [<outfile>] (if omitted, output file is '<infile>.c'")
979        else:
980            fname_in = sys.argv[1]
981            fname_base = os.path.splitext (fname_in)
982            if (len (sys.argv) == 2):
983                fname_out = str (fname_base[0]) + '.c'
984            else:
985                fname_out = sys.argv[2]
986            if (len (fname_in) > 0):
987                python_file = open (sys.argv[1], "r")
988                if (len (fname_out) > 0):
989                    file_out = open (fname_out, "w+")
990                functions = ["MultAsgn", "Iq41", "Iq2"]
991                tpls = [functions, fname_in, 0]
992                c_txt = translate (tpls)
993                file_out.write (c_txt)
994                file_out.close()
995    except Exception as excp:
996        print ("Error:\n" + str(excp.args))
997    print("...Done")
Note: See TracBrowser for help on using the repository browser.