Module: internal Author: Keith Playford 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 define open abstract class () end; define open generic limited-list (of :: ) => (type :: subclass()); define open generic limited-list-first (list :: ) => (object); define open generic limited-list-first-setter (object, list :: ) => (object); define open generic limited-list-rest (list :: ) => (list :: ); define open generic limited-list-rest-setter (list :: , list :: ) => (list :: ); define open generic prepend (object, list :: ) => (new-list :: ); //// Convenient access. define inline sealed method list-first (list :: , #key default) => (first) // We just don't support default... limited-list-first(list) end method; define inline sealed method list-first-setter (value :: , list :: , #key default) => (first) limited-list-first(list) := value end method; define inline sealed method list-rest (list :: ) => (rest :: ) limited-list-rest(list) end method; define inline sealed method list-rest-setter (new-rest :: , list :: ) => (rest :: ) limited-list-rest(list) := new-rest end method; //// Shared implementation. define open primary class () slot %limited-list-rest :: , required-init-keyword: rest:; end class; define open primary class () end class; // // AS // define method as (class :: subclass(), collection :: ) => (l :: ) let result :: = empty(class); for (item in collection) result := prepend(item, result); end for; reverse!(result) end method as; define sealed method as (class :: subclass(), v :: ) => (l :: ) for (result = empty(class) then prepend(vector-element(v, index), result), index :: from v.size - 1 to 0 by -1) finally result end end; define sealed method as (class :: subclass(), v :: ) => (l :: ) let rep = v.representation; for (result = empty(class) then prepend(island-deque-element(rep, index), result), index :: from rep.last-index to rep.first-index by -1) finally result end end; // // SIZE // define sealed method size (list :: ) => (s :: false-or()) let nil = empty(object-class(list)); if (list == nil) 0 else let list :: = list; iterate sum (count :: = 0, fast :: = list, slow :: = list) let fast-tail = fast.%limited-list-rest; if (fast-tail == nil) count + 1 elseif (fast == slow & count > 0) #f else let fast-tail :: = fast-tail; let fast-tail-tail = fast-tail.%limited-list-rest; case fast-tail-tail == nil => count + 2; otherwise => let fast-tail-tail :: = fast-tail-tail; let slowtail :: = %limited-list-rest(slow); sum(count + 2, fast-tail-tail, slowtail); end end if end iterate end end method size; // // ELEMENT // define sealed method element (lst :: , key :: , #key default = unsupplied()) => (o :: ) if (key < 0) if (unsupplied?(default)) element-range-error(lst, key) else default end else iterate loop (l :: = lst, i :: = 0) if (~empty?(l)) let l :: = l; if (i == key) limited-list-first(l) else loop(%limited-list-rest(l), i + 1) end; elseif (unsupplied?(default)) element-range-error(lst, key) else default end if end iterate end if end method element; // // ELEMENT-NO-BOUNDS-CHECK // define sealed method element-no-bounds-check (lst :: , key :: , #key default) => (result :: ) for (k :: from 0 below key, remain :: = lst then remain.%limited-list-rest) finally remain.limited-list-first end for end method element-no-bounds-check; // // ELEMENT-SETTER // define sealed method element-setter (new-value, lst :: , key :: ) => (new-value :: ) iterate loop (l :: = lst, i :: = 0) if (~empty?(l)) let l :: = l; if (i == key) limited-list-first(l) := new-value else loop(%limited-list-rest(l), i + 1) end; else element-range-error(lst, key) end if end iterate end method element-setter; // // ELEMENT-NO-BOUNDS-CHECK-SETTER // define sealed method element-no-bounds-check-setter (new-value, lst :: , key :: ) => new-value; for (k :: from 0 below key, remain :: = lst then remain.%limited-list-rest) finally remain.limited-list-first := new-value end for end method element-no-bounds-check-setter; define inline sealed method first (list :: , #key default) => (first) if (instance?(list, )) limited-list-first(list) else element-range-error(list, 0); end; end method; define inline sealed method rest (list :: ) => (rest :: ) if (instance?(list, )) limited-list-rest(list) else error("Cannot take rest of the empty limited list %=", list); end; end method; define inline sealed method rest (sequence :: ) => (sequence-tail :: ) sequence.tail; end method rest; //// Iteration. define inline function limited-list-next-state (collection :: , state :: ) => (l :: ) limited-list-rest(state) end function; define inline function limited-list-finished-state? (collection :: , state :: , limit) => (result :: ) empty?(state) end function; define inline function limited-list-copy-state (collection :: , state :: ) => (l :: ) state end function; define inline function limited-list-current-key (collection :: , state :: ) => (result :: ) iterate search (l :: = collection, k :: = 0) if (l == state) k else search(limited-list-rest(l), k + 1) end if end iterate end function; define inline function limited-list-current-element (collection :: , state :: ) => (result) limited-list-first(state) end function; define inline function limited-list-current-element-setter (new-value, collection :: , state :: ) => (result) limited-list-first(state) := new-value end function; define inline method forward-iteration-protocol (list :: ) => (initial-state :: , limit :: , next-state :: , finished-state? :: , current-key :: , current-element :: , current-element-setter :: , copy-state :: ) values(list, empty(object-class(list)), limited-list-next-state, limited-list-finished-state?, limited-list-current-key, limited-list-current-element, limited-list-current-element-setter, limited-list-copy-state) end method; define macro limited-list-definer { define limited-list ?class:name of ?element:name ?opt-fill } => { define sealed class ?class () end; define sealed domain make (subclass(?class)); define sealed domain initialize (?class); define sideways sealed inline method limited-list (type == ?element) => (list-class == ?class) ?class end method; define sealed method type-for-copy (list :: ?class) => (class :: singleton(?class)) ?class end; define sealed method make (class == ?class, #key size :: = 0, fill :: ?element = ?opt-fill) => (list :: ?class) for (i :: from 0 below size, result :: ?class = empty(?class) then prepend(fill, result)) finally result end; end method; define sealed /* made-inline */ class "non-empty-" ## ?class (, ?class) sealed slot limited-list-first :: ?element, required-init-keyword: first:; end class; define sealed inline method limited-list-rest (l :: "non-empty-" ## ?class) => (rest :: ?class) // Eek!!! %guarantee-type(l.%limited-list-rest, ?class) // l.limited-list-rest end; define sealed inline method limited-list-rest-setter (rest :: ?class, l :: "non-empty-" ## ?class) => (rest :: ?class) %limited-list-rest(l) := rest end; define sealed domain limited-list-first-setter (, ?class); define sealed domain limited-list-rest-setter (, ?class); define sealed class "empty-" ## ?class (, ?class) end; define constant "$empty-" ## ?class :: "empty-" ## ?class = make("empty-" ## ?class); define inline sealed method prepend (object :: ?element, list :: ?class) => (list :: "non-empty-" ## ?class) make("non-empty-" ## ?class, first: object, rest: list); end method; define sealed domain prepend (, ?class); define inline sealed method empty (class :: subclass(?class)) => (empty :: "empty-" ## ?class) "$empty-" ## ?class; end method; define inline sealed method empty? (list :: ?class) => (well? :: ) list == "$empty-" ## ?class; end method; define inline function ?class ## "-next-state" (collection :: ?class, state :: ?class) => (l :: ?class) let state :: "non-empty-" ## ?class = %guarantee-type(state, "non-empty-" ## ?class); limited-list-rest(state) end function; define inline function ?class ## "-current-element" (collection :: ?class, state :: ?class) => (e :: ?element) let state :: "non-empty-" ## ?class = %guarantee-type(state, "non-empty-" ## ?class); limited-list-first(state) end function; define inline function ?class ## "-current-element-setter" (e :: ?element, collection :: ?class, state :: ?class) => (e :: ?element) let state :: "non-empty-" ## ?class = %guarantee-type(state, "non-empty-" ## ?class); limited-list-first(state) := e end function; define inline sealed method forward-iteration-protocol (list :: ?class) => (initial-state :: ?class, limit :: ?class, next-state :: , finished-state? :: , current-key :: , current-element :: , current-element-setter :: , copy-state :: ) values(list, empty(?class), ?class ## "-next-state", limited-list-finished-state?, limited-list-current-key, ?class ## "-current-element", ?class ## "-current-element-setter", limited-list-copy-state) end method; } { define limited-list "<" ## ?element:name ## ">" ?opt-fill } => { define limited-list "" of "<" ## ?element ## ">" = ?opt-fill } opt-fill: { } => { #f } { = ?fill:expression } => { ?fill } end macro; //// Standard limited list classes. define limited-list ; define limited-list ; define limited-list ; define inline method limited-list (type :: ) => (list-type :: subclass()) end method; // eof