Changes in / [5ab99b7:d5014e4] in sasmodels


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/py2c.py

    rd7f33e5 r0bd0877  
    112112# Update Notes 
    113113# ============ 
    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 
     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 
    124124#                 square(x)(pow(x,2)) and cube(x)(pow(x,3)), implemented in 
    125125#                 translate_power, called from visit_BinOp 
    126 # 12/07/2017, OE: Translation of integer division, '\\' in python, implemented 
     126# 2017-12-07, OE: Translation of integer division, '\\' in python, implemented 
    127127#                 in translate_integer_divide, called from visit_BinOp 
    128 # 12/07/2017, OE: C variable definition handled in 'define_c_vars' 
     128# 2017-12-07, OE: C variable definition handled in 'define_c_vars' 
    129129#               : Python integer division, '//', translated to C in 
    130130#                 'translate_integer_divide' 
    131 # 12/15/2017, OE: Precedence maintained by writing opening and closing 
     131# 2017-12-15, OE: Precedence maintained by writing opening and closing 
    132132#                 parenthesesm '(',')', in procedure 'visit_BinOp'. 
    133 # 12/18/2017, OE: Added call to 'add_current_line()' at the beginning 
     133# 2017-12-18, 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. 
    142143 
    143144from __future__ import print_function 
     
    184185 
    185186 
    186 def 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  
     187# TODO: should not allow eval of arbitrary python 
    195188def isevaluable(s): 
    196189    try: 
     
    329322                except AttributeError: 
    330323                    arg_name = arg.id 
    331                 w_str = ("Default Parameters are unknown to C: '%s = %s" 
     324                w_str = ("C does not support default parameters: %s=%s" 
    332325                         % (arg_name, str(default.n))) 
    333326                self.warnings.append(w_str) 
     
    508501        self.current_function = node.name 
    509502 
     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 
    510508        self.newline(extra=1) 
    511509        self.decorators(node) 
     
    523521        del self.c_pointers[:] 
    524522        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(node.body) 
     588                self.body(else_) 
    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 
    617621    def visit_For(self, node): 
    618622        # node: for iterator is stored in node.target. 
     
    627631                    iterator = self.current_statement 
    628632                    self.current_statement = '' 
    629                     if iterator not in self.c_int_vars: 
    630                         self.c_int_vars.append(iterator) 
     633                    self.add_c_int_var(iterator) 
    631634                    start, stop, step = self.get_for_range(node) 
    632635                    self.write_c("for (" + iterator + "=" + str(start) + 
     
    736739            self.write_c('return') 
    737740        else: 
    738             self.write_c('return(') 
     741            self.write_c('return ') 
    739742            self.visit(node.value) 
    740         self.write_c(')') 
    741743        self.add_semi_colon() 
    742744        self.in_expr = False 
     
    855857                name not in self.c_constants and not name.isdigit()): 
    856858            if self.in_subscript: 
    857                 self.c_int_vars.append(node.id) 
     859                self.add_c_int_var(node.id) 
    858860            else: 
    859861                self.c_vars.append(node.id) 
     
    12521254    Convert a list of functions to a list of C code strings. 
    12531255 
     1256    Returns list of corresponding code snippets (with trailing lines in 
     1257    each block) and a list of warnings generated by the translator. 
     1258 
    12541259    A function is given by the tuple (source, filename, line number). 
    12551260 
     
    12661271    """ 
    12671272    snippets = [] 
    1268     #snippets.append("#include <math.h>") 
    1269     #snippets.append("") 
     1273    warnings = [] 
    12701274    for source, fname, lineno in functions: 
    12711275        line_directive = '#line %d "%s"\n'%(lineno, fname.replace('\\', '\\\\')) 
     
    12751279        source = PRINT_STR.sub(SUBST_STR, source) 
    12761280        tree = ast.parse(source) 
    1277         c_code = to_source(tree, constants=constants, fname=fname, lineno=lineno) 
     1281        generator = SourceGenerator(constants=constants, fname=fname, lineno=lineno) 
     1282        generator.visit(tree) 
     1283        c_code = "".join(generator.c_proc) 
    12781284        snippets.append(c_code) 
    1279     return snippets 
    1280  
    1281 def main(): 
    1282     import os 
    1283     #print("Parsing...using Python" + sys.version) 
    1284     if len(sys.argv) == 1: 
    1285         print("""\ 
    1286 Usage: python py2c.py <infile> [<outfile>] 
    1287  
    1288 if 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(""" 
     1285        warnings.extend(generator.warnings) 
     1286    return snippets, warnings 
     1287 
     1288def 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 
     1296C_HEADER = """ 
    13151297#include <stdio.h> 
    13161298#include <stdbool.h> 
     
    13301312    return ans; 
    13311313} 
    1332  
    1333 """) 
     1314""" 
     1315 
     1316USAGE = """\ 
     1317Usage: python py2c.py <infile> [<outfile>] 
     1318 
     1319if outfile is omitted, output file is '<infile>.c' 
     1320""" 
     1321 
     1322def 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) 
    13341352        file_out.write(c_code) 
     1353 
     1354    if warnings: 
     1355        print("\n".join(warnings)) 
    13351356    #print("...Done") 
    13361357 
Note: See TracChangeset for help on using the changeset viewer.