Module: internal Author: Jonathan Bachrach Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND // BOOTED: define ... class ... end; //////////// // INTERFACE //////////// // Functions on define sealed generic first-setter (new-value, sequence :: ) => (new-value); define sealed generic second-setter (new-value, sequence :: ) => (new-value); define sealed generic third-setter (new-value, sequence :: ) => (new-value); // Open generics on define open generic last-setter (new-value, sequence :: ) => (new-value); ///////////////// // IMPLEMENTATION ///////////////// // // FIRST-SETTER /////////////// define sealed inline method first-setter (new-value, sequence :: ) => (new-value); sequence[0] := new-value end method; // // SECOND-SETTER //////////////// define sealed inline method second-setter (new-value, sequence :: ) => (new-value); sequence[1] := new-value end method; // // THIRD-SETTER /////////////// define sealed inline method third-setter (new-value, sequence :: ) => (new-value); sequence[2] := new-value end method; // // LAST-SETTER ////////////// define method last-setter (new-value, sequence :: ) => (new-value); sequence[sequence.size - 1] := new-value end method last-setter; // // Specialized inherited generic methods // // // REPLACE-SUBSEQUENCE! // define method replace-subsequence! (target :: , insert :: , #key start :: = 0, end: last = unsupplied()) => (result-sequence :: ); let target-size :: = target.size; let insert-size :: = insert.size; let last :: = check-start-compute-end(target, start, last); let delete-size :: = last - start; if (delete-size = insert-size) // Can modify in place with-fip-of target for (state = initial-state then next-state(target, state), index from 0 below start) finally for (state = state then next-state(target, state), e in insert) current-element(target, state) := e; end for end for end with-fip-of; target else // The fun starts here // Don't know if target is stretchy so we have to create a new one let new-size :: = target-size - delete-size + insert-size; let new-target = make(type-for-copy(target), size: new-size); with-fip-of new-target if (start = 0 & last = target-size) // Don't need to copy from target for (state = initial-state then next-state(new-target, state), e in insert) /* Use with-setter? */ current-element(new-target, state) := e; end else // Have to copy stuff from target with-fip-of target with prefix o- for (state = initial-state then next-state(new-target, state), o-state = o-initial-state then o-next-state(target, o-state), index from 0 below start) current-element(new-target, state) := o-current-element(target, o-state); finally // Copy insert to new target for (state = state then next-state(new-target, state), e in insert) current-element(new-target, state) := e; finally // Copy rest of target if necessary if (last = target-size) new-target else for (o-state = o-state then next-state(target, o-state), index from start below last) // Skip replaced segment finally for (state = state then next-state(new-target, state), o-state = o-state then o-next-state(target, o-state), index from last below target-size) current-element(new-target, state) := o-current-element(target, o-state); end for end for end if end for end for end with-fip-of end if end with-fip-of; new-target end if end method replace-subsequence!; // // FILL! // define method fill! (target :: , value, #key start :: = 0, end: last = unsupplied()) => (target :: ) if (start = 0 & last.unsupplied?) next-method() else with-fip-of target for (state = initial-state then next-state(target, state), index from 0, until: start == index | finished-state?(target, state, limit)) finally case index ~== start => invalid-sequence-start-error(target, start); unsupplied?(last) => // Modify elements to the end of the sequence for (state = state then next-state(target, state), until: finished-state?(target, state, limit)) current-element(target, state) := value end for; last >= index => // Modify elements from start to end or size of sequence, // and then check that end was valid. let last :: = last; for (state = state then next-state(target, state), index from index, until: index == last | finished-state?(target, state, limit)) current-element(target, state) := value finally unless (index == last) invalid-sequence-end-error(target, last) end end for; otherwise => invalid-sequence-bounds-error(target, start, last); end end end; target end if end method fill!; // // ITERATION PROTOCOL // define inline method forward-iteration-protocol (sequence :: ) => (initial-state :: , limit :: , next-state :: , finished-state? :: , current-key :: , current-element :: , current-element-setter :: , copy-state :: ); values(0, sequence.size, sequence-next-state, sequence-finished-state?, sequence-current-key, element, element-setter, identity-copy-state) end method forward-iteration-protocol; define inline method backward-iteration-protocol (sequence :: ) => (final-state :: , limit :: , previous-state :: , finished-state? :: , current-key :: , current-element :: , current-element-setter :: , copy-state :: ); values(sequence.size - 1, -1, sequence-previous-state, sequence-finished-state?, sequence-current-key, element, element-setter, identity-copy-state) end method backward-iteration-protocol;