<div dir="ltr"><div><div>+1<br><br></div>

<p class="MsoNormal"><span style="mso-ansi-language:EN-US" lang="EN-US">I presume
copyChain is a bit more expensive than copy (I didn’t measure it though). More
expensive but allways correct.</span></p><p class="MsoNormal"><span style="mso-ansi-language:EN-US" lang="EN-US"><br></span></p>

<p class="MsoNormal"><span style="mso-ansi-language:EN-US" lang="EN-US">If the
inexpensive copy is used extensively, and my suggestion is a performance killer,
then let’s keep current solution: cleverly use expensive copy exactly where we
now we are going to need it. Otherwise, I suggest renaming copyChain into copy,
and hence have something much more robust.</span></p>

</div><div class="gmail_extra"><br><div class="gmail_quote">2016-05-20 1:03 GMT+02:00  <span dir="ltr">&lt;<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Levente Uzonyi uploaded a new version of Regex-Core to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Regex-Core-ul.52.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/trunk/Regex-Core-ul.52.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Regex-Core-ul.52<br>
Author: ul<br>
Time: 20 May 2016, 1:02:48.025069 am<br>
UUID: 25d06172-cbd2-4454-a5e7-0dcfc27525b4<br>
Ancestors: Regex-Core-pre.51<br>
<br>
RxmLink changes:<br>
- implemented #copyChain, #copyUsing: and #postCopyUsing: to create a copy of the matcher chain without creating duplicates of links being referenced from more than one place<br>
- implemented missing #postCopy methods<br>
- removed unused variables from subclasses<br>
<br>
- use #copyChain instead of #veryDeepCopy in RxMatcher &gt;&gt; #makeQuantified:min:max: to avoid unnecessary duplication of non-link objects<br>
<br>
=============== Diff against Regex-Core-pre.51 ===============<br>
<br>
Item was changed:<br>
  ----- Method: RxMatcher&gt;&gt;makeQuantified:min:max: (in category &#39;private&#39;) -----<br>
  makeQuantified: anRxmLink min: min max: max<br>
        &quot;Perform recursive poor-man&#39;s transformation of the {&lt;min&gt;,&lt;max&gt;} quantifiers.&quot;<br>
        | aMatcher |<br>
<br>
        &quot;&lt;atom&gt;{,&lt;max&gt;}       ==&gt;  (&lt;atom&gt;{1,&lt;max&gt;})?&quot;<br>
        min = 0 ifTrue: [<br>
                ^ self makeOptional: (self makeQuantified: anRxmLink min: 1 max: max) ].<br>
<br>
        &quot;&lt;atom&gt;{&lt;min&gt;,}       ==&gt;  &lt;atom&gt;{&lt;min&gt;-1, &lt;min&gt;-1}&lt;atom&gt;+&quot;<br>
        max ifNil: [<br>
+               ^ (self makeQuantified: anRxmLink min: 1 max: min-1) pointTailTo: (self makePlus: anRxmLink copyChain) ].<br>
-               ^ (self makeQuantified: anRxmLink min: 1 max: min-1) pointTailTo: (self makePlus: anRxmLink veryDeepCopy) ].<br>
<br>
        &quot;&lt;atom&gt;{&lt;max&gt;,&lt;max&gt;}  ==&gt;  &lt;atom&gt;&lt;atom&gt; ... &lt;atom&gt;&quot;<br>
        min = max<br>
                ifTrue: [<br>
+                       aMatcher := anRxmLink copyChain.<br>
+                       (min-1) timesRepeat: [ aMatcher pointTailTo: anRxmLink copyChain ].<br>
-                       aMatcher := anRxmLink veryDeepCopy.<br>
-                       (min-1) timesRepeat: [ aMatcher pointTailTo: anRxmLink veryDeepCopy ].<br>
                        ^ aMatcher ].<br>
<br>
        &quot;&lt;atom&gt;{&lt;min&gt;,&lt;max&gt;}  ==&gt;  &lt;atom&gt;{&lt;min&gt;,&lt;min&gt;}(&lt;atom&gt;{1,&lt;max&gt;-1})?&quot;<br>
+       aMatcher := self makeOptional: anRxmLink copyChain.<br>
-       aMatcher := self makeOptional: anRxmLink veryDeepCopy.<br>
        (max - min - 1) timesRepeat: [<br>
+                aMatcher := self makeOptional: (anRxmLink copyChain pointTailTo: aMatcher) ].<br>
-                aMatcher := self makeOptional: (anRxmLink veryDeepCopy pointTailTo: aMatcher) ].<br>
        ^ (self makeQuantified: anRxmLink min: min max: min) pointTailTo: aMatcher!<br>
<br>
Item was added:<br>
+ ----- Method: RxmBranch&gt;&gt;postCopyUsing: (in category &#39;copying&#39;) -----<br>
+ postCopyUsing: anIdentityDictionary<br>
+<br>
+       super postCopyUsing: anIdentityDictionary.<br>
+       alternative ifNotNil: [<br>
+               alternative := alternative copyUsing: anIdentityDictionary ]!<br>
<br>
Item was added:<br>
+ ----- Method: RxmLink&gt;&gt;copyChain (in category &#39;copying&#39;) -----<br>
+ copyChain<br>
+       &quot;Create a full copy of all the links in this chain, including branches, while letting them share and reuse non-link objects as much as possible.&quot;<br>
+<br>
+       ^self copyUsing: IdentityDictionary new!<br>
<br>
Item was added:<br>
+ ----- Method: RxmLink&gt;&gt;copyUsing: (in category &#39;copying&#39;) -----<br>
+ copyUsing: anIdentityDictionary<br>
+       &quot;Copy the receiver if it&#39;s not present in the argument dictionary, or just return the previously made copy. The rest of the object graph will be copied by #postCopyUsing:.&quot;<br>
+<br>
+       ^anIdentityDictionary<br>
+               at: self<br>
+               ifAbsent: [<br>
+                       &quot;It may be tempting to use #at:ifAbsentPut: instead, but the argument block must not modify the receiver, so that wouldn&#39;t work.&quot;<br>
+                       anIdentityDictionary<br>
+                               at: self<br>
+                               put: (self shallowCopy<br>
+                                       postCopyUsing: anIdentityDictionary;<br>
+                                       yourself) ]!<br>
<br>
Item was added:<br>
+ ----- Method: RxmLink&gt;&gt;postCopyUsing: (in category &#39;copying&#39;) -----<br>
+ postCopyUsing: anIdentityDictionary<br>
+       &quot;Copy the rest of the chain the same way as it&#39;s done in #copyUsing:.&quot;<br>
+<br>
+       next ifNotNil: [<br>
+               next := next copyUsing: anIdentityDictionary ]!<br>
<br>
Item was changed:<br>
  RxmLink subclass: #RxmLookahead<br>
+       instanceVariableNames: &#39;lookahead&#39;<br>
-       instanceVariableNames: &#39;lookahead positive&#39;<br>
        classVariableNames: &#39;&#39;<br>
        poolDictionaries: &#39;&#39;<br>
        category: &#39;Regex-Core&#39;!<br>
<br>
  !RxmLookahead commentStamp: &#39;&lt;historical&gt;&#39; prior: 0!<br>
  Instance holds onto a lookead which matches but does not consume anything.<br>
<br>
  Instance variables:<br>
        predicate               &lt;RxmLink&gt;!<br>
<br>
Item was removed:<br>
- ----- Method: RxmLookahead&gt;&gt;initialize (in category &#39;initialization&#39;) -----<br>
- initialize<br>
-       super initialize.<br>
-       positive := true.!<br>
<br>
Item was added:<br>
+ ----- Method: RxmLookahead&gt;&gt;postCopy (in category &#39;copying&#39;) -----<br>
+ postCopy<br>
+<br>
+       super postCopy.<br>
+       lookahead := lookahead copy!<br>
<br>
Item was added:<br>
+ ----- Method: RxmLookahead&gt;&gt;postCopyUsing: (in category &#39;copying&#39;) -----<br>
+ postCopyUsing: anIdentityDictionary<br>
+<br>
+       super postCopyUsing: anIdentityDictionary.<br>
+       lookahead := lookahead copyUsing: anIdentityDictionary!<br>
<br>
Item was changed:<br>
  RxmLink subclass: #RxmSubstring<br>
+       instanceVariableNames: &#39;sampleStream ignoreCase&#39;<br>
-       instanceVariableNames: &#39;sampleStream caseSensitive ignoreCase&#39;<br>
        classVariableNames: &#39;&#39;<br>
        poolDictionaries: &#39;&#39;<br>
        category: &#39;Regex-Core&#39;!<br>
<br>
  !RxmSubstring commentStamp: &#39;Tbn 11/12/2010 23:14&#39; prior: 0!<br>
  -- Regular Expression Matcher v 1.1 (C) 1996, 1999 Vassili Bykov<br>
  --<br>
  Instance holds onto a string and matches exactly this string, and exactly once.<br>
<br>
  Instance variables:<br>
        string  &lt;String&gt;!<br>
<br>
Item was added:<br>
+ ----- Method: RxmSubstring&gt;&gt;postCopy (in category &#39;copying&#39;) -----<br>
+ postCopy<br>
+<br>
+       super postCopy.<br>
+       sampleStream := sampleStream copy!<br>
<br>
Item was added:<br>
+ ----- Method: RxmSubstring&gt;&gt;postCopyUsing: (in category &#39;copying&#39;) -----<br>
+ postCopyUsing: anIdentityDictionary<br>
+<br>
+       super postCopyUsing: anIdentityDictionary.<br>
+       sampleStream := sampleStream copy!<br>
<br>
<br>
</blockquote></div><br></div></div>