KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > frontend > AbstractExtensionInfo


1 package polyglot.frontend;
2
3 import polyglot.ast.*;
4 import polyglot.types.*;
5 import polyglot.util.*;
6 import polyglot.visit.*;
7 import polyglot.main.Options;
8 import polyglot.main.Report;
9
10 import java.io.*;
11 import java.util.*;
12
13 /**
14  * This is an abstract <code>ExtensionInfo</code>.
15  */

16 public abstract class AbstractExtensionInfo implements ExtensionInfo {
17     protected Compiler JavaDoc compiler;
18     private Options options;
19     protected TypeSystem ts = null;
20     protected NodeFactory nf = null;
21     protected SourceLoader source_loader = null;
22     protected TargetFactory target_factory = null;
23     protected Stats stats;
24
25     /**
26      * A list of all active (that is, uncompleted) <code>SourceJob</code>s.
27      */

28     protected LinkedList worklist;
29
30     /**
31      * A map from <code>Source</code>s to <code>SourceJob</code>s or to
32      * the <code>COMPLETED_JOB</code> object if the SourceJob previously existed
33      * but has now finished. The map contains entries for all
34      * <code>Source</code>s that have had <code>Job</code>s added for them.
35      */

36     protected Map jobs;
37
38     protected static final Object JavaDoc COMPLETED_JOB = "COMPLETED JOB";
39
40     /** The currently running job, or null if no job is running. */
41     protected Job currentJob;
42
43     public Options getOptions() {
44         if (this.options == null) {
45             this.options = createOptions();
46         }
47         return options;
48     }
49
50     protected Options createOptions() {
51         return new Options(this);
52     }
53
54     /** Return a Stats object to accumulate and report statistics. */
55     public Stats getStats() {
56         if (this.stats == null) {
57             this.stats = new Stats(this);
58         }
59         return stats;
60     }
61
62     public Compiler JavaDoc compiler() {
63         return compiler;
64     }
65
66     public void initCompiler(Compiler JavaDoc compiler) {
67     this.compiler = compiler;
68         jobs = new HashMap();
69         worklist = new LinkedList();
70
71         // Register the extension with the compiler.
72
compiler.addExtension(this);
73
74         currentJob = null;
75
76         // Create the type system and node factory.
77
typeSystem();
78         nodeFactory();
79
80         initTypeSystem();
81     }
82
83     protected abstract void initTypeSystem();
84
85     /**
86      * Run all jobs in the work list (and any children they have) to
87      * completion. This method returns <code>true</code> if all jobs were
88      * successfully completed. If all jobs were successfully completed, then
89      * the worklist will be empty.
90      *
91      * The scheduling of <code>Job</code>s uses two methods to maintain
92      * scheduling invariants: <code>selectJobFromWorklist</code> selects
93      * a <code>SourceJob</code> from <code>worklist</code> (a list of
94      * jobs that still need to be processed); <code>enforceInvariants</code> is
95      * called before a pass is performed on a <code>SourceJob</code> and is
96      * responsible for ensuring all dependencies are satisfied before the
97      * pass proceeds, i.e. enforcing any scheduling invariants.
98      */

99     public boolean runToCompletion() {
100         boolean okay = true;
101
102         while (okay && ! worklist.isEmpty()) {
103             SourceJob job = selectJobFromWorklist();
104
105             if (Report.should_report(Report.frontend, 1)) {
106         Report.report(1, "Running job " + job);
107             }
108
109             okay &= runAllPasses(job);
110
111             if (job.completed()) {
112                 // the job has finished. Let's remove it from the map so it
113
// can be garbage collected, and free up the AST.
114
jobs.put(job.source(), COMPLETED_JOB);
115
116                 if (Report.should_report(Report.frontend, 1)) {
117                     Report.report(1, "Completed job " + job);
118                 }
119             }
120             else {
121                 // the job is not yet completed (although, it really
122
// should be...)
123
if (Report.should_report(Report.frontend, 1)) {
124                     Report.report(1, "Failed to complete job " + job);
125                 }
126                 worklist.add(job);
127             }
128         }
129
130         if (Report.should_report(Report.frontend, 1))
131         Report.report(1, "Finished all passes -- " +
132                         (okay ? "okay" : "failed"));
133
134         return okay;
135     }
136
137     /**
138      * Select and remove a <code>SourceJob</code> from the non-empty
139      * <code>worklist</code>. Return the selected <code>SourceJob</code>
140      * which will be scheduled to run all of its remaining passes.
141      */

142     protected SourceJob selectJobFromWorklist() {
143         return (SourceJob)worklist.remove(0);
144     }
145
146     /**
147      * Read a source file and compile it up to the the current job's last
148      * barrier.
149      */

150     public boolean readSource(FileSource source) {
151         // Add a new SourceJob for the given source. If a Job for the source
152
// already exists, then we will be given the existing job.
153
SourceJob job = addJob(source);
154
155         if (job == null) {
156             // addJob returns null if the job has already been completed, in
157
// which case we can just ignore the request to read in the source.
158
return true;
159         }
160
161         // Run the new job up to the currentJob's SourceJob's last barrier, to
162
// make sure that dependencies are satisfied.
163
Pass.ID barrier;
164
165         if (currentJob != null) {
166             if (currentJob.sourceJob().lastBarrier() == null) {
167                 throw new InternalCompilerError("A Source Job which has " +
168                             "not reached a barrier cannot read another " +
169                             "source file.");
170             }
171
172             barrier = currentJob.sourceJob().lastBarrier().id();
173         }
174         else {
175             barrier = Pass.FIRST_BARRIER;
176         }
177
178         // Make sure we reach at least the first barrier defined
179
// in the base compiler. This forces types to be constructed.
180
// If FIRST_BARRIER is before "barrier",
181
// then the second runToPass will just return true.
182
return runToPass(job, barrier) && runToPass(job, Pass.FIRST_BARRIER);
183     }
184
185     /**
186      * Run all pending passes on <code>job</code>.
187      */

188     public boolean runAllPasses(Job job) {
189         List pending = job.pendingPasses();
190
191         // Run until there are no more passes.
192
if (!pending.isEmpty()) {
193             Pass lastPass = (Pass)pending.get(pending.size() - 1);
194             return runToPass(job, lastPass);
195         }
196
197         return true;
198     }
199
200     /**
201      * Run a job until the <code>goal</code> pass completes.
202      */

203     public boolean runToPass(Job job, Pass.ID goal) {
204         if (Report.should_report(Report.frontend, 1))
205             Report.report(1, "Running " + job + " to pass named " + goal);
206
207         if (job.completed(goal)) {
208             return true;
209         }
210
211         Pass pass = job.passByID(goal);
212
213         return runToPass(job, pass);
214     }
215
216     /**
217      * Run a job up to the <code>goal</code> pass.
218      */

219     public boolean runToPass(Job job, Pass goal) {
220         if (Report.should_report(Report.frontend, 1))
221         Report.report(1, "Running " + job + " to pass " + goal);
222
223         while (! job.pendingPasses().isEmpty()) {
224             Pass pass = (Pass) job.pendingPasses().get(0);
225
226             try {
227                 runPass(job, pass);
228             }
229             catch (CyclicDependencyException e) {
230                 // cause the pass to fail.
231
job.finishPass(pass, false);
232             }
233
234             if (pass == goal) {
235                 break;
236             }
237         }
238
239         if (job.completed()) {
240             if (Report.should_report(Report.frontend, 1))
241                 Report.report(1, "Job " + job + " completed");
242         }
243
244         return job.status();
245     }
246
247     /**
248      * Run the pass <code>pass</code> on the job. Before running the pass on
249      * the job, if the job is a <code>SourceJob</code>, then this method will
250      * ensure that the scheduling invariants are enforced by calling
251      * <code>enforceInvariants</code>.
252      */

253     protected void runPass(Job job, Pass pass) throws CyclicDependencyException
254     {
255         // make sure that all scheduling invariants are satisfied before running
256
// the next pass. We may thus execute some other passes on other
257
// jobs running the given pass.
258
try {
259             enforceInvariants(job, pass);
260         }
261         catch (CyclicDependencyException e) {
262             // A job that depends on this job is still running
263
// an earlier pass. We cannot continue this pass,
264
// but we can just silently fail since the job we're
265
// that depends on this one will eventually try
266
// to run this pass again when it reaches a barrier.
267
return;
268         }
269
270         if (getOptions().disable_passes.contains(pass.name())) {
271             if (Report.should_report(Report.frontend, 1))
272                 Report.report(1, "Skipping pass " + pass);
273             job.finishPass(pass, true);
274             return;
275         }
276
277         if (Report.should_report(Report.frontend, 1))
278             Report.report(1, "Trying to run pass " + pass + " in " + job);
279
280         if (job.isRunning()) {
281             // We're currently running. We can't reach the goal.
282
throw new CyclicDependencyException(job +
283                                             " cannot reach pass " +
284                                             pass);
285         }
286
287         pass.resetTimers();
288
289         boolean result = false;
290         if (job.status()) {
291             Job oldCurrentJob = this.currentJob;
292             this.currentJob = job;
293             Report.should_report.push(pass.name());
294
295             // Stop the timer on the old pass. */
296
Pass oldPass = oldCurrentJob != null
297                          ? oldCurrentJob.runningPass()
298                          : null;
299
300             if (oldPass != null) {
301                 oldPass.toggleTimers(true);
302             }
303
304             job.setRunningPass(pass);
305             pass.toggleTimers(false);
306
307             result = pass.run();
308
309             pass.toggleTimers(false);
310             job.setRunningPass(null);
311
312             Report.should_report.pop();
313             this.currentJob = oldCurrentJob;
314
315             // Restart the timer on the old pass. */
316
if (oldPass != null) {
317                 oldPass.toggleTimers(true);
318             }
319
320             // pretty-print this pass if we need to.
321
if (getOptions().print_ast.contains(pass.name())) {
322                 System.err.println("--------------------------------" +
323                                    "--------------------------------");
324                 System.err.println("Pretty-printing AST for " + job +
325                                    " after " + pass.name());
326
327                 PrettyPrinter pp = new PrettyPrinter();
328                 pp.printAst(job.ast(), new CodeWriter(System.err, 78));
329             }
330
331             // dump this pass if we need to.
332
if (getOptions().dump_ast.contains(pass.name())) {
333                 System.err.println("--------------------------------" +
334                                    "--------------------------------");
335                 System.err.println("Dumping AST for " + job +
336                                    " after " + pass.name());
337
338         NodeVisitor dumper =
339           new DumpAst(new CodeWriter(System.err, 78));
340         dumper = dumper.begin();
341         job.ast().visit(dumper);
342         dumper.finish();
343             }
344
345             // This seems to work around a VM bug on linux with JDK
346
// 1.4.0. The mark-sweep collector will sometimes crash.
347
// Running the GC explicitly here makes the bug go away.
348
// If this fails, maybe run with bigger heap.
349

350             // System.gc();
351
}
352
353         Stats stats = getStats();
354         stats.accumPassTimes(pass.id(), pass.inclusiveTime(),
355                              pass.exclusiveTime());
356
357         if (Report.should_report(Report.time, 2)) {
358             Report.report(2, "Finished " + pass +
359                           " status=" + str(result) + " inclusive_time=" +
360                           pass.inclusiveTime() + " exclusive_time=" +
361                           pass.exclusiveTime());
362         }
363         else if (Report.should_report(Report.frontend, 1)) {
364             Report.report(1, "Finished " + pass +
365                           " status=" + str(result));
366         }
367
368         job.finishPass(pass, result);
369     }
370
371     /**
372      * Before running <code>Pass pass</code> on <code>SourceJob job</code>
373      * make sure that all appropriate scheduling invariants are satisfied,
374      * to ensure that all passes of other jobs that <code>job</code> depends
375      * on will have already been done.
376      *
377      */

378     protected void enforceInvariants(Job job, Pass pass) throws CyclicDependencyException {
379         SourceJob srcJob = job.sourceJob();
380         if (srcJob == null) {
381             return;
382         }
383
384         BarrierPass lastBarrier = srcJob.lastBarrier();
385         if (lastBarrier != null) {
386             // make sure that _all_ dependent jobs have completed at least up to
387
// the last barrier (not just children).
388
//
389
// Ideally the invariant should be that only the source jobs that
390
// job _depends on_ should be brought up to the last barrier.
391
// This is work to be done in the future...
392
List allDependentSrcs = new ArrayList(srcJob.dependencies());
393             Iterator i = allDependentSrcs.iterator();
394             while (i.hasNext()) {
395                 Source s = (Source)i.next();
396                 Object JavaDoc o = jobs.get(s);
397                 if (o == COMPLETED_JOB) continue;
398                 if (o == null) {
399                     throw new InternalCompilerError("Unknown source " + s);
400                 }
401                 SourceJob sj = (SourceJob)o;
402                 if (sj.pending(lastBarrier.id())) {
403                     // Make the job run up to the last barrier.
404
// We ignore the return result, since even if the job
405
// fails, we will keep on going and see
406
// how far we get...
407
if (Report.should_report(Report.frontend, 3)) {
408                         Report.report(3, "Running " + sj +
409                                   " to " + lastBarrier.id() + " for " + srcJob);
410                     }
411                     runToPass(sj, lastBarrier.id());
412                 }
413             }
414         }
415
416         if (pass instanceof GlobalBarrierPass) {
417             // need to make sure that _all_ jobs have completed just up to
418
// this global barrier.
419

420             // If we hit a cyclic dependency, ignore it and run the other
421
// jobs up to that pass. Then try again to run the cyclic
422
// pass. If we hit the cycle again for the same job, stop.
423
LinkedList barrierWorklist = new LinkedList(jobs.values());
424
425             while (! barrierWorklist.isEmpty()) {
426                 Object JavaDoc o = barrierWorklist.removeFirst();
427                 if (o == COMPLETED_JOB) continue;
428                 SourceJob sj = (SourceJob)o;
429                 if (sj.completed(pass.id()) ||
430                     sj.nextPass() == sj.passByID(pass.id())) {
431                     // the source job has either done this global pass
432
// (which is possible if the job was loaded late in the
433
// game), or is right up to the global barrier.
434
continue;
435                 }
436
437                 // Make the job run up to just before the global barrier.
438
// We ignore the return result, since even if the job
439
// fails, we will keep on going and see
440
// how far we get...
441
Pass beforeGlobal = sj.getPreviousTo(pass.id());
442                 if (Report.should_report(Report.frontend, 3)) {
443                     Report.report(3, "Running " + sj +
444                               " to " + beforeGlobal.id() + " for " + srcJob);
445                 }
446
447                 // Don't use runToPass, since that catches the
448
// CyclicDependencyException that we should report
449
// back to the caller.
450
while (! sj.pendingPasses().isEmpty()) {
451                     Pass p = (Pass) sj.pendingPasses().get(0);
452
453                     runPass(sj, p);
454
455                     if (p == beforeGlobal) {
456                         break;
457                     }
458                 }
459             }
460         }
461     }
462
463     private static String JavaDoc str(boolean okay) {
464         if (okay) {
465             return "done";
466         }
467         else {
468             return "failed";
469         }
470     }
471
472     /**
473      * Get the file name extension of source files. This is
474      * either the language extension's default file name extension
475      * or the string passed in with the "-sx" command-line option.
476      */

477     public String JavaDoc[] fileExtensions() {
478     String JavaDoc[] sx = getOptions() == null ? null : getOptions().source_ext;
479
480     if (sx == null) {
481         sx = defaultFileExtensions();
482         }
483
484         if (sx.length == 0) {
485             return defaultFileExtensions();
486         }
487
488         return sx;
489     }
490
491     /** Get the default list of file extensions. */
492     public String JavaDoc[] defaultFileExtensions() {
493         String JavaDoc ext = defaultFileExtension();
494         return new String JavaDoc[] { ext };
495     }
496
497     /** Get the source file loader object for this extension. */
498     public SourceLoader sourceLoader() {
499         if (source_loader == null) {
500             source_loader = new SourceLoader(this, getOptions().source_path);
501         }
502
503         return source_loader;
504     }
505
506     /** Get the target factory object for this extension. */
507     public TargetFactory targetFactory() {
508         if (target_factory == null) {
509             target_factory = new TargetFactory(getOptions().output_directory,
510                                                getOptions().output_ext,
511                                                getOptions().output_stdout);
512         }
513
514         return target_factory;
515     }
516
517     /** Create the type system for this extension. */
518     protected abstract TypeSystem createTypeSystem();
519
520     /** Get the type system for this extension. */
521     public TypeSystem typeSystem() {
522     if (ts == null) {
523         ts = createTypeSystem();
524     }
525     return ts;
526     }
527
528     /** Create the node factory for this extension. */
529     protected abstract NodeFactory createNodeFactory();
530
531     /** Get the AST node factory for this extension. */
532     public NodeFactory nodeFactory() {
533     if (nf == null) {
534         nf = createNodeFactory();
535     }
536     return nf;
537     }
538
539     /**
540      * Get the job extension for this language extension. The job
541      * extension is used to extend the <code>Job</code> class
542      * without subtyping.
543      */

544     public JobExt jobExt() {
545       return null;
546     }
547
548     /**
549      * Adds a dependency from the current job to the given Source.
550      */

551     public void addDependencyToCurrentJob(Source s) {
552         if (s == null)
553             return;
554         if (currentJob != null) {
555             Object JavaDoc o = jobs.get(s);
556             if (o != COMPLETED_JOB) {
557                 if (Report.should_report(Report.frontend, 2)) {
558                     Report.report(2, "Adding dependency from " +
559                             currentJob.source() + " to " +
560                             s);
561                 }
562                 currentJob.sourceJob().addDependency(s);
563             }
564         }
565         else {
566             throw new InternalCompilerError("No current job!");
567         }
568     }
569
570     /**
571      * Add a new <code>SourceJob</code> for the <code>Source source</code>.
572      * A new job will be created if
573      * needed. If the <code>Source source</code> has already been processed,
574      * and its job discarded to release resources, then <code>null</code>
575      * will be returned.
576      */

577     public SourceJob addJob(Source source) {
578         return addJob(source, null);
579     }
580
581     /**
582      * Add a new <code>SourceJob</code> for the <code>Source source</code>,
583      * with AST <code>ast</code>.
584      * A new job will be created if
585      * needed. If the <code>Source source</code> has already been processed,
586      * and its job discarded to release resources, then <code>null</code>
587      * will be returned.
588      */

589     public SourceJob addJob(Source source, Node ast) {
590         Object JavaDoc o = jobs.get(source);
591         SourceJob job = null;
592         if (o == COMPLETED_JOB) {
593             // the job has already been completed.
594
// We don't need to add a job
595
return null;
596         }
597         else if (o == null) {
598             // No appropriate job yet exists, we will create one.
599

600             job = this.createSourceJob(source, ast);
601
602             // record the job in the map and the worklist.
603
jobs.put(source, job);
604             worklist.addLast(job);
605
606             if (Report.should_report(Report.frontend, 3)) {
607                 Report.report(3, "Adding job for " + source + " at the " +
608                     "request of job " + currentJob);
609             }
610         }
611         else {
612             job = (SourceJob)o;
613         }
614
615         // if the current source job caused this job to load, record the
616
// dependency.
617
if (currentJob instanceof SourceJob) {
618            ((SourceJob)currentJob).addDependency(source);
619         }
620
621         return job;
622     }
623
624     /**
625      * Create a new <code>SourceJob</code> for the given source and AST.
626      * In general, this method should only be called by <code>addJob</code>.
627      */

628     protected SourceJob createSourceJob(Source source, Node ast) {
629         return new SourceJob(this, jobExt(), source, ast);
630     }
631
632     /**
633      * Create a new non-<code>SourceJob</code> <code>Job</code>, for the
634      * given AST. In general this method should only be called by
635      * <code>spawnJob</code>.
636      *
637      * @param ast the AST the new Job is for.
638      * @param context the context that the AST occurs in
639      * @param outer the <code>Job</code> that spawned this job.
640      * @param begin the first pass to perform for this job.
641      * @param end the last pass to perform for this job.
642      */

643     protected Job createJob(Node ast, Context context, Job outer, Pass.ID begin, Pass.ID end) {
644     return new InnerJob(this, jobExt(), ast, context, outer, begin, end);
645     }
646
647     /**
648      * Spawn a new job. All passes between the pass <code>begin</code>
649      * and <code>end</code> inclusive will be performed immediately on
650      * the AST <code>ast</code>.
651      *
652      * @param c the context that the AST occurs in
653      * @param ast the AST the new Job is for.
654      * @param outerJob the <code>Job</code> that spawned this job.
655      * @param begin the first pass to perform for this job.
656      * @param end the last pass to perform for this job.
657      * @return the new job. The caller can check the result with
658      * <code>j.status()</code> and get the ast with <code>j.ast()</code>.
659      */

660     public Job spawnJob(Context c, Node ast, Job outerJob,
661                            Pass.ID begin, Pass.ID end) {
662         Job j = createJob(ast, c, outerJob, begin, end);
663
664         if (Report.should_report(Report.frontend, 1))
665             Report.report(1, this +" spawning " + j);
666
667         // Run all the passes
668
runAllPasses(j);
669
670         // Return the job. The caller can check the result with j.status().
671
return j;
672     }
673
674     /** Get the parser for this language extension. */
675     public abstract Parser parser(Reader reader, FileSource source,
676                                   ErrorQueue eq);
677
678     /**
679      * Replace the pass named <code>id</code> in <code>passes</code> with
680      * the list of <code>newPasses</code>.
681      */

682     public void replacePass(List passes, Pass.ID id, List newPasses) {
683         for (ListIterator i = passes.listIterator(); i.hasNext(); ) {
684           Pass p = (Pass) i.next();
685
686           if (p.id() == id) {
687             if (p instanceof BarrierPass) {
688               throw new InternalCompilerError("Cannot replace a barrier pass.");
689             }
690
691             i.remove();
692
693             for (Iterator j = newPasses.iterator(); j.hasNext(); ) {
694               i.add(j.next());
695             }
696
697             return;
698           }
699         }
700
701         throw new InternalCompilerError("Pass " + id + " not found.");
702     }
703
704     /**
705      * Remove the pass named <code>id</code> from <code>passes</code>.
706      */

707     public void removePass(List passes, Pass.ID id) {
708         for (ListIterator i = passes.listIterator(); i.hasNext(); ) {
709           Pass p = (Pass) i.next();
710
711           if (p.id() == id) {
712             if (p instanceof BarrierPass) {
713               throw new InternalCompilerError("Cannot remove a barrier pass.");
714             }
715
716             i.remove();
717             return;
718           }
719         }
720
721         throw new InternalCompilerError("Pass " + id + " not found.");
722     }
723
724     /**
725      * Insert the list of <code>newPasses</code> into <code>passes</code>
726      * immediately before the pass named <code>id</code>.
727      */

728     public void beforePass(List passes, Pass.ID id, List newPasses) {
729         for (ListIterator i = passes.listIterator(); i.hasNext(); ) {
730           Pass p = (Pass) i.next();
731
732           if (p.id() == id) {
733             // Backup one position.
734
i.previous();
735
736             for (Iterator j = newPasses.iterator(); j.hasNext(); ) {
737               i.add(j.next());
738             }
739
740             return;
741           }
742         }
743
744         throw new InternalCompilerError("Pass " + id + " not found.");
745     }
746
747     /**
748      * Insert the list of <code>newPasses</code> into <code>passes</code>
749      * immediately after the pass named <code>id</code>.
750      */

751     public void afterPass(List passes, Pass.ID id, List newPasses) {
752         for (ListIterator i = passes.listIterator(); i.hasNext(); ) {
753           Pass p = (Pass) i.next();
754
755           if (p.id() == id) {
756             for (Iterator j = newPasses.iterator(); j.hasNext(); ) {
757               i.add(j.next());
758             }
759
760             return;
761           }
762         }
763
764         throw new InternalCompilerError("Pass " + id + " not found.");
765     }
766
767     /**
768      * Replace the pass named <code>id</code> in <code>passes</code> with
769      * the pass <code>pass</code>.
770      */

771     public void replacePass(List passes, Pass.ID id, Pass pass) {
772         replacePass(passes, id, Collections.singletonList(pass));
773     }
774
775     /**
776      * Insert the pass <code>pass</code> into <code>passes</code>
777      * immediately before the pass named <code>id</code>.
778      */

779     public void beforePass(List passes, Pass.ID id, Pass pass) {
780         beforePass(passes, id, Collections.singletonList(pass));
781     }
782
783     /**
784      * Insert the pass <code>pass</code> into <code>passes</code>
785      * immediately after the pass named <code>id</code>.
786      */

787     public void afterPass(List passes, Pass.ID id, Pass pass) {
788         afterPass(passes, id, Collections.singletonList(pass));
789     }
790
791     /**
792      * Get the complete list of passes for the job.
793      */

794     public abstract List passes(Job job);
795
796     /**
797      * Get the sub-list of passes for the job between passes
798      * <code>begin</code> and <code>end</code>, inclusive.
799      */

800     public List passes(Job job, Pass.ID begin, Pass.ID end) {
801         List l = passes(job);
802         Pass p = null;
803
804         Iterator i = l.iterator();
805
806         while (i.hasNext()) {
807             p = (Pass) i.next();
808             if (begin == p.id()) break;
809             if (! (p instanceof BarrierPass)) i.remove();
810         }
811
812         while (p.id() != end && i.hasNext()) {
813             p = (Pass) i.next();
814         }
815
816         while (i.hasNext()) {
817             p = (Pass) i.next();
818             i.remove();
819         }
820
821         return l;
822     }
823
824     public String JavaDoc toString() {
825         return getClass().getName() + " worklist=" + worklist;
826     }
827 }
828
Popular Tags