module: walker 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 define function shallow-copy-instance (object) => (copy); let class = object-class(object); let sz = if (walker-repeated-slot?(class)) size(object) end; let copy = walker-allocate-object(class, sz); let slotds = slot-descriptors(class); for (slotd in slotds) let sd = as-walker-slot-descriptor(class, slotd); walker-slot-value(copy, sd) := walker-slot-value(object, sd); end; if (sz) let sz :: = sz; for (i :: from 0 below sz) copy[i] := object[i] end; end if; copy end function; define macro dont-copy-slots-definer { define dont-copy-slots ?class:name using ?walker:name = { ?entries } } => { define method walker-shallow-getters (walker_ :: ?walker, x_ :: subclass(?class)) => (res :: ) concatenate(?=next-method(), list(?entries)) end method } entries: { } => { } { ?getter:name, ... } => { ?getter, ... } { ?getter:name => ?default:expression, ... } => { pair(?getter, method (?=self) ?default end), ... } end macro; define macro dont-copy-object-definer { define dont-copy-object ?:name ?copier } => { define method deep-copy (copier :: ?copier, object :: ?name) => (value) object end method } copier: { } => { } { using ?:name } => { ?name } end macro; define open class () end class; define dont-copy-object using ; define dont-copy-object using ; define dont-copy-object using ; define dont-copy-object using ; define dont-copy-object using ; define dont-copy-object using ; define inline function copier-register-copied (copier :: , object, copy) walker-walked(copier)[object] := copy end function; define open generic do-deep-copy (copier :: , object) => (copy); /* define macro do-copy-slots { do-copy-slots () (?object:name, ?copy:name, ?start:expression) } => { } { do-copy-slots (?slot:name, ...) (?object:name, ?copy:name, ?start:expression) } => { walker-slot-value(?copy, ?index) := walker-slot-value(?object, ?index); do-copy-slots (...) (?start + 1) } end macro; define macro copy-slots-definer { define copy-slots (?slots:*) (?:name) } => { define function "copy-slots-" ## "?name" (copier :: , object) let class = object-class(object); let copy = walker-allocate-object(class, 0); copier-register-copied(copier, object, copy); do-copy-slots (?slots) (?object, ?copy, 0); end function } end macro; define copy-slots (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) (10); */ /* define method do-deep-copy (copier :: , object) => (value) let class = object-class(object); let repeated? = walker-repeated-slot?(class); let sz = if (repeated?) size(object) end; let copy = walker-allocate-object(class, sz); copier-register-copied(copier, object, copy); let (shallow-slotds, defaulted-slotds, deep-slotds) = walker-all-slot-descriptors(copier, class); for (slotd in shallow-slotds) walker-slot-value(copy, slotd) := walker-slot-value(object, slotd); end for; for (slotd/default in defaulted-slotds) let slotd = walker-default-slot-descriptor(slotd/default); let default-thunk = walker-default-thunk(slotd/default); walker-slot-value(copy, slotd) := default-thunk(object); end for; for (slotd in deep-slotds) walker-slot-value(copy, slotd) := deep-copy(copier, walker-slot-value(object, slotd)); end for; if (repeated?) for (i :: from 0 below sz) copy[i] := deep-copy(copier, object[i]); end for; end if; copy end method; */ define inline function do-deep-copy-simple (copier :: , object, class :: , walker-class :: ) => (value) let copy = walker-allocate-simple-object(class); copier-register-copied(copier, object, copy); let deep-slotds = walker-class-deep-slot-descriptors(walker-class); for (slotd :: in deep-slotds) walker-slot-value(copy, slotd) := deep-copy(copier, walker-slot-value(object, slotd)); end for; copy end function; define function do-deep-copy-repeated (copier :: , object, class :: , walker-class :: ) => (value) let sz = size(object); let copy = walker-allocate-repeated-object(class, sz); copier-register-copied(copier, object, copy); let deep-slotds = walker-class-deep-slot-descriptors(walker-class); for (slotd :: in deep-slotds) walker-slot-value(copy, slotd) := deep-copy(copier, walker-slot-value(object, slotd)); end for; for (i :: from 0 below sz) copy[i] := deep-copy(copier, object[i]); end for; copy end function; define function do-deep-copy-complex (copier :: , object, class :: , walker-class :: ) => (value) let copy = walker-allocate-simple-object(class); copier-register-copied(copier, object, copy); let shallow-slotds = walker-class-shallow-slot-descriptors(walker-class); let defaulted-slotds = walker-class-defaulted-slot-descriptors(walker-class); let deep-slotds = walker-class-deep-slot-descriptors(walker-class); for (slotd :: in shallow-slotds) walker-slot-value(copy, slotd) := walker-slot-value(object, slotd); end for; for (slotd/default :: in defaulted-slotds) let slotd = walker-default-slot-descriptor(slotd/default); let default-thunk = walker-default-thunk(slotd/default); walker-slot-value(copy, slotd) := default-thunk(object); end for; for (slotd :: in deep-slotds) walker-slot-value(copy, slotd) := deep-copy(copier, walker-slot-value(object, slotd)); end for; copy end function; define method do-deep-copy (copier :: , object) => (value) let class = object-class(object); let walker-class = walker-class(copier, class); select (walker-class-kind(walker-class)) $walker-simple => do-deep-copy-simple(copier, object, class, walker-class); $walker-complex => do-deep-copy-complex(copier, object, class, walker-class); $walker-repeated => do-deep-copy-repeated(copier, object, class, walker-class); end select; end method; define method do-deep-copy (copier :: , object :: ) => (value) let copy :: = pair(#f, #f); copier-register-copied(copier, object, copy); head(copy) := deep-copy(copier, head(object)); tail(copy) := deep-copy(copier, tail(object)); copy end method; define method do-deep-copy (copier :: , object :: ) => (value) let size :: = size(object); let copy :: = make(, size: size); copier-register-copied(copier, object, copy); for (i :: from 0 below size) copy[i] := deep-copy(copier, object[i]); end for; copy end method; define method do-deep-copy (copier :: , object :: ) => (value) let size :: = size(object); let copy :: = make(, size: size); copier-register-copied(copier, object, copy); for (i :: from 0 below size) copy[i] := deep-copy(copier, object[i]); end for; copy end method; define method do-deep-copy (copier :: , object :: ) => (value) let size :: = size(object); let copy ::
= make(object-class(object), size: size); copier-register-copied(copier, object, copy); for (val keyed-by key in object) copy[key] := val; end for; copy end method; define method do-deep-copy (copier :: , object :: ) => (value) let copy = copy-sequence(object); copier-register-copied(copier, object, copy); copy end method; define inline function maybe-do-deep-copy (copier :: , object) => (value) let copy = walked(copier, object, default: not-found()); if (found?(copy)) copy else do-deep-copy(copier, object); end if end function; define open generic deep-copy (copier :: , object) => (value); define method deep-copy (copier :: , object) => (value) maybe-do-deep-copy(copier, object) end method; define method copier-reset (copier :: , #rest all-keys, #key capacity) => (copier :: ) apply(walker-reset, copier, all-keys) end method; // eof