Hi Yanni This is a feature or a known issue, I am not sure yet! In serialization, when you substitute an object by another, such substitution(*) is then serialized using the same rules, so you might need the guard condition to avoid the infinite loop. This was the simpler implementation, but maybe it's undesirable or it's too error prone. Do you think we should change this? *: note the substitution can be not just an object but a graph of objects, some of them able to be substituted too. MartÃn On Fri, Nov 25, 2011 at 6:20 PM, Yanni Chiu <yanni@rogers.com> wrote:
The attached test case, reproduced below:
| result | self analyzer when: [:x | FLPair = x class and: [x left isNil not] ] substituteBy: [:x | x copy left: $A ]. result := self resultOfSerializeAndMaterializ**e: (FLPair new left: $a; right: $b; yourself). self assert: result left = $A.
causes an infinite loop with IdentityDictionary (see stack trace at end).
The similar test case #testTransientPairLeft, works because the guard condition is negated by the replacement (i.e. "x left isNil not" is made false by the replacement).
The attached test case does not make "x left isNil not" false. It causes an infinite recursion, so use "ctrl-." to stop it before too long.
Is this a bug, or the intention of the #when:substituteBy: feature? I've worked around it, by making sure to always have the substituted value fail the guard clause.
-- Yanni
==== stack trace ==== IdentityDictionary>>scanFor: IdentityDictionary(**HashedCollection)>>**findElementOrNil: IdentityDictionary(Dictionary)**>>at:ifAbsent: FLPluggableSubstitutionCluster**(FLSubstitutionCluster)>>add:**traceWith: FLAnalysis>>mapAndTrace: FLAnalysis>>run [:anObject | (FLAnalysis newWith: self firstInMapperChain root: anObject) run; yourself] in FLAnalyzer>>setDefaultAnalysis FLAnalyzer>>analysisFor: FLSerialization>>analysisStep FLSerialization>>run [:anObject :aStream | (FLSerialization root: anObject on: aStream analyzer: self analyzer) run; yourself] in FLSerializer>>** defaultSerialization [self nextPutSignatureOn: aStream. self nextPutVersionOn: aStream. ^ self serializationFactory value: anObject value: aStream] in FLSerializer>>serialize:on: BlockClosure>>ensure: FLSerializer>>serialize:on: [:aStream | self serializer serialize: anObject on: aStream] in FLPluggableSubstitutionTest(**FLSerializationTest)>>**serialize: [:aStream | aValuable value: aStream binary] in FLFileStreamStrategy>>** writeStreamDo: [anotherBlock value: file] in MultiByteFileStream class(FileStream class)>>detectFile:do: BlockClosure>>ensure: MultiByteFileStream class(FileStream class)>>detectFile:do: MultiByteFileStream class(FileStream class)>>forceNewFileNamed:do: