Changes in / [d5014e4:5ab99b7] in sasmodels


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/py2c.py

    r0bd0877 rd7f33e5  
    112112# Update Notes 
    113113# ============ 
    114 # 2017-11-22, OE: Each 'visit_*' method is to build a C statement string. It 
    115 #                 shold insert 4 blanks per indentation level. The 'body' 
    116 #                 method will combine all the strings, by adding the 
    117 #                 'current_statement' to the c_proc string list 
    118 # 2017-11-22, OE: variables, argument definition implemented.  Note: An 
    119 #                argument is considered an array if it is the target of an 
    120 #                 assignment. In that case it is translated to <var>[0] 
    121 # 2017-11-27, OE: 'pow' basicly working 
    122 # 2017-12-07, OE: Multiple assignment: a1,a2,...,an=b1,b2,...bn implemented 
    123 # 2017-12-07, OE: Power function, including special cases of 
     114# 11/22/2017, O.E.  Each 'visit_*' method is to build a C statement string. It 
     115#                     shold insert 4 blanks per indentation level. 
     116#                     The 'body' method will combine all the strings, by adding 
     117#                     the 'current_statement' to the c_proc string list 
     118#    11/2017, OE: variables, argument definition implemented. 
     119#    Note: An argument is considered an array if it is the target of an 
     120#         assignment. In that case it is translated to <var>[0] 
     121# 11/27/2017, OE: 'pow' basicly working 
     122#   /12/2017, OE: Multiple assignment: a1,a2,...,an=b1,b2,...bn implemented 
     123#   /12/2017, OE: Power function, including special cases of 
    124124#                 square(x)(pow(x,2)) and cube(x)(pow(x,3)), implemented in 
    125125#                 translate_power, called from visit_BinOp 
    126 # 2017-12-07, OE: Translation of integer division, '\\' in python, implemented 
     126# 12/07/2017, OE: Translation of integer division, '\\' in python, implemented 
    127127#                 in translate_integer_divide, called from visit_BinOp 
    128 # 2017-12-07, OE: C variable definition handled in 'define_c_vars' 
     128# 12/07/2017, OE: C variable definition handled in 'define_c_vars' 
    129129#               : Python integer division, '//', translated to C in 
    130130#                 'translate_integer_divide' 
    131 # 2017-12-15, OE: Precedence maintained by writing opening and closing 
     131# 12/15/2017, OE: Precedence maintained by writing opening and closing 
    132132#                 parenthesesm '(',')', in procedure 'visit_BinOp'. 
    133 # 2017-12-18, OE: Added call to 'add_current_line()' at the beginning 
     133# 12/18/2017, OE: Added call to 'add_current_line()' at the beginning 
    134134#                 of visit_Return 
    135135# 2018-01-03, PK: Update interface for use in sasmodels 
     
    140140# 2018-01-03, PK: simplistic print function, for debugging 
    141141# 2018-01-03, PK: while expr: ... => while (expr) { ... } 
    142 # 2018-01-04, OE: Fixed bug in 'visit_If': visiting node.orelse in case else exists. 
    143142 
    144143from __future__ import print_function 
     
    185184 
    186185 
    187 # TODO: should not allow eval of arbitrary python 
     186def to_source(tree, constants=None, fname=None, lineno=0): 
     187    """ 
     188    This function can convert a syntax tree into C sourcecode. 
     189    """ 
     190    generator = SourceGenerator(constants=constants, fname=fname, lineno=lineno) 
     191    generator.visit(tree) 
     192    c_code = "".join(generator.c_proc) 
     193    return c_code 
     194 
    188195def isevaluable(s): 
    189196    try: 
     
    322329                except AttributeError: 
    323330                    arg_name = arg.id 
    324                 w_str = ("C does not support default parameters: %s=%s" 
     331                w_str = ("Default Parameters are unknown to C: '%s = %s" 
    325332                         % (arg_name, str(default.n))) 
    326333                self.warnings.append(w_str) 
     
    501508        self.current_function = node.name 
    502509 
    503         # remember the location of the next warning that will be inserted 
    504         # so that we can stuff the function name ahead of the warning list 
    505         # if any warnings are generated by the function. 
    506         warning_index = len(self.warnings) 
    507  
    508510        self.newline(extra=1) 
    509511        self.decorators(node) 
     
    521523        del self.c_pointers[:] 
    522524        self.current_function = "" 
    523         if warning_index != len(self.warnings): 
    524             self.warnings.insert(warning_index, "Warning in function '" + node.name + "':") 
    525525 
    526526    def visit_ClassDef(self, node): 
     
    586586                self.newline() 
    587587                self.write_c('else {') 
    588                 self.body(else_) 
     588                self.body(node.body) 
    589589                self.add_c_line('}') 
    590590                break 
     
    615615        return start, stop, step 
    616616 
    617     def add_c_int_var(self, name): 
    618         if name not in self.c_int_vars: 
    619             self.c_int_vars.append(name) 
    620  
    621617    def visit_For(self, node): 
    622618        # node: for iterator is stored in node.target. 
     
    631627                    iterator = self.current_statement 
    632628                    self.current_statement = '' 
    633                     self.add_c_int_var(iterator) 
     629                    if iterator not in self.c_int_vars: 
     630                        self.c_int_vars.append(iterator) 
    634631                    start, stop, step = self.get_for_range(node) 
    635632                    self.write_c("for (" + iterator + "=" + str(start) + 
     
    739736            self.write_c('return') 
    740737        else: 
    741             self.write_c('return ') 
     738            self.write_c('return(') 
    742739            self.visit(node.value) 
     740        self.write_c(')') 
    743741        self.add_semi_colon() 
    744742        self.in_expr = False 
     
    857855                name not in self.c_constants and not name.isdigit()): 
    858856            if self.in_subscript: 
    859                 self.add_c_int_var(node.id) 
     857                self.c_int_vars.append(node.id) 
    860858            else: 
    861859                self.c_vars.append(node.id) 
     
    12541252    Convert a list of functions to a list of C code strings. 
    12551253 
    1256     Returns list of corresponding code snippets (with trailing lines in 
    1257     each block) and a list of warnings generated by the translator. 
    1258  
    12591254    A function is given by the tuple (source, filename, line number). 
    12601255 
     
    12711266    """ 
    12721267    snippets = [] 
    1273     warnings = [] 
     1268    #snippets.append("#include <math.h>") 
     1269    #snippets.append("") 
    12741270    for source, fname, lineno in functions: 
    12751271        line_directive = '#line %d "%s"\n'%(lineno, fname.replace('\\', '\\\\')) 
     
    12791275        source = PRINT_STR.sub(SUBST_STR, source) 
    12801276        tree = ast.parse(source) 
    1281         generator = SourceGenerator(constants=constants, fname=fname, lineno=lineno) 
    1282         generator.visit(tree) 
    1283         c_code = "".join(generator.c_proc) 
     1277        c_code = to_source(tree, constants=constants, fname=fname, lineno=lineno) 
    12841278        snippets.append(c_code) 
    1285         warnings.extend(generator.warnings) 
    1286     return snippets, warnings 
    1287  
    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  
    1295  
    1296 C_HEADER = """ 
     1279    return snippets 
     1280 
     1281def main(): 
     1282    import os 
     1283    #print("Parsing...using Python" + sys.version) 
     1284    if len(sys.argv) == 1: 
     1285        print("""\ 
     1286Usage: python py2c.py <infile> [<outfile>] 
     1287 
     1288if outfile is omitted, output file is '<infile>.c' 
     1289""") 
     1290        return 
     1291 
     1292    fname_in = sys.argv[1] 
     1293    if len(sys.argv) == 2: 
     1294        fname_base = os.path.splitext(fname_in)[0] 
     1295        fname_out = str(fname_base) + '.c' 
     1296    else: 
     1297        fname_out = sys.argv[2] 
     1298 
     1299    with open(fname_in, "r") as python_file: 
     1300        code = python_file.read() 
     1301    name = "gauss" 
     1302    code = (code 
     1303            .replace(name+'.n', 'GAUSS_N') 
     1304            .replace(name+'.z', 'GAUSS_Z') 
     1305            .replace(name+'.w', 'GAUSS_W') 
     1306            .replace('if __name__ == "__main__"', "def main()") 
     1307    ) 
     1308 
     1309 
     1310    c_code = "".join(translate([(code, fname_in, 1)])) 
     1311    c_code = c_code.replace("double main()", "int main(int argc, char *argv[])") 
     1312 
     1313    with open(fname_out, "w") as file_out: 
     1314        file_out.write(""" 
    12971315#include <stdio.h> 
    12981316#include <stdbool.h> 
     
    13121330    return ans; 
    13131331} 
    1314 """ 
    1315  
    1316 USAGE = """\ 
    1317 Usage: python py2c.py <infile> [<outfile>] 
    1318  
    1319 if outfile is omitted, output file is '<infile>.c' 
    1320 """ 
    1321  
    1322 def main(): 
    1323     import os 
    1324     #print("Parsing...using Python" + sys.version) 
    1325     if len(sys.argv) == 1: 
    1326         print(USAGE) 
    1327         return 
    1328  
    1329     fname_in = sys.argv[1] 
    1330     if len(sys.argv) == 2: 
    1331         fname_base = os.path.splitext(fname_in)[0] 
    1332         fname_out = str(fname_base) + '.c' 
    1333     else: 
    1334         fname_out = sys.argv[2] 
    1335  
    1336     with open(fname_in, "r") as python_file: 
    1337         code = python_file.read() 
    1338     name = "gauss" 
    1339     code = (code 
    1340             .replace(name+'.n', 'GAUSS_N') 
    1341             .replace(name+'.z', 'GAUSS_Z') 
    1342             .replace(name+'.w', 'GAUSS_W') 
    1343             .replace('if __name__ == "__main__"', "def main()") 
    1344            ) 
    1345  
    1346     translation, warnings = translate([(code, fname_in, 1)]) 
    1347     c_code = "".join(translation) 
    1348     c_code = c_code.replace("double main()", "int main(int argc, char *argv[])") 
    1349  
    1350     with open(fname_out, "w") as file_out: 
    1351         file_out.write(C_HEADER) 
     1332 
     1333""") 
    13521334        file_out.write(c_code) 
    1353  
    1354     if warnings: 
    1355         print("\n".join(warnings)) 
    13561335    #print("...Done") 
    13571336 
Note: See TracChangeset for help on using the changeset viewer.