1.1 --- a/README.txt Mon Apr 07 02:20:21 2008 +0200
1.2 +++ b/README.txt Thu Apr 17 23:04:50 2008 +0200
1.3 @@ -250,6 +250,28 @@
1.4 Keyword arguments are set using an attribute-like mechanism, though, where the
1.5 position of each argument discovered using the parameter table.
1.6
1.7 +Where the target of the invocation is known, the above procedure can be
1.8 +optimised slightly by attempting to add keyword argument values directly to
1.9 +the stack:
1.10 +
1.11 + Value Stack
1.12 + -----------
1.13 +
1.14 + ... ... ... ... ...
1.15 + fn fn fn fn fn
1.16 + a a a a a
1.17 + b b b b b
1.18 + ___ ___ ___ --> 3
1.19 + 1 1 1 | 1
1.20 + 2 1 | 2
1.21 + 3 -----------
1.22 +
1.23 + (reserve for (add in-place) (add in-place) (evaluate) (store by
1.24 + parameter c) index)
1.25 +
1.26 +Method Invocations
1.27 +------------------
1.28 +
1.29 Method invocations incorporate an implicit first argument which is obtained
1.30 from the context of the method:
1.31
2.1 --- a/micropython/ast.py Mon Apr 07 02:20:21 2008 +0200
2.2 +++ b/micropython/ast.py Thu Apr 17 23:04:50 2008 +0200
2.3 @@ -296,9 +296,7 @@
2.4
2.5 # Evaluate the arguments.
2.6
2.7 - positional = 1
2.8 - start_keywords = None
2.9 - employed_keywords = set()
2.10 + employed_positions = set()
2.11 extra_keywords = []
2.12
2.13 for frame_pos, arg in enumerate(args):
2.14 @@ -307,13 +305,6 @@
2.15
2.16 if isinstance(arg, compiler.ast.Keyword):
2.17
2.18 - # Note the start of keyword arguments.
2.19 -
2.20 - if positional:
2.21 - #self.new_op(ReserveFrame(len(args) - frame_pos))
2.22 - start_keywords = frame_pos
2.23 - positional = 0
2.24 -
2.25 # Optimise where the target is known now.
2.26
2.27 if target is not None:
2.28 @@ -340,14 +331,16 @@
2.29
2.30 # Test for illegal conditions.
2.31
2.32 - if pos < start_keywords:
2.33 + if pos in employed_positions:
2.34 raise TranslateError(self.module.full_name(), node,
2.35 "Keyword argument %r overwrites parameter %r." % (arg.name, pos))
2.36 - elif pos in employed_keywords:
2.37 - raise TranslateError(self.module.full_name(), node,
2.38 - "Keyword argument %r is repeated, overwriting parameter %r." % (arg.name, pos))
2.39 +
2.40 + employed_positions.add(pos)
2.41
2.42 - employed_keywords.add(pos)
2.43 + # Add space for arguments appearing before this one.
2.44 +
2.45 + if frame_pos < pos:
2.46 + self.new_op(ReserveFrame(pos - frame_pos)
2.47
2.48 # Generate code for the keyword and the positioning
2.49 # operation.
2.50 @@ -355,9 +348,9 @@
2.51 self.dispatch(arg.expr)
2.52
2.53 # If the position corresponds to the current frame element,
2.54 - # skip generating the instruction.
2.55 + # skip generating the store instruction.
2.56
2.57 - if frame_pos != pos:
2.58 + if frame_pos > pos:
2.59 self.new_op(StoreFrame(pos))
2.60
2.61 # Otherwise, generate the code needed to obtain the details of
2.62 @@ -390,16 +383,18 @@
2.63
2.64 else:
2.65 self.dispatch(arg)
2.66 + employed_positions.add(frame_pos)
2.67
2.68 frame_pos = len(args)
2.69
2.70 - # If any extra keywords were identified, generate them now.
2.71 -
2.72 - for arg in extra_keywords:
2.73 - const = self.module.constant_values[arg.name]
2.74 - self.new_op(LoadConst(const))
2.75 - self.dispatch(arg.expr)
2.76 - frame_pos += 1
2.77 + # NOTE: If any extra keywords were identified, generate them now.
2.78 + # NOTE: This needs to populate a ** argument dictionary.
2.79 + #
2.80 + # for arg in extra_keywords:
2.81 + # const = self.module.constant_values[arg.name]
2.82 + # self.new_op(LoadConst(const))
2.83 + # self.dispatch(arg.expr)
2.84 + # frame_pos += 1
2.85
2.86 # NOTE: Somehow, the above needs to be combined with * and ** arguments.
2.87
2.88 @@ -409,15 +404,18 @@
2.89
2.90 # Make sure that enough arguments have been given.
2.91
2.92 + nargs_max = len(target.positional_names)
2.93 ndefaults = len(target.defaults)
2.94 - nargs_max = len(target.positional_names)
2.95 nargs_min = nargs_max - ndefaults
2.96 +
2.97 + for i in range(0, nargs_min):
2.98 + if i not in employed_positions:
2.99 + raise TranslateError(self.module.full_name(), node,
2.100 + "Argument %r not supplied for %r: need at least %d arguments." % (i+1, target.name, nargs_min))
2.101 +
2.102 nargs = len(args)
2.103
2.104 - if nargs < nargs_min:
2.105 - raise TranslateError(self.module.full_name(), node,
2.106 - "Insufficient arguments for %r: need at least %d arguments." % (target.name, nargs_min))
2.107 - elif nargs > nargs_max and not target.has_star and not target.has_dstar:
2.108 + if nargs > nargs_max and not target.has_star and not target.has_dstar:
2.109 raise TranslateError(self.module.full_name(), node,
2.110 "Too many arguments for %r: need at most %d arguments." % (target.name, nargs_max))
2.111
2.112 @@ -425,15 +423,14 @@
2.113 # Here, we use negative index values to visit the right hand end of
2.114 # the defaults list.
2.115
2.116 - for i in range(nargs - nargs_max, 0):
2.117 - self.new_op(LoadConst(target))
2.118 - self.new_op(LoadAttr(target.default_attrs[ndefaults + i]))
2.119 + for pos in range(nargs_min, nargs_max):
2.120 + if pos not in employed_positions:
2.121 + self.new_op(LoadConst(target))
2.122 + self.new_op(LoadAttr(target.default_attrs[pos - nargs_min]))
2.123
2.124 # If the position corresponds to the current frame element,
2.125 # skip generating the instruction.
2.126
2.127 - pos = nargs_max + i
2.128 -
2.129 if frame_pos != pos:
2.130 self.new_op(StoreFrame(pos))
2.131