1.1 --- a/micropython/ast.py Sun Apr 06 21:26:06 2008 +0200
1.2 +++ b/micropython/ast.py Mon Apr 07 02:20:21 2008 +0200
1.3 @@ -103,6 +103,17 @@
1.4 self.dispatch(unit.node)
1.5 return self.code
1.6
1.7 + def get_default_code(self, unit):
1.8 +
1.9 + "Return the code for the defaults in the given 'unit'."
1.10 +
1.11 + self.code = []
1.12 + for attr, default in zip(unit.default_attrs, unit.defaults):
1.13 + self.dispatch(default)
1.14 + self.new_op(LoadConst(unit))
1.15 + self.new_op(StoreAttr(attr))
1.16 + return self.code
1.17 +
1.18 def __repr__(self):
1.19 return "Translation(%r)" % self.module
1.20
1.21 @@ -290,11 +301,17 @@
1.22 employed_keywords = set()
1.23 extra_keywords = []
1.24
1.25 - for i, arg in enumerate(args):
1.26 + for frame_pos, arg in enumerate(args):
1.27 +
1.28 + # Handle positional and keyword arguments separately.
1.29 +
1.30 if isinstance(arg, compiler.ast.Keyword):
1.31 +
1.32 + # Note the start of keyword arguments.
1.33 +
1.34 if positional:
1.35 - #self.new_op(ReserveFrame(len(args) - i))
1.36 - start_keywords = i
1.37 + #self.new_op(ReserveFrame(len(args) - frame_pos))
1.38 + start_keywords = frame_pos
1.39 positional = 0
1.40
1.41 # Optimise where the target is known now.
1.42 @@ -336,7 +353,12 @@
1.43 # operation.
1.44
1.45 self.dispatch(arg.expr)
1.46 - self.new_op(StoreFrame(pos))
1.47 +
1.48 + # If the position corresponds to the current frame element,
1.49 + # skip generating the instruction.
1.50 +
1.51 + if frame_pos != pos:
1.52 + self.new_op(StoreFrame(pos))
1.53
1.54 # Otherwise, generate the code needed to obtain the details of
1.55 # the parameter location.
1.56 @@ -369,28 +391,57 @@
1.57 else:
1.58 self.dispatch(arg)
1.59
1.60 + frame_pos = len(args)
1.61 +
1.62 # If any extra keywords were identified, generate them now.
1.63
1.64 for arg in extra_keywords:
1.65 const = self.module.constant_values[arg.name]
1.66 self.new_op(LoadConst(const))
1.67 self.dispatch(arg.expr)
1.68 + frame_pos += 1
1.69
1.70 # NOTE: Somehow, the above needs to be combined with * and ** arguments.
1.71
1.72 # Either test for a complete set of arguments.
1.73
1.74 if target is not None:
1.75 +
1.76 + # Make sure that enough arguments have been given.
1.77 +
1.78 + ndefaults = len(target.defaults)
1.79 nargs_max = len(target.positional_names)
1.80 - nargs_min = nargs_max - len(target.defaults)
1.81 - if len(args) < nargs_min:
1.82 + nargs_min = nargs_max - ndefaults
1.83 + nargs = len(args)
1.84 +
1.85 + if nargs < nargs_min:
1.86 raise TranslateError(self.module.full_name(), node,
1.87 "Insufficient arguments for %r: need at least %d arguments." % (target.name, nargs_min))
1.88 - elif len(args) > nargs_max and not target.has_star and not target.has_dstar:
1.89 + elif nargs > nargs_max and not target.has_star and not target.has_dstar:
1.90 raise TranslateError(self.module.full_name(), node,
1.91 - "Too many arguments for %r: need at most %d arguments." % (target.name, nargs))
1.92 + "Too many arguments for %r: need at most %d arguments." % (target.name, nargs_max))
1.93 +
1.94 + # Where defaults are involved, put them into the frame.
1.95 + # Here, we use negative index values to visit the right hand end of
1.96 + # the defaults list.
1.97 +
1.98 + for i in range(nargs - nargs_max, 0):
1.99 + self.new_op(LoadConst(target))
1.100 + self.new_op(LoadAttr(target.default_attrs[ndefaults + i]))
1.101 +
1.102 + # If the position corresponds to the current frame element,
1.103 + # skip generating the instruction.
1.104 +
1.105 + pos = nargs_max + i
1.106 +
1.107 + if frame_pos != pos:
1.108 + self.new_op(StoreFrame(pos))
1.109 +
1.110 + frame_pos += 1
1.111
1.112 # Or generate instructions to do this at run-time.
1.113 + # NOTE: CheckFrame has to check the number of arguments and to fill in
1.114 + # NOTE: defaults.
1.115
1.116 else:
1.117 self.new_op(CheckFrame())