# HG changeset patch # User Paul Boddie # Date 1307991540 -7200 # Node ID dced8cb98f4a3c414ea1f8a5aa9269543bfe5d3e # Parent f2f566f67b5fd1ea5644566d348012f228cdbb5a Introduced a native functions module and a generic binary operator wrapper function for primitive types, reducing the hand-written code in the RSVP library, which now uses actual RSVP instructions in some places as opposed to altering the machine's state directly. Moved various __bool__ method implementations back into the __builtins__ module. diff -r f2f566f67b5f -r dced8cb98f4a TO_DO.txt --- a/TO_DO.txt Mon Jun 13 00:18:13 2011 +0200 +++ b/TO_DO.txt Mon Jun 13 20:59:00 2011 +0200 @@ -18,6 +18,13 @@ Update docs/assignment.txt. +Prevent assignments within classes, such as method aliasing, from causing the source of an +assignment from being automatically generated. Instead, only external references should be +registered. + +Prevent "from import ..." statements from registering references to such local +aliases such that they cause the source of each alias to be automatically generated. + Consider attribute assignment observations, along with the possibility of class and module attribute assignment. diff -r f2f566f67b5f -r dced8cb98f4a lib/builtins.py --- a/lib/builtins.py Mon Jun 13 00:18:13 2011 +0200 +++ b/lib/builtins.py Mon Jun 13 20:59:00 2011 +0200 @@ -1,9 +1,7 @@ #!/usr/bin/env python """ -Simple built-in classes and functions. Objects which provide code that shall -always be compiled should provide docstrings. Objects without code should be -provided by native library code. +Simple built-in classes and functions. Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Paul Boddie @@ -19,10 +17,24 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . + +-------- + +Objects which provide code that shall always be compiled should provide +docstrings. Objects without code should be provided by native library code. + +Classes without docstrings do not have instantiators generated for them. + +Methods defined in classes are generated if they have docstrings, regardless of +whether their classes have docstrings. """ +import native + class object: - def __init__(self): pass + def __init__(self): + "No-operation." + pass def __bool__(self): pass class basestring(object): @@ -34,29 +46,57 @@ IndexError def __getslice__(self, start, end=None): pass - def __iadd__(self, other): pass - def __add__(self, other): pass - def __radd__(self, other): pass + + def __iadd__(self, other): + "Return a new string for the operation." + return _binary_op(self, other, native._str_add) + + __add__ = __radd__ = __iadd__ + def __mul__(self, other): pass def __rmul__(self, other): pass def __mod__(self, other): pass def __rmod__(self, other): pass - def __lt__(self, other): pass - def __gt__(self, other): pass - def __le__(self, other): pass - def __ge__(self, other): pass - def __eq__(self, other): pass - def __ne__(self, other): pass + + def __lt__(self, other): + "Return a new boolean for the comparison." + return _binary_op(self, other, native._str_lt) + + def __gt__(self, other): + "Return a new boolean for the comparison." + return _binary_op(self, other, native._str_gt) + + def __le__(self, other): + "Return a new boolean for the comparison." + return not self.__gt__(other) + + def __ge__(self, other): + "Return a new boolean for the comparison." + return not self.__lt__(other) + + def __eq__(self, other): + "Return a new boolean for the comparison." + return _binary_op(self, other, native._str_eq) + + def __ne__(self, other): + "Return a new boolean for the comparison." + return not self.__eq__(other) + def __len__(self): pass def __str__(self): pass - def __bool__(self): pass + + def __bool__(self): + return not native._str_eq(self, "") + def join(self, l): pass def split(self, s): pass def startswith(self, s): pass def endswith(self, s): pass class bool(object): - def __bool__(self): pass + def __bool__(self): + "Identity operation." + return self def __str__(self): pass class buffer(object): @@ -117,45 +157,112 @@ class int(object): def __init__(self, number_or_string=None): pass - def __iadd__(self, other): pass - def __isub__(self, other): pass - def __iand__(self, other): pass - def __ior__(self, other): pass - def __add__(self, other): pass - def __radd__(self, other): pass - def __sub__(self, other): pass - def __rsub__(self, other): pass - def __mul__(self, other): pass - def __rmul__(self, other): pass - def __div__(self, other): pass - def __rdiv__(self, other): pass + + def __iadd__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_add) + + def __isub__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_sub) + + def __imul__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_mul) + + def __idiv__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_div) + + def __imod__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_mod) + + def __ipow__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_pow) + + def __iand__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_and) + + def __ior__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_or) + + def __ixor__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_xor) + + __add__ = __radd__ = __iadd__ + __sub__ = __isub__ + + def __rsub__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_rsub) + + __mul__ = __rmul__ = __imul__ + __div__ = __idiv__ + + def __rdiv__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_rdiv) + def __floordiv__(self, other): pass def __rfloordiv__(self, other): pass - def __mod__(self, other): pass - def __rmod__(self, other): pass - def __pow__(self, other): pass - def __rpow__(self, other): pass - def __and__(self, other): pass - def __rand__(self, other): pass - def __or__(self, other): pass - def __ror__(self, other): pass - def __xor__(self, other): pass - def __rxor__(self, other): pass - def __lt__(self, other): pass - def __gt__(self, other): pass - def __le__(self, other): pass - def __ge__(self, other): pass - def __eq__(self, other): pass - def __ne__(self, other): pass + + __mod__ = __imod__ + + def __rmod__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_rmod) + + __pow__ = __ipow__ + + def __rpow__(self, other): + "Return a new int for the operation." + return _binary_op(self, other, native._int_rpow) + + __and__ = __rand__ = __iand__ + __or__ = __ror__ = __ior__ + __xor__ = __rxor__ = __ixor__ + + def __lt__(self, other): + "Return a new boolean for the comparison." + return _binary_op(self, other, native._int_lt) + + def __gt__(self, other): + "Return a new boolean for the comparison." + return _binary_op(self, other, native._int_gt) + + def __le__(self, other): + "Return a new boolean for the comparison." + return not self.__gt__(other) + + def __ge__(self, other): + "Return a new boolean for the comparison." + return not self.__lt__(other) + + def __eq__(self, other): + "Return a new boolean for the comparison." + return _binary_op(self, other, native._int_eq) + + def __ne__(self, other): + "Return a new boolean for the comparison." + return not self.__eq__(other) + def __neg__(self): pass def __pos__(self): pass def __str__(self): pass - def __bool__(self): pass def __lshift__(self): pass def __rlshift__(self): pass def __rshift__(self): pass def __rrshift__(self): pass + def __bool__(self): + "Return whether this int is non-zero." + return not native._int_eq(self, 0) + class list(object): "Implementation of list." @@ -557,6 +664,15 @@ # Utility functions. +def _binary_op(self, other, op): + + "Test the type of 'other' and perform 'op'." + + if self.__class__ is other.__class__: + return op(self, other) + else: + return NotImplemented + def _get_absolute_index(index, length): """ diff -r f2f566f67b5f -r dced8cb98f4a lib/native.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/native.py Mon Jun 13 20:59:00 2011 +0200 @@ -0,0 +1,46 @@ +#!/usr/bin/env python + +""" +Native library functions. + +Copyright (C) 2011 Paul Boddie + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +""" + +def _int_add(self, other): pass +def _int_sub(self, other): pass +def _int_mul(self, other): pass +def _int_div(self, other): pass +def _int_mod(self, other): pass +def _int_pow(self, other): pass +def _int_and(self, other): pass +def _int_or(self, other): pass +def _int_xor(self, other): pass + +def _int_rsub(self, other): pass +def _int_rdiv(self, other): pass +def _int_rmod(self, other): pass +def _int_rpow(self, other): pass + +def _int_lt(self, other): pass +def _int_gt(self, other): pass +def _int_eq(self, other): pass + +def _str_add(self, other): pass +def _str_lt(self, other): pass +def _str_gt(self, other): pass +def _str_eq(self, other): pass + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r f2f566f67b5f -r dced8cb98f4a micropython/__init__.py --- a/micropython/__init__.py Mon Jun 13 00:18:13 2011 +0200 +++ b/micropython/__init__.py Mon Jun 13 20:59:00 2011 +0200 @@ -125,7 +125,7 @@ last_module = self.importer.modules_ordered[-1] for module in self.importer.modules_ordered: - suppress_builtins = not with_builtins and module.name == "__builtins__" + suppress_builtins = not with_builtins and module.name in ("__builtins__", "native") # Position the module in the image and make a translation. @@ -249,7 +249,7 @@ for module in self.importer.modules_ordered: - if not with_builtins and module.name == "__builtins__": + if not with_builtins and module.name in ("__builtins__", "native"): continue module.code_location = module.blocks[0].location diff -r f2f566f67b5f -r dced8cb98f4a micropython/inspect.py --- a/micropython/inspect.py Mon Jun 13 00:18:13 2011 +0200 +++ b/micropython/inspect.py Mon Jun 13 20:59:00 2011 +0200 @@ -654,8 +654,11 @@ self.define_attribute_user(node) # Ensure the presence of the given name in this namespace. + # NOTE: Consider not registering assignments involving methods, since + # NOTE: this is merely creating aliases for such methods. self.use_specific_attribute(None, node.name) + return None visitAssTuple = visitAssList diff -r f2f566f67b5f -r dced8cb98f4a micropython/raw.py --- a/micropython/raw.py Mon Jun 13 00:18:13 2011 +0200 +++ b/micropython/raw.py Mon Jun 13 20:59:00 2011 +0200 @@ -34,7 +34,7 @@ pass def is_generated(self, with_builtins): - return with_builtins or self.item.module.name != "__builtins__" or self.item.astnode.doc is not None + return with_builtins or self.item.module.name not in ("__builtins__", "native") or self.item.astnode.doc is not None class UntranslatableInstruction(Exception): pass diff -r f2f566f67b5f -r dced8cb98f4a rsvplib.py --- a/rsvplib.py Mon Jun 13 00:18:13 2011 +0200 +++ b/rsvplib.py Mon Jun 13 20:59:00 2011 +0200 @@ -69,25 +69,16 @@ def _check_index(self, pos, nelements): return pos >= 0 and pos < nelements - def builtins_int_arithmetic_op(self, op): - frame = self.local_sp_stack[-1] + # Native functionality. - # Get operands addresses. - - left_value = self.frame_stack[frame] - right_value = self.frame_stack[frame + 1] + def builtins_no_op(self): + pass - # Test operand suitability. - # NOTE: Support other types. - - if not (self.machine._CheckInstance(left_value.ref, self.int_class) and - self.machine._CheckInstance(right_value.ref, self.int_class)): - - self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance) - return self.machine.RaiseException() - - left_data = left_value.ref + self.instance_data_offset - right_data = right_value.ref + self.instance_data_offset + def native_int_arithmetic_op(self, op): + self.machine.LoadName(0) # left value + left_data = self.machine.value + self.instance_data_offset + self.machine.LoadName(1) # right value + right_data = self.machine.value + self.instance_data_offset # Make a new object. @@ -104,28 +95,11 @@ self.machine.result_context = addr self.machine.result_value = addr - def builtins_logical_op(self, operand_class, op): - frame = self.local_sp_stack[-1] - - # Get operands addresses. - - left_value = self.frame_stack[frame] - right_value = self.frame_stack[frame + 1] - - # Test operand suitability. - # NOTE: Handle comparisons of incompatible types more appropriately. - # NOTE: Return NotImplemented. - - if not (self.machine._CheckInstance(left_value.ref, operand_class) and - self.machine._CheckInstance(right_value.ref, operand_class)): - - notimpl = self.constants[NotImplemented] - self.machine.result_context = notimpl - self.machine.result_value = notimpl - return - - left_data = left_value.ref + self.instance_data_offset - right_data = right_value.ref + self.instance_data_offset + def native_logical_op(self, op): + self.machine.LoadName(0) # left value + left_data = self.machine.value + self.instance_data_offset + self.machine.LoadName(1) # right value + right_data = self.machine.value + self.instance_data_offset # Test the data. # NOTE: The data is considered ready to use. @@ -142,98 +116,44 @@ # still performed on the operands to ensure that they qualify for these # native operations. - def builtins_int_add(self): - return self.builtins_int_arithmetic_op(operator.add) - - def builtins_int_sub(self): - return self.builtins_int_arithmetic_op(operator.sub) + def native_int_add(self): + return self.native_int_arithmetic_op(operator.add) - def builtins_int_pow(self): - return self.builtins_int_arithmetic_op(operator.pow) - - def builtins_int_lt(self): - return self.builtins_logical_op(self.int_class, operator.lt) + def native_int_sub(self): + return self.native_int_arithmetic_op(operator.sub) - def builtins_int_le(self): - return self.builtins_logical_op(self.int_class, operator.le) - - def builtins_int_gt(self): - return self.builtins_logical_op(self.int_class, operator.gt) + def native_int_pow(self): + return self.native_int_arithmetic_op(operator.pow) - def builtins_int_ge(self): - return self.builtins_logical_op(self.int_class, operator.ge) + def native_int_and(self): + return self.native_int_arithmetic_op(operator.and_) - def builtins_int_eq(self): - return self.builtins_logical_op(self.int_class, operator.eq) + def native_int_or(self): + return self.native_int_arithmetic_op(operator.or_) - def builtins_int_ne(self): - return self.builtins_logical_op(self.int_class, operator.ne) - - def builtins_str_lt(self): - return self.builtins_logical_op(self.str_class, operator.lt) + def native_int_lt(self): + return self.native_logical_op(operator.lt) - def builtins_str_le(self): - return self.builtins_logical_op(self.str_class, operator.le) + def native_int_gt(self): + return self.native_logical_op(operator.gt) - def builtins_str_gt(self): - return self.builtins_logical_op(self.str_class, operator.gt) + def native_int_eq(self): + return self.native_logical_op(operator.eq) - def builtins_str_ge(self): - return self.builtins_logical_op(self.str_class, operator.ge) - - def builtins_str_eq(self): - return self.builtins_logical_op(self.str_class, operator.eq) + def native_str_lt(self): + return self.native_logical_op(operator.lt) - def builtins_str_ne(self): - return self.builtins_logical_op(self.str_class, operator.ne) + def native_str_gt(self): + return self.native_logical_op(operator.gt) - def builtins_int_and(self): - return self.builtins_int_arithmetic_op(operator.and_) - - def builtins_int_or(self): - return self.builtins_int_arithmetic_op(operator.or_) + def native_str_eq(self): + return self.native_logical_op(operator.eq) # Specific operator methods. - def builtins_int_bool(self): - frame = self.local_sp_stack[-1] - - # Get operands addresses. - - left_value = self.frame_stack[frame] - - # Test operand suitability. - - if not self.machine._CheckInstance(left_value.ref, self.int_class): - self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance) - return self.machine.RaiseException() - - left_data = left_value.ref + self.instance_data_offset - - # Test the data. - # NOTE: The data is considered ready to use. - - if self.machine.load(left_data) != 0: - self.machine.result_context = self.constants[True] - self.machine.result_value = self.constants[True] - else: - self.machine.result_context = self.constants[False] - self.machine.result_value = self.constants[False] - def builtins_int_neg(self): - frame = self.local_sp_stack[-1] - - # Get operands addresses. - - left_value = self.frame_stack[frame] - - # Test operand suitability. - - if not self.machine._CheckInstance(left_value.ref, self.int_class): - self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance) - return self.machine.RaiseException() - - left_data = left_value.ref + self.instance_data_offset + self.machine.LoadName(0) # left value + left_data = self.machine.value + self.instance_data_offset # Make a new object. @@ -252,15 +172,6 @@ # Various built-in methods. - def builtins_bool_bool(self): - frame = self.local_sp_stack[-1] - - # Get operands addresses. - - left_value = self.frame_stack[frame] - self.machine.result_context = left_value.ref - self.machine.result_value = left_value.ref - def builtins_list_new(self): frame = self.local_sp_stack[-1] @@ -502,9 +413,6 @@ self.machine.result_context = data.context self.machine.result_value = data.ref - def builtins_object_init(self): - pass - def builtins_getattr(self): frame = self.local_sp_stack[-1] @@ -569,30 +477,18 @@ # Native method implementations: - "__builtins__.basestring.__lt__" : builtins_str_lt, - "__builtins__.basestring.__le__" : builtins_str_le, - "__builtins__.basestring.__gt__" : builtins_str_gt, - "__builtins__.basestring.__ge__" : builtins_str_ge, - "__builtins__.basestring.__eq__" : builtins_str_eq, - "__builtins__.basestring.__ne__" : builtins_str_ne, - "__builtins__.bool.__bool__" : builtins_bool_bool, - "__builtins__.int.__add__" : builtins_int_add, - "__builtins__.int.__radd__" : builtins_int_add, # NOTE: To be made distinct. - "__builtins__.int.__sub__" : builtins_int_sub, - "__builtins__.int.__pow__" : builtins_int_pow, - "__builtins__.int.__iadd__" : builtins_int_add, - "__builtins__.int.__bool__" : builtins_int_bool, + "native._int_add" : native_int_add, + "native._int_sub" : native_int_sub, + "native._int_pow" : native_int_pow, + "native._int_and" : native_int_and, + "native._int_or" : native_int_or, + "native._int_lt" : native_int_lt, + "native._int_gt" : native_int_gt, + "native._int_eq" : native_int_eq, + "native._str_lt" : native_str_lt, + "native._str_gt" : native_str_gt, + "native._str_eq" : native_str_eq, "__builtins__.int.__neg__" : builtins_int_neg, - "__builtins__.int.__lt__" : builtins_int_lt, - "__builtins__.int.__le__" : builtins_int_le, - "__builtins__.int.__gt__" : builtins_int_gt, - "__builtins__.int.__ge__" : builtins_int_ge, - "__builtins__.int.__eq__" : builtins_int_eq, - "__builtins__.int.__ne__" : builtins_int_ne, - "__builtins__.int.__and__" : builtins_int_and, - "__builtins__.int.__rand__" : builtins_int_and, - "__builtins__.int.__or__" : builtins_int_or, - "__builtins__.int.__ror__" : builtins_int_or, "__builtins__.list.__get_single_item__" : builtins_list_get_single_item, "__builtins__.list.__len__" : builtins_list_len, "__builtins__.list.append" : builtins_list_append, @@ -602,8 +498,7 @@ # Native initialisers: - "__builtins__.object.__init__" : builtins_object_init, # NOTE: A no-operation. - "__builtins__.BaseException.__init__" : builtins_object_init, # NOTE: To be made distinct, potentially in the builtins module. + "__builtins__.BaseException.__init__" : builtins_no_op, # NOTE: To be made distinct, potentially in the builtins module. # Native functions: