2017-03-23 | Paul Boddie | file changeset files shortlog | Represent integers as __attr values with bit 0 set. Since pointers must be aligned (to four-byte boundaries on many modern systems, maybe two-byte boundaries on older or embedded systems, eight-byte boundaries on some 64-bit systems), any value with bit 0 set will not be referencing an object. This avoids allocating objects for integers and instead just allows them to be passed around. Bit 0 needs to be tested when attributes are accessed, and for integers, a common instance is employed to provide any instance attributes, an instance table reference and a reference to the integer class. | integers-as-tagged-attrs |
paul@503 | 1 | class C: |
paul@503 | 2 | def __init__(self): |
paul@503 | 3 | self.x = 123 |
paul@503 | 4 | |
paul@503 | 5 | def f(self): |
paul@503 | 6 | return self.x |
paul@503 | 7 | |
paul@505 | 8 | class D: |
paul@505 | 9 | pass |
paul@505 | 10 | |
paul@503 | 11 | c = C() |
paul@503 | 12 | f = C.f |
paul@503 | 13 | fn = get_using(C.f, c) |
paul@503 | 14 | print fn # __main__.C.f |
paul@503 | 15 | print fn() # 123 |
paul@505 | 16 | |
paul@503 | 17 | fn = get_using(C.f, C) |
paul@503 | 18 | print fn # __main__.C.f |
paul@503 | 19 | try: |
paul@503 | 20 | print fn() # fails |
paul@503 | 21 | except UnboundMethodInvocation: |
paul@503 | 22 | print "fn(): method is unbound" |
paul@505 | 23 | |
paul@754 | 24 | try: |
paul@754 | 25 | print f() # fails |
paul@754 | 26 | except UnboundMethodInvocation: |
paul@754 | 27 | print "f(): method is unbound" |
paul@754 | 28 | |
paul@505 | 29 | d = D() |
paul@505 | 30 | try: |
paul@505 | 31 | fn = get_using(C.f, d) |
paul@505 | 32 | except TypeError: |
paul@505 | 33 | print "get_using(C.f, d): d is not compatible with C" |
paul@505 | 34 | |
paul@505 | 35 | fn = get_using(c, C.f) |
paul@505 | 36 | print fn # <__main__.C instance> |
paul@505 | 37 | try: |
paul@505 | 38 | print fn() # fails |
paul@505 | 39 | except TypeError: |
paul@505 | 40 | print "fn(): object is not callable" |