1.1 --- a/lplc Mon Jan 09 16:01:23 2017 +0100
1.2 +++ b/lplc Mon Jan 09 16:05:35 2017 +0100
1.3 @@ -1,7 +1,9 @@
1.4 #!/usr/bin/env python
1.5
1.6 from errors import *
1.7 +from os import rename
1.8 from os.path import abspath, exists, join, split
1.9 +from subprocess import Popen, PIPE
1.10 from time import time
1.11 import importer, deducer, optimiser, generator, translator
1.12 import sys
1.13 @@ -28,25 +30,75 @@
1.14 print >>sys.stderr, "%s took %.2f seconds" % (activity, time() - now)
1.15 return time()
1.16
1.17 +def call(tokens, verbose=False):
1.18 + out = not verbose and PIPE or None
1.19 + cmd = Popen(tokens, stdout=out, stderr=out)
1.20 + stdout, stderr = cmd.communicate()
1.21 + return cmd.wait()
1.22 +
1.23 # Main program.
1.24
1.25 if __name__ == "__main__":
1.26 - args = sys.argv[2:]
1.27 + args = sys.argv[1:]
1.28 path = libdirs + sys.path[:]
1.29
1.30 - filename = abspath(sys.argv[1])
1.31 + # Determine the options and arguments.
1.32 +
1.33 + verbose = False
1.34 + reset = False
1.35 + debug = False
1.36 + make = True
1.37 + make_verbose = True
1.38 +
1.39 + filenames = []
1.40 + outputs = []
1.41 +
1.42 + # Obtain program filenames by default.
1.43 +
1.44 + l = filenames
1.45 +
1.46 + for arg in args:
1.47 + if arg == "-v": verbose = True
1.48 + elif arg == "-r": reset = True
1.49 + elif arg == "-g": debug = True
1.50 + elif arg == "-c": make = False
1.51 + elif arg == "-q": make_verbose = False
1.52 + elif arg == "-o": l = outputs
1.53 + else:
1.54 + l.append(arg)
1.55 +
1.56 + # Revert to collecting program filenames after obtaining the output
1.57 + # executable filename.
1.58 +
1.59 + if l is outputs: l = filenames
1.60 +
1.61 + # Obtain the program filename.
1.62 +
1.63 + if len(filenames) > 1:
1.64 + print >>sys.stderr, "Only one main program file can be specified."
1.65 + sys.exit(1)
1.66 +
1.67 + filename = abspath(filenames[0])
1.68 path.append(split(filename)[0])
1.69
1.70 - verbose = "-v" in args
1.71 - reset = "-r" in args
1.72 - debug = "-g" in args
1.73 + # Obtain the output filename.
1.74 +
1.75 + output = outputs and outputs[0] or "main"
1.76 +
1.77 + # Define the output data directories.
1.78 +
1.79 + datadir = "_lplc"
1.80 + cache_dir = join(datadir, "_cache")
1.81 + deduced_dir = join(datadir, "_deduced")
1.82 + output_dir = join(datadir, "_output")
1.83 + generated_dir = join(datadir, "_generated")
1.84
1.85 # Load the program.
1.86
1.87 try:
1.88 start = now = time()
1.89
1.90 - i = importer.Importer(path, "_cache", verbose)
1.91 + i = importer.Importer(path, cache_dir, verbose)
1.92 m = i.initialise(filename, reset)
1.93 success = i.finalise()
1.94
1.95 @@ -58,25 +110,44 @@
1.96 show_missing(i.missing)
1.97 sys.exit(1)
1.98
1.99 - d = deducer.Deducer(i, "_deduced")
1.100 + d = deducer.Deducer(i, deduced_dir)
1.101 d.to_output()
1.102
1.103 now = stopwatch("Deduction", now)
1.104
1.105 - o = optimiser.Optimiser(i, d, "_output")
1.106 + o = optimiser.Optimiser(i, d, output_dir)
1.107 o.to_output()
1.108
1.109 now = stopwatch("Optimisation", now)
1.110
1.111 - g = generator.Generator(i, o, "_generated")
1.112 + g = generator.Generator(i, o, generated_dir)
1.113 g.to_output(debug)
1.114
1.115 now = stopwatch("Generation", now)
1.116
1.117 - t = translator.Translator(i, d, o, "_generated")
1.118 + t = translator.Translator(i, d, o, generated_dir)
1.119 t.to_output()
1.120
1.121 - stopwatch("Translation", now)
1.122 + now = stopwatch("Translation", now)
1.123 +
1.124 + # Compile the program unless otherwise indicated.
1.125 +
1.126 + if make:
1.127 + make_clean_cmd = ["make", "-C", generated_dir, "clean"]
1.128 + make_cmd = make_clean_cmd[:-1]
1.129 +
1.130 + retval = call(make_clean_cmd, make_verbose)
1.131 + if not retval:
1.132 + retval = call(make_cmd, make_verbose)
1.133 +
1.134 + if not retval:
1.135 + stopwatch("Compilation", now)
1.136 + else:
1.137 + sys.exit(retval)
1.138 +
1.139 + # Move the executable into the current directory.
1.140 +
1.141 + rename(join(generated_dir, "main"), output)
1.142
1.143 # Report any errors.
1.144