# HG changeset patch # User Paul Boddie # Date 1483974335 -3600 # Node ID 5cf942043f29569e3e8ee65a770be42699c662f8 # Parent 8daf9478524150b540b902e05b3bf6490b1b4a59 Changed the output directories, added output compilation (enabled by default), made option handling more flexible, introduced output executable and compilation options. diff -r 8daf94785241 -r 5cf942043f29 lplc --- a/lplc Mon Jan 09 16:01:23 2017 +0100 +++ b/lplc Mon Jan 09 16:05:35 2017 +0100 @@ -1,7 +1,9 @@ #!/usr/bin/env python from errors import * +from os import rename from os.path import abspath, exists, join, split +from subprocess import Popen, PIPE from time import time import importer, deducer, optimiser, generator, translator import sys @@ -28,25 +30,75 @@ print >>sys.stderr, "%s took %.2f seconds" % (activity, time() - now) return time() +def call(tokens, verbose=False): + out = not verbose and PIPE or None + cmd = Popen(tokens, stdout=out, stderr=out) + stdout, stderr = cmd.communicate() + return cmd.wait() + # Main program. if __name__ == "__main__": - args = sys.argv[2:] + args = sys.argv[1:] path = libdirs + sys.path[:] - filename = abspath(sys.argv[1]) + # Determine the options and arguments. + + verbose = False + reset = False + debug = False + make = True + make_verbose = True + + filenames = [] + outputs = [] + + # Obtain program filenames by default. + + l = filenames + + for arg in args: + if arg == "-v": verbose = True + elif arg == "-r": reset = True + elif arg == "-g": debug = True + elif arg == "-c": make = False + elif arg == "-q": make_verbose = False + elif arg == "-o": l = outputs + else: + l.append(arg) + + # Revert to collecting program filenames after obtaining the output + # executable filename. + + if l is outputs: l = filenames + + # Obtain the program filename. + + if len(filenames) > 1: + print >>sys.stderr, "Only one main program file can be specified." + sys.exit(1) + + filename = abspath(filenames[0]) path.append(split(filename)[0]) - verbose = "-v" in args - reset = "-r" in args - debug = "-g" in args + # Obtain the output filename. + + output = outputs and outputs[0] or "main" + + # Define the output data directories. + + datadir = "_lplc" + cache_dir = join(datadir, "_cache") + deduced_dir = join(datadir, "_deduced") + output_dir = join(datadir, "_output") + generated_dir = join(datadir, "_generated") # Load the program. try: start = now = time() - i = importer.Importer(path, "_cache", verbose) + i = importer.Importer(path, cache_dir, verbose) m = i.initialise(filename, reset) success = i.finalise() @@ -58,25 +110,44 @@ show_missing(i.missing) sys.exit(1) - d = deducer.Deducer(i, "_deduced") + d = deducer.Deducer(i, deduced_dir) d.to_output() now = stopwatch("Deduction", now) - o = optimiser.Optimiser(i, d, "_output") + o = optimiser.Optimiser(i, d, output_dir) o.to_output() now = stopwatch("Optimisation", now) - g = generator.Generator(i, o, "_generated") + g = generator.Generator(i, o, generated_dir) g.to_output(debug) now = stopwatch("Generation", now) - t = translator.Translator(i, d, o, "_generated") + t = translator.Translator(i, d, o, generated_dir) t.to_output() - stopwatch("Translation", now) + now = stopwatch("Translation", now) + + # Compile the program unless otherwise indicated. + + if make: + make_clean_cmd = ["make", "-C", generated_dir, "clean"] + make_cmd = make_clean_cmd[:-1] + + retval = call(make_clean_cmd, make_verbose) + if not retval: + retval = call(make_cmd, make_verbose) + + if not retval: + stopwatch("Compilation", now) + else: + sys.exit(retval) + + # Move the executable into the current directory. + + rename(join(generated_dir, "main"), output) # Report any errors. diff -r 8daf94785241 -r 5cf942043f29 test_all.sh --- a/test_all.sh Mon Jan 09 16:01:23 2017 +0100 +++ b/test_all.sh Mon Jan 09 16:05:35 2017 +0100 @@ -1,5 +1,8 @@ #!/bin/sh +LPLC="./lplc" +DATADIR="_lplc" + # Expect failure from the "bad" tests. expect_failure() { @@ -11,8 +14,8 @@ check_type_warnings() { - if [ -e "_deduced/type_warnings" ] && \ - [ `stat -c %s "_deduced/type_warnings"` -ne 0 ] ; then + if [ -e "$DATADIR/_deduced/type_warnings" ] && \ + [ `stat -c %s "$DATADIR/_deduced/type_warnings"` -ne 0 ] ; then echo "Type warnings in deduced information." 1>&2 return 1 @@ -61,7 +64,7 @@ # Run tests without an existing cache. echo "$FILENAME..." 1>&2 - if ! ./lplc "$FILENAME" -r ; then + if ! "$LPLC" -c -r "$FILENAME" ; then if ! expect_failure; then exit 1 else @@ -73,7 +76,7 @@ # Check for unresolved names in the cache. echo " (depends)..." 1>&2 - for CACHEFILE in "_cache/"* ; do + for CACHEFILE in "$DATADIR/_cache/"* ; do STARTLINE=`grep -n '^deferred:' "$CACHEFILE" | cut -d: -f 1` if tail -n +$(($STARTLINE + 2)) "$CACHEFILE" | grep -q '' ; then echo "Unresolved names in the cache." 1>&2 @@ -89,7 +92,7 @@ # Run tests with an existing cache. echo " (cached)..." 1>&2 - if ! ./lplc "$FILENAME" ; then exit 1 ; fi + if ! "$LPLC" -c "$FILENAME" ; then exit 1 ; fi echo " (warnings)..." 1>&2 if ! check_type_warnings ; then exit 1 ; fi @@ -101,13 +104,13 @@ OUTLOG="_results/$TESTNAME.out" echo " (build)..." 1>&2 - if ! make -C _generated clean > "$BUILDLOG" || \ - ! make -C _generated > "$BUILDLOG" ; then + if ! make -C "$DATADIR/_generated" clean > "$BUILDLOG" || \ + ! make -C "$DATADIR/_generated" > "$BUILDLOG" ; then exit 1 fi echo " (run)..." 1>&2 - if ! "_generated/main" > "$OUTLOG" < "$TESTINPUT" ; then + if ! "$DATADIR/_generated/main" > "$OUTLOG" < "$TESTINPUT" ; then exit 1 fi fi