# HG changeset patch # User Paul Boddie # Date 1486416647 -3600 # Node ID c4203b80000740853a2fa1fd2e668a45dc631880 # Parent 3c61a4e22626aab669a779f2141fa86e02b3cba9 Introduced warnings about inappropriate numbers of arguments for invocations where multiple targets have been identified. diff -r 3c61a4e22626 -r c4203b800007 results.py --- a/results.py Mon Feb 06 22:29:25 2017 +0100 +++ b/results.py Mon Feb 06 22:30:47 2017 +0100 @@ -33,6 +33,9 @@ def reference(self): return None + def references(self): + return None + def get_name(self): return None @@ -112,9 +115,15 @@ "A resolved reference mix-in." + def __init__(self, ref): + self.ref = ref + def reference(self): return self.ref + def references(self): + return [self.ref] + def get_name(self): return self.ref and self.ref.get_name() or None @@ -139,7 +148,7 @@ def __init__(self, name, ref, expr=None): NameRef.__init__(self, name, expr) - self.ref = ref + ResolvedRef.__init__(self, ref) def __repr__(self): return "ResolvedNameRef(%r, %r, %r)" % (self.name, self.ref, self.expr) @@ -160,9 +169,6 @@ "An instance reference." - def __init__(self, ref): - self.ref = ref - def reference(self): return self.ref diff -r 3c61a4e22626 -r c4203b800007 translator.py --- a/translator.py Mon Feb 06 22:29:25 2017 +0100 +++ b/translator.py Mon Feb 06 22:30:47 2017 +0100 @@ -194,6 +194,9 @@ self.refs = refs self.accessor_kinds = accessor_kinds + def references(self): + return self.refs + def get_origin(self): return self.refs and len(self.refs) == 1 and first(self.refs).get_origin() @@ -286,6 +289,8 @@ else: return Expression(str(expr)) + + # The actual translation process itself. class TranslatedModule(CommonModule): @@ -1129,20 +1134,32 @@ expr = self.process_structure_node(n.node) objpath = expr.get_origin() + + # Identified target details. + target = None target_structure = None + + # Specific function target information. + function = None + + # Instantiation involvement. + instantiation = False literal_instantiation = False + + # Invocation requirements. + context_required = True - - # Obtain details of the callable. + parameters = None + + # Obtain details of the callable and of its parameters. # Literals may be instantiated specially. if expr.is_name() and expr.name.startswith("$L") and objpath: instantiation = literal_instantiation = objpath - parameters = None target = encode_literal_instantiator(objpath) context_required = False @@ -1186,7 +1203,30 @@ # Other targets are retrieved at run-time. else: - parameters = None + refs = expr.references() + + # Attempt to test the number of arguments and warn about possible + # invocation problems. + + if refs: + for ref in refs: + _objpath = ref.get_origin() + _parameters = self.importer.function_parameters.get(_objpath) + + if _parameters is None: + continue + + # Determine whether the possible target has a different + # number of parameters to the number of arguments given. + + num_parameters = len(_parameters) + _defaults = len(self.importer.function_defaults.get(_objpath, [])) + + if len(n.args) < num_parameters - _defaults or len(n.args) > num_parameters: + print "In %s, at line %d, inappropriate number of " \ + "arguments given. Need %d arguments to call %s." % ( + self.get_namespace_path(), n.lineno, num_parameters, + _objpath) # Arguments are presented in a temporary frame array with any context # always being the first argument. Where it would be unused, it may be @@ -1198,6 +1238,9 @@ else: args = ["__NULL"] + # Complete the array with null values, permitting tests for a complete + # set of arguments. + args += [None] * (not parameters and len(n.args) or parameters and len(parameters) or 0) kwcodes = [] kwargs = [] @@ -1888,9 +1931,6 @@ self.writeline("}") def statement(self, expr): - # NOTE: Should never be None. - if not expr: - self.writestmt("...;") s = str(expr) if s: self.writestmt("%s;" % s)