# -*- Mode: Python -*-

# don't look, ethel!  but it was too late...

import os
import struct
import types

me = os.open ('/proc/curproc/mem', os.O_RDWR)

def read_long (addr):
    os.lseek (me, addr, 0)
    return struct.unpack ('l', os.read (me, 4))[0]

def write_long (addr, val):
    os.lseek (me, addr, 0)
    os.write (me, struct.pack ('l', val))

def INCREF (addr):
    write_long (addr, read_long (addr) + 1)

def DECREF (addr):
    n = read_long (addr)
    if n > 2:
        write_long (addr, n - 1)
    else:
        raise ValueError, "can't DECREF to zero, too risky"

#    0           4        8       12     16
# <refcnt> <tuple-type> <size> <item0> <item1> ...
#
def tuple_write_address (t, index, obj_addr):
    "write <address> to tuple <t> at <index>, return original value"
    orig_value = t[index]
    addr = id(t) + 12 + (4 * index)
    if (read_long (id (t) + 4) != id(types.TupleType)):
        raise ValueError, "not a tuple!"
    DECREF (read_long (addr))
    INCREF (obj_addr)
    write_long (addr, obj_addr)
    return orig_value

def tuple_write (t, index, object):
    "write <object> to tuple <t> at <index>, return original value"
    return tuple_write_address (t, index, id(object))

def get_object_at_address (addr):
    t = (None,)
    tuple_write_address (t, 0, addr)
    x = t[0]
    INCREF (addr)
    return x

def get_compact_methods_dict (compact_class):
    import compact_object
    if type(compact_class) != compact_object.compact_class_type:
        raise ValueError, "not a compact class"
    #    0       4         8          12
    # <refcnt> <type> <slot_names> <methods> <name>
    return get_object_at_address (id (compact_class) + 12)

if __name__ == '__main__':
    t = tuple (range (10))
    five = tuple_write (t, 5, 'hello there')
    import coro
    smd = get_compact_methods_dict (coro._semaphore_class)
