1.1 --- a/docs/concepts.txt Sat May 23 02:46:04 2009 +0200
1.2 +++ b/docs/concepts.txt Sun May 24 00:21:41 2009 +0200
1.3 @@ -9,6 +9,7 @@
1.4 * Objects and structures
1.5 * Parameters and lookups
1.6 * Instantiation
1.7 + * Register usage
1.8
1.9 Namespaces and Attribute Definition
1.10 ===================================
1.11 @@ -419,3 +420,17 @@
1.12 resulting instance, along with locations for the attributes of the instance.
1.13 Since the instance header contains data common to all instances of a class, a
1.14 template header is copied to the start of the newly reserved memory region.
1.15 +
1.16 +Register Usage
1.17 +==============
1.18 +
1.19 +During code generation, much of the evaluation produces results which are
1.20 +implicitly recorded in the "active value" register, and various instructions
1.21 +will consume the active value. In addition, some instructions will consume a
1.22 +separate "active source value" from a register, typically those which are
1.23 +assigning the result of an expression to an assignment target.
1.24 +
1.25 +Since values often need to be retained for later use, a set of temporary
1.26 +storage locations are typically employed. However, optimisations may reduce
1.27 +the need to use such temporary storage where instructions which provide the
1.28 +"active value" can be re-executed and will produce the same result.
2.1 --- a/micropython/ast.py Sat May 23 02:46:04 2009 +0200
2.2 +++ b/micropython/ast.py Sun May 24 00:21:41 2009 +0200
2.3 @@ -588,8 +588,8 @@
2.4
2.5 if self.unit is not node.unit:
2.6 self.new_op(LoadConst(node.unit))
2.7 + self.record_value()
2.8
2.9 - self.record_value()
2.10 self._visitName(node, self.name_store_instructions) # AssName equivalent
2.11 self.set_source()
2.12 self.discard_value()
2.13 @@ -600,6 +600,7 @@
2.14
2.15 else:
2.16 body_block = self.new_block()
2.17 + check_block = self.new_block()
2.18
2.19 # Check frames using the function's details.
2.20
2.21 @@ -607,6 +608,12 @@
2.22 nparams = len(fn.positional_names)
2.23 ndefaults = len(fn.defaults)
2.24
2.25 + self._generateFunctionContextTest(node, check_block, body_block)
2.26 +
2.27 + # Check the number of parameters and defaults.
2.28 +
2.29 + self.set_block(check_block)
2.30 +
2.31 self.new_op(CheckFrame((nparams, ndefaults, fn.has_star)))
2.32 if ndefaults > 0:
2.33 self.new_op(FillDefaults((nparams, ndefaults, fn)))
2.34 @@ -670,6 +677,7 @@
2.35
2.36 else:
2.37 body_block = self.new_block()
2.38 + check_block = self.new_block()
2.39
2.40 # Check frames using the function's details.
2.41
2.42 @@ -677,6 +685,12 @@
2.43 nparams = len(fn.positional_names)
2.44 ndefaults = len(fn.defaults)
2.45
2.46 + self._generateFunctionContextTest(node, check_block, body_block)
2.47 +
2.48 + # Check the number of parameters and defaults.
2.49 +
2.50 + self.set_block(check_block)
2.51 +
2.52 self.new_op(CheckFrame((nparams, ndefaults, fn.has_star)))
2.53 if ndefaults > 0:
2.54 self.new_op(FillDefaults((nparams, ndefaults, fn)))
5.1 --- a/micropython/trans.py Sat May 23 02:46:04 2009 +0200
5.2 +++ b/micropython/trans.py Sun May 24 00:21:41 2009 +0200
5.3 @@ -151,7 +151,10 @@
5.4
5.5 def set_source(self):
5.6
5.7 - "Set the source of an assignment using the current assignment value."
5.8 + """
5.9 + Set the source of an assignment using the current assignment value. This
5.10 + sets the source input for the current instruction.
5.11 + """
5.12
5.13 self.optimiser.set_source(self.expr_temp[-1])
5.14
5.15 @@ -206,6 +209,7 @@
5.16 temp_position = 0
5.17 else:
5.18 temp_position = max(self.temp_positions) + 1
5.19 +
5.20 self.temp_positions.add(temp_position)
5.21 self.max_temp_position = max(self.max_temp_position, temp_position)
5.22 return self.unit.all_local_usage + temp_position # position in frame
5.23 @@ -852,6 +856,52 @@
5.24 else:
5.25 return None
5.26
5.27 + def _generateFunctionContextTest(self, node, check_block, body_block):
5.28 +
5.29 + """
5.30 + Generate code to test the context for 'node', jumping to 'check_block'
5.31 + and 'body_block' from this code.
5.32 + """
5.33 +
5.34 + adjust_block = self.new_block()
5.35 +
5.36 + # Check the context.
5.37 +
5.38 + temp = LoadName(Attr(0, None, None))
5.39 +
5.40 + # No usable context => remove the context and continue.
5.41 +
5.42 + self.new_op(temp)
5.43 + self.new_op(CheckContext())
5.44 + self.new_op(JumpIfFalse(adjust_block))
5.45 +
5.46 + # Check for a class as the context.
5.47 + # Not a class as context => preserve the context and continue.
5.48 +
5.49 + self.new_op(temp)
5.50 + self.new_op(CheckClassContext())
5.51 + self.new_op(JumpIfFalse(check_block))
5.52 +
5.53 + # Check the context's compatibility with the first parameter.
5.54 + # Compatible class => remove the context and continue.
5.55 + # NOTE: Handle insufficient arguments.
5.56 +
5.57 + self.new_op(LoadName(Attr(1, None, None)))
5.58 + self.new_op(CheckSelf())
5.59 + self.optimiser.set_source(temp)
5.60 + self.new_op(JumpIfTrue(adjust_block))
5.61 +
5.62 + # Incompatible class => type error.
5.63 +
5.64 + self.make_exception("TypeError", node)
5.65 + self.new_op(StoreException())
5.66 + self.new_op(RaiseException())
5.67 +
5.68 + # Remove the context from the parameters.
5.69 +
5.70 + self.set_block(adjust_block)
5.71 + self.new_op(AdjustFrame(1))
5.72 +
5.73 def _visitName(self, node, classes):
5.74
5.75 """
6.1 --- a/rsvp.py Sat May 23 02:46:04 2009 +0200
6.2 +++ b/rsvp.py Sun May 24 00:21:41 2009 +0200
6.3 @@ -256,9 +256,10 @@
6.4
6.5 print "Execution terminated",
6.6 if self.exception is not None:
6.7 - context, ref = self.exception
6.8 + ref = self.exception
6.9 + addr = self.load(ref + 1)
6.10 print "with exception:", self.load(ref)
6.11 - print "at address:", self.load(ref + 1)
6.12 + print "At address %d: %r" % (addr, self.load(addr))
6.13 else:
6.14 print "successfully."
6.15
6.16 @@ -412,8 +413,7 @@
6.17 else:
6.18 self.value = self.load(ref + offset)
6.19 else:
6.20 - exc = self._MakeObject(2, self.attr_error_instance)
6.21 - self.exception = exc, exc
6.22 + self.exception = self._MakeObject(2, self.attr_error_instance)
6.23 return self.RaiseException()
6.24
6.25 def LoadAttrIndexContext(self):
6.26 @@ -425,8 +425,7 @@
6.27 loaded_context, loaded_ref = self.load(offset) # offset is address of class attribute
6.28 self.value = ref, loaded_ref
6.29 else:
6.30 - exc = self._MakeObject(2, self.attr_error_instance)
6.31 - self.exception = exc, exc
6.32 + self.exception = self._MakeObject(2, self.attr_error_instance)
6.33 return self.RaiseException()
6.34
6.35 def LoadAttrIndexContextCond(self):
6.36 @@ -441,8 +440,7 @@
6.37 else:
6.38 self.value = self.load(ref + offset)
6.39 else:
6.40 - exc = self._MakeObject(2, self.attr_error_instance)
6.41 - self.exception = exc, exc
6.42 + self.exception = self._MakeObject(2, self.attr_error_instance)
6.43 return self.RaiseException()
6.44
6.45 def StoreAttrIndex(self):
6.46 @@ -452,14 +450,12 @@
6.47 attr_index, class_attr, offset = element
6.48 if attr_index == self.operand:
6.49 if class_attr:
6.50 - exc = self._MakeObject(2, self.type_error_instance)
6.51 - self.exception = exc, exc
6.52 + self.exception = self._MakeObject(2, self.type_error_instance)
6.53 return self.RaiseException()
6.54 else:
6.55 self.save(ref + offset, self.source)
6.56 else:
6.57 - exc = self._MakeObject(2, self.attr_error_instance)
6.58 - self.exception = exc, exc
6.59 + self.exception = self._MakeObject(2, self.attr_error_instance)
6.60 return self.RaiseException()
6.61
6.62 # NOTE: LoadAttrIndexContext is a possibility if a particular attribute can always be overridden.
6.63 @@ -490,8 +486,7 @@
6.64 if param_index == self.operand:
6.65 self.frame_stack[frame + offset + 1] = self.source # add 1 to skip the context always generated
6.66 else:
6.67 - exc = self._MakeObject(2, self.type_error_instance)
6.68 - self.exception = exc, exc
6.69 + self.exception = self._MakeObject(2, self.type_error_instance)
6.70 return self.RaiseException()
6.71
6.72 def LoadCallable(self):
6.73 @@ -511,6 +506,20 @@
6.74 # NOTE: self() inside methods impossible.
6.75 self.value = context, context
6.76
6.77 + def CheckContext(self):
6.78 + self.status = self.value[1] is not None
6.79 +
6.80 + def CheckClassContext(self):
6.81 + context_context, context_ref = self.value
6.82 + context_data = self.load(context_ref)
6.83 +
6.84 + # Classes are not themselves usable as the self argument.
6.85 + # NOTE: This may change at some point.
6.86 + # However, where classes appear as the context, instance
6.87 + # compatibility is required in the first argument.
6.88 +
6.89 + self.status = context_data.attrcode is None # absent attrcode == class
6.90 +
6.91 def CheckFrame(self):
6.92 (nargs, ndefaults, has_star) = self.operand
6.93
6.94 @@ -551,13 +560,11 @@
6.95 self_context, self_ref = self.frame_stack[frame + 1]
6.96 if not self._CheckInstance(self_ref, context_context):
6.97 #raise Exception, "CheckFrame %r (%r vs. %r)" % (self.operand, self.load(self_ref), self.load(context_context))
6.98 - exc = self._MakeObject(2, self.type_error_instance)
6.99 - self.exception = exc, exc
6.100 + self.exception = self._MakeObject(2, self.type_error_instance)
6.101 return self.RaiseException()
6.102 else:
6.103 #raise Exception, "CheckFrame %r (no self argument)" % self.operand
6.104 - exc = self._MakeObject(2, self.type_error_instance)
6.105 - self.exception = exc, exc
6.106 + self.exception = self._MakeObject(2, self.type_error_instance)
6.107 return self.RaiseException()
6.108
6.109 # Test the frame size.
6.110 @@ -565,8 +572,7 @@
6.111
6.112 if not ((nargs - ndefaults) <= nlocals and (nlocals <= nargs or has_star)):
6.113 #raise Exception, "CheckFrame %r (%r <= %r <= %r)" % (self.operand, nargs - ndefaults, nlocals, nargs)
6.114 - exc = self._MakeObject(2, self.type_error_instance)
6.115 - self.exception = exc, exc
6.116 + self.exception = self._MakeObject(2, self.type_error_instance)
6.117 return self.RaiseException()
6.118
6.119 def FillDefaults(self):
6.120 @@ -644,7 +650,7 @@
6.121
6.122 def RaiseException(self):
6.123 # NOTE: Adding the program counter as the first attribute.
6.124 - self.save(self.exception[1] + 1, self.pc)
6.125 + self.save(self.exception + 1, self.pc)
6.126 # Jumping to the current handler.
6.127 return self.handler_stack[-1]
6.128
6.129 @@ -726,8 +732,7 @@
6.130 # Test operand suitability.
6.131
6.132 if not self._CheckInstance(left, self.int_class) and self._CheckInstance(right, self.int_class):
6.133 - exc = self._MakeObject(2, self.type_error_instance)
6.134 - self.exception = exc, exc
6.135 + self.exception = self._MakeObject(2, self.type_error_instance)
6.136 return self.RaiseException()
6.137
6.138 # NOTE: Assume single location for data.
6.139 @@ -759,8 +764,7 @@
6.140 # Test operand suitability.
6.141
6.142 if not self._CheckInstance(left, self.int_class):
6.143 - exc = self._MakeObject(2, self.type_error_instance)
6.144 - self.exception = exc, exc
6.145 + self.exception = self._MakeObject(2, self.type_error_instance)
6.146 return self.RaiseException()
6.147
6.148 # NOTE: Assume single location for data.
6.149 @@ -785,8 +789,7 @@
6.150 # Test operand suitability.
6.151
6.152 if not self._CheckInstance(left, self.int_class):
6.153 - exc = self._MakeObject(2, self.type_error_instance)
6.154 - self.exception = exc, exc
6.155 + self.exception = self._MakeObject(2, self.type_error_instance)
6.156 return self.RaiseException()
6.157
6.158 # NOTE: Assume single location for data.
6.159 @@ -848,8 +851,7 @@
6.160 elif item_pos < 0 and item_pos >= -nelements:
6.161 item_pos = nelements + item_pos
6.162 else:
6.163 - exc = self._MakeObject(2, self.index_error_instance)
6.164 - self.exception = exc, exc
6.165 + self.exception = self._MakeObject(2, self.index_error_instance)
6.166 return self.RaiseException()
6.167
6.168 self.result = self.load(obj + 1 + item_pos)