1.1 --- a/importer.py Wed Feb 08 16:20:27 2017 +0100
1.2 +++ b/importer.py Wed Feb 08 17:24:31 2017 +0100
1.3 @@ -35,7 +35,7 @@
1.4
1.5 special_attributes = ("__args__", "__file__", "__fn__", "__name__", "__parent__")
1.6
1.7 - def __init__(self, path, cache=None, verbose=False):
1.8 + def __init__(self, path, cache=None, verbose=False, warnings=None):
1.9
1.10 """
1.11 Initialise the importer with the given search 'path' - a list of
1.12 @@ -46,11 +46,15 @@
1.13
1.14 The optional 'verbose' parameter causes output concerning the activities
1.15 of the object to be produced if set to a true value (not the default).
1.16 +
1.17 + The optional 'warnings' parameter may indicate classes of warnings to be
1.18 + produced.
1.19 """
1.20
1.21 self.path = path
1.22 self.cache = cache
1.23 self.verbose = verbose
1.24 + self.warnings = warnings
1.25
1.26 # Module importing queue, required modules, removed modules and active
1.27 # modules in the final program.
1.28 @@ -116,6 +120,12 @@
1.29
1.30 self.make_cache()
1.31
1.32 + def give_warning(self, name):
1.33 +
1.34 + "Return whether the indicated warning 'name' should be given."
1.35 +
1.36 + return self.warnings and (name in self.warnings or "all" in self.warnings)
1.37 +
1.38 def make_cache(self):
1.39
1.40 "Make a cache directory if it does not already exist."
2.1 --- a/lplc Wed Feb 08 16:20:27 2017 +0100
2.2 +++ b/lplc Wed Feb 08 17:24:31 2017 +0100
2.3 @@ -43,12 +43,59 @@
2.4 stdout, stderr = cmd.communicate()
2.5 return cmd.wait()
2.6
2.7 +def start_arg_list(l, arg, prefix, needed):
2.8 +
2.9 + """
2.10 + Add to 'l' any value given as part of 'arg' having the given option
2.11 + 'prefix'. The 'needed' number of values is provided in case no value is
2.12 + found.
2.13 +
2.14 + Return 'l' and 'needed' decremented by 1 together in a tuple.
2.15 + """
2.16 +
2.17 + s = arg[len(prefix):].strip()
2.18 + if s:
2.19 + l.append(s)
2.20 + return l, needed - 1
2.21 + else:
2.22 + return l, needed
2.23 +
2.24 # Main program.
2.25
2.26 if __name__ == "__main__":
2.27 + basename = split(sys.argv[0])[-1]
2.28 args = sys.argv[1:]
2.29 path = libdirs
2.30
2.31 + if "--help" in args or not args:
2.32 + print >>sys.stderr, """\
2.33 +Usage: %s [ <options> ] <filename>
2.34 +
2.35 +Compile the program whose principal file is given in place of <filename>.
2.36 +The following options may be specified:
2.37 +
2.38 +-c Only partially compile the program; do not attempt to build or link it
2.39 +-g Generate debugging information for the built executable
2.40 +-q Silence messages produced when building an executable
2.41 +-r Reset (discard) cached program information; inspect the whole program again
2.42 +-tb Provide a traceback for any internal errors (development only)
2.43 +-v Report compiler activities in a verbose fashion (development only)
2.44 +
2.45 +Some options may be followed by values, either immediately after the option
2.46 +(without any space between) or in the arguments that follow them:
2.47 +
2.48 +-o Indicate the output executable name
2.49 +-W Show warnings on the topics indicated
2.50 +
2.51 +Currently, the following warnings are supported:
2.52 +
2.53 +all Show all possible warnings
2.54 +
2.55 +args Show invocations where a callable may be involved that cannot accept the
2.56 + arguments provided
2.57 +""" % basename
2.58 + sys.exit(1)
2.59 +
2.60 # Determine the options and arguments.
2.61
2.62 debug = False
2.63 @@ -57,6 +104,7 @@
2.64 reset = False
2.65 traceback = False
2.66 verbose = False
2.67 + warnings = []
2.68
2.69 filenames = []
2.70 outputs = []
2.71 @@ -64,6 +112,7 @@
2.72 # Obtain program filenames by default.
2.73
2.74 l = filenames
2.75 + needed = None
2.76
2.77 for arg in args:
2.78 if arg == "-c": make = False
2.79 @@ -71,20 +120,21 @@
2.80 elif arg == "-q": make_verbose = False
2.81 elif arg == "-r": reset = True
2.82 elif arg == "-tb": traceback = True
2.83 - elif arg == "-o": l = outputs
2.84 + elif arg.startswith("-o"): l, needed = start_arg_list(outputs, arg, "-o", 1)
2.85 elif arg == "-v": verbose = True
2.86 + elif arg.startswith("-W"): l, needed = start_arg_list(warnings, arg, "-W", 1)
2.87 else:
2.88 l.append(arg)
2.89 + if needed:
2.90 + needed -= 1
2.91
2.92 - # Revert to collecting program filenames after obtaining the output
2.93 - # executable filename.
2.94 -
2.95 - if l is outputs: l = filenames
2.96 + if needed == 0:
2.97 + l = filenames
2.98
2.99 # Obtain the program filename.
2.100
2.101 - if len(filenames) > 1:
2.102 - print >>sys.stderr, "Only one main program file can be specified."
2.103 + if len(filenames) != 1:
2.104 + print >>sys.stderr, "One main program file must be specified."
2.105 sys.exit(1)
2.106
2.107 filename = abspath(filenames[0])
2.108 @@ -92,6 +142,9 @@
2.109
2.110 # Obtain the output filename.
2.111
2.112 + if outputs and not make:
2.113 + print >>sys.stderr, "Output specified but building disabled."
2.114 +
2.115 output = outputs and outputs[0] or "_main"
2.116
2.117 # Define the output data directories.
2.118 @@ -107,7 +160,7 @@
2.119 try:
2.120 start = now = time()
2.121
2.122 - i = importer.Importer(path, cache_dir, verbose)
2.123 + i = importer.Importer(path, cache_dir, verbose, warnings)
2.124 m = i.initialise(filename, reset)
2.125 success = i.finalise()
2.126
3.1 --- a/translator.py Wed Feb 08 16:20:27 2017 +0100
3.2 +++ b/translator.py Wed Feb 08 17:24:31 2017 +0100
3.3 @@ -1215,9 +1215,11 @@
3.4
3.5 target_structure = "&%s" % encode_path(objpath)
3.6
3.7 - # Other targets are retrieved at run-time.
3.8 -
3.9 - else:
3.10 + # Other targets are retrieved at run-time. Some information about them
3.11 + # may be available and be used to provide warnings about argument
3.12 + # compatibility.
3.13 +
3.14 + elif self.importer.give_warning("args"):
3.15 unsuitable = self.get_referenced_attribute_invocations(location)
3.16
3.17 if unsuitable: