1.1 --- a/micropython/ast.py Wed Aug 27 00:45:14 2008 +0200
1.2 +++ b/micropython/ast.py Mon Sep 01 01:32:32 2008 +0200
1.3 @@ -138,6 +138,44 @@
1.4 self.unit.temp_usage = self.max_temp_position + 1
1.5 return self.code
1.6
1.7 + def get_instantiator_code(self, cls):
1.8 +
1.9 + "Return the code for the given class 'cls'."
1.10 +
1.11 + self.unit = cls.get_instantiator()
1.12 + self.code = []
1.13 + self.temp_positions = set()
1.14 + self.max_temp_position = -1
1.15 +
1.16 + init_method = cls.get_init_method()
1.17 +
1.18 + # Convert this frame back to being an invocation frame.
1.19 +
1.20 + self.new_op(RecoverFrame())
1.21 +
1.22 + # Fix the current frame to include a new storage slot at the beginning.
1.23 +
1.24 + self.new_op(AdjustFrame(-1))
1.25 +
1.26 + # Make an object.
1.27 +
1.28 + self.new_op(MakeObject(len(cls.instance_attributes())))
1.29 + self.new_op(StoreFrame(0))
1.30 +
1.31 + # Invoke the appropriate initialiser.
1.32 +
1.33 + self.new_op(LoadAddress(init_method))
1.34 + self.new_op(LoadCallable())
1.35 + self.new_op(JumpWithFrame())
1.36 +
1.37 + # Store the object as the result.
1.38 +
1.39 + self.new_op(LoadName(init_method.all_locals()["self"])) # load the context in the invocation frame
1.40 + self.new_op(StoreResult())
1.41 + self.new_op(Return())
1.42 +
1.43 + return self.code
1.44 +
1.45 # Name-related methods.
1.46
1.47 def get_scope(self, name):
1.48 @@ -261,6 +299,9 @@
1.49 if temp_position in self.temp_positions:
1.50 self.temp_positions.remove(temp_position)
1.51
1.52 + def set_frame_usage(self, node, extend):
1.53 + extend.attr = self.max_temp_position + node.unit.local_usage # NOTE: See get_code for similar code.
1.54 +
1.55 # Code writing methods.
1.56
1.57 def new_op(self, op):
1.58 @@ -390,8 +431,7 @@
1.59 LoadCallable,
1.60 TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands
1.61 CheckFrame,
1.62 - LoadContext, # as the object providing the result
1.63 - JumpWithFrame # as the target
1.64 + LoadContext # as the object providing the result
1.65 ))
1.66
1.67 def _is_resultant_no_operation(self, instruction):
1.68 @@ -532,15 +572,6 @@
1.69 target = last.attr.value
1.70 context = last.attr.context
1.71
1.72 - # Handle calls to classes.
1.73 -
1.74 - if isinstance(target, Class):
1.75 - target = target.get_instantiator()
1.76 - context = Undefined()
1.77 -
1.78 - # A special context is chosen to avoid generating unnecessary
1.79 - # context loading and checking instructions.
1.80 -
1.81 return target, context
1.82 else:
1.83 return None
1.84 @@ -785,7 +816,7 @@
1.85
1.86 target, context, temp = self._generateCallFuncContext()
1.87 self._generateCallFuncArgs(target, context, temp, args, node)
1.88 - return temp
1.89 + return temp, target
1.90
1.91 def _generateCallFuncContext(self):
1.92
1.93 @@ -803,6 +834,8 @@
1.94 target, context = None, None
1.95
1.96 # Store the target in temporary storage for subsequent referencing.
1.97 + # NOTE: This may not be appropriate for class invocations
1.98 + # NOTE: (instantiation).
1.99
1.100 temp = self._optimise_temp_storage()
1.101
1.102 @@ -814,6 +847,13 @@
1.103 self.new_op(LoadContext())
1.104 self.new_op(StoreFrame(0))
1.105
1.106 + # For known instantiations, provide a new object as the first argument
1.107 + # to the __init__ method.
1.108 +
1.109 + elif isinstance(target, Class):
1.110 + self.new_op(MakeObject(len(target.instance_attributes())))
1.111 + self.new_op(StoreFrame(0))
1.112 +
1.113 # Otherwise omit the context.
1.114
1.115 else:
1.116 @@ -849,9 +889,22 @@
1.117 if target is None or isinstance(context, Instance):
1.118 ncontext = 1
1.119 expect_context = 0
1.120 +
1.121 + # Handle calls to classes.
1.122 +
1.123 + elif isinstance(target, Class):
1.124 + ncontext = 1
1.125 + expect_context = 0
1.126 + target = target.get_init_method()
1.127 +
1.128 + # Method calls via classes.
1.129 +
1.130 elif isinstance(context, Class):
1.131 ncontext = 0
1.132 expect_context = 1
1.133 +
1.134 + # Function calls.
1.135 +
1.136 else:
1.137 ncontext = 0
1.138 expect_context = 0
1.139 @@ -991,7 +1044,7 @@
1.140 raise TranslateError(self.module.full_name(), node,
1.141 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min))
1.142
1.143 - nargs = len(args)
1.144 + nargs = frame_pos
1.145
1.146 if nargs > nargs_max and not target.has_star and not target.has_dstar:
1.147 raise TranslateError(self.module.full_name(), node,
1.148 @@ -1049,11 +1102,15 @@
1.149 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min]))
1.150 self.new_op(StoreFrame(pos))
1.151
1.152 - def _doCallFunc(self, instruction):
1.153 + def _doCallFunc(self, instruction, target=None):
1.154
1.155 "Make the invocation."
1.156
1.157 - self.new_op(instruction)
1.158 + if isinstance(target, Class):
1.159 + self.new_op(LoadAddress(target.get_init_method()))
1.160 + else:
1.161 + self.new_op(instruction)
1.162 + self.new_op(LoadCallable())
1.163 self.new_op(JumpWithFrame())
1.164
1.165 def _endCallFuncArgs(self, nargs):
1.166 @@ -1063,10 +1120,13 @@
1.167 self.frame_makers[-1].attr = nargs
1.168 self.frame_makers.pop()
1.169
1.170 - def _endCallFunc(self, instruction=None, load_result=1):
1.171 + def _endCallFunc(self, instruction=None, target=None, load_result=1):
1.172
1.173 "Finish the invocation and tidy up afterwards."
1.174
1.175 + if isinstance(target, Class):
1.176 + self.new_op(LoadName(target.get_init_method().all_locals()["self"])) # load the context in the invocation frame
1.177 + self.new_op(StoreResult())
1.178 self.new_op(DropFrame())
1.179 if load_result:
1.180 self.new_op(LoadResult())
1.181 @@ -1482,9 +1542,9 @@
1.182
1.183 self._startCallFunc()
1.184 self.dispatch(node.node)
1.185 - temp = self._generateCallFunc(node.args, node)
1.186 - self._doCallFunc(temp)
1.187 - self._endCallFunc(temp)
1.188 + temp, target = self._generateCallFunc(node.args, node)
1.189 + self._doCallFunc(temp, target)
1.190 + self._endCallFunc(temp, target)
1.191
1.192 def visitClass(self, node):
1.193
1.194 @@ -1632,9 +1692,9 @@
1.195 self._startCallFunc()
1.196 self.dispatch(node.list)
1.197 self._generateAttr(node, "__iter__", self.attribute_load_instructions)
1.198 - temp = self._generateCallFunc([], node)
1.199 - self._doCallFunc(temp)
1.200 - self._endCallFunc(temp)
1.201 + temp, target = self._generateCallFunc([], node)
1.202 + self._doCallFunc(temp, target)
1.203 + self._endCallFunc(temp, target)
1.204
1.205 temp_iterator = self._optimise_temp_storage()
1.206
1.207 @@ -1647,9 +1707,9 @@
1.208 self._startCallFunc()
1.209 self.new_op(temp_iterator)
1.210 self._generateAttr(node, "next", self.attribute_load_instructions)
1.211 - temp = self._generateCallFunc([], node)
1.212 - self._doCallFunc(temp)
1.213 - self._endCallFunc(temp)
1.214 + temp, target = self._generateCallFunc([], node)
1.215 + self._doCallFunc(temp, target)
1.216 + self._endCallFunc(temp, target)
1.217
1.218 # Test for StopIteration.
1.219
1.220 @@ -1717,7 +1777,7 @@
1.221
1.222 self.new_op(Return())
1.223
1.224 - extend.attr = self.max_temp_position + node.unit.local_usage # NOTE: See get_code for similar code.
1.225 + self.set_frame_usage(node, extend)
1.226
1.227 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr")
1.228