1.1 --- a/micropython/ast.py Sat Aug 23 22:32:17 2008 +0200
1.2 +++ b/micropython/ast.py Sun Aug 24 03:06:00 2008 +0200
1.3 @@ -32,7 +32,8 @@
1.4 "A translated module."
1.5
1.6 supported_optimisations = [
1.7 - "constant_storage", "known_target", "self_access", "temp_storage", "load_operations", "no_operations", "unused_results"
1.8 + "constant_storage", "source_storage", "known_target", "self_access",
1.9 + "temp_storage", "load_operations", "no_operations", "unused_results"
1.10 ]
1.11
1.12 # Attribute access instructions, for use with the appropriate handlers.
1.13 @@ -213,10 +214,12 @@
1.14
1.15 def record_value(self):
1.16 self.expr_temp = self._optimise_temp_storage()
1.17 + self.active_source = self.active
1.18
1.19 def discard_value(self):
1.20 self.discard_temp(self.expr_temp)
1.21 self.expr_temp = None
1.22 + self.active_source = None
1.23
1.24 def set_source(self):
1.25 if self.active is not None:
1.26 @@ -322,12 +325,16 @@
1.27
1.28 self.active = None
1.29 self.active_value = None
1.30 + self.active_source = None
1.31
1.32 # Optimisation tests.
1.33
1.34 def _should_optimise_constant_storage(self):
1.35 return "constant_storage" in self.optimisations
1.36
1.37 + def _should_optimise_source_storage(self):
1.38 + return "source_storage" in self.optimisations
1.39 +
1.40 def _should_optimise_known_target(self):
1.41 return "known_target" in self.optimisations
1.42
1.43 @@ -380,6 +387,7 @@
1.44 LoadAddressContext, LoadAttr, LoadAttrIndex, # as the object being referenced
1.45 StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced
1.46 TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands
1.47 + CheckFrame,
1.48 LoadContext, # as the object providing the result
1.49 JumpWithFrame # as the target
1.50 ))
1.51 @@ -454,10 +462,11 @@
1.52 to a temporary variable retaining the result of the last instruction.
1.53 """
1.54
1.55 - # LoadResult cannot be relied upon, since in general the result register
1.56 + # LoadResult cannot be relied upon in general since the result register
1.57 # could be updated since first being referenced.
1.58
1.59 - return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst))
1.60 + return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst)) or \
1.61 + isinstance(self.active_value, LoadResult) and self.active_value is self.active
1.62
1.63 def _have_correct_self_for_target(self, context):
1.64
1.65 @@ -489,6 +498,25 @@
1.66 else:
1.67 return 0
1.68
1.69 + def _optimise_source_storage(self):
1.70 +
1.71 + """
1.72 + Where the source value in an assignment can be inserted into the
1.73 + eventual target without intermediate storage, optimise away the storage
1.74 + instruction.
1.75 + """
1.76 +
1.77 + if self._should_optimise_source_storage() and \
1.78 + self.active_source is not None and \
1.79 + self.active_source.source is None and \
1.80 + self.active_source.input is None and \
1.81 + self.active_source is self.active:
1.82 +
1.83 + self.remove_op()
1.84 + return 1
1.85 + else:
1.86 + return 0
1.87 +
1.88 def _optimise_known_target(self):
1.89
1.90 """
1.91 @@ -779,7 +807,7 @@
1.92 # Where a target or context are not known or where an instance is known
1.93 # to be the context, load the context.
1.94
1.95 - if context is None or isinstance(context, Instance):
1.96 + if target is None or isinstance(context, Instance):
1.97 self.new_op(temp)
1.98 self.new_op(LoadContext())
1.99 self.new_op(StoreFrame(0))
1.100 @@ -803,11 +831,20 @@
1.101 # Evaluate the arguments.
1.102
1.103 employed_positions = set()
1.104 + employed_keywords = set()
1.105 extra_keywords = []
1.106
1.107 + # Find keyword arguments in advance in order to help resolve targets.
1.108 +
1.109 + for arg in args:
1.110 + if isinstance(arg, compiler.ast.Keyword):
1.111 + employed_keywords.add(arg.name)
1.112 +
1.113 + possible_targets = self.paramtable.all_possible_objects(employed_keywords)
1.114 +
1.115 # Note the presence of the context in the frame where appropriate.
1.116
1.117 - if context is None or isinstance(context, Instance):
1.118 + if target is None or isinstance(context, Instance):
1.119 ncontext = 1
1.120 expect_context = 0
1.121 elif isinstance(context, Class):
1.122 @@ -973,9 +1010,10 @@
1.123 else:
1.124 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1)
1.125
1.126 - # Only check non-empty frames.
1.127 + # Only check non-empty frames (using the callable's details).
1.128
1.129 if employed_positions or max_pos >= 0:
1.130 + self.new_op(temp)
1.131 self.new_op(CheckFrame(max_pos + 1))
1.132
1.133 # Set the frame size.
1.134 @@ -1403,8 +1441,13 @@
1.135 def visitAssList(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AssList")
1.136
1.137 def visitAssName(self, node):
1.138 +
1.139 + # Optimise away intermediate source storage.
1.140 +
1.141 + no_source = self._optimise_source_storage()
1.142 self._visitName(node, self.name_store_instructions)
1.143 - self.set_source()
1.144 + if not no_source:
1.145 + self.set_source()
1.146
1.147 visitAssTuple = visitAssList
1.148
1.149 @@ -1661,6 +1704,9 @@
1.150 # Visiting of the code occurs when get_code is invoked on this node.
1.151
1.152 else:
1.153 + extend = ExtendFrame()
1.154 + self.new_op(extend)
1.155 +
1.156 self.dispatch(node.code)
1.157 if not isinstance(self.last_op(), Return):
1.158 self.dispatch(compiler.ast.Name("None"))
1.159 @@ -1668,6 +1714,8 @@
1.160
1.161 self.new_op(Return())
1.162
1.163 + extend.attr = self.max_temp_position + 1 # NOTE: See get_code for similar code.
1.164 +
1.165 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr")
1.166
1.167 def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor")