1.1 --- a/micropython/rsvp.py Sat Oct 10 03:09:29 2009 +0200
1.2 +++ b/micropython/rsvp.py Sun Oct 11 02:40:20 2009 +0200
1.3 @@ -1,7 +1,7 @@
1.4 #!/usr/bin/env python
1.5
1.6 """
1.7 -RSVP instruction classes.
1.8 +RSVP instruction and serialisation classes.
1.9
1.10 Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
1.11
1.12 @@ -19,8 +19,8 @@
1.13 this program. If not, see <http://www.gnu.org/licenses/>.
1.14 """
1.15
1.16 -from micropython.data import Attr, Const
1.17 -from micropython.program import Block
1.18 +from micropython.data import Attr, Const, Class, Function, Module
1.19 +from micropython.program import Block, DataObject, DataValue
1.20
1.21 def name(attr):
1.22 if isinstance(attr, Attr):
1.23 @@ -30,6 +30,234 @@
1.24 else:
1.25 return attr.full_name() or "<unnamed>"
1.26
1.27 +# Serialisation-related classes.
1.28 +
1.29 +class RSVPObject:
1.30 +
1.31 + "A generic data object wrapper."
1.32 +
1.33 + def __init__(self, item):
1.34 + self.item = item
1.35 +
1.36 + def set_location(self, location, with_builtins):
1.37 + self.item.location = location
1.38 + return location + 1
1.39 +
1.40 + def finalise_location(self, with_builtins):
1.41 + pass
1.42 +
1.43 + def _finalise_location(self, with_builtins):
1.44 +
1.45 + """
1.46 + Set the code body location for items now that the code blocks have been
1.47 + positioned.
1.48 + """
1.49 +
1.50 + item = self.item
1.51 +
1.52 + if not with_builtins and item.module.name == "__builtins__" and item.astnode.doc is None:
1.53 + item.code_body_location = item.full_name()
1.54 + else:
1.55 + item.code_body_location = item.get_body_block().location
1.56 +
1.57 +class RSVPAttr(RSVPObject):
1.58 +
1.59 + "A wrapper for attributes/values."
1.60 +
1.61 + def as_raw(self, objtable, paramtable, with_builtins):
1.62 + item = self.item
1.63 + return [
1.64 + DataValue(
1.65 + item.get_context() and item.get_context().location,
1.66 + item.get_value() and item.get_value().location
1.67 + )
1.68 + ]
1.69 +
1.70 +class RSVPBlock(RSVPObject):
1.71 +
1.72 + "A wrapper for blocks."
1.73 +
1.74 + def set_location(self, location, with_builtins):
1.75 + item = self.item
1.76 + item.location = location
1.77 + return location + len(item.code)
1.78 +
1.79 + def as_raw(self, objtable, paramtable, with_builtins):
1.80 + return self.item.code
1.81 +
1.82 +class RSVPClass(RSVPObject):
1.83 +
1.84 + "A wrapper for classes."
1.85 +
1.86 + def set_location(self, location, with_builtins):
1.87 + self.item.instance_template_location = location
1.88 + return RSVPObject.set_location(self, location + 1, with_builtins)
1.89 +
1.90 + def finalise_location(self, with_builtins):
1.91 + self._finalise_location(with_builtins)
1.92 +
1.93 + def as_raw(self, objtable, paramtable, with_builtins):
1.94 + item = self.item
1.95 + classcode = objtable.as_list().get_code(item.full_name())
1.96 + attrcode = objtable.get_index(item.full_name())
1.97 +
1.98 + # Include a template of an instance for use when instantiating classes.
1.99 +
1.100 + call_method = item.all_class_attributes().get("__call__")
1.101 + call_method_value = call_method and call_method.get_value()
1.102 + call_method_code_location = call_method_value and call_method_value.code_location
1.103 + call_method_funccode = call_method_value and paramtable.as_list().get_code(call_method_value.full_name())
1.104 +
1.105 + instantiator_funccode = paramtable.as_list().get_code(item.get_instantiator().full_name())
1.106 +
1.107 + # NOTE: The instantiator code is the first block of the class.
1.108 +
1.109 + with_instantiator = with_builtins or item.module.name != "__builtins__" or item.astnode.doc is not None
1.110 +
1.111 + if not with_instantiator:
1.112 + instantiator_code_location = item.full_name()
1.113 + else:
1.114 + instantiator_code_location = item.get_instantiator().blocks[0].location
1.115 +
1.116 + return [
1.117 +
1.118 + # Template instance...
1.119 +
1.120 + DataObject(
1.121 + classcode,
1.122 + attrcode, # is instance
1.123 + call_method_code_location,
1.124 + item.full_name(),
1.125 + len(item.instance_attributes()) + 1, # size
1.126 + call_method_funccode # funccode
1.127 + ),
1.128 +
1.129 + # Class...
1.130 +
1.131 + DataObject(
1.132 + classcode,
1.133 + None, # is not instance
1.134 + instantiator_code_location,
1.135 + item.full_name(),
1.136 + len(item.class_attributes()) + 1, # size
1.137 + instantiator_funccode # funccode
1.138 + )
1.139 + ]
1.140 +
1.141 +class RSVPConst(RSVPObject):
1.142 +
1.143 + "A wrapper for constants."
1.144 +
1.145 + def set_location(self, location, with_builtins):
1.146 + location = RSVPObject.set_location(self, location, with_builtins)
1.147 + return location + len(self.raw_data())
1.148 +
1.149 + def as_raw(self, objtable, paramtable, with_builtins):
1.150 + item = self.item
1.151 + # NOTE: Need class details!
1.152 + return [
1.153 + DataObject(
1.154 + objtable.as_list().get_code(item.value_type_name()),
1.155 + objtable.get_index(item.value_type_name()), # is instance
1.156 + None,
1.157 + item.value_type_name(),
1.158 + 1 # size
1.159 + )
1.160 + ] + self.raw_data()
1.161 +
1.162 + def raw_data(self):
1.163 + item = self.item
1.164 + value = item.get_value()
1.165 + # NOTE: Start simple and use single entries for most types.
1.166 + if item.value_type_name() in ("__builtins__.tuple", "__builtins__.list"):
1.167 + return [len(value)] + list(value)
1.168 + else:
1.169 + return [value]
1.170 +
1.171 +class RSVPFunction(RSVPObject):
1.172 +
1.173 + "A wrapper for functions."
1.174 +
1.175 + def set_location(self, location, with_builtins):
1.176 + item = self.item
1.177 + location = RSVPObject.set_location(self, location, with_builtins)
1.178 +
1.179 + # Set the code location only where the code has been
1.180 + # generated.
1.181 +
1.182 + if not with_builtins and item.module.name == "__builtins__" and item.astnode.doc is None:
1.183 + item.code_location = item.full_name()
1.184 +
1.185 + # Skip any defaults for named functions.
1.186 +
1.187 + elif item.name is not None:
1.188 + item.code_location = location + len(item.defaults)
1.189 +
1.190 + # Skip any defaults for lambda functions.
1.191 +
1.192 + else:
1.193 + item.code_location = location
1.194 +
1.195 + return location
1.196 +
1.197 + def finalise_location(self, with_builtins):
1.198 + self._finalise_location(with_builtins)
1.199 +
1.200 + def as_raw(self, objtable, paramtable, with_builtins):
1.201 + item = self.item
1.202 + # NOTE: Need class and parameter details! Should arguably be an instance of types.FunctionType.
1.203 + return [
1.204 + DataObject(
1.205 + objtable.as_list().get_code("__builtins__.function"),
1.206 + objtable.get_index("__builtins__.function"), # is instance
1.207 + item.code_location,
1.208 + "__builtins__.function",
1.209 + len(item.defaults) + 1, # size (not accurate for lambda functions before instantiation)
1.210 + paramtable.as_list().get_code(item.full_name()) # funccode
1.211 + )
1.212 + ]
1.213 +
1.214 +class RSVPModule(RSVPObject):
1.215 +
1.216 + "A wrapper for modules."
1.217 +
1.218 + def as_raw(self, objtable, paramtable, with_builtins):
1.219 + item = self.item
1.220 + return [
1.221 + DataObject(
1.222 + objtable.as_list().get_code(item.full_name()),
1.223 + None, # modules treated like classes
1.224 + None,
1.225 + item.full_name(),
1.226 + len(item.module_attributes()) + 1 # size
1.227 + )
1.228 + ]
1.229 +
1.230 +# Serialisation-related data and functions.
1.231 +
1.232 +def get_object(item):
1.233 + if isinstance(item, Attr):
1.234 + cls = RSVPAttr
1.235 + elif isinstance(item, Block):
1.236 + cls = RSVPBlock
1.237 + elif isinstance(item, Class):
1.238 + cls = RSVPClass
1.239 + elif isinstance(item, Const):
1.240 + cls = RSVPConst
1.241 + elif isinstance(item, Function):
1.242 + cls = RSVPFunction
1.243 + elif isinstance(item, Module):
1.244 + cls = RSVPModule
1.245 + else:
1.246 + cls = None
1.247 +
1.248 + if cls is not None:
1.249 + return cls(item)
1.250 + else:
1.251 + return None
1.252 +
1.253 +# Instruction-related classes.
1.254 +
1.255 class Instruction:
1.256
1.257 "A generic instruction."