requires: {}. provides: {#Root}. "NOTE: Contains forward references to IdentitySet and ExtensibleSequence." x@(Root traits) = y@(Root traits) [x == y]. x@(Root traits) ~== y@(Root traits) [(x == y) not]. x@(Root traits) ~= y@(Root traits) [(x = y) not]. x@(Root traits) hash [x identityHash]. x@(Root traits) shallowCopy [x clone]. x@(Root traits) copy [x shallowCopy]. x@(Root traits) slotValuesDo: block [ x slotNames do: [| :slotName | block value: (x atSlotNamed: slotName)] ]. x@(Root traits) delegatesDo: block "Apply the code to all the immediately delegated objects." [ x delegateNames do: [| :slotName | block value: (x atSlotNamed: slotName)] ]. x@(Root traits) allDelegatesDo: block "Recurse through the delegation chains, avoiding repeated visits." [ | seen | seen: IdentitySet newEmpty. x allDelegatesDo: block withSeen: seen ]. x@(Root traits) allDelegatesDo: block withSeen: seen "Recurse through the delegation chains. seen, should be an empty Set to avoid circularity." [ x delegatesDo: [| :each | (seen includes: each) ifFalse: [seen include: each. block value: each. each allDelegatesDo: block withSeen: seen]]. Nil ]. x@(Root traits) commonTraitsWith: y@(Root traits) "Search for a common traits ancestor. y can be traits or instance." [| xt xts yt end pos | xts: (ExtensibleSequence newEmpty addLast: x traits). yt: y. end: Traits traits. [xt == end] whileFalse: [xts addLast: (xt: x parent). (pos: (xts findFirst: y)) ifNotNil: [^ (xts at: pos)]. y: y parent]. Traits traits ]. x@(Root traits) is: y@(Root traits) "Determine if anything in x's delegation chains equals y's traits." [| yt | yt: y traits. x traits == yt or: [x allDelegatesDo: [| :each | each == yt ifTrue: [^ True]]. False] ]. x@(Root traits) as: y@(Root traits) [ x traits == y traits ifTrue: [x] ifFalse: [error: 'Invalid coercion'] ]. x@(Root traits) printName [ x name ]. "This definition was moved to Stream. x@(Root traits) printOn: s [ s nextPutAll: x print ]." x addProtectedSlot: slotName@(Symbol traits) in: ancestorName@(Symbol traits) valued: val "Ensure that x delegates to the ancestor, then ensure that the ancestor has a slot of that name with that value, and finally define a method on the child to define a new slot on the *receiver* when mutations are attempted." [| mutatorName | (x delegateNames includes: ancestorName) ifFalse: [^ Nil]. (x atSlotNamed: ancestorName) addImmutableSlot: slotName valued: val. mutatorName: ((slotName as: String) ; ':' as: Symbol). [| :obj :val | obj addSlot: #slotName valued: val] asMethod: mutatorName on: {x traits. Root traits}. val ]. x@(Oddball traits) copy "While Oddballs are cloneable, copying shouldn't respect that." [x]. x@(Oddball traits) shallowCopy "While Oddballs are cloneable, copying shouldn't respect that." [x].