From 417bbaab5bdcd277ed4b3805be15613f82a61bdc Mon Sep 17 00:00:00 2001 From: Kui Tang Date: Sun, 17 Jul 2011 21:30:53 -0400 Subject: [PATCH] working symboltable and topsort --- flowconduit/symboltable.py | 21 +++++++++++------- flowconduit/topsort.py | 45 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 flowconduit/topsort.py diff --git a/flowconduit/symboltable.py b/flowconduit/symboltable.py index caaf783..b44096b 100644 --- a/flowconduit/symboltable.py +++ b/flowconduit/symboltable.py @@ -4,22 +4,27 @@ Based on http://code.activestate.com/recipes/577434-nested-contexts-a-chain-of-mapping-objects/ """ -from collections import Mapping +from collections import Mapping, Iterable from itertools import chain, imap class SymbolTable(dict): - def __init__(self, parent=None): + def __init__(self, parents=None): 'Create a new root context.' - self.parent = parent - self.map = {} - self.maps = [ self.map ] - if parent is not None: + self.parents = parents + self.map = {} + self.maps = [ self.map ] + if parents is not None: # Remember, it's a list of pointers. - self.maps += parent.maps + added = set() + for p in parents: + for m in p.maps: + if id(m) not in added: + added.add(id(m)) + self.maps.append(m) def new_child(self): 'Make a child context.' - return self.__class__(parent=self) + return self.__class__(parents=[ self ]) def root(self): return self if self.parent is None else self.parent.root diff --git a/flowconduit/topsort.py b/flowconduit/topsort.py new file mode 100644 index 0000000..4fa37e4 --- /dev/null +++ b/flowconduit/topsort.py @@ -0,0 +1,45 @@ +# Based on CLRS 3rd ed, 613 +# + +from itertools import chain +from functools import reduce +from collections import deque, defaultdict + +intern('gray') +intern('black') + +class TopsortState(object): + def __init__(self): + self.visited = {} + self.result = deque() + +class CycleError(Exception): pass + +def dfs(adj, state): + #verts = chain(adj.iterkeys(), *adj.itervalues()) + # TODO: Figure out the generator + verts = chain((j for i in adj.values() for j in i), adj.keys()) + for u in verts: + if u not in state.visited: dfs_visit(adj, u, state) + +def dfs_visit(adj, u, state): + state.visited[u] = 'gray' + for v in adj[u]: + if v not in state.visited: dfs_visit(adj, v, state) + elif state.visited[v] == 'gray': + raise CycleError("Cycle with edge (%s, %s) detected."%(u,v)) + state.visited[u] = 'black' + state.result.appendleft(u) + +def topsort(adj): + state = TopsortState() + dfs(adj, state) + del state.visited + return state.result + +def topsort_from_src(adj, src): + state = TopsortState() + dfs_visit(adj, src, state) + del state.visited + return state.result +