linklist.py

Go to the documentation of this file.
00001 '''
00002 (single) linked lists. Different from python 'lists' because
00003 need real links. Want to implement mutation operations with
00004 nodes having efficient delete, splice methods:
00005    eg self.del() will use self._prev to adjust links
00006       self.splice(a,b,c,d...) will create a linked list of nodes,
00007        and use self._prev to adjust pointers
00008 
00009 Nil singleton is created by creating 1 instance of local __Nil class
00010 '''
00011 from struct import Struct
00012 
00013 class __Nil(object):
00014     'effectively, the nil object'
00015     def set_prev(self,node): pass
00016     def rm_prev(self): pass
00017     def nilp(self): return True
00018     def rm(self): pass
00019     def repl(self,*v,**kw): pass
00020     def splice(self,*v,**kw):pass
00021     def mutate(self):
00022         'nothing happens here'
00023         pass
00024     def __repr__(self): return 'Nil'
00025 
00026 class Node(object):
00027     def __init__(self,val,lst):
00028         '''like lisp "cons": takes a val and a node:
00029         returns a node = (val . lst) in lisp notation
00030         '''
00031         self.val  = val
00032         self.link = lst
00033 
00034     def __repr__(self): return 'Node(%s)' % repr(self.val)
00035     def __str__(self):  return 'Node(%s)' % str(self.val)
00036 
00037     def nilp(self):return False
00038 
00039     def set_prev(self,node):
00040         'set the _prev field of node'
00041         self._prev = node
00042 
00043     def rm_prev(self):
00044         'remove the _prev attribute from a node'
00045         del self._prev
00046 
00047     def rm(self):
00048         'remove self from the list'
00049         self._prev.link = self.link
00050     
00051     def repl(self,v):
00052         v.link = self.link
00053         self._prev.link = v
00054 
00055     def splice(self,*vals):
00056         p = self._prev
00057         l = self.link
00058         p.link = l
00059         for v in vals:
00060             nn     = Node(v,l)
00061             p.link = nn
00062             p      = nn
00063 
00064     def mutate(self,oth=None):
00065         '''expects that mutator and _prev attrs are set:
00066               applies mutator to self
00067               sets _prev.link to new self ??
00068               sets self.link._prev to new self
00069               deletes self._prev
00070         '''
00071         self.mutator(oth)
00072         self.link.set_prev(self)
00073         self.rm_prev()
00074 
00075 Nil = __Nil()
00076 
00077 class LList(object):
00078     '''creates a list head:
00079     This exists only so that mutate can be the major op of lists
00080     '''
00081     def __init__(self,*args):
00082         'create a list from a seq of args'
00083         p = self
00084         p.link = Nil
00085         for n in args:
00086             v = Node(n,Nil)
00087             p.link = v
00088             p = v
00089 
00090     def nilp(self): return self.link.nilp()
00091 
00092     @staticmethod
00093     def from_iter(iter):
00094         'create LList from single iterator'
00095         rv = LList()
00096         p  = rv
00097         for n in iter:
00098             v       = Node(n,Nil)
00099             p.link  = v
00100             p       = v
00101         return rv
00102 
00103     def __iter__(self):
00104         'LList implements next, so is self-iterating'
00105         return self.nextn()
00106     
00107     def nextn(self):
00108         '''start with 1st node of the LList, cdr down the list
00109         stop iteration is node is Nil
00110         '''
00111         p = self.link
00112         while(True):
00113             if p.nilp():
00114                 raise StopIteration
00115             yield p
00116             p = p.link
00117 
00118     def mutate(self,mutator,arg=None):
00119         '''
00120         set up the mutator (if it needs it)
00121         'cdr' down the list, mutating each node
00122         clr mutator (if it needs it)
00123         '''
00124         mutator.setup()
00125         cur = self.link
00126         if not cur.nilp():
00127             cur._prev = self
00128         while not cur.nilp():
00129             cur.mutate(arg)
00130             cur = cur.link
00131         mutator.clr()
00132 
00133     def __cdrn__(self,fn):
00134         if self.nilp(): return 'Nil'
00135 
00136         return 'LList(%s)' % ','.join([fn(n) for n in self])
00137         
00138     def __repr__(self): return self.__cdrn__(repr)
00139 
00140     def __str__(self):  return self.__cdrn__(str)
00141 
00142 import fval as fv
00143 
00144 class _LLMutator(object):
00145     def __init__(self,*a,**kw): pass
00146     def setup(self,*a,**kw): pass
00147     def clr(self,*a,**kw):   pass
00148     def mutate(self,*a,**kw) : pass
00149 
00150 def vmutate(self,arg=None):
00151     '''use the value mutating function, but pass self so that
00152     list mutating actions take place there
00153     '''
00154     if not arg: arg = Struct()
00155     arg.lines = self
00156     rv = self.val.mutate(arg)
00157     return rv
00158 
00159 class LLMutatorVal(_LLMutator):
00160     def __init__(self,vmutator,*a,**kw):
00161         self.vm    = vmutator
00162         self.vm_a  = a
00163         self.vm_kw = kw
00164 
00165     def setup(self):
00166         self.vm.setup(*self.vm_a,**self.vm_kw)
00167         Node.mutator = vmutate
00168 
00169     def clr(self):
00170         self.vm.restore(*self.vm_a,**self.vm_kw)
00171         del Node.mutator
00172 
00173 class LLMutatorTriv(_LLMutator):
00174     def __init__(self,fn):
00175         self.triv = fn
00176     def setup(self):
00177         Node.mutator = self.triv
00178     def clr(self):
00179         del Node.mutator

Generated on Wed Jan 28 02:45:34 2009 for OpenADFortTk (SourceProcessing) by  doxygen 1.5.7.1