1.1 --- a/docs/invocation.txt Fri Jun 11 00:56:08 2010 +0200
1.2 +++ b/docs/invocation.txt Fri Jun 11 00:58:42 2010 +0200
1.3 @@ -163,13 +163,31 @@
1.4
1.5 Approach #2 - add arguments, add defaults while checking frame
1.6
1.7 -Defaults for lambda functions:
1.8 +Dynamic functions:
1.9
1.10 - f = lambda x, y=default: ...
1.11 + def f(x):
1.12 + def g(y=x): # dynamic: y depends on non-constant value
1.13 + ...
1.14 + def h(y=2): # static: y depends on constant value
1.15 + ...
1.16 +
1.17 + def f(x):
1.18 + g = lambda y=x: ... # dynamic: y depends on non-constant value
1.19 + h = lambda y=2: ... # static: y depends on constant value
1.20
1.21 - Defines instance of f with method:
1.22 +Representation of dynamic functions:
1.23 +
1.24 + f = lambda x, y=nonconst: ...
1.25 +
1.26 + def f(x, y=nonconst):
1.27 + ...
1.28
1.29 - def <lambda>(<context>, x, y=default):
1.30 + Defines instance with method:
1.31 +
1.32 + def <lambda>(<context>, x, y=nonconst):
1.33 + ...
1.34 +
1.35 + def f(<context>, x, y=nonconst):
1.36 ...
1.37
1.38 Where default is attribute #1.
2.1 --- a/micropython/__init__.py Fri Jun 11 00:56:08 2010 +0200
2.2 +++ b/micropython/__init__.py Fri Jun 11 00:58:42 2010 +0200
2.3 @@ -167,9 +167,9 @@
2.4 self.code.append(obj)
2.5
2.6 # Append any default values to the image.
2.7 - # Only do this for named functions (not lambdas).
2.8 + # Only do this for functions which are not dynamic.
2.9
2.10 - if obj.name is not None:
2.11 + if not obj.is_dynamic():
2.12 self.code += obj.default_attrs
2.13
2.14 # Omit built-in function code where requested.
3.1 --- a/micropython/ast.py Fri Jun 11 00:56:08 2010 +0200
3.2 +++ b/micropython/ast.py Fri Jun 11 00:58:42 2010 +0200
3.3 @@ -586,70 +586,20 @@
3.4 # Only store the name when visiting this node from outside.
3.5
3.6 if self.unit is not node.unit:
3.7 - self.new_op(LoadFunction(node.unit))
3.8 + self._visitFunctionDeclaration(node)
3.9 +
3.10 + # Record the declared function.
3.11 +
3.12 self.record_value()
3.13
3.14 self._visitName(node, self.name_store_instructions) # AssName equivalent
3.15 self.set_source()
3.16 self.discard_value()
3.17
3.18 - self._generateFunctionDefaults(node.unit)
3.19 -
3.20 # Visiting of the code occurs when get_code is invoked on this node.
3.21
3.22 else:
3.23 - # Check frames using the function's details.
3.24 -
3.25 - fn = node.unit
3.26 - nparams = len(fn.positional_names)
3.27 - ndefaults = len(fn.defaults)
3.28 -
3.29 - fn.body_block = self.new_block()
3.30 -
3.31 - # Check the number of parameters and defaults.
3.32 -
3.33 - self.new_op(CheckFrame((nparams, ndefaults)))
3.34 - if ndefaults > 0:
3.35 - self.new_op(LoadFunction(fn))
3.36 - self.new_op(FillDefaults((nparams, ndefaults)))
3.37 -
3.38 - # Produce the body.
3.39 -
3.40 - self.set_block(fn.body_block)
3.41 -
3.42 - extend = ExtendFrame()
3.43 - self.new_op(extend)
3.44 -
3.45 - # For functions with star parameters, make a special list for the
3.46 - # extra arguments and re-map the parameter.
3.47 -
3.48 - if fn.has_star:
3.49 - self.new_op(CopyExtra(nparams))
3.50 -
3.51 - # Ensure that the star parameter has a slot in the frame.
3.52 -
3.53 - self.new_op(CheckExtra(nparams))
3.54 - self.new_op(StoreTemp(nparams))
3.55 -
3.56 - # Add any attribute usage guards.
3.57 -
3.58 - if self.optimiser.should_optimise_accesses_by_attribute_usage() and hasattr(node, "_attrnames"):
3.59 - self._generateGuards(node)
3.60 -
3.61 - # Visit the actual code.
3.62 -
3.63 - self.dispatch(node.code)
3.64 -
3.65 - # Add a return statement where one is not already produced.
3.66 -
3.67 - if not isinstance(self.last_op(), Return):
3.68 - self.dispatch(compiler.ast.Name("None"))
3.69 - self.new_op(StoreResult())
3.70 - self.new_op(Return())
3.71 -
3.72 - # Make sure that enough frame space is reserved from the start.
3.73 -
3.74 - self.set_frame_usage(node, extend)
3.75 + self._visitFunctionDefinition(node)
3.76
3.77 def visitGlobal(self, node): pass
3.78
3.79 @@ -675,58 +625,15 @@
3.80 # outside.
3.81
3.82 if self.unit is not node.unit:
3.83 - fn = node.unit
3.84 - ndefaults = len(fn.defaults)
3.85 - temp = self._generateFunctionDefaults(fn)
3.86 -
3.87 - if ndefaults > 0:
3.88 - self.new_op(LoadConst(fn))
3.89 - else:
3.90 - self.new_op(LoadFunction(fn))
3.91
3.92 - # Populate the new object required for the function.
3.93 + # Provide the declared function.
3.94
3.95 - if temp is not None:
3.96 - self.new_op(LoadCallable())
3.97 - self.new_op(temp)
3.98 - self.new_op(StoreCallable())
3.99 -
3.100 - self.new_op(temp)
3.101 - #self.discard_temp(temp)
3.102 + self._visitFunctionDeclaration(node)
3.103
3.104 # Visiting of the code occurs when get_code is invoked on this node.
3.105
3.106 else:
3.107 - # Check frames using the function's details.
3.108 -
3.109 - fn = node.unit
3.110 - nparams = len(fn.positional_names)
3.111 - ndefaults = len(fn.defaults)
3.112 -
3.113 - fn.body_block = self.new_block()
3.114 -
3.115 - # Check the number of parameters and defaults.
3.116 -
3.117 - self.new_op(CheckFrame((nparams, ndefaults)))
3.118 - if ndefaults > 0:
3.119 - self.new_op(LoadTemp(0)) # context provides storage
3.120 - self.new_op(FillDefaults((nparams, ndefaults)))
3.121 -
3.122 - # Produce the body.
3.123 -
3.124 - self.set_block(fn.body_block)
3.125 -
3.126 - extend = ExtendFrame()
3.127 - self.new_op(extend)
3.128 -
3.129 - self.dispatch(node.code)
3.130 -
3.131 - self.new_op(StoreResult())
3.132 - self.new_op(Return())
3.133 -
3.134 - # Make sure that enough frame space is reserved from the start.
3.135 -
3.136 - self.set_frame_usage(node, extend)
3.137 + self._visitFunctionDefinition(node)
3.138
3.139 def visitModule(self, node):
3.140 extend = ExtendFrame()
4.1 --- a/micropython/data.py Fri Jun 11 00:56:08 2010 +0200
4.2 +++ b/micropython/data.py Fri Jun 11 00:58:42 2010 +0200
4.3 @@ -206,6 +206,9 @@
4.4 self.namespace[name] = Attr(None, self, name)
4.5
4.6 attr = self.namespace[name]
4.7 + self._set_using_attr(attr, attr_or_value, single_assignment)
4.8 +
4.9 + def _set_using_attr(self, attr, attr_or_value, single_assignment=1):
4.10
4.11 # Handle attribute assignment as well as assignment of basic objects.
4.12 # Attempt to fix the context if not explicitly defined.
4.13 @@ -557,6 +560,25 @@
4.14
4.15 self.context_values.update(context_values)
4.16
4.17 + def is_constant(self):
4.18 +
4.19 + """
4.20 + Return whether this attribute references something that can be regarded
4.21 + as being constant within a particular scope.
4.22 + """
4.23 +
4.24 + return self.assignments == 1
4.25 +
4.26 + def is_strict_constant(self):
4.27 +
4.28 + """
4.29 + Return whether this attribute references something that can be regarded
4.30 + as being constant.
4.31 + """
4.32 +
4.33 + value = self.get_value()
4.34 + return not (value is None or isinstance(value, Instance))
4.35 +
4.36 def is_static_attribute(self):
4.37
4.38 """
4.39 @@ -643,11 +665,16 @@
4.40 return 0
4.41
4.42 def __repr__(self):
4.43 - return "Attr(%r, %s, %r) # [%s], %r" % (
4.44 + return "Attr(%r, %s, %r) # {[%s] (%r)}" % (
4.45 self.position, shortrepr(self.parent), self.name,
4.46 self._context_values_str(), self.assignments
4.47 )
4.48
4.49 + def __shortrepr__(self):
4.50 + return "Attr(%r, %s, %r)" % (
4.51 + self.position, shortrepr(self.parent), self.name
4.52 + )
4.53 +
4.54 def _context_values_str(self):
4.55 l = []
4.56 for (c, v) in self.context_values:
4.57 @@ -1075,7 +1102,8 @@
4.58
4.59 "An inspected function."
4.60
4.61 - def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, module=None, node=None):
4.62 + def __init__(self, name, parent, argnames, defaults, has_star, has_dstar,
4.63 + dynamic_def=0, module=None, node=None):
4.64
4.65 """
4.66 Initialise the function with the given 'name', 'parent', list of
4.67 @@ -1091,14 +1119,10 @@
4.68 self.defaults = defaults
4.69 self.has_star = has_star
4.70 self.has_dstar = has_dstar
4.71 + self.dynamic_def = dynamic_def
4.72 self.astnode = node
4.73 node._def = self
4.74
4.75 - # For lambda functions with defaults, add a context argument.
4.76 -
4.77 - if name is None and defaults:
4.78 - self.argnames.insert(0, "<context>")
4.79 -
4.80 # Initialise the positional names.
4.81
4.82 self.positional_names = self.argnames[:]
4.83 @@ -1139,6 +1163,7 @@
4.84
4.85 # Image generation details.
4.86
4.87 + self.dynamic = None
4.88 self.location = None
4.89 self.code_location = None
4.90 self.code_body_location = None
4.91 @@ -1157,7 +1182,7 @@
4.92 if isinstance(name, tuple):
4.93 self._add_parameters(name)
4.94 else:
4.95 - self.set(name, None)
4.96 + self.set(name, Instance())
4.97
4.98 def __repr__(self):
4.99 if self.location is not None:
4.100 @@ -1177,12 +1202,46 @@
4.101 def get_body_block(self):
4.102 return self.body_block
4.103
4.104 - # Namespace-related methods.
4.105 + # Defaults-related methods.
4.106 +
4.107 + def store_default(self, attr_or_value):
4.108 +
4.109 + """
4.110 + Reserve space for defaults, set outside the function, potentially on a
4.111 + dynamic basis, using the 'attr_or_value'.
4.112 + """
4.113 +
4.114 + attr = Attr(None, self, None)
4.115 + self._set_using_attr(attr, attr_or_value)
4.116 + self.default_attrs.append(attr)
4.117 +
4.118 + def make_dynamic(self):
4.119 +
4.120 + "Return whether this function must be handled using a dynamic object."
4.121
4.122 - def store_default(self, value):
4.123 - attr = Attr(None, self, None)
4.124 - attr.update([self.get_context_and_value(value)], 1)
4.125 - self.default_attrs.append(attr)
4.126 + if self.dynamic is None:
4.127 + for attr in self.default_attrs:
4.128 + if not attr.is_strict_constant() and self.dynamic_def:
4.129 + self.dynamic = 1
4.130 + self._make_dynamic()
4.131 + break
4.132 + else:
4.133 + self.dynamic = 0
4.134 +
4.135 + return self.dynamic
4.136 +
4.137 + is_dynamic = make_dynamic
4.138 +
4.139 + def _make_dynamic(self):
4.140 +
4.141 + "Where functions have dynamic defaults, add a context argument."
4.142 +
4.143 + name = "<context>"
4.144 + self.argnames.insert(0, name)
4.145 + self.positional_names.insert(0, name)
4.146 + self.set(name, Instance())
4.147 +
4.148 + # Namespace-related methods.
4.149
4.150 def make_global(self, name):
4.151 if name not in self.argnames and not self.has_key(name):
4.152 @@ -1285,7 +1344,7 @@
4.153 "Make an instantiator function from a method, keeping all arguments."
4.154
4.155 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults,
4.156 - self.has_star, self.has_dstar, self.module, self.astnode)
4.157 + self.has_star, self.has_dstar, self.dynamic_def, self.module, self.astnode)
4.158 function.default_attrs = self.default_attrs
4.159 return function
4.160
5.1 --- a/micropython/inspect.py Fri Jun 11 00:56:08 2010 +0200
5.2 +++ b/micropython/inspect.py Fri Jun 11 00:58:42 2010 +0200
5.3 @@ -67,8 +67,9 @@
5.4
5.5 Assignments to names within functions are not generally considered to cause the
5.6 targets of such assignments to provide constant values since functions can be
5.7 -invoked many times with different inputs. However, there may be benefits in
5.8 -considering a local to be constant within a single invocation.
5.9 +invoked many times with different inputs. This affects particularly the
5.10 +definition of functions or lambdas within functions. However, there may be
5.11 +benefits in considering a local to be constant within a single invocation.
5.12 """
5.13
5.14 from micropython.common import *
5.15 @@ -111,6 +112,7 @@
5.16
5.17 self.in_init = 0 # Find instance attributes in __init__ methods.
5.18 self.in_method = 0 # Find instance attributes in all methods.
5.19 + self.in_function = 0 # Note function presence, affecting definitions.
5.20 self.in_loop = 0 # Note loop "membership", affecting assignments.
5.21 self.namespaces = []
5.22 self.module = None
5.23 @@ -261,6 +263,10 @@
5.24
5.25 # Namespace methods.
5.26
5.27 + def in_class(self, namespaces=None):
5.28 + namespaces = namespaces or self.namespaces
5.29 + return len(namespaces) > 1 and isinstance(namespaces[-2], Class)
5.30 +
5.31 def store(self, name, obj):
5.32
5.33 "Record attribute or local 'name', storing 'obj'."
5.34 @@ -436,6 +442,7 @@
5.35 node.defaults,
5.36 (node.flags & 4 != 0),
5.37 (node.flags & 8 != 0),
5.38 + self.in_loop or self.in_function,
5.39 self,
5.40 node
5.41 )
5.42 @@ -454,18 +461,16 @@
5.43
5.44 self.functions.append((node, self.namespaces + [function]))
5.45
5.46 + # Store the function.
5.47 +
5.48 if name is not None:
5.49 self.store(name, function)
5.50 else:
5.51 self.store_lambda(function)
5.52
5.53 - # Where defaults exist, an instance needs creating. Thus, it makes
5.54 - # no sense to return a reference to the function here, since the
5.55 - # recipient will not be referencing the function itself.
5.56 + # Test the defaults and assess whether an dynamic object will result.
5.57
5.58 - if node.defaults:
5.59 - return Instance() # indicates no known target
5.60 -
5.61 + function.make_dynamic()
5.62 return function
5.63
5.64 def _visitFunctionBody(self, node, namespaces):
5.65 @@ -475,14 +480,21 @@
5.66 # Current namespace is the function.
5.67 # Previous namespace is the class.
5.68
5.69 - if len(namespaces) > 1 and isinstance(namespaces[-2], Class):
5.70 + if self.in_class(namespaces):
5.71 if namespaces[-1].name == "__init__":
5.72 self.in_init = 1
5.73 self.in_method = 1
5.74
5.75 + in_function = self.in_function
5.76 + in_loop = self.in_loop
5.77 + self.in_function = 1
5.78 + self.in_loop = 0
5.79 +
5.80 self.namespaces = namespaces
5.81 self.dispatch(node.code)
5.82
5.83 + self.in_loop = in_loop
5.84 + self.in_function = in_function
5.85 self.in_init = 0
5.86 self.in_method = 0
5.87
5.88 @@ -597,6 +609,9 @@
5.89 print "Class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name())
5.90 return None
5.91 else:
5.92 + if self.in_loop:
5.93 + print "Warning: class %r in %r defined in a loop." % (node.name, self.full_name())
5.94 +
5.95 cls = Class(node.name, self.get_namespace(), self, node)
5.96
5.97 # Visit the base class expressions, attempting to find concrete
5.98 @@ -698,6 +713,7 @@
5.99 self.use_name("__iter__", node.list)
5.100 self.use_name("next")
5.101
5.102 + in_loop = self.in_loop
5.103 self.in_loop = 1
5.104 self.dispatch(node.assign)
5.105 self.dispatch(node.list)
5.106 @@ -708,7 +724,7 @@
5.107 self.new_branch()
5.108 self.dispatch(node.body)
5.109 self.shelve_branch()
5.110 - self.in_loop = 0
5.111 + self.in_loop = in_loop
5.112
5.113 # Maintain a branch for the else clause or the current retained usage
5.114 # where execution avoids the conditional clauses.
5.115 @@ -987,12 +1003,13 @@
5.116
5.117 # Propagate attribute usage to branches.
5.118
5.119 + in_loop = self.in_loop
5.120 self.in_loop = 1
5.121 self.dispatch(node.test)
5.122 self.new_branch(node)
5.123 self.dispatch(node.body)
5.124 self.shelve_branch()
5.125 - self.in_loop = 0
5.126 + self.in_loop = in_loop
5.127
5.128 # Maintain a branch for the else clause or the current retained usage
5.129 # where execution avoids the conditional clauses.
6.1 --- a/micropython/rsvp.py Fri Jun 11 00:56:08 2010 +0200
6.2 +++ b/micropython/rsvp.py Fri Jun 11 00:58:42 2010 +0200
6.3 @@ -177,12 +177,12 @@
6.4 if not self.is_generated(with_builtins):
6.5 item.code_location = item.full_name()
6.6
6.7 - # Skip any defaults for named functions.
6.8 + # Skip any defaults for static functions.
6.9
6.10 - elif item.name is not None:
6.11 + elif not item.is_dynamic():
6.12 item.code_location = location + len(item.defaults)
6.13
6.14 - # Skip any defaults for lambda functions.
6.15 + # Skip any defaults for dynamic functions.
6.16
6.17 else:
6.18 item.code_location = location
7.1 --- a/micropython/trans.py Fri Jun 11 00:56:08 2010 +0200
7.2 +++ b/micropython/trans.py Fri Jun 11 00:58:42 2010 +0200
7.3 @@ -619,7 +619,10 @@
7.4 t = self.optimiser.optimise_known_target()
7.5 if t:
7.6 target, context = t
7.7 - if isinstance(target, Instance): # lambda object
7.8 +
7.9 + # Detect dynamic functions acting like instances.
7.10 +
7.11 + if isinstance(target, Function) and target.is_dynamic():
7.12 target, context = None, None
7.13 else:
7.14 target, context = None, None
7.15 @@ -904,10 +907,9 @@
7.16 'employed_positions' collection.
7.17 """
7.18
7.19 - # Where a lambda is involved, construct a dynamic object to hold the
7.20 - # defaults.
7.21 + # Where appropriate, construct a dynamic object to hold the defaults.
7.22
7.23 - dynamic = target.name is None
7.24 + dynamic = target.is_dynamic()
7.25
7.26 # Here, we use negative index values to visit the right hand end of
7.27 # the defaults list.
7.28 @@ -1019,6 +1021,103 @@
7.29 if temp_context is not None:
7.30 self.discard_temp(temp_context)
7.31
7.32 + def _visitFunctionDeclaration(self, node):
7.33 +
7.34 + """
7.35 + Visit the function declaration at 'node', which can be a lambda or a
7.36 + named function. As a consequence an instruction will be generated which
7.37 + provides a reference to the function.
7.38 + """
7.39 +
7.40 + fn = node.unit
7.41 + ndefaults = len(fn.defaults)
7.42 + temp = self._generateFunctionDefaults(fn)
7.43 +
7.44 + # Populate the new object required for the function.
7.45 +
7.46 + if temp is not None:
7.47 + self.new_op(LoadConst(fn))
7.48 + self.new_op(LoadCallable())
7.49 + self.new_op(temp)
7.50 + self.new_op(StoreCallable())
7.51 +
7.52 + self.new_op(temp)
7.53 + #self.discard_temp(temp)
7.54 + else:
7.55 + self.new_op(LoadFunction(fn))
7.56 +
7.57 + def _visitFunctionDefinition(self, node):
7.58 +
7.59 + """
7.60 + Visit the function definition at 'node', which can be a lambda or a
7.61 + named function, generating the prelude with argument and default
7.62 + checking, plus the body of the function itself.
7.63 + """
7.64 +
7.65 + # Check frames using the function's details.
7.66 +
7.67 + fn = node.unit
7.68 + nparams = len(fn.positional_names)
7.69 + ndefaults = len(fn.defaults)
7.70 +
7.71 + fn.body_block = self.new_block()
7.72 +
7.73 + # Check the number of parameters and defaults.
7.74 +
7.75 + self.new_op(CheckFrame((nparams, ndefaults)))
7.76 +
7.77 + if fn.is_dynamic():
7.78 + self.new_op(LoadTemp(0)) # context provides storage
7.79 + else:
7.80 + self.new_op(LoadFunction(fn))
7.81 +
7.82 + if ndefaults > 0:
7.83 + self.new_op(FillDefaults((nparams, ndefaults)))
7.84 +
7.85 + # Produce the body.
7.86 +
7.87 + self.set_block(fn.body_block)
7.88 +
7.89 + extend = ExtendFrame()
7.90 + self.new_op(extend)
7.91 +
7.92 + # For functions with star parameters, make a special list for the
7.93 + # extra arguments and re-map the parameter.
7.94 +
7.95 + if fn.has_star:
7.96 + self.new_op(CopyExtra(nparams))
7.97 +
7.98 + # Ensure that the star parameter has a slot in the frame.
7.99 +
7.100 + self.new_op(CheckExtra(nparams))
7.101 + self.new_op(StoreTemp(nparams))
7.102 +
7.103 + # Add any attribute usage guards.
7.104 +
7.105 + if self.optimiser.should_optimise_accesses_by_attribute_usage() and hasattr(node, "_attrnames"):
7.106 + self._generateGuards(node)
7.107 +
7.108 + # Visit the actual code.
7.109 +
7.110 + self.dispatch(node.code)
7.111 +
7.112 + # Add a return statement where one is not already produced.
7.113 +
7.114 + if not isinstance(self.last_op(), Return):
7.115 +
7.116 + # Return None for normal functions without explicit return
7.117 + # statements.
7.118 +
7.119 + if fn.name is not None:
7.120 + self.dispatch(compiler.ast.Name("None"))
7.121 +
7.122 + self.new_op(StoreResult())
7.123 + self.new_op(Return())
7.124 +
7.125 + # Make sure that enough frame space is reserved from the start.
7.126 +
7.127 + self.set_frame_usage(node, extend)
7.128 +
7.129 def _generateFunctionDefaults(self, function):
7.130
7.131 """
7.132 @@ -1031,10 +1130,10 @@
7.133 if not attr_to_default:
7.134 return None
7.135
7.136 - # Where a lambda is involved, construct a dynamic object to hold the
7.137 - # defaults.
7.138 + # Where non-constant defaults are involved, construct a dynamic object
7.139 + # to hold the defaults.
7.140
7.141 - dynamic = function.name is None
7.142 + dynamic = function.is_dynamic()
7.143
7.144 if dynamic:
7.145 self.make_instance(self.get_builtin_class("function", function), len(attr_to_default))
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/tests/call_func_default_global.py Fri Jun 11 00:58:42 2010 +0200
8.3 @@ -0,0 +1,11 @@
8.4 +#!/usr/bin/env python
8.5 +
8.6 +d = 4
8.7 +
8.8 +def f(a, b, c=d):
8.9 + return c
8.10 +
8.11 +result_3 = f(1, 2, 3)
8.12 +result_4 = f(1, 2)
8.13 +
8.14 +# vim: tabstop=4 expandtab shiftwidth=4
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/tests/call_func_default_global_multiple.py Fri Jun 11 00:58:42 2010 +0200
9.3 @@ -0,0 +1,25 @@
9.4 +#!/usr/bin/env python
9.5 +
9.6 +d = 4
9.7 +
9.8 +i = 0
9.9 +l = []
9.10 +
9.11 +while i < 3:
9.12 + def f(a, b, c=d):
9.13 + return c
9.14 + l.append(f)
9.15 + i += 1
9.16 +
9.17 +f0 = l[0]
9.18 +f1 = l[1]
9.19 +f2 = l[2]
9.20 +
9.21 +result0_3 = f0(1, 2, 3)
9.22 +result1_3 = f1(1, 2, 3)
9.23 +result2_3 = f2(1, 2, 3)
9.24 +result0_4 = f0(1, 2)
9.25 +result1_4 = f1(1, 2)
9.26 +result2_4 = f2(1, 2)
9.27 +
9.28 +# vim: tabstop=4 expandtab shiftwidth=4
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/tests/call_func_default_global_non_constant.py Fri Jun 11 00:58:42 2010 +0200
10.3 @@ -0,0 +1,12 @@
10.4 +#!/usr/bin/env python
10.5 +
10.6 +d = 2
10.7 +d = 4 # make non-constant
10.8 +
10.9 +def f(a, b, c=d):
10.10 + return c
10.11 +
10.12 +result_3 = f(1, 2, 3)
10.13 +result_4 = f(1, 2)
10.14 +
10.15 +# vim: tabstop=4 expandtab shiftwidth=4
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/tests/lambda_defaults_local_non_constant.py Fri Jun 11 00:58:42 2010 +0200
11.3 @@ -0,0 +1,18 @@
11.4 +#!/usr/bin/env python
11.5 +
11.6 +def make_add(x):
11.7 + return lambda a, b=x: a + b
11.8 +
11.9 +def g(f, x):
11.10 + return f(x)
11.11 +
11.12 +add_2 = make_add(2)
11.13 +add_3 = make_add(3)
11.14 +
11.15 +result_3 = add_2(1)
11.16 +result_4 = g(add_2, 2)
11.17 +
11.18 +result_5 = add_3(2)
11.19 +result_6 = g(add_3, 3)
11.20 +
11.21 +# vim: tabstop=4 expandtab shiftwidth=4
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/tests/lambda_defaults_non_constant.py Fri Jun 11 00:58:42 2010 +0200
12.3 @@ -0,0 +1,16 @@
12.4 +#!/usr/bin/env python
12.5 +
12.6 +x = 1
12.7 +x = 2
12.8 +
12.9 +def make_add():
12.10 + return lambda a, b=x: a + x
12.11 +
12.12 +def g(f, x):
12.13 + return f(x)
12.14 +
12.15 +add_2 = make_add()
12.16 +result_3 = add_2(1)
12.17 +result2_3 = g(add_2, 1)
12.18 +
12.19 +# vim: tabstop=4 expandtab shiftwidth=4
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/tests/nested_functions_using_defaults.py Fri Jun 11 00:58:42 2010 +0200
13.3 @@ -0,0 +1,14 @@
13.4 +#!/usr/bin/env python
13.5 +
13.6 +def a(x):
13.7 + def b(p=x):
13.8 + return p
13.9 + return b
13.10 +
13.11 +f2 = a(2)
13.12 +f3 = a(3)
13.13 +
13.14 +result_2 = f2()
13.15 +result_3 = f3()
13.16 +
13.17 +# vim: tabstop=4 expandtab shiftwidth=4