# HG changeset patch # User Paul Boddie # Date 1205972028 -3600 # Node ID 999f14fecba913a74f2d353fdae1d561c452b427 # Parent a7cbfb7bb92b4931bfdd6c560ad75aba978c4a74 Added some tests of argument compatibility for predictable cases. Improved the ProcessingError __repr__ string. Added failure tests for keyword arguments. diff -r a7cbfb7bb92b -r 999f14fecba9 README.txt --- a/README.txt Wed Mar 19 20:57:38 2008 +0100 +++ b/README.txt Thu Mar 20 01:13:48 2008 +0100 @@ -269,6 +269,19 @@ argument, in order to optimise instance attribute access in methods, we should seek to restrict the object type. +Verifying Supplied Arguments +---------------------------- + +In order to ensure a correct invocation, it is also necessary to check the +number of supplied arguments. If the target of the invocation is known at +compile-time, no additional instructions need to be emitted; otherwise, the +generated code must test for the following situations: + + 1. That the number of supplied arguments is equal to the number of expected + parameters. + + 2. That no keyword argument overwrites an existing positional parameter. + Tuples, Frames and Allocation ----------------------------- diff -r a7cbfb7bb92b -r 999f14fecba9 micropython/ast.py --- a/micropython/ast.py Wed Mar 19 20:57:38 2008 +0100 +++ b/micropython/ast.py Thu Mar 20 01:13:48 2008 +0100 @@ -262,11 +262,14 @@ # Evaluate the arguments. positional = 1 + start_keywords = None + employed_keywords = set() for i, arg in enumerate(args): if isinstance(arg, compiler.ast.Keyword): if positional: self.new_op(ReserveFrame(len(args) - i)) + start_keywords = i positional = 0 self.dispatch(arg.expr) @@ -294,6 +297,17 @@ raise pos = table_entry[arg.name] + + # Test for illegal conditions. + + if pos < start_keywords: + raise TranslateError(self.module.full_name(), node, + "Keyword argument %r overwrites parameter %r." % (arg.name, pos)) + elif pos in employed_keywords: + raise TranslateError(self.module.full_name(), node, + "Keyword argument %r is repeated, overwriting parameter %r." % (arg.name, pos)) + + employed_keywords.add(pos) self.new_op(StoreFrame(pos)) # Otherwise, generate the code needed to obtain the details of diff -r a7cbfb7bb92b -r 999f14fecba9 micropython/common.py --- a/micropython/common.py Wed Mar 19 20:57:38 2008 +0100 +++ b/micropython/common.py Thu Mar 20 01:13:48 2008 +0100 @@ -29,7 +29,7 @@ self.message = message def __repr__(self): - return "ProcessingError in %r at line %d: %s" % (self.unit_name, self.node.lineno, self.message) + return "Error in %r at line %d: %s" % (self.unit_name, self.node.lineno, self.message) def __str__(self): return repr(self) diff -r a7cbfb7bb92b -r 999f14fecba9 tests/failure/keyword_conflict.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/failure/keyword_conflict.py Thu Mar 20 01:13:48 2008 +0100 @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +def f(a, b, c): + pass + +g = f +g(1, a=3, b=2) # uncertain target - not detected + +def g(a, c, b): + pass + +g(1, a=3, b=2) + +f(1, 2, 3) +f(1, a=2, c=3) +f(c=3, b=2, a=1) + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r a7cbfb7bb92b -r 999f14fecba9 tests/failure/keyword_repeat.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/failure/keyword_repeat.py Thu Mar 20 01:13:48 2008 +0100 @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +def f(a, b, c): + pass + +g = f +g(1, b=3, b=2) +g(c=3, b=2, a=1, b=0) # uncertain target - not detected + +def g(a, c, b): + pass + +g(1, a=3, b=2) + +f(1, 2, 3) +f(1, b=2, c=3) +f(c=3, b=2, a=1, b=0) + +# vim: tabstop=4 expandtab shiftwidth=4