Changeset 5dd7cfb in sasmodels


Ignore:
Timestamp:
Jan 17, 2018 1:49:12 PM (6 years ago)
Author:
Paul Kienzle <pkienzle@…>
Children:
6f91c91
Parents:
6ceca44
Message:

track line numbers; allow expressions in array initializers

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/py2c.py

    rd5014e4 r5dd7cfb  
    147147import ast 
    148148from ast import NodeVisitor 
     149try: # for debugging, astor lets us print out the node as python 
     150    import astor 
     151except ImportError: 
     152    pass 
    149153 
    150154BINOP_SYMBOLS = {} 
     
    193197        return False 
    194198 
     199def render_expression(tree): 
     200    generator = SourceGenerator() 
     201    generator.visit(tree) 
     202    c_code = "".join(generator.current_statement) 
     203    return c_code 
     204 
    195205class SourceGenerator(NodeVisitor): 
    196206    """This visitor is able to transform a well formed syntax tree into python 
     
    199209    """ 
    200210 
    201     def __init__(self, indent_with="    ", add_line_information=False, 
    202                  constants=None, fname=None, lineno=0): 
    203         self.result = [] 
     211    def __init__(self, indent_with="    ", constants=None, fname=None, lineno=0): 
    204212        self.indent_with = indent_with 
    205         self.add_line_information = add_line_information 
    206213        self.indentation = 0 
    207         self.new_lines = 0 
    208214 
    209215        # for C 
     
    215221        self.lineno_offset = lineno 
    216222        self.warnings = [] 
    217         self.statements = [] 
    218223        self.current_statement = "" 
    219224        # TODO: use set rather than list for c_vars, ... 
     
    230235        self.tuples = [] 
    231236        self.required_functions = [] 
    232         self.is_sequence = False 
    233237        self.visited_args = False 
    234  
    235     def write_python(self, x): 
    236         if self.new_lines: 
    237             if self.result: 
    238                 self.result.append('\n' * self.new_lines) 
    239             self.result.append(self.indent_with * self.indentation) 
    240             self.new_lines = 0 
    241         self.result.append(x) 
    242238 
    243239    def write_c(self, statement): 
    244240        # TODO: build up as a list rather than adding to string 
    245241        self.current_statement += statement 
     242 
     243    def write_python(self, x): 
     244        raise NotImplementedError("shouldn't be trying to write pythnon") 
    246245 
    247246    def add_c_line(self, line): 
     
    267266            self.add_unique_var(arg.id) 
    268267 
    269     def newline(self, node=None, extra=0): 
    270         self.new_lines = max(self.new_lines, 1 + extra) 
    271         if node is not None and self.add_line_information: 
    272             self.write_c('// line: %s' % node.lineno) 
    273             self.new_lines = 1 
    274         if self.current_statement: 
    275             self.statements.append(self.current_statement) 
    276             self.current_statement = '' 
     268    def track_lineno(self, node): 
     269        #print("newline", node, [s for s in dir(node) if not s.startswith('_')]) 
     270        if hasattr(node, 'lineno'): 
     271            line = '#line %d "%s"\n' % (node.lineno+self.lineno_offset-1, self.fname) 
     272            self.c_proc.append(line) 
    277273 
    278274    def body(self, statements): 
     
    293289            self.unsupported(node, "for...else/while...else not supported") 
    294290 
    295             self.newline() 
     291            self.track_lineno(node) 
    296292            self.write_c('else:') 
    297293            self.body(node.orelse) 
     
    327323 
    328324    def decorators(self, node): 
     325        if node.decorator_list: 
     326            self.unsupported(node.decorator_list[0]) 
    329327        for decorator in node.decorator_list: 
    330             self.newline(decorator) 
     328            self.trac_lineno(decorator) 
    331329            self.write_python('@') 
    332330            self.visit(decorator) 
     
    335333 
    336334    def visit_Assert(self, node): 
    337         self.newline(node) 
     335        self.unsupported(node) 
     336 
     337        self.track_lineno(node) 
    338338        self.write_c('assert ') 
    339339        self.visit(node.test) 
     
    369369    def visit_Assign(self, node): 
    370370        self.add_current_line() 
     371        self.track_lineno(node) 
    371372        self.in_expr = True 
    372373        for idx, target in enumerate(node.targets): # multi assign, as in 'a = b = c = 7' 
     
    379380        del self.tuples[:] 
    380381        self.write_c(' = ') 
    381         self.is_sequence = False 
    382382        self.visited_args = False 
    383383        self.visit(node.value) 
     
    392392            self.add_semi_colon() 
    393393            self.add_current_line() 
    394         if self.is_sequence and not self.visited_args: 
    395             for target in node.targets: 
    396                 if hasattr(target, 'id'): 
    397                     if target.id in self.c_vars and target.id not in self.c_dcl_pointers: 
    398                         if target.id not in self.c_dcl_pointers: 
    399                             self.c_dcl_pointers.append(target.id) 
    400                             if target.id in self.c_vars: 
    401                                 self.c_vars.remove(target.id) 
     394        #if self.is_sequence and not self.visited_args: 
     395        #    for target in node.targets: 
     396        #        if hasattr(target, 'id'): 
     397        #            if target.id in self.c_vars and target.id not in self.c_dcl_pointers: 
     398        #                if target.id not in self.c_dcl_pointers: 
     399        #                    self.c_dcl_pointers.append(target.id) 
     400        #                    if target.id in self.c_vars: 
     401        #                        self.c_vars.remove(target.id) 
    402402        self.current_statement = '' 
    403403        self.in_expr = False 
     
    417417    def visit_ImportFrom(self, node): 
    418418        return  # import ignored 
    419         self.newline(node) 
     419        self.track_lineno(node) 
    420420        self.write_python('from %s%s import ' %('.' * node.level, node.module)) 
    421421        for idx, item in enumerate(node.names): 
     
    426426    def visit_Import(self, node): 
    427427        return  # import ignored 
    428         self.newline(node) 
     428        self.track_lineno(node) 
    429429        for item in node.names: 
    430430            self.write_python('import ') 
     
    433433    def visit_Expr(self, node): 
    434434        #self.in_expr = True 
    435         self.newline(node) 
     435        #self.track_lineno(node) 
    436436        self.generic_visit(node) 
    437437        #self.in_expr = False 
     
    506506        warning_index = len(self.warnings) 
    507507 
    508         self.newline(extra=1) 
    509508        self.decorators(node) 
    510         self.newline(node) 
     509        self.track_lineno(node) 
    511510        self.arguments = [] 
    512511        self.visit(node.args) 
     
    525524 
    526525    def visit_ClassDef(self, node): 
     526        self.unsupported(node) 
     527 
    527528        have_args = [] 
    528529        def paren_or_comma(): 
     
    533534                self.write_python('(') 
    534535 
    535         self.newline(extra=2) 
    536536        self.decorators(node) 
    537         self.newline(node) 
     537        self.track_lineno(node) 
    538538        self.write_python('class %s' % node.name) 
    539539        for base in node.bases: 
     
    559559    def visit_If(self, node): 
    560560 
     561        self.track_lineno(node) 
    561562        self.write_c('if ') 
    562563        self.in_expr = True 
     
    573574            elif len(else_) == 1 and isinstance(else_[0], ast.If): 
    574575                node = else_[0] 
    575                 #self.newline() 
     576                self.track_lineno(node) 
    576577                self.write_c('else if ') 
    577578                self.in_expr = True 
     
    584585                #break 
    585586            else: 
    586                 self.newline() 
     587                self.track_lineno(else_) 
    587588                self.write_c('else {') 
    588589                self.body(else_) 
     
    651652 
    652653    def visit_While(self, node): 
    653         self.newline(node) 
     654        self.track_lineno(node) 
    654655        self.write_c('while ') 
    655656        self.visit(node.test) 
     
    662663        self.unsupported(node) 
    663664 
    664         self.newline(node) 
     665        self.track_lineno(node) 
    665666        self.write_python('with ') 
    666667        self.visit(node.context_expr) 
     
    672673 
    673674    def visit_Pass(self, node): 
    674         self.newline(node) 
     675        #self.track_lineno(node) 
    675676        #self.write_python('pass') 
     677        pass 
    676678 
    677679    def visit_Print(self, node): 
     
    679681 
    680682        # CRUFT: python 2.6 only 
    681         self.newline(node) 
     683        self.track_lineno(node) 
    682684        self.write_c('print ') 
    683685        want_comma = False 
     
    697699        self.unsupported(node) 
    698700 
    699         self.newline(node) 
     701        self.track_lineno(node) 
    700702        self.write_python('del ') 
    701703        for idx, target in enumerate(node): 
     
    707709        self.unsupported(node) 
    708710 
    709         self.newline(node) 
     711        self.track_linno(node) 
    710712        self.write_python('try:') 
    711713        self.body(node.body) 
     
    716718        self.unsupported(node) 
    717719 
    718         self.newline(node) 
     720        self.track_lineno(node) 
    719721        self.write_python('try:') 
    720722        self.body(node.body) 
    721         self.newline(node) 
     723        self.track_lineno(node) 
    722724        self.write_python('finally:') 
    723725        self.body(node.finalbody) 
     
    726728        self.unsupported(node) 
    727729 
    728         self.newline(node) 
     730        self.track_lineno(node) 
    729731        self.write_python('global ' + ', '.join(node.names)) 
    730732 
    731733    def visit_Nonlocal(self, node): 
    732         self.newline(node) 
     734        self.track_lineno(node) 
    733735        self.write_python('nonlocal ' + ', '.join(node.names)) 
    734736 
    735737    def visit_Return(self, node): 
    736738        self.add_current_line() 
     739        self.track_lineno(node) 
    737740        self.in_expr = True 
    738741        if node.value is None: 
     
    747750 
    748751    def visit_Break(self, node): 
    749         self.newline(node) 
     752        self.track_lineno(node) 
    750753        self.write_c('break') 
    751754 
    752755    def visit_Continue(self, node): 
    753         self.newline(node) 
     756        self.track_lineno(node) 
    754757        self.write_c('continue') 
    755758 
     
    758761 
    759762        # CRUFT: Python 2.6 / 3.0 compatibility 
    760         self.newline(node) 
     763        self.track_lineno(node) 
    761764        self.write_python('raise') 
    762765        if hasattr(node, 'exc') and node.exc is not None: 
     
    870873    def visit_Str(self, node): 
    871874        s = node.s 
    872         s = s.replace('\\','\\\\').replace('"','\\"').replace('\n','\\n') 
     875        s = s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n') 
    873876        self.write_c('"') 
    874877        self.write_c(s) 
     
    877880    def visit_Bytes(self, node): 
    878881        s = node.s 
    879         s = s.replace('\\','\\\\').replace('"','\\"').replace('\n','\\n') 
     882        s = s.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n') 
    880883        self.write_c('"') 
    881884        self.write_c(s) 
     
    892895                self.visit(item) 
    893896 
    894     def sequence_visit(left, right): 
    895         def visit(self, node): 
    896             self.is_sequence = True 
    897             s = "" 
    898             for idx, item in enumerate(node.elts): 
    899                 if idx > 0 and s: 
    900                     s += ', ' 
    901                 if hasattr(item, 'id'): 
    902                     s += item.id 
    903                 elif hasattr(item, 'n'): 
    904                     s += str(item.n) 
    905             if s: 
    906                 self.c_vectors.append(s) 
    907                 vec_name = "vec"  + str(len(self.c_vectors)) 
    908                 self.write_c(vec_name) 
    909         return visit 
    910  
    911     visit_List = sequence_visit('[', ']') 
    912     visit_Set = sequence_visit('{', '}') 
    913     del sequence_visit 
     897    def visit_List(self, node): 
     898        #self.unsupported(node) 
     899        #print("visiting", node) 
     900        #print(astor.to_source(node)) 
     901        #print(node.elts) 
     902        exprs = [render_expression(item) for item in node.elts] 
     903        if exprs: 
     904            self.c_vectors.append(', '.join(exprs)) 
     905            vec_name = "vec"  + str(len(self.c_vectors)) 
     906            self.write_c(vec_name) 
     907 
     908    def visit_Set(self, node): 
     909        self.unsupported(node) 
    914910 
    915911    def visit_Dict(self, node): 
     
    11271123 
    11281124    def visit_comprehension(self, node): 
     1125        self.unsupported(node) 
     1126 
    11291127        self.write_c(' for ') 
    11301128        self.visit(node.target) 
    1131         self.write_C(' in ') 
     1129        self.write_c(' in ') 
    11321130        #self.write_python(' in ') 
    11331131        self.visit(node.iter) 
     
    12861284    return snippets, warnings 
    12871285 
    1288 def to_source(tree, constants=None, fname=None, lineno=0): 
    1289     """ 
    1290     This function can convert a syntax tree into C sourcecode. 
    1291     """ 
    1292     c_code = "".join(generator.c_proc) 
    1293     return c_code 
    1294  
    12951286 
    12961287C_HEADER = """ 
Note: See TracChangeset for help on using the changeset viewer.