294 /** The number of elements in this scope. |
294 /** The number of elements in this scope. |
295 * This includes deleted elements, whose value is the sentinel. |
295 * This includes deleted elements, whose value is the sentinel. |
296 */ |
296 */ |
297 int nelems = 0; |
297 int nelems = 0; |
298 |
298 |
|
299 int removeCount = 0; |
|
300 |
299 /** Use as a "not-found" result for lookup. |
301 /** Use as a "not-found" result for lookup. |
300 * Also used to mark deleted entries in the table. |
302 * Also used to mark deleted entries in the table. |
301 */ |
303 */ |
302 private static final Entry sentinel = new Entry(null, null, null, null); |
304 private static final Entry sentinel = new Entry(null, null, null, null); |
303 |
305 |
567 return new Iterable<Symbol>() { |
571 return new Iterable<Symbol>() { |
568 public Iterator<Symbol> iterator() { |
572 public Iterator<Symbol> iterator() { |
569 return new Iterator<Symbol>() { |
573 return new Iterator<Symbol>() { |
570 private ScopeImpl currScope = ScopeImpl.this; |
574 private ScopeImpl currScope = ScopeImpl.this; |
571 private Scope.Entry currEntry = elems; |
575 private Scope.Entry currEntry = elems; |
|
576 private int seenRemoveCount = currScope.removeCount; |
572 { |
577 { |
573 update(); |
578 update(); |
574 } |
579 } |
575 |
580 |
576 public boolean hasNext() { |
581 public boolean hasNext() { |
|
582 if (seenRemoveCount != currScope.removeCount && |
|
583 currEntry != null && |
|
584 !currEntry.scope.includes(currEntry.sym)) { |
|
585 doNext(); //skip entry that is no longer in the Scope |
|
586 seenRemoveCount = currScope.removeCount; |
|
587 } |
577 return currEntry != null; |
588 return currEntry != null; |
578 } |
589 } |
579 |
590 |
580 public Symbol next() { |
591 public Symbol next() { |
|
592 if (!hasNext()) { |
|
593 throw new NoSuchElementException(); |
|
594 } |
|
595 |
|
596 return doNext(); |
|
597 } |
|
598 private Symbol doNext() { |
581 Symbol sym = (currEntry == null ? null : currEntry.sym); |
599 Symbol sym = (currEntry == null ? null : currEntry.sym); |
582 if (currEntry != null) { |
600 if (currEntry != null) { |
583 currEntry = currEntry.sibling; |
601 currEntry = currEntry.sibling; |
584 } |
602 } |
585 update(); |
603 update(); |
594 skipToNextMatchingEntry(); |
612 skipToNextMatchingEntry(); |
595 if (lookupKind == RECURSIVE) { |
613 if (lookupKind == RECURSIVE) { |
596 while (currEntry == null && currScope.next != null) { |
614 while (currEntry == null && currScope.next != null) { |
597 currScope = currScope.next; |
615 currScope = currScope.next; |
598 currEntry = currScope.elems; |
616 currEntry = currScope.elems; |
|
617 seenRemoveCount = currScope.removeCount; |
599 skipToNextMatchingEntry(); |
618 skipToNextMatchingEntry(); |
600 } |
619 } |
601 } |
620 } |
602 } |
621 } |
603 |
622 |
616 final LookupKind lookupKind) { |
635 final LookupKind lookupKind) { |
617 return new Iterable<Symbol>() { |
636 return new Iterable<Symbol>() { |
618 public Iterator<Symbol> iterator() { |
637 public Iterator<Symbol> iterator() { |
619 return new Iterator<Symbol>() { |
638 return new Iterator<Symbol>() { |
620 Scope.Entry currentEntry = lookup(name, sf); |
639 Scope.Entry currentEntry = lookup(name, sf); |
|
640 int seenRemoveCount = currentEntry.scope != null ? |
|
641 currentEntry.scope.removeCount : -1; |
621 |
642 |
622 public boolean hasNext() { |
643 public boolean hasNext() { |
|
644 if (currentEntry.scope != null && |
|
645 seenRemoveCount != currentEntry.scope.removeCount && |
|
646 !currentEntry.scope.includes(currentEntry.sym)) { |
|
647 doNext(); //skip entry that is no longer in the Scope |
|
648 } |
623 return currentEntry.scope != null && |
649 return currentEntry.scope != null && |
624 (lookupKind == RECURSIVE || |
650 (lookupKind == RECURSIVE || |
625 currentEntry.scope == ScopeImpl.this); |
651 currentEntry.scope == ScopeImpl.this); |
626 } |
652 } |
627 public Symbol next() { |
653 public Symbol next() { |
|
654 if (!hasNext()) { |
|
655 throw new NoSuchElementException(); |
|
656 } |
|
657 return doNext(); |
|
658 } |
|
659 private Symbol doNext() { |
628 Scope.Entry prevEntry = currentEntry; |
660 Scope.Entry prevEntry = currentEntry; |
629 currentEntry = currentEntry.next(sf); |
661 currentEntry = currentEntry.next(sf); |
630 return prevEntry.sym; |
662 return prevEntry.sym; |
631 } |
663 } |
632 public void remove() { |
664 public void remove() { |
684 public Entry sibling; |
716 public Entry sibling; |
685 |
717 |
686 /** The entry's scope. |
718 /** The entry's scope. |
687 * scope == null iff this == sentinel |
719 * scope == null iff this == sentinel |
688 */ |
720 */ |
689 public Scope scope; |
721 public ScopeImpl scope; |
690 |
722 |
691 public Entry(Symbol sym, Entry shadowed, Entry sibling, Scope scope) { |
723 public Entry(Symbol sym, Entry shadowed, Entry sibling, ScopeImpl scope) { |
692 this.sym = sym; |
724 this.sym = sym; |
693 this.shadowed = shadowed; |
725 this.shadowed = shadowed; |
694 this.sibling = sibling; |
726 this.sibling = sibling; |
695 this.scope = scope; |
727 this.scope = scope; |
696 } |
728 } |