[Types-sig] a toy

Edward Welbourne Edward Welbourne <eddy@chaos.org.uk>
Wed, 9 Dec 1998 22:11:14 +0000 (GMT)


class Toy:

    def __init__(self, how):
	self.__protos__ = how

    def __getattr__(self, key):
	for col in self.__protos__:
	    try: return col(self, key)
	    except AttributeError: pass

	raise AttributeError

def toy(what, how):

    # provide our object with read-only access to what
    # under the name __datum__.
    def fetch(obj, key, dat=what):
	if key == '__datum__': return dat
	raise AttributeError, key

    how = [ fetch ] + how

    return Toy(how)

def namespace(what=None, how=[]):
    if what == None: what = {}

    def getit(obj, key, bok=what): return bok[key]
    def setit(obj, key, val, bok=what): bok[key] = val
    def delit(obj, key, bok=what): del bok[key]

    book = { '__dict__' : what,
	     # we could leave __dict__ out, of course ;^>
	     '__getattr__': getit,
	     '__setattr__': setit,
	     '__delattr__': delit }

    def bokit(obj, key, bok=book):
	try: return bok[key]
	except KeyError: raise AttributeError, key

    how = [ bokit ] + how

    return Toy(how)

def klass(what, bases, how=[]):
    row = []
    for base in bases:
	try: row.append(b.__getattr__)
	except AttributeError: pass

    return namespace(what, row + how)

def instance(C, *args):
    def getinstat(obj, key, c=C):
	val = c.__getattr__(key)
	try:
	    if not (val.im_self is None): return val
	except AttributeError: pass
	else: val.im_self = obj
	return val

    inst = namespace({}, [ getinstat ])
    try: init = inst.__init__
    except AttributeError:
	if args: raise TypeError, ('arguments given for class with no initialiser',
				   C, args)
    else:
	apply(init, (inst,) + args)

    return inst

#	Eddy.