-- Copyright 1993-1998, by the Cecil Project -- Department of Computer Science and Engineering, University of Washington -- See the LICENSE file for license information. --DOC Stream views of lists are not positionable or extensible but are --DOC insertable and removable. -- Note: insertion at front of stream doesn't affect underlying list template object list_stream_view[T] isa m_stream[T], removable_stream[T], insertable_stream[T]; --DOCSKIP keep predicates out of manual predicate list_stream_view_at_end[T] isa list_stream_view[T], stream_at_end[T]; predicate list_stream_view_before_end[T] isa list_stream_view[T], stream_before_end[T]; -- list stream views aren't fully reversible, -- but they can test for the beginning of the stream predicate list_stream_view_at_start[T] isa list_stream_view[T] when list_stream_view.is_at_start; predicate list_stream_view_after_start[T] isa list_stream_view[T] when list_stream_view.is_at_start.not; divide list_stream_view[T] into list_stream_view_at_start[T], list_stream_view_after_start[T]; --DOCENDSKIP private var field prev_cell(@:list_stream_view[`T]):simple_list[T] := nil[T]; private var field next_cell(@:list_stream_view[`T]):simple_list[T] := nil[T]; method view_stream(l@:simple_list[`T]):list_stream_view[T] { concrete object isa list_stream_view[T] { next_cell := l } } method is_at_end(s@:list_stream_view[`T]):bool { s.next_cell.is_empty } method is_at_start(s@:list_stream_view[`T]):bool { s.prev_cell.is_empty } method forward(s@:list_stream_view_before_end[`T], at_end:&():void):void { s.prev_cell := s.next_cell; s.next_cell := s.next_cell.rest; } method peek_next(s@:list_stream_view_before_end[`T], at_end:&():T):T { s.next_cell.first } method set_peek_next(s@:list_stream_view_before_end[`T], x:T):void { s.next_cell.first := x; } method remove_next(s@:list_stream_view_before_end[`T]):void { s.next_cell := s.next_cell.rest; s.prev_cell.rest := s.next_cell; } method insert(s@:list_stream_view[`T], x:T):void { s.next_cell := cons(x, s.next_cell); if(s.is_at_start.not, { s.prev_cell.rest := s.next_cell; }); s.forward; } -- view of a mutable list. -- insertion at front of stream also inserts at from of list template representation m_list_stream_view[T] isa list_stream_view[T]; --DOCSKIP those pesky predicates.... predicate m_list_stream_view_at_end[T] isa m_list_stream_view[T], stream_at_end[T]; predicate m_list_stream_view_before_end[T] isa m_list_stream_view[T], stream_before_end[T]; predicate m_list_stream_view_at_start[T] isa m_list_stream_view[T], list_stream_view_at_start[T]; predicate m_list_stream_view_after_start[T] isa m_list_stream_view[T], list_stream_view_after_start[T]; --DOCENDSKIP private field contents(@:m_list_stream_view[`T]):m_list[T]; method view_stream(l@:m_list[`T]):m_list_stream_view[T] { concrete object isa m_list_stream_view[T] { next_cell := l.front, contents := l } } -- treat inserting at beginning specially method insert(s@:m_list_stream_view_at_start[`T], x:T):void { resend; s.contents.front := s.next_cell; }