# HG changeset patch # User Paul Boddie # Date 1208466290 -7200 # Node ID 2fc92f96d601790fcae815ef5f858b056284f25b # Parent f5dff4743a7714ebf8f2807da8300264daafc3b7 Optimised keyword argument placement for known targets. Removed extra argument code generation for the time being. diff -r f5dff4743a77 -r 2fc92f96d601 README.txt --- a/README.txt Mon Apr 07 02:20:21 2008 +0200 +++ b/README.txt Thu Apr 17 23:04:50 2008 +0200 @@ -250,6 +250,28 @@ Keyword arguments are set using an attribute-like mechanism, though, where the position of each argument discovered using the parameter table. +Where the target of the invocation is known, the above procedure can be +optimised slightly by attempting to add keyword argument values directly to +the stack: + + Value Stack + ----------- + + ... ... ... ... ... + fn fn fn fn fn + a a a a a + b b b b b + ___ ___ ___ --> 3 + 1 1 1 | 1 + 2 1 | 2 + 3 ----------- + + (reserve for (add in-place) (add in-place) (evaluate) (store by + parameter c) index) + +Method Invocations +------------------ + Method invocations incorporate an implicit first argument which is obtained from the context of the method: diff -r f5dff4743a77 -r 2fc92f96d601 micropython/ast.py --- a/micropython/ast.py Mon Apr 07 02:20:21 2008 +0200 +++ b/micropython/ast.py Thu Apr 17 23:04:50 2008 +0200 @@ -296,9 +296,7 @@ # Evaluate the arguments. - positional = 1 - start_keywords = None - employed_keywords = set() + employed_positions = set() extra_keywords = [] for frame_pos, arg in enumerate(args): @@ -307,13 +305,6 @@ if isinstance(arg, compiler.ast.Keyword): - # Note the start of keyword arguments. - - if positional: - #self.new_op(ReserveFrame(len(args) - frame_pos)) - start_keywords = frame_pos - positional = 0 - # Optimise where the target is known now. if target is not None: @@ -340,14 +331,16 @@ # Test for illegal conditions. - if pos < start_keywords: + if pos in employed_positions: 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_positions.add(pos) - employed_keywords.add(pos) + # Add space for arguments appearing before this one. + + if frame_pos < pos: + self.new_op(ReserveFrame(pos - frame_pos) # Generate code for the keyword and the positioning # operation. @@ -355,9 +348,9 @@ self.dispatch(arg.expr) # If the position corresponds to the current frame element, - # skip generating the instruction. + # skip generating the store instruction. - if frame_pos != pos: + if frame_pos > pos: self.new_op(StoreFrame(pos)) # Otherwise, generate the code needed to obtain the details of @@ -390,16 +383,18 @@ else: self.dispatch(arg) + employed_positions.add(frame_pos) frame_pos = len(args) - # If any extra keywords were identified, generate them now. - - for arg in extra_keywords: - const = self.module.constant_values[arg.name] - self.new_op(LoadConst(const)) - self.dispatch(arg.expr) - frame_pos += 1 + # NOTE: If any extra keywords were identified, generate them now. + # NOTE: This needs to populate a ** argument dictionary. + # + # for arg in extra_keywords: + # const = self.module.constant_values[arg.name] + # self.new_op(LoadConst(const)) + # self.dispatch(arg.expr) + # frame_pos += 1 # NOTE: Somehow, the above needs to be combined with * and ** arguments. @@ -409,15 +404,18 @@ # Make sure that enough arguments have been given. + nargs_max = len(target.positional_names) ndefaults = len(target.defaults) - nargs_max = len(target.positional_names) nargs_min = nargs_max - ndefaults + + for i in range(0, nargs_min): + if i not in employed_positions: + raise TranslateError(self.module.full_name(), node, + "Argument %r not supplied for %r: need at least %d arguments." % (i+1, target.name, nargs_min)) + nargs = len(args) - if nargs < nargs_min: - raise TranslateError(self.module.full_name(), node, - "Insufficient arguments for %r: need at least %d arguments." % (target.name, nargs_min)) - elif nargs > nargs_max and not target.has_star and not target.has_dstar: + if nargs > nargs_max and not target.has_star and not target.has_dstar: raise TranslateError(self.module.full_name(), node, "Too many arguments for %r: need at most %d arguments." % (target.name, nargs_max)) @@ -425,15 +423,14 @@ # Here, we use negative index values to visit the right hand end of # the defaults list. - for i in range(nargs - nargs_max, 0): - self.new_op(LoadConst(target)) - self.new_op(LoadAttr(target.default_attrs[ndefaults + i])) + for pos in range(nargs_min, nargs_max): + if pos not in employed_positions: + self.new_op(LoadConst(target)) + self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) # If the position corresponds to the current frame element, # skip generating the instruction. - pos = nargs_max + i - if frame_pos != pos: self.new_op(StoreFrame(pos))