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 // // STRETCHY-SEQUENCES // // Should these classes really be defined? Not in the DRM... // But used by deques for now? define open abstract class (, ) end class ; define open abstract class (, ) end class ; // // REPLACE-SUBSEQUENCE! // define method replace-subsequence! (dst :: , src :: , #key start = 0, end: last = dst.size) => (s :: ) let dst-size :: = dst.size; let new-size :: = start + (src.size + (dst-size - last)); case new-size < dst-size => for (di :: from start, e in src) dst[di] := e; finally for (di :: from di, si :: from last below dst-size) dst[di] := dst[si]; end for; end for; dst.size := new-size; new-size > dst-size => dst.size := new-size; for (si :: from dst-size - 1 to last by -1, di :: from new-size - 1 by -1) dst[di] := dst[si]; end for; for (di :: from start, e in src) dst[di] := e; end for; otherwise => for (di :: from start, e in src) dst[di] := e; end for end case; dst end method replace-subsequence!; //////////// // INTERFACE //////////// define open abstract class (, ) end class ; define open generic limited-stretchy-vector (of :: false-or()) => (type :: ); ///////////////// // IMPLEMENTATION ///////////////// // // MAKE // define sealed inline method make (class == , #rest all-keys, #key size, capacity, fill) => vector :: ; apply(make, , all-keys) end method make; // // AS // define method as (class == , coll :: ) => (vector :: ) as(, coll) end method as; define sealed inline method as (class == , coll :: ) => (vector :: ) coll end method as; // // TYPE-FOR-COPY // define method type-for-copy (vector :: ) => (type :: ) end method type-for-copy; define class () end; // // SHARED-STRETCHY-VECTOR // define open class () end class; define open primary class () slot %size :: , required-init-keyword: size:; end class; define open generic collection-fill (x :: ) => (res); define open generic stretchy-representation (x :: ) => (res :: ); define open generic stretchy-representation-setter (v, x :: ) => (res :: ); define open generic stretchy-representation-type (x :: ) => (res :: subclass()); define open generic stretchy-vector-element (rep :: , key :: ) => (res :: ); define open generic stretchy-vector-element-setter (value :: , rep :: , key :: ) => (value :: ); define method collection-fill (x :: ) => (res) #f end method; // // EMPTY? // define method empty? (vector :: ) => (well? :: ) vector.stretchy-representation.%size = 0 end method empty?; // // ADD! // define inline method add! (vector :: , new-element) => (v :: ) let old-size = vector.size; trusted-size(vector) := old-size + 1; check-type(new-element, element-type(vector)); without-bounds-checks vector[old-size] := new-element; end without-bounds-checks; vector end method add!; // // SIZE-SETTER // define method trusted-size-setter (new-size :: , vector :: ) => (new-size :: ) // TODO: could remove fills and do this in size-setter let v = vector.stretchy-representation; if (new-size > v.size) let nv :: = make(stretchy-representation-type(vector), capacity: new-size.power-of-two-ceiling, size: new-size); for (i :: from 0 below v.%size) stretchy-vector-element(nv, i) := stretchy-vector-element(v, i) finally for (j :: from i below new-size) stretchy-vector-element(nv, j) := collection-fill(vector) end for; end for; vector.stretchy-representation := nv; new-size; elseif (new-size < v.%size) let s = v.%size; v.%size := new-size; for (i :: from new-size below s) stretchy-vector-element(v, i) := collection-fill(vector) end for; new-size; else v.%size := new-size end if; end method trusted-size-setter; define method size-setter (new-size :: , vector :: ) => (new-size :: ) check-nat(new-size); let size = size(vector); trusted-size(vector) := new-size; end method size-setter; // // REMOVE! // define method remove! (vector :: , target, #key test = \==, count = unsupplied()) => (vector :: ) let count :: = if (unsupplied?(count)) vector.size else count end; let src = vector.stretchy-representation; let src-size = src.%size; iterate grovel (count :: = count, src-index :: = 0, dst-index :: = 0) if (src-index < src-size) let item = stretchy-vector-element(src, src-index); case count > 0 & test(item, target) => grovel(count - 1, src-index + 1, dst-index); otherwise => stretchy-vector-element(src, dst-index) := item; grovel(count, src-index + 1, dst-index + 1) end case else for (i :: from dst-index below src-index) stretchy-vector-element(src, i) := collection-fill(vector) end; src.%size := dst-index end if end iterate; vector end method remove!; // // ACTUAL LIMITED STRETCHY VECTORS // define macro limited-stretchy-vector-minus-constructor-definer { define limited-stretchy-vector-minus-constructor "<" ## ?:name ## ">" (?superclasses:*) (#key ?fill:expression) } => { define sealed class "" (?superclasses) slot stretchy-representation :: "", init-value: "$empty-"; end class ""; define sealed domain stretchy-representation (""); define sealed domain stretchy-representation-setter ("", ""); define constant "$empty-" :: "" = make("", capacity: 0, size: 0); define sealed primary class "" () repeated slot "stretchy-" ## ?name ## "-vector-element" :: "<" ## ?name ## ">", init-keyword: fill:, init-value: ?fill, size-getter: size, size-init-keyword: capacity:, size-init-value: 0; end class ""; define sealed domain size(""); define sealed domain make(singleton("")); define sealed domain initialize(""); define sealed inline method stretchy-vector-element (rep :: "", key :: ) => (res :: "<" ## ?name ## ">"); "stretchy-" ## ?name ## "-vector-element"(rep, key) end method; define sealed inline method stretchy-vector-element-setter (new-value :: "<" ## ?name ## ">", rep :: "", key :: ) => (new-value :: "<" ## ?name ## ">"); "stretchy-" ## ?name ## "-vector-element"(rep, key) := new-value; end method; define sealed inline method as (class == "", vector :: "") => (vector :: "") vector end method as; define sealed inline method collection-fill (vector :: "") => (res) ?fill end method; define sealed inline method stretchy-representation-type (vector :: "") => (res :: singleton("")) "" end method; define sealed inline method size (vector :: "") => (sz :: ) vector.stretchy-representation.%size end method size; define sealed inline method element (collection :: "", index :: , #key default = unsupplied()) => (object :: "<" ## ?name ## ">") let v = collection.stretchy-representation; if (element-range-check(index, v.%size)) "stretchy-" ## ?name ## "-vector-element"(v, index) else if (unsupplied?(default)) element-range-error(collection, index) else check-type(default, element-type(collection)); default end if end if end method element; // We assume here that the underlying vector only grows. // If this ceases to be true the following code will need to be changed. define inline sealed method element-no-bounds-check (collection :: "", index :: , #key default) => (object :: "<" ## ?name ## ">") "stretchy-" ## ?name ## "-vector-element" (collection.stretchy-representation, index) end method element-no-bounds-check; define inline sealed method element-no-bounds-check-setter (new-value :: "<" ## ?name ## ">", collection :: "", index :: ) => (new-value :: "<" ## ?name ## ">"); "stretchy-" ## ?name ## "-vector-element" (collection.stretchy-representation, index) := new-value end method element-no-bounds-check-setter; // We assume the representation vector is only ever replaced by a larger // vector. If this assumption ceases to hold the following code will need // to be altered. define inline function "stretchy-" ## ?name ## "-vector-current-element" (vector :: "", state :: ) => (res :: "<" ## ?name ## ">") "stretchy-" ## ?name ## "-vector-element"(vector.stretchy-representation, state) end function; define inline function "stretchy-" ## ?name ## "-vector-current-element-setter" (new-value :: "<" ## ?name ## ">", vector :: "", state :: ) => (res :: "<" ## ?name ## ">") "stretchy-" ## ?name ## "-vector-element" (vector.stretchy-representation, state) := new-value end function; /* THESE ARE CURRENTLY DEFINED ON STRETCHY-VECTOR AND COPIED DOWN define sealed method size-setter (new-size :: , vector :: "") => (new-size :: ) check-nat(new-size); let v = vector.stretchy-representation; if (new-size > v.size) let nv :: "" = make("", capacity: new-size.power-of-two-ceiling, size: new-size, fill: ?fill); for (i :: from 0 below v.%size) "stretchy-" ## ?name ## "-vector-element"(nv, i) := "stretchy-" ## ?name ## "-vector-element"(v, i) end; vector.stretchy-representation := nv; new-size; elseif (new-size < v.%size) let s = v.%size; v.%size := new-size; for (i :: from new-size below s) "stretchy-" ## ?name ## "-vector-element"(v, i) := ?fill end; new-size; else v.%size := new-size end if; end method size-setter; define sealed method remove! (vector :: "", target, #key test = \==, count = unsupplied()) => (vector :: "") let count :: = if (unsupplied?(count)) vector.size else count end; let src = vector.stretchy-representation; let src-size = src.%size; iterate grovel (count :: = count, src-index :: = 0, dst-index :: = 0) if (src-index < src-size) let item = "stretchy-" ## ?name ## "-vector-element"(src, src-index); case count > 0 & test(item, target) => grovel(count - 1, src-index + 1, dst-index); otherwise => "stretchy-" ## ?name ## "-vector-element"(src, dst-index) := item; grovel(count, src-index + 1, dst-index + 1) end case else for (i :: from dst-index below src-index) "stretchy-" ## ?name ## "-vector-element"(src, i) := ?fill end; src.%size := dst-index end if end iterate; vector end method remove!; */ define sealed 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, "stretchy-" ## ?name ## "-vector-current-element", "stretchy-" ## ?name ## "-vector-current-element-setter", identity-copy-state) end method forward-iteration-protocol; define sealed 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, "stretchy-" ## ?name ## "-vector-current-element", "stretchy-" ## ?name ## "-vector-current-element-setter", identity-copy-state) end method backward-iteration-protocol; define sealed domain element-type (""); define sealed domain make (singleton("")); define sealed domain initialize (""); define sealed copy-down-method choose (test :: , sequence :: "") => (result :: ""); define sealed copy-down-method remove (sequence :: "", value :: "<" ## ?name ## ">", #key test :: = \==, count :: false-or() = #f) => (new-sequence :: ""); // SHOULD BE COPY DOWNS BUT FAILS TO WORK define sealed /* copy-down- */ method as (class == "", collection :: ) => (sv :: ""); let new-vector :: "" = make(""); for (item in collection) new-vector := add!(new-vector, item); end for; new-vector end method; // SHOULD BE COPY DOWNS BUT FAILS TO WORK define sealed /* copy-down- */ method as (class == "", collection :: ) => (sv :: ""); let size = size(collection); if (size = 0) make("", size: 0); else let new-vector :: "" = make("", size: size, fill: collection[0]); let d = new-vector.stretchy-representation; without-bounds-checks for (item in collection, index :: from 0) stretchy-vector-element(d, index) := item end; end without-bounds-checks; new-vector end if end method; define sealed copy-down-method trusted-size-setter (new-size :: , vector :: "") => (new-size :: ); define sealed copy-down-method size-setter (new-size :: , vector :: "") => (new-size :: ); define sealed copy-down-method empty? (vector :: "") => (well? :: ); define sealed copy-down-method add! (vector :: "", new-element :: "<" ## ?name ## ">") => (v :: ""); define sealed copy-down-method remove! (vector :: "", target :: "<" ## ?name ## ">", #key test = \==, count = unsupplied()) => (vector :: ""); } end macro; define inline method stretchy-initialize (vector :: , capacity :: , size :: , fill) => () check-nat(size); check-nat(capacity); if (capacity < size) error(make(, format-string: "capacity %= < size %=", format-arguments: list(capacity, size))) end if; if (capacity > 0) // otherwise empty-stretchy-vector vector.stretchy-representation := make(stretchy-representation-type(vector), capacity: capacity, size: size, fill: fill); end if; end method; define macro limited-stretchy-vector-minus-selector-definer { define limited-stretchy-vector-minus-selector "<" ## ?:name ## ">" (?superclasses:*) (#key ?fill:expression) } => { define limited-stretchy-vector-minus-constructor "<" ## ?name ## ">" (?superclasses) (fill: ?fill); define method initialize (vector :: "", #key size :: = 0, capacity :: = size, fill :: "<" ## ?name ## ">" = ?fill) => () ?=next-method(); stretchy-initialize(vector, capacity, size, fill); vector end method initialize; define sealed inline method element-type (t :: "") => (type :: ) "<" ## ?name ## ">" end method; define sealed method element-setter (new-value :: "<" ## ?name ## ">", collection :: "", index :: ) => (object :: "<" ## ?name ## ">") if (index < 0) element-range-error(collection, index) end if; if (index >= collection.size) if (index = collection.size) trusted-size(collection) := index + 1; else collection.size := index + 1 end if end if; // We assume here that the underlying vector only grows. // If this ceases to be true the following code will need to be changed. "stretchy-" ## ?name ## "-vector-element" (collection.stretchy-representation, index) := new-value end method element-setter; define sealed inline method type-for-copy (vector :: "") => (type :: ) "" end method type-for-copy } end macro; define macro limited-stretchy-vector-definer { define limited-stretchy-vector "<" ## ?:name ## ">" (#key ?fill:expression) } => { define limited-stretchy-vector-minus-selector "<" ## ?name ## ">" () (fill: ?fill); define method concrete-limited-stretchy-vector-class (of == "<" ## ?name ## ">") => (res :: ) "" end method } end macro; define limited-stretchy-vector (fill: #f); define method limited-stretchy-vector (of :: ) => (type :: ) let concrete-class = concrete-limited-stretchy-vector-class(of); let default-concrete-class = ; if (size | concrete-class == default-concrete-class) make(, class: , element-type: of, concrete-class: default-concrete-class); else concrete-class end if; end method; define method limited (class == , #key of :: = , #all-keys) => (type :: ) limited-stretchy-vector(of) end method; define inline copy-down-method map-into-stretchy-one (fun :: , target :: , coll :: ) => (target :: ); define inline copy-down-method map-into-rigid-one (fun :: , target :: , coll :: ) => (target :: ); define inline copy-down-method map-into-rigid-one (fun :: , target :: , coll :: ) => (target :: ); // eof