Lichen

lplc

538:2846b907e92b
2017-02-04 Paul Boddie Tidied up built-in class location computation.
     1 #!/usr/bin/env python     2      3 from errors import *     4 from os import rename     5 from os.path import abspath, exists, join, split     6 from pyparser import error     7 from subprocess import Popen, PIPE     8 from time import time     9 import importer, deducer, optimiser, generator, translator    10 import sys    11     12 libdirs = [    13     join(split(__file__)[0], "lib"),    14     "/usr/share/lichen/lib"    15     ]    16     17 def load_module(filename, module_name):    18     for libdir in libdirs:    19         path = join(libdir, filename)    20         if exists(path):    21             return i.load_from_file(path, module_name)    22     return None    23     24 def show_missing(missing):    25     missing = list(missing)    26     missing.sort()    27     for module_name, name in missing:    28         print >>sys.stderr, "Module %s references an unknown object: %s" % (module_name, name)    29     30 def show_syntax_error(exc):    31     print >>sys.stderr, "Syntax error at column %d on line %d in file %s:" % (exc.offset, exc.lineno, exc.filename)    32     print >>sys.stderr    33     print >>sys.stderr, exc.text.rstrip()    34     print >>sys.stderr, " " * exc.offset + "^"    35     36 def stopwatch(activity, now):    37     print >>sys.stderr, "%s took %.2f seconds" % (activity, time() - now)    38     return time()    39     40 def call(tokens, verbose=False):    41     out = not verbose and PIPE or None    42     cmd = Popen(tokens, stdout=out, stderr=out)    43     stdout, stderr = cmd.communicate()    44     return cmd.wait()    45     46 # Main program.    47     48 if __name__ == "__main__":    49     args = sys.argv[1:]    50     path = libdirs    51     52     # Determine the options and arguments.    53     54     debug = False    55     make = True    56     make_verbose = True    57     reset = False    58     traceback = False    59     verbose = False    60     61     filenames = []    62     outputs = []    63     64     # Obtain program filenames by default.    65     66     l = filenames    67     68     for arg in args:    69         if arg == "-c": make = False    70         elif arg == "-g": debug = True    71         elif arg == "-q": make_verbose = False    72         elif arg == "-r": reset = True    73         elif arg == "-tb": traceback = True    74         elif arg == "-o": l = outputs    75         elif arg == "-v": verbose = True    76         else:    77             l.append(arg)    78     79             # Revert to collecting program filenames after obtaining the output    80             # executable filename.    81     82             if l is outputs: l = filenames    83     84     # Obtain the program filename.    85     86     if len(filenames) > 1:    87         print >>sys.stderr, "Only one main program file can be specified."    88         sys.exit(1)    89     90     filename = abspath(filenames[0])    91     path.append(split(filename)[0])    92     93     # Obtain the output filename.    94     95     output = outputs and outputs[0] or "_main"    96     97     # Define the output data directories.    98     99     datadir = "_lplc"   100     cache_dir = join(datadir, "_cache")   101     deduced_dir = join(datadir, "_deduced")   102     output_dir = join(datadir, "_output")   103     generated_dir = join(datadir, "_generated")   104    105     # Load the program.   106    107     try:   108         start = now = time()   109    110         i = importer.Importer(path, cache_dir, verbose)   111         m = i.initialise(filename, reset)   112         success = i.finalise()   113    114         now = stopwatch("Inspection", now)   115    116         # Check for success, indicating missing references otherwise.   117    118         if not success:   119             show_missing(i.missing)   120             sys.exit(1)   121    122         d = deducer.Deducer(i, deduced_dir)   123         d.to_output()   124    125         now = stopwatch("Deduction", now)   126    127         o = optimiser.Optimiser(i, d, output_dir)   128         o.to_output()   129    130         now = stopwatch("Optimisation", now)   131    132         g = generator.Generator(i, o, generated_dir)   133         g.to_output(debug)   134    135         now = stopwatch("Generation", now)   136    137         t = translator.Translator(i, d, o, generated_dir)   138         t.to_output()   139    140         now = stopwatch("Translation", now)   141    142         # Compile the program unless otherwise indicated.   143    144         if make:   145             make_clean_cmd = ["make", "-C", generated_dir, "clean"]   146             make_cmd = make_clean_cmd[:-1]   147    148             retval = call(make_clean_cmd, make_verbose)   149             if not retval:   150                 retval = call(make_cmd, make_verbose)   151    152             if not retval:   153                 stopwatch("Compilation", now)   154             else:   155                 sys.exit(retval)   156    157             # Move the executable into the current directory.   158    159             rename(join(generated_dir, "main"), output)   160    161     # Report any errors.   162    163     except error.SyntaxError, exc:   164         show_syntax_error(exc)   165         if traceback:   166             raise   167         sys.exit(1)   168    169     except ProcessingError, exc:   170         print exc   171         if traceback:   172             raise   173         sys.exit(1)   174    175     else:   176         sys.exit(0)   177    178 # vim: tabstop=4 expandtab shiftwidth=4