1.1 --- a/docs/structures.txt Sat Aug 23 22:32:17 2008 +0200
1.2 +++ b/docs/structures.txt Sun Aug 24 03:06:00 2008 +0200
1.3 @@ -202,8 +202,8 @@
1.4
1.5 0 1 2 3 4 5
1.6 code for code code class attribute ...
1.7 - function reference #args, function reference
1.8 - #defaults reference
1.9 + function reference #args, function (default)
1.10 + #defaults reference reference
1.11
1.12 Here, the code reference would lead to code for the function. Note that the
1.13 function locals are completely distinct from this structure and are not
2.1 --- a/micropython/__init__.py Sat Aug 23 22:32:17 2008 +0200
2.2 +++ b/micropython/__init__.py Sun Aug 24 03:06:00 2008 +0200
2.3 @@ -230,7 +230,7 @@
2.4 "Return a table with details of attributes for classes and modules."
2.5
2.6 if self.objtable is None:
2.7 - t = self.objtable = micropython.table.Table()
2.8 + t = self.objtable = micropython.table.ObjectTable()
2.9 for module in self.get_modules():
2.10 t.add(module.full_name(), module.module_attributes())
2.11 for obj in module.all_objects:
2.12 @@ -244,7 +244,7 @@
2.13 "Return a table with details of class compatibility."
2.14
2.15 if self.clstable is None:
2.16 - t = self.clstable = micropython.table.Table()
2.17 + t = self.clstable = micropython.table.ClassTable()
2.18 for module in self.get_modules():
2.19 for obj in module.all_objects:
2.20 if isinstance(obj, micropython.inspect.Class):
2.21 @@ -263,7 +263,7 @@
2.22 objtable = self.get_object_table()
2.23
2.24 if self.paramtable is None:
2.25 - t = self.paramtable = micropython.table.Table()
2.26 + t = self.paramtable = micropython.table.ParameterTable()
2.27
2.28 # Visit each module, getting function and method details.
2.29
3.1 --- a/micropython/ast.py Sat Aug 23 22:32:17 2008 +0200
3.2 +++ b/micropython/ast.py Sun Aug 24 03:06:00 2008 +0200
3.3 @@ -32,7 +32,8 @@
3.4 "A translated module."
3.5
3.6 supported_optimisations = [
3.7 - "constant_storage", "known_target", "self_access", "temp_storage", "load_operations", "no_operations", "unused_results"
3.8 + "constant_storage", "source_storage", "known_target", "self_access",
3.9 + "temp_storage", "load_operations", "no_operations", "unused_results"
3.10 ]
3.11
3.12 # Attribute access instructions, for use with the appropriate handlers.
3.13 @@ -213,10 +214,12 @@
3.14
3.15 def record_value(self):
3.16 self.expr_temp = self._optimise_temp_storage()
3.17 + self.active_source = self.active
3.18
3.19 def discard_value(self):
3.20 self.discard_temp(self.expr_temp)
3.21 self.expr_temp = None
3.22 + self.active_source = None
3.23
3.24 def set_source(self):
3.25 if self.active is not None:
3.26 @@ -322,12 +325,16 @@
3.27
3.28 self.active = None
3.29 self.active_value = None
3.30 + self.active_source = None
3.31
3.32 # Optimisation tests.
3.33
3.34 def _should_optimise_constant_storage(self):
3.35 return "constant_storage" in self.optimisations
3.36
3.37 + def _should_optimise_source_storage(self):
3.38 + return "source_storage" in self.optimisations
3.39 +
3.40 def _should_optimise_known_target(self):
3.41 return "known_target" in self.optimisations
3.42
3.43 @@ -380,6 +387,7 @@
3.44 LoadAddressContext, LoadAttr, LoadAttrIndex, # as the object being referenced
3.45 StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced
3.46 TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands
3.47 + CheckFrame,
3.48 LoadContext, # as the object providing the result
3.49 JumpWithFrame # as the target
3.50 ))
3.51 @@ -454,10 +462,11 @@
3.52 to a temporary variable retaining the result of the last instruction.
3.53 """
3.54
3.55 - # LoadResult cannot be relied upon, since in general the result register
3.56 + # LoadResult cannot be relied upon in general since the result register
3.57 # could be updated since first being referenced.
3.58
3.59 - return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst))
3.60 + return isinstance(self.active_value, (LoadName, LoadTemp, LoadAddress, LoadConst)) or \
3.61 + isinstance(self.active_value, LoadResult) and self.active_value is self.active
3.62
3.63 def _have_correct_self_for_target(self, context):
3.64
3.65 @@ -489,6 +498,25 @@
3.66 else:
3.67 return 0
3.68
3.69 + def _optimise_source_storage(self):
3.70 +
3.71 + """
3.72 + Where the source value in an assignment can be inserted into the
3.73 + eventual target without intermediate storage, optimise away the storage
3.74 + instruction.
3.75 + """
3.76 +
3.77 + if self._should_optimise_source_storage() and \
3.78 + self.active_source is not None and \
3.79 + self.active_source.source is None and \
3.80 + self.active_source.input is None and \
3.81 + self.active_source is self.active:
3.82 +
3.83 + self.remove_op()
3.84 + return 1
3.85 + else:
3.86 + return 0
3.87 +
3.88 def _optimise_known_target(self):
3.89
3.90 """
3.91 @@ -779,7 +807,7 @@
3.92 # Where a target or context are not known or where an instance is known
3.93 # to be the context, load the context.
3.94
3.95 - if context is None or isinstance(context, Instance):
3.96 + if target is None or isinstance(context, Instance):
3.97 self.new_op(temp)
3.98 self.new_op(LoadContext())
3.99 self.new_op(StoreFrame(0))
3.100 @@ -803,11 +831,20 @@
3.101 # Evaluate the arguments.
3.102
3.103 employed_positions = set()
3.104 + employed_keywords = set()
3.105 extra_keywords = []
3.106
3.107 + # Find keyword arguments in advance in order to help resolve targets.
3.108 +
3.109 + for arg in args:
3.110 + if isinstance(arg, compiler.ast.Keyword):
3.111 + employed_keywords.add(arg.name)
3.112 +
3.113 + possible_targets = self.paramtable.all_possible_objects(employed_keywords)
3.114 +
3.115 # Note the presence of the context in the frame where appropriate.
3.116
3.117 - if context is None or isinstance(context, Instance):
3.118 + if target is None or isinstance(context, Instance):
3.119 ncontext = 1
3.120 expect_context = 0
3.121 elif isinstance(context, Class):
3.122 @@ -973,9 +1010,10 @@
3.123 else:
3.124 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1)
3.125
3.126 - # Only check non-empty frames.
3.127 + # Only check non-empty frames (using the callable's details).
3.128
3.129 if employed_positions or max_pos >= 0:
3.130 + self.new_op(temp)
3.131 self.new_op(CheckFrame(max_pos + 1))
3.132
3.133 # Set the frame size.
3.134 @@ -1403,8 +1441,13 @@
3.135 def visitAssList(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AssList")
3.136
3.137 def visitAssName(self, node):
3.138 +
3.139 + # Optimise away intermediate source storage.
3.140 +
3.141 + no_source = self._optimise_source_storage()
3.142 self._visitName(node, self.name_store_instructions)
3.143 - self.set_source()
3.144 + if not no_source:
3.145 + self.set_source()
3.146
3.147 visitAssTuple = visitAssList
3.148
3.149 @@ -1661,6 +1704,9 @@
3.150 # Visiting of the code occurs when get_code is invoked on this node.
3.151
3.152 else:
3.153 + extend = ExtendFrame()
3.154 + self.new_op(extend)
3.155 +
3.156 self.dispatch(node.code)
3.157 if not isinstance(self.last_op(), Return):
3.158 self.dispatch(compiler.ast.Name("None"))
3.159 @@ -1668,6 +1714,8 @@
3.160
3.161 self.new_op(Return())
3.162
3.163 + extend.attr = self.max_temp_position + 1 # NOTE: See get_code for similar code.
3.164 +
3.165 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr")
3.166
3.167 def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor")
4.1 --- a/micropython/rsvp.py Sat Aug 23 22:32:17 2008 +0200
4.2 +++ b/micropython/rsvp.py Sun Aug 24 03:06:00 2008 +0200
4.3 @@ -186,6 +186,7 @@
4.4 # Invocation-related instructions, using a special result "register".
4.5
4.6 class JumpWithFrame(Instruction): "Jump, adopting the invocation frame, to the callable found as the current value."
4.7 +class ExtendFrame(Immediate): "Extend the current frame for temporary storage use."
4.8 class Return(Instruction): "Return from a subprogram."
4.9 class LoadResult(Instruction): "Load into the current value a returned value."
4.10 class StoreResult(Instruction): "Store the current value as a value to be returned."
5.1 --- a/micropython/table.py Sat Aug 23 22:32:17 2008 +0200
5.2 +++ b/micropython/table.py Sun Aug 24 03:06:00 2008 +0200
5.3 @@ -143,27 +143,51 @@
5.4 if entry is None:
5.5 result.append(None)
5.6 else:
5.7 - offset, attr = entry
5.8 - if attr.parent is not None:
5.9 - location = attr.parent.location or 0
5.10 - else:
5.11 - location = 0
5.12 - if attr.position is not None:
5.13 - position = attr.position + location + 1 # skip structure header
5.14 - else:
5.15 - position = None # NOTE: Should fix unpositioned attributes.
5.16 -
5.17 - # Class offset/code, attribute type, context instance override flag, location/position.
5.18 -
5.19 - result.append((offset, attr.is_class_attribute(), attr.defined_within_hierarchy(), position))
5.20 + result.append(self.entry_as_raw(entry))
5.21
5.22 return result
5.23
5.24 +class ObjectList(List):
5.25 +
5.26 + "An object list."
5.27 +
5.28 + def entry_as_raw(self, entry):
5.29 + offset, attr = entry
5.30 +
5.31 + if attr.parent is not None:
5.32 + location = attr.parent.location or 0
5.33 + else:
5.34 + location = 0
5.35 + if attr.position is not None:
5.36 + position = attr.position + location + 1 # skip structure header
5.37 + else:
5.38 + position = None # NOTE: Should fix unpositioned attributes.
5.39 +
5.40 + # Class offset/code, attribute type, context instance override flag, location/position.
5.41 +
5.42 + return (offset, attr.is_class_attribute(), attr.defined_within_hierarchy(), position)
5.43 +
5.44 +class ClassList(List):
5.45 +
5.46 + "A class list."
5.47 +
5.48 + def entry_as_raw(self, entry):
5.49 + offset, attr = entry
5.50 + return offset
5.51 +
5.52 +class ParameterList(List):
5.53 +
5.54 + "A parameter list."
5.55 +
5.56 + def entry_as_raw(self, entry):
5.57 + return entry
5.58 +
5.59 class Table:
5.60
5.61 "A lookup table."
5.62
5.63 TableError = TableError
5.64 + list_class = None # overridden
5.65
5.66 def __init__(self):
5.67 self.attributes = set()
5.68 @@ -275,7 +299,7 @@
5.69 """
5.70
5.71 if self.displaced_list is None:
5.72 - self.displaced_list = List(self.attribute_names())
5.73 + self.displaced_list = self.list_class(self.attribute_names())
5.74
5.75 # Visit each row of the matrix.
5.76
5.77 @@ -284,4 +308,22 @@
5.78
5.79 return self.displaced_list
5.80
5.81 +class ObjectTable(Table):
5.82 +
5.83 + "An object table."
5.84 +
5.85 + list_class = ObjectList
5.86 +
5.87 +class ClassTable(Table):
5.88 +
5.89 + "A class table."
5.90 +
5.91 + list_class = ClassList
5.92 +
5.93 +class ParameterTable(Table):
5.94 +
5.95 + "A parameter table."
5.96 +
5.97 + list_class = ParameterList
5.98 +
5.99 # vim: tabstop=4 expandtab shiftwidth=4
6.1 --- a/rsvp.py Sat Aug 23 22:32:17 2008 +0200
6.2 +++ b/rsvp.py Sun Aug 24 03:06:00 2008 +0200
6.3 @@ -32,7 +32,7 @@
6.4 * Invocation frame pointer stack
6.5 * Exception handler stack
6.6 * Registers: current value, boolean status value, source value, result,
6.7 - current exception
6.8 + current exception, current callable
6.9
6.10 The memory contains constants, global variable references and program code.
6.11
6.12 @@ -87,6 +87,7 @@
6.13 self.value = None
6.14 self.status = None
6.15 self.source = None
6.16 + self.callable = None
6.17 self.result = None
6.18 self.exception = None
6.19
6.20 @@ -289,13 +290,7 @@
6.21 self.invocation_sp_stack.append(len(self.frame_stack))
6.22 self.frame_stack.extend([None] * self.operand)
6.23
6.24 - def JumpWithFrame(self):
6.25 - self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame
6.26 - context, ref = self.value
6.27 - return self.jump(ref.code_location, self.pc + 1) # return to the instruction after this one
6.28 -
6.29 def DropFrame(self):
6.30 - result = self.pull()
6.31 self.local_sp_stack.pop()
6.32 frame = self.invocation_sp_stack.pop()
6.33 self.frame_stack = self.frame_stack[:frame] # reset stack before call
6.34 @@ -315,15 +310,35 @@
6.35 # NOTE: This should cause an argument error.
6.36 raise Exception, "StoreFrameIndex % r" % element
6.37
6.38 - def CheckFrame(self): pass
6.39 + def LoadCallable(self):
6.40 + context, ref = self.value
6.41 + self.callable = self.load(ref + 1)
6.42 +
6.43 + def StoreCallable(self):
6.44 + context, ref = self.value
6.45 + self.save(ref + 1, self.callable)
6.46 +
6.47 + def LoadContext(self):
6.48 + context, ref = self.value
6.49 + self.value = None, context
6.50 +
6.51 + def CheckFrame(self):
6.52 + context, ref = self.value
6.53 + nargs, ndefaults = self.load(ref + 2)
6.54 + if not (nargs - ndefaults <= self.operand <= nargs):
6.55 + raise Exception, "CheckFrame %r" % (nargs - ndefaults, self.operand, nargs)
6.56 + # NOTE: Support population of defaults.
6.57 + # NOTE: Support sliding of the frame to exclude any inappropriate context.
6.58
6.59 def CheckSelf(self): pass
6.60
6.61 - def LoadCallable(self): pass
6.62 + def JumpWithFrame(self):
6.63 + self.local_sp_stack.append(self.invocation_sp_stack[-1]) # adopt the invocation frame
6.64 + return self.jump(self.callable, self.pc + 1) # return to the instruction after this one
6.65
6.66 - def LoadContext(self):
6.67 - context, ref = self.value
6.68 - self.push((None, context))
6.69 + def ExtendFrame(self):
6.70 + frame = self.local_sp_stack[-1]
6.71 + frame.extend([None] * self.operand)
6.72
6.73 def Return(self):
6.74 self.pc = self.pull_pc()
6.75 @@ -372,4 +387,7 @@
6.76 # LoadBoolean is implemented in the generated code.
6.77 # StoreBoolean is implemented by testing against the True value.
6.78
6.79 + def InvertBoolean(self):
6.80 + self.status = not self.status
6.81 +
6.82 # vim: tabstop=4 expandtab shiftwidth=4