1.1 --- a/micropython/ast.py Sun Feb 17 02:38:04 2008 +0100
1.2 +++ b/micropython/ast.py Mon Feb 18 01:22:25 2008 +0100
1.3 @@ -78,7 +78,8 @@
1.4
1.5 self.unit = self.module
1.6 self.code = []
1.7 - self.dispatch(self.module.module)
1.8 + if self.module.module is not None:
1.9 + self.dispatch(self.module.module)
1.10 return self.code
1.11
1.12 def get_code(self, unit):
1.13 @@ -105,6 +106,9 @@
1.14 # Code writing methods.
1.15
1.16 def new_label(self):
1.17 +
1.18 + "Return a new label object for use with set_label."
1.19 +
1.20 number = self.label_number
1.21 label = Label(number)
1.22 self.labels[label] = label
1.23 @@ -121,12 +125,21 @@
1.24 label.location = len(self.code) + self.unit.code_location
1.25
1.26 def new_op(self, op):
1.27 +
1.28 + "Add 'op' to the generated code."
1.29 +
1.30 self.code.append(op)
1.31
1.32 def replace_op(self, op):
1.33 +
1.34 + "Replace the last added instruction with 'op'."
1.35 +
1.36 self.code[-1] = op
1.37
1.38 def last_op(self):
1.39 +
1.40 + "Return the last added instruction."
1.41 +
1.42 return self.code[-1]
1.43
1.44 # Visitor methods.
1.45 @@ -138,9 +151,22 @@
1.46 return ASTVisitor.dispatch(self, node, *args)
1.47
1.48 def _visitAttr(self, node, classes):
1.49 - AttrInstruction, AttrIndexInstruction = classes
1.50 +
1.51 + """
1.52 + Visit the attribute-related 'node', generating instructions based on the
1.53 + given 'classes'.
1.54 + """
1.55 +
1.56 self.dispatch(node.expr)
1.57 + self._generateAttr(node.attrname, classes)
1.58
1.59 + def _generateAttr(self, attrname, classes):
1.60 +
1.61 + """
1.62 + Generate code for the access to 'attrname' using the given 'classes'.
1.63 + """
1.64 +
1.65 + AttrInstruction, AttrIndexInstruction = classes
1.66 # NOTE: Only simple cases are used for optimisations.
1.67
1.68 last = self.last_op()
1.69 @@ -151,17 +177,32 @@
1.70 target = last.attr.value
1.71 target_name = target.full_name()
1.72 table_entry = self.objtable.table[target_name]
1.73 - pos = table_entry[node.attrname]
1.74 + pos = table_entry[attrname]
1.75 self.replace_op(AttrInstruction(pos))
1.76
1.77 else:
1.78 - index = self.objtable.get_index(node.attrname)
1.79 + index = self.objtable.get_index(attrname)
1.80 self.new_op(AttrIndexInstruction(index))
1.81
1.82 def _visitName(self, node, classes):
1.83 +
1.84 + """
1.85 + Visit the name-related 'node', generating instructions based on the
1.86 + given 'classes'.
1.87 + """
1.88 +
1.89 name = node.name
1.90 scope = self.get_scope(name)
1.91 #print self.module.name, node.lineno, name, scope
1.92 + self._generateName(name, scope, classes, node)
1.93 +
1.94 + def _generateName(self, name, scope, classes, node):
1.95 +
1.96 + """
1.97 + Generate code for the access to 'name' in 'scope' using the given
1.98 + 'classes', and using the given 'node' as the source of the access.
1.99 + """
1.100 +
1.101 NameInstruction, AttrInstruction = classes
1.102
1.103 if scope == "local":
1.104 @@ -245,6 +286,12 @@
1.105
1.106 self.dispatch(node.node)
1.107
1.108 + # Generate the call.
1.109 +
1.110 + self._generateCallFunc(node.args, node)
1.111 +
1.112 + def _generateCallFunc(self, args, node):
1.113 +
1.114 # NOTE: Only simple cases are used for optimisations.
1.115
1.116 last = self.last_op()
1.117 @@ -257,10 +304,10 @@
1.118
1.119 positional = 1
1.120
1.121 - for i, arg in enumerate(node.args):
1.122 + for i, arg in enumerate(args):
1.123 if isinstance(arg, compiler.ast.Keyword):
1.124 if positional:
1.125 - self.new_op(ReserveFrame(len(node.args) - i))
1.126 + self.new_op(ReserveFrame(len(args) - i))
1.127 positional = 0
1.128
1.129 self.dispatch(arg.expr)
1.130 @@ -322,7 +369,7 @@
1.131 def visitClass(self, node):
1.132 unit = self.unit
1.133 self.unit = node.unit
1.134 - self.unit.code_location = self.module.code_location + len(self.code)
1.135 + self.unit.code_location = self.module.code_location # class body code is not independently addressable
1.136 self.dispatch(node.code)
1.137 self.unit = unit
1.138
1.139 @@ -364,7 +411,60 @@
1.140
1.141 def visitFloorDiv(self, node): pass
1.142
1.143 - def visitFor(self, node): pass
1.144 + def visitFor(self, node):
1.145 + exit_label = self.new_label()
1.146 + next_label = self.new_label()
1.147 + else_label = self.new_label()
1.148 +
1.149 + # Get the "list" to be iterated over, obtain its iterator.
1.150 +
1.151 + self.dispatch(node.list)
1.152 + self._generateAttr("__iter__", (LoadAttr, LoadAttrIndex))
1.153 + self._generateCallFunc([], node)
1.154 + # Iterator on stack.
1.155 +
1.156 + # In the loop...
1.157 +
1.158 + self.set_label(next_label)
1.159 +
1.160 + # Use the iterator to get the next value.
1.161 +
1.162 + self.new_op(Duplicate())
1.163 + self._generateAttr("next", (LoadAttr, LoadAttrIndex))
1.164 + self._generateCallFunc([], node)
1.165 +
1.166 + # Test for StopIteration.
1.167 +
1.168 + self.new_op(CheckException("StopIteration")) # NOTE: To be done properly.
1.169 + if node.else_ is not None:
1.170 + self.new_op(JumpIfTrue(else_label))
1.171 + else:
1.172 + self.new_op(JumpIfTrue(exit_label))
1.173 +
1.174 + # Assign to the target.
1.175 +
1.176 + self.dispatch(node.assign)
1.177 +
1.178 + # Process the body with the current next and exit points.
1.179 +
1.180 + self.loop_labels.append((next_label, exit_label))
1.181 + self.dispatch(node.body)
1.182 + self.loop_labels.pop()
1.183 +
1.184 + # Repeat the loop.
1.185 +
1.186 + self.new_op(Jump(next_label))
1.187 +
1.188 + # Produce the "else" section.
1.189 +
1.190 + if node.else_ is not None:
1.191 + self.set_label(exit_label)
1.192 + self.dispatch(node.else_)
1.193 +
1.194 + # Pop the iterator.
1.195 +
1.196 + self.set_label(exit_label)
1.197 + self.new_op(Pop())
1.198
1.199 def visitFrom(self, node): pass
1.200
1.201 @@ -485,17 +585,23 @@
1.202
1.203 def visitWhile(self, node):
1.204 exit_label = self.new_label()
1.205 - self.dispatch(node.test)
1.206 - self.new_op(JumpIfFalse(exit_label))
1.207 + next_label = self.new_label()
1.208 + else_label = self.new_label()
1.209
1.210 - next_label = self.new_label()
1.211 self.set_label(next_label)
1.212 + self.dispatch(node.test)
1.213 + if node.else_ is not None:
1.214 + self.new_op(JumpIfFalse(else_label))
1.215 + else:
1.216 + self.new_op(JumpIfFalse(exit_label))
1.217 +
1.218 self.loop_labels.append((next_label, exit_label))
1.219
1.220 self.dispatch(node.body)
1.221 self.new_op(Jump(next_label))
1.222
1.223 if node.else_ is not None:
1.224 + self.set_label(else_label)
1.225 self.dispatch(node.else_)
1.226
1.227 self.set_label(exit_label)