Enhance the Walker to call a third supplied function to actually work on a Node,...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 19 Mar 2002 16:01:59 +0000 (16:01 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 19 Mar 2002 16:01:59 +0000 (16:01 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@297 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Node/__init__.py
src/engine/SCons/Sig/__init__.py
src/engine/SCons/Taskmaster.py

index 4c54c53363865015b97e53cf6404a4bc9998c9b3..ef12c6e2adecb54b2305e29ed1880476ef0c0e39 100644 (file)
@@ -253,8 +253,9 @@ class Node:
                       self.children(),
                       1)
 
-def get_children(node): return node.children()
+def get_children(node, parent): return node.children()
 def ignore_cycle(node, stack): pass
+def do_nothing(node, parent): pass
 
 class Walker:
     """An iterator for walking a Node tree.
@@ -270,10 +271,13 @@ class Walker:
     This class does not get caught in node cycles caused, for example,
     by C header file include loops.
     """
-    def __init__(self, node, kids_func=get_children, cycle_func=ignore_cycle):
+    def __init__(self, node, kids_func=get_children,
+                             cycle_func=ignore_cycle,
+                             eval_func=do_nothing):
         self.kids_func = kids_func
         self.cycle_func = cycle_func
-        node.wkids = copy.copy(kids_func(node))
+        self.eval_func = eval_func
+        node.wkids = copy.copy(kids_func(node, None))
         self.stack = [node]
         self.history = {} # used to efficiently detect and avoid cycles
         self.history[node] = None
@@ -293,12 +297,18 @@ class Walker:
                 if self.history.has_key(node):
                     self.cycle_func(node, self.stack)
                 else:
-                    node.wkids = copy.copy(self.kids_func(node))
+                    node.wkids = copy.copy(self.kids_func(node, self.stack[-1]))
                     self.stack.append(node)
                     self.history[node] = None
             else:
                 node = self.stack.pop()
                 del self.history[node]
+                if node:
+                    if self.stack:
+                        parent = self.stack[-1]
+                    else:
+                        parent = None
+                    self.eval_func(node, parent)
                 return node
 
     def is_done(self):
index cedeb94766ec6e1b39686626ff85411f5ac17a7b..146c7c11bf4c3292d67601a2f74f9b4584311caa 100644 (file)
@@ -204,7 +204,7 @@ class Calculator:
         # derived files, because calling get_signature() on the
         # derived nodes will in turn call bsig() again and do that
         # for us.  Hence:
-        def walk_non_derived(n, myself=node):
+        def walk_non_derived(n, parent, myself=node):
             if not n.builder or n is myself:
                 return filter(lambda x, i=myself.ignore: x not in i,
                               n.all_children())
index cdee37811daca5a5e4c6f5ffeb7db15708573584..0106f46378b17594b6a64a56cb6e6560927faf81 100644 (file)
@@ -114,7 +114,7 @@ class Task:
         """
         nodes = {}
         for t in self.targets:
-            def get_parents(node): return node.get_parents()
+            def get_parents(node, parent): return node.get_parents()
             walker = SCons.Node.Walker(t, get_parents)
             while 1:
                 n = walker.next()
@@ -165,7 +165,7 @@ class Taskmaster:
 
     def __init__(self, targets=[], tasker=Task, calc=Calc()):
         
-        def out_of_date(node):
+        def out_of_date(node, parent):
             if node.get_state():
                 # The state is set, so someone has already been here
                 # (finished or currently executing).  Find another one.
@@ -182,8 +182,39 @@ class Taskmaster:
                 desc = "Dependency cycle: " + string.join(map(str, nodes), " -> ")
                 raise SCons.Errors.UserError, desc
 
-        #XXX In Python 2.2 we can get rid of f1 and f2:
-        self.walkers = map(lambda x, f1=out_of_date, f2=cycle_error: SCons.Node.Walker(x, f1, f2),
+        def eval_node(node, parent, self=self):
+            if node.get_state():
+                # The state is set, so someone has already been here
+                # (finished or currently executing).  Find another one.
+                return
+            if not node.builder:
+                # It's a source file, we don't need to build it,
+                # but mark it as "up to date" so targets won't
+                # wait for it.
+                node.set_state(SCons.Node.up_to_date)
+                # set the signature for non-derived files
+                # here so they don't get recalculated over
+                # and over again:
+                node.set_csig(self.calc.csig(node))
+                return
+            try:
+                tlist = node.builder.targets(node)
+            except AttributeError:
+                tlist = [ node ]
+            task = self.tasker(self, tlist, self.walkers[0].is_done())
+            if not tlist[0].children_are_executed():
+                for t in tlist:
+                    t.set_state(SCons.Node.pending)
+                    t.task = task
+                self.pending = self.pending + 1
+                return
+            task.make_ready()
+
+        #XXX In Python 2.2 we can get rid of f1, f2 and f3:
+        self.walkers = map(lambda x, f1=out_of_date,
+                                     f2=cycle_error,
+                                     f3=eval_node:
+                                  SCons.Node.Walker(x, f1, f2, f3),
                            targets)
         self.tasker = tasker
         self.calc = calc
@@ -209,33 +240,8 @@ class Taskmaster:
             if n == None:
                 self.walkers.pop(0)
                 continue
-            if n.get_state():
-                # The state is set, so someone has already been here
-                # (finished or currently executing).  Find another one.
-                continue
-            if not n.builder:
-                # It's a source file, we don't need to build it,
-                # but mark it as "up to date" so targets won't
-                # wait for it.
-                n.set_state(SCons.Node.up_to_date)
-                # set the signature for non-derived files
-                # here so they don't get recalculated over
-                # and over again:
-                n.set_csig(self.calc.csig(n))
-                continue
-            try:
-                tlist = n.builder.targets(n)
-            except AttributeError:
-                tlist = [ n ]
-            task = self.tasker(self, tlist, self.walkers[0].is_done())
-            if not tlist[0].children_are_executed():
-                for t in tlist:
-                    t.set_state(SCons.Node.pending)
-                    t.task = task
-                self.pending = self.pending + 1
-                continue
-            task.make_ready()
-            return
+            if self.ready:
+                return
             
     def is_blocked(self):
         return not self.ready and self.pending