1.1 --- a/micropython/__init__.py Sat Oct 10 03:09:29 2009 +0200
1.2 +++ b/micropython/__init__.py Sun Oct 11 02:40:20 2009 +0200
1.3 @@ -39,8 +39,7 @@
1.4 which the functionality of the micropython package may be accessed.
1.5 """
1.6
1.7 -from micropython.common import *
1.8 -from micropython.program import Block
1.9 +from micropython.common import TableGenerationError
1.10 import micropython.ast
1.11 import micropython.data
1.12 import micropython.opt
1.13 @@ -89,7 +88,10 @@
1.14
1.15 def get_image(self, with_builtins=0):
1.16
1.17 - "Return a dictionary mapping modules to structures."
1.18 + """
1.19 + Return the program image including built-in objects if 'with_builtins'
1.20 + is specified and set to a true value.
1.21 + """
1.22
1.23 if self.code is not None:
1.24 return self.code
1.25 @@ -102,13 +104,12 @@
1.26
1.27 # Append constants to the image.
1.28
1.29 - for pos, const in enumerate(self.importer.constants()):
1.30 + for const in self.importer.constants():
1.31 self.code.append(const)
1.32
1.33 last_module = self.importer.modules_ordered[-1]
1.34
1.35 for module in self.importer.modules_ordered:
1.36 - pos = len(self.code)
1.37 suppress_builtins = not with_builtins and module.name == "__builtins__"
1.38
1.39 # Position the module in the image and make a translation.
1.40 @@ -118,13 +119,11 @@
1.41 # Add header details.
1.42
1.43 self.code.append(module)
1.44 - pos += 1
1.45
1.46 # Append module attributes to the image.
1.47
1.48 attributes = module.module_attributes()
1.49 self.code += module.attributes_as_list()
1.50 - pos += len(attributes.keys())
1.51
1.52 # Append classes and functions to the image.
1.53
1.54 @@ -134,13 +133,11 @@
1.55 # Add header details.
1.56
1.57 self.code.append(obj)
1.58 - pos += 1
1.59
1.60 # Append class attributes to the image.
1.61
1.62 attributes = obj.class_attributes()
1.63 self.code += obj.attributes_as_list()
1.64 - pos += len(attributes.keys())
1.65
1.66 # Omit built-in function code where requested.
1.67
1.68 @@ -153,7 +150,6 @@
1.69 instantiator = obj.get_instantiator()
1.70 code = trans.get_instantiator_code(obj)
1.71 self.code += code
1.72 - pos += len(code)
1.73
1.74 # Class-level code is generated separately at the module
1.75 # level, and the code location is set within the code
1.76 @@ -164,14 +160,12 @@
1.77 # Add header details.
1.78
1.79 self.code.append(obj)
1.80 - pos += 1
1.81
1.82 # Append any default values to the image.
1.83 # Only do this for named functions (not lambdas).
1.84
1.85 if obj.name is not None:
1.86 self.code += obj.default_attrs
1.87 - pos += len(obj.default_attrs)
1.88
1.89 # Omit built-in function code where requested.
1.90
1.91 @@ -183,7 +177,6 @@
1.92 else:
1.93 code = trans.get_code(obj)
1.94 self.code += code
1.95 - pos += len(code)
1.96
1.97 # Omit built-in module code where requested.
1.98
1.99 @@ -195,14 +188,15 @@
1.100 else:
1.101 code = trans.get_module_code()
1.102 self.code += code
1.103 - pos += len(code)
1.104
1.105 return self.code
1.106
1.107 - def get_raw_image(self, with_builtins=0):
1.108 + def get_raw_image(self, architecture=None, with_builtins=0):
1.109
1.110 "Return the raw image representation of the program."
1.111
1.112 + architecture = architecture or micropython.rsvp
1.113 +
1.114 self.get_image(with_builtins)
1.115
1.116 objtable = self.get_object_table()
1.117 @@ -213,56 +207,12 @@
1.118 pos = 0
1.119
1.120 for item in self.code:
1.121 -
1.122 - # Blocks are positioned leaving space for their expansion.
1.123 -
1.124 - if isinstance(item, Block):
1.125 - item.location = pos
1.126 - pos += len(item.code)
1.127 -
1.128 - # Other multi-location objects.
1.129 -
1.130 - elif isinstance(item, (
1.131 - micropython.data.Class, micropython.data.Const,
1.132 - micropython.data.Function, micropython.data.Module
1.133 - )):
1.134 -
1.135 - if isinstance(item, micropython.data.Class):
1.136 -
1.137 - # Append a template of an instance for use when
1.138 - # instantiating classes.
1.139 -
1.140 - item.instance_template_location = pos
1.141 - pos += 1
1.142 -
1.143 - # Record the location of the object.
1.144 + arch_item = architecture.get_object(item)
1.145
1.146 - item.location = pos
1.147 - pos += 1
1.148 -
1.149 - # Code and details are associated with certain objects.
1.150 -
1.151 - if isinstance(item, micropython.data.Function):
1.152 -
1.153 - # Set the code location only where the code has been
1.154 - # generated.
1.155 -
1.156 - if not with_builtins and item.module.name == "__builtins__" and item.astnode.doc is None:
1.157 - item.code_location = item.full_name()
1.158 + # Get the raw version for the architecture.
1.159
1.160 - # Skip any defaults for named functions.
1.161 -
1.162 - elif item.name is not None:
1.163 - item.code_location = pos + len(item.defaults)
1.164 -
1.165 - # Skip any defaults for lambda functions.
1.166 -
1.167 - else:
1.168 - item.code_location = pos
1.169 -
1.170 - elif isinstance(item, micropython.data.Const):
1.171 - pos += len(item.raw_data())
1.172 -
1.173 + if arch_item is not None:
1.174 + pos = arch_item.set_location(pos, with_builtins)
1.175 else:
1.176 pos += 1
1.177
1.178 @@ -271,50 +221,16 @@
1.179 self.raw_code = []
1.180
1.181 for item in self.code:
1.182 -
1.183 - if isinstance(item, micropython.data.Attr):
1.184 - self.raw_code += item.as_raw(objtable, paramtable)
1.185 + arch_item = architecture.get_object(item)
1.186
1.187 - elif isinstance(item, Block):
1.188 - assert item.location == len(self.raw_code)
1.189 - self.raw_code += item.as_raw(objtable, paramtable)
1.190 -
1.191 - elif isinstance(item, micropython.data.Class):
1.192 - assert item.instance_template_location == len(self.raw_code)
1.193 - self.raw_code += item.as_raw(objtable, paramtable,
1.194 - with_builtins or item.module.name != "__builtins__" or item.astnode.doc is not None)
1.195 - assert item.location == len(self.raw_code) - 1
1.196 + # Get the raw version for the architecture.
1.197
1.198 - elif isinstance(item, micropython.data.Const):
1.199 - assert item.location == len(self.raw_code)
1.200 - self.raw_code += item.as_raw(objtable, paramtable)
1.201 -
1.202 - elif isinstance(item, micropython.data.Function):
1.203 - assert item.location == len(self.raw_code)
1.204 - self.raw_code += item.as_raw(objtable, paramtable)
1.205 -
1.206 - # Check the code location only where the code has been generated.
1.207 -
1.208 - assert (not with_builtins and item.module.name == "__builtins__" and item.astnode.doc is None) or \
1.209 - item.name is not None and item.code_location == len(self.raw_code) + len(item.defaults) or \
1.210 - item.name is None and item.code_location == len(self.raw_code)
1.211 -
1.212 - elif isinstance(item, micropython.data.Module):
1.213 - assert item.location == len(self.raw_code)
1.214 - self.raw_code += item.as_raw(objtable, paramtable)
1.215 -
1.216 + if arch_item is not None:
1.217 + self.raw_code += arch_item.as_raw(objtable, paramtable, with_builtins)
1.218 + arch_item.finalise_location(with_builtins)
1.219 else:
1.220 self.raw_code.append(item)
1.221
1.222 - # Set the code body location for items now that the code blocks have
1.223 - # been positioned.
1.224 -
1.225 - if isinstance(item, (micropython.data.Class, micropython.data.Function)):
1.226 - if not with_builtins and item.module.name == "__builtins__" and item.astnode.doc is None:
1.227 - item.code_body_location = item.full_name()
1.228 - else:
1.229 - item.code_body_location = item.get_body_block().location
1.230 -
1.231 # Fix the module locations.
1.232
1.233 for module in self.importer.modules_ordered:
2.1 --- a/micropython/data.py Sat Oct 10 03:09:29 2009 +0200
2.2 +++ b/micropython/data.py Sun Oct 11 02:40:20 2009 +0200
2.3 @@ -431,14 +431,6 @@
2.4 l.append("(c=%s, v=%s)" % (shortrepr(c), shortrepr(v)))
2.5 return ", ".join(l)
2.6
2.7 - def as_raw(self, objtable, paramtable):
2.8 - return [
2.9 - DataValue(
2.10 - self.get_context() and self.get_context().location,
2.11 - self.get_value() and self.get_value().location
2.12 - )
2.13 - ]
2.14 -
2.15 # Instances are special in that they need to be wrapped together with context in
2.16 # a running program, but they are not generally constant.
2.17
2.18 @@ -475,7 +467,7 @@
2.19 self.value = value
2.20
2.21 def get_value(self):
2.22 - return value
2.23 + return self.value
2.24
2.25 def __repr__(self):
2.26 if self.location is not None:
2.27 @@ -485,25 +477,6 @@
2.28
2.29 __shortrepr__ = __repr__
2.30
2.31 - def as_raw(self, objtable, paramtable):
2.32 - # NOTE: Need class details!
2.33 - return [
2.34 - DataObject(
2.35 - objtable.as_list().get_code(self.value_type_name()),
2.36 - objtable.get_index(self.value_type_name()), # is instance
2.37 - None,
2.38 - self.value_type_name(),
2.39 - 1 # size
2.40 - )
2.41 - ] + self.raw_data()
2.42 -
2.43 - def raw_data(self):
2.44 - # NOTE: Start simple and use single entries for most types.
2.45 - if self.value_type_name() in ("__builtins__.tuple", "__builtins__.list"):
2.46 - return [len(self.value)] + list(self.value)
2.47 - else:
2.48 - return [self.value]
2.49 -
2.50 # Support constants as dictionary keys in order to build constant tables.
2.51
2.52 def __eq__(self, other):
2.53 @@ -578,51 +551,6 @@
2.54 def __shortrepr__(self):
2.55 return "Class(%r, %s)" % (self.name, shortrepr(self.parent))
2.56
2.57 - def as_raw(self, objtable, paramtable, with_instantiator=1):
2.58 - classcode = objtable.as_list().get_code(self.full_name())
2.59 - attrcode = objtable.get_index(self.full_name())
2.60 -
2.61 - # Include a template of an instance for use when instantiating classes.
2.62 -
2.63 - call_method = self.all_class_attributes().get("__call__")
2.64 - call_method_value = call_method and call_method.get_value()
2.65 - call_method_code_location = call_method_value and call_method_value.code_location
2.66 - call_method_funccode = call_method_value and paramtable.as_list().get_code(call_method_value.full_name())
2.67 -
2.68 - instantiator_funccode = paramtable.as_list().get_code(self.get_instantiator().full_name())
2.69 -
2.70 - # NOTE: The instantiator code is the first block of the class.
2.71 -
2.72 - if not with_instantiator:
2.73 - instantiator_code_location = self.full_name()
2.74 - else:
2.75 - instantiator_code_location = self.get_instantiator().blocks[0].location
2.76 -
2.77 - return [
2.78 -
2.79 - # Template instance...
2.80 -
2.81 - DataObject(
2.82 - classcode,
2.83 - attrcode, # is instance
2.84 - call_method_code_location,
2.85 - self.full_name(),
2.86 - len(self.instance_attributes()) + 1, # size
2.87 - call_method_funccode # funccode
2.88 - ),
2.89 -
2.90 - # Class...
2.91 -
2.92 - DataObject(
2.93 - classcode,
2.94 - None, # is not instance
2.95 - instantiator_code_location,
2.96 - self.full_name(),
2.97 - len(self.class_attributes()) + 1, # size
2.98 - instantiator_funccode # funccode
2.99 - )
2.100 - ]
2.101 -
2.102 def get_body_block(self):
2.103 return self.get_instantiator().blocks[0]
2.104
2.105 @@ -995,19 +923,6 @@
2.106 self.name, shortrepr(self.parent)
2.107 )
2.108
2.109 - def as_raw(self, objtable, paramtable):
2.110 - # NOTE: Need class and parameter details! Should arguably be an instance of types.FunctionType.
2.111 - return [
2.112 - DataObject(
2.113 - objtable.as_list().get_code("__builtins__.function"),
2.114 - objtable.get_index("__builtins__.function"), # is instance
2.115 - self.code_location,
2.116 - "__builtins__.function",
2.117 - len(self.defaults) + 1, # size (not accurate for lambda functions before instantiation)
2.118 - paramtable.as_list().get_code(self.full_name()) # funccode
2.119 - )
2.120 - ]
2.121 -
2.122 def get_body_block(self):
2.123 return self.body_block
2.124
2.125 @@ -1200,17 +1115,6 @@
2.126 def __shortrepr__(self):
2.127 return "Module(%r)" % self.name
2.128
2.129 - def as_raw(self, objtable, paramtable):
2.130 - return [
2.131 - DataObject(
2.132 - objtable.as_list().get_code(self.full_name()),
2.133 - None, # modules treated like classes
2.134 - None,
2.135 - self.full_name(),
2.136 - len(self.module_attributes()) + 1 # size
2.137 - )
2.138 - ]
2.139 -
2.140 # Attribute methods.
2.141
2.142 "Return the module attribute names provided by the module."
3.1 --- a/micropython/program.py Sat Oct 10 03:09:29 2009 +0200
3.2 +++ b/micropython/program.py Sun Oct 11 02:40:20 2009 +0200
3.3 @@ -30,12 +30,6 @@
3.4 def __repr__(self):
3.5 return "Block(%r, location=%r)" % (id(self), self.location)
3.6
3.7 - def as_raw(self, objtable, paramtable):
3.8 - for i, item in enumerate(self.code):
3.9 - if hasattr(item, "location"):
3.10 - item.location = location + i
3.11 - return self.code
3.12 -
3.13 class DataValue:
3.14
3.15 "A representation of a raw program value."
3.16 @@ -45,7 +39,7 @@
3.17 self.ref = ref
3.18
3.19 def __repr__(self):
3.20 - return "%r, %r" % (
3.21 + return "value: (%r, %r)" % (
3.22 self.context, self.ref
3.23 )
3.24
3.25 @@ -68,7 +62,7 @@
3.26 return DataObject(self.classcode, self.attrcode, codeaddr, self.name, self.size, self.funccode)
3.27
3.28 def __repr__(self):
3.29 - return "%r # %s" % (
3.30 + return "object: %r # %s" % (
3.31 (self.classcode, self.attrcode, self.codeaddr, self.funccode, self.size), self.name
3.32 )
3.33
4.1 --- a/micropython/rsvp.py Sat Oct 10 03:09:29 2009 +0200
4.2 +++ b/micropython/rsvp.py Sun Oct 11 02:40:20 2009 +0200
4.3 @@ -1,7 +1,7 @@
4.4 #!/usr/bin/env python
4.5
4.6 """
4.7 -RSVP instruction classes.
4.8 +RSVP instruction and serialisation classes.
4.9
4.10 Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
4.11
4.12 @@ -19,8 +19,8 @@
4.13 this program. If not, see <http://www.gnu.org/licenses/>.
4.14 """
4.15
4.16 -from micropython.data import Attr, Const
4.17 -from micropython.program import Block
4.18 +from micropython.data import Attr, Const, Class, Function, Module
4.19 +from micropython.program import Block, DataObject, DataValue
4.20
4.21 def name(attr):
4.22 if isinstance(attr, Attr):
4.23 @@ -30,6 +30,234 @@
4.24 else:
4.25 return attr.full_name() or "<unnamed>"
4.26
4.27 +# Serialisation-related classes.
4.28 +
4.29 +class RSVPObject:
4.30 +
4.31 + "A generic data object wrapper."
4.32 +
4.33 + def __init__(self, item):
4.34 + self.item = item
4.35 +
4.36 + def set_location(self, location, with_builtins):
4.37 + self.item.location = location
4.38 + return location + 1
4.39 +
4.40 + def finalise_location(self, with_builtins):
4.41 + pass
4.42 +
4.43 + def _finalise_location(self, with_builtins):
4.44 +
4.45 + """
4.46 + Set the code body location for items now that the code blocks have been
4.47 + positioned.
4.48 + """
4.49 +
4.50 + item = self.item
4.51 +
4.52 + if not with_builtins and item.module.name == "__builtins__" and item.astnode.doc is None:
4.53 + item.code_body_location = item.full_name()
4.54 + else:
4.55 + item.code_body_location = item.get_body_block().location
4.56 +
4.57 +class RSVPAttr(RSVPObject):
4.58 +
4.59 + "A wrapper for attributes/values."
4.60 +
4.61 + def as_raw(self, objtable, paramtable, with_builtins):
4.62 + item = self.item
4.63 + return [
4.64 + DataValue(
4.65 + item.get_context() and item.get_context().location,
4.66 + item.get_value() and item.get_value().location
4.67 + )
4.68 + ]
4.69 +
4.70 +class RSVPBlock(RSVPObject):
4.71 +
4.72 + "A wrapper for blocks."
4.73 +
4.74 + def set_location(self, location, with_builtins):
4.75 + item = self.item
4.76 + item.location = location
4.77 + return location + len(item.code)
4.78 +
4.79 + def as_raw(self, objtable, paramtable, with_builtins):
4.80 + return self.item.code
4.81 +
4.82 +class RSVPClass(RSVPObject):
4.83 +
4.84 + "A wrapper for classes."
4.85 +
4.86 + def set_location(self, location, with_builtins):
4.87 + self.item.instance_template_location = location
4.88 + return RSVPObject.set_location(self, location + 1, with_builtins)
4.89 +
4.90 + def finalise_location(self, with_builtins):
4.91 + self._finalise_location(with_builtins)
4.92 +
4.93 + def as_raw(self, objtable, paramtable, with_builtins):
4.94 + item = self.item
4.95 + classcode = objtable.as_list().get_code(item.full_name())
4.96 + attrcode = objtable.get_index(item.full_name())
4.97 +
4.98 + # Include a template of an instance for use when instantiating classes.
4.99 +
4.100 + call_method = item.all_class_attributes().get("__call__")
4.101 + call_method_value = call_method and call_method.get_value()
4.102 + call_method_code_location = call_method_value and call_method_value.code_location
4.103 + call_method_funccode = call_method_value and paramtable.as_list().get_code(call_method_value.full_name())
4.104 +
4.105 + instantiator_funccode = paramtable.as_list().get_code(item.get_instantiator().full_name())
4.106 +
4.107 + # NOTE: The instantiator code is the first block of the class.
4.108 +
4.109 + with_instantiator = with_builtins or item.module.name != "__builtins__" or item.astnode.doc is not None
4.110 +
4.111 + if not with_instantiator:
4.112 + instantiator_code_location = item.full_name()
4.113 + else:
4.114 + instantiator_code_location = item.get_instantiator().blocks[0].location
4.115 +
4.116 + return [
4.117 +
4.118 + # Template instance...
4.119 +
4.120 + DataObject(
4.121 + classcode,
4.122 + attrcode, # is instance
4.123 + call_method_code_location,
4.124 + item.full_name(),
4.125 + len(item.instance_attributes()) + 1, # size
4.126 + call_method_funccode # funccode
4.127 + ),
4.128 +
4.129 + # Class...
4.130 +
4.131 + DataObject(
4.132 + classcode,
4.133 + None, # is not instance
4.134 + instantiator_code_location,
4.135 + item.full_name(),
4.136 + len(item.class_attributes()) + 1, # size
4.137 + instantiator_funccode # funccode
4.138 + )
4.139 + ]
4.140 +
4.141 +class RSVPConst(RSVPObject):
4.142 +
4.143 + "A wrapper for constants."
4.144 +
4.145 + def set_location(self, location, with_builtins):
4.146 + location = RSVPObject.set_location(self, location, with_builtins)
4.147 + return location + len(self.raw_data())
4.148 +
4.149 + def as_raw(self, objtable, paramtable, with_builtins):
4.150 + item = self.item
4.151 + # NOTE: Need class details!
4.152 + return [
4.153 + DataObject(
4.154 + objtable.as_list().get_code(item.value_type_name()),
4.155 + objtable.get_index(item.value_type_name()), # is instance
4.156 + None,
4.157 + item.value_type_name(),
4.158 + 1 # size
4.159 + )
4.160 + ] + self.raw_data()
4.161 +
4.162 + def raw_data(self):
4.163 + item = self.item
4.164 + value = item.get_value()
4.165 + # NOTE: Start simple and use single entries for most types.
4.166 + if item.value_type_name() in ("__builtins__.tuple", "__builtins__.list"):
4.167 + return [len(value)] + list(value)
4.168 + else:
4.169 + return [value]
4.170 +
4.171 +class RSVPFunction(RSVPObject):
4.172 +
4.173 + "A wrapper for functions."
4.174 +
4.175 + def set_location(self, location, with_builtins):
4.176 + item = self.item
4.177 + location = RSVPObject.set_location(self, location, with_builtins)
4.178 +
4.179 + # Set the code location only where the code has been
4.180 + # generated.
4.181 +
4.182 + if not with_builtins and item.module.name == "__builtins__" and item.astnode.doc is None:
4.183 + item.code_location = item.full_name()
4.184 +
4.185 + # Skip any defaults for named functions.
4.186 +
4.187 + elif item.name is not None:
4.188 + item.code_location = location + len(item.defaults)
4.189 +
4.190 + # Skip any defaults for lambda functions.
4.191 +
4.192 + else:
4.193 + item.code_location = location
4.194 +
4.195 + return location
4.196 +
4.197 + def finalise_location(self, with_builtins):
4.198 + self._finalise_location(with_builtins)
4.199 +
4.200 + def as_raw(self, objtable, paramtable, with_builtins):
4.201 + item = self.item
4.202 + # NOTE: Need class and parameter details! Should arguably be an instance of types.FunctionType.
4.203 + return [
4.204 + DataObject(
4.205 + objtable.as_list().get_code("__builtins__.function"),
4.206 + objtable.get_index("__builtins__.function"), # is instance
4.207 + item.code_location,
4.208 + "__builtins__.function",
4.209 + len(item.defaults) + 1, # size (not accurate for lambda functions before instantiation)
4.210 + paramtable.as_list().get_code(item.full_name()) # funccode
4.211 + )
4.212 + ]
4.213 +
4.214 +class RSVPModule(RSVPObject):
4.215 +
4.216 + "A wrapper for modules."
4.217 +
4.218 + def as_raw(self, objtable, paramtable, with_builtins):
4.219 + item = self.item
4.220 + return [
4.221 + DataObject(
4.222 + objtable.as_list().get_code(item.full_name()),
4.223 + None, # modules treated like classes
4.224 + None,
4.225 + item.full_name(),
4.226 + len(item.module_attributes()) + 1 # size
4.227 + )
4.228 + ]
4.229 +
4.230 +# Serialisation-related data and functions.
4.231 +
4.232 +def get_object(item):
4.233 + if isinstance(item, Attr):
4.234 + cls = RSVPAttr
4.235 + elif isinstance(item, Block):
4.236 + cls = RSVPBlock
4.237 + elif isinstance(item, Class):
4.238 + cls = RSVPClass
4.239 + elif isinstance(item, Const):
4.240 + cls = RSVPConst
4.241 + elif isinstance(item, Function):
4.242 + cls = RSVPFunction
4.243 + elif isinstance(item, Module):
4.244 + cls = RSVPModule
4.245 + else:
4.246 + cls = None
4.247 +
4.248 + if cls is not None:
4.249 + return cls(item)
4.250 + else:
4.251 + return None
4.252 +
4.253 +# Instruction-related classes.
4.254 +
4.255 class Instruction:
4.256
4.257 "A generic instruction."