From bstjean at yahoo.com Thu Apr 1 08:11:34 2021 From: bstjean at yahoo.com (Benoit St-Jean) Date: Thu, 1 Apr 2021 04:11:34 -0400 Subject: [squeak-dev] SqueakMap servers are down References: <1667a3b6-0f1f-e541-d64a-42ec5fcd4478.ref@yahoo.com> Message-ID: <1667a3b6-0f1f-e541-d64a-42ec5fcd4478@yahoo.com> Looks like all SqueakMap servers are down... Tried latest Squeak release down to Squeak 4.3 and I cannot update the package list. -- ----------------- Benoît St-Jean Yahoo! Messenger: bstjean Twitter: @BenLeChialeux Pinterest: benoitstjean Instagram: Chef_Benito IRC: lamneth GitHub: bstjean Blogue: endormitoire.wordpress.com "A standpoint is an intellectual horizon of radius zero". (A. Einstein) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: cpknnmgbinoddpcb.png Type: image/png Size: 72717 bytes Desc: not available URL: From m at jaromir.net Thu Apr 1 08:50:01 2021 From: m at jaromir.net (Jaromir Matas) Date: Thu, 1 Apr 2021 03:50:01 -0500 (CDT) Subject: [squeak-dev] A bug in active process termination (crashing image) Message-ID: <1617267001412-0.post@n4.nabble.com> Active process termination part of #terminate contains a line that's been a mystery to me: | ctxt unwindBlock oldList outerMost | self isActiveProcess ifTrue: [ctxt := thisContext. [ctxt := ctxt findNextUnwindContextUpTo: nil. ctxt ~~ nil] whileTrue: [(ctxt tempAt: 2) ifNil: ---> ["N.B. Unlike Context>>unwindTo: we do not set complete (tempAt: 2) to true." unwindBlock := ctxt tempAt: 1. thisContext terminateTo: ctxt. unwindBlock value]]. thisContext terminateTo: nil. It appears however that the absence of the assignment (ctxt tempAt: 2 put: true.) will cause the image crash e.g. in this scenario (probably irrecoverably; I had to kill it): | p | p := [ [ Processor activeProcess terminate ] ensure: [ Processor activeProcess terminate ]. ] fork. Processor yield. Transcript show: p isTerminated printString I already mentioned this anomaly in [1] where it was causing an inability to close a debugger. The same algorithm is used in Context >> #resume:[through:] and #unwindTo:, but always with the assignment. I was wondering whether the reason for the intentional omission of the assignment was just saving a line considered useless or whether there was a deeper idea... Anybody remembers? Thanks for any advice. [1] http://forum.world.st/Bug-in-Process-terminate-Returning-from-unwind-contexts-tp5127570p5128018.html ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From Patrick.Rein at hpi.de Fri Apr 2 08:10:25 2021 From: Patrick.Rein at hpi.de (Rein, Patrick) Date: Fri, 2 Apr 2021 08:10:25 +0000 Subject: [squeak-dev] Squeak Oversight Board Election 2021 Message-ID: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Hi All, It's that time again (although with a new person telling you this). Time to raise your voices and elect your leaders! Can you believe it's been over a year already? It's a time for you to stand up, help your community and volunteer to serve! Squeak wants you! Every year we elect the SOB (Squeak Oversight Board) consisting of seven members from our community. The current board members are: 1. Vanessa Freudenberg 2. Tim Rowledge 3. Marcel Taeumel 4. Craig Latta 5. David T. Lewis 6. Chris Muller 7. John-Reed Maffeo For more info on the board please see: https://squeakboard.wordpress.com/our-mission/ Everything about the election, including schedule and more, can be tracked here: http://wiki.squeak.org/squeak/6656 Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members and campaigning! Candidates should nominate themselves and start their campaign on the squeak-dev mailing list. Or if you nominate someone else, make sure that person really wants to run. :) I will not put anyone on the candidate list until that person makes it known on squeak-dev that he/she intends to run. During this period, the candidates should ideally present themselves on squeak-dev, unless they have already done so, and the community can ask questions. I encourage you to reach out to potential candidates, people that are active in the community and represent your views, and ask them to run. Some people will not run without encouragement. Also, I know that some people wait to the last minute to run for the board to see if others will run but please consider getting this year off to a faster start and just jump right in! The schedule and process are as follows: Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members and campaigning! Friday 16th of April 2021, 18.00 UTC: Candidate list is finalized. Friday 16th of April 2021, 19.00 UTC: Online election starts. Friday 30th of April 2021, 19.00 UTC: Online election ends. Results will be announced immediately after the election ends. The voting period is two week long and ballots are sent out via email. And how do you end up on the voter list? See below. :) IMPORTANT: New voters will NOT be added once the election is started. You MUST try to get on the voter list before the 16th of April 2021 or you will NOT be able to vote. If your Email has changed please try to make sure it is changed on the list of voters before the election starts. -------------------------- If you were invited to vote last year you are already on the voter list, no worries! If you are a new Squeaker and wish to vote you should do ONE of the following: * Get a "known" Squeaker to vouch for you. If a known Squeaker sends an email to voters (at) squeak.org giving me a name and email for you, then I will add you. * Send an email to voters (at) squeak.org yourself (and CC to squeak-dev if you like) with information/arguments showing me that you are indeed serious about voting and that you are indeed a Squeaker. When the voting period starts all voters will receive an email with instructions and a link to the voting website. If there are any further questions, just reply *in this thread* and I will closely track it - or send email to voters (at) squeak.org which is updated and points to me. ...so let's get on with it! All the best, Patrick Rein From tim at rowledge.org Fri Apr 2 17:20:51 2021 From: tim at rowledge.org (tim Rowledge) Date: Fri, 2 Apr 2021 10:20:51 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: <74793F41-945B-454D-8917-44D4FDB4B687@rowledge.org> > On 2021-04-02, at 1:10 AM, Rein, Patrick wrote: > > > Candidates should nominate themselves and start their campaign on the > squeak-dev mailing list. Me! Me! Vote for me! tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim How come it's 'Java One' every year? Aren't they making any progress? From ron at usmedrec.com Fri Apr 2 22:35:05 2021 From: ron at usmedrec.com (Ron Teitelbaum) Date: Fri, 2 Apr 2021 18:35:05 -0400 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <74793F41-945B-454D-8917-44D4FDB4B687@rowledge.org> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <74793F41-945B-454D-8917-44D4FDB4B687@rowledge.org> Message-ID: That wins for the shortest nomination email! Ron On Fri, Apr 2, 2021, 1:20 PM tim Rowledge wrote: > > > > On 2021-04-02, at 1:10 AM, Rein, Patrick wrote: > > > > > > Candidates should nominate themselves and start their campaign on the > > squeak-dev mailing list. > > Me! Me! Vote for me! > > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > How come it's 'Java One' every year? Aren't they making any progress? > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jrmaffeo at gmail.com Sat Apr 3 01:06:12 2021 From: jrmaffeo at gmail.com (John-Reed Maffeo) Date: Fri, 2 Apr 2021 18:06:12 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: Patrick, Thank You for stepping up to help keep This Ship of Fools^H^H^H^H Squeak on an even keel ;-) On Fri, Apr 2, 2021 at 1:10 AM Rein, Patrick wrote: > Hi All, > > It's that time again (although with a new person telling you this). > Time to raise your voices and elect your leaders! Can you believe > it's been over a year already? > > It's a time for you to stand up, help your community and volunteer to > serve! > > Squeak wants you! > > Every year we elect the SOB (Squeak Oversight Board) consisting of > seven members from our community. The current board members are: > 1. Vanessa Freudenberg > 2. Tim Rowledge > 3. Marcel Taeumel > 4. Craig Latta > 5. David T. Lewis > 6. Chris Muller > 7. John-Reed Maffeo > > For more info on the board please see: > https://squeakboard.wordpress.com/our-mission/ > > Everything about the election, including schedule and more, can be tracked > here: > http://wiki.squeak.org/squeak/6656 > > Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members > and campaigning! > > Candidates should nominate themselves and start their campaign on the > squeak-dev mailing list. Or if you nominate someone else, make sure > that person really wants to run. :) I will not put anyone on the > candidate list until that person makes it known on squeak-dev that > he/she intends to run. > > During this period, the candidates should ideally present themselves > on squeak-dev, unless they have already done so, and the community can > ask questions. > > I encourage you to reach out to potential candidates, people that are > active in the community and represent your views, and ask them to run. > Some people will not run without encouragement. Also, I know that > some people wait to the last minute to run for the board to see if > others will run but please consider getting this year off to a faster > start and just jump right in! > > The schedule and process are as follows: > > Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members > and campaigning! > Friday 16th of April 2021, 18.00 UTC: Candidate list is finalized. > Friday 16th of April 2021, 19.00 UTC: Online election starts. > Friday 30th of April 2021, 19.00 UTC: Online election ends. > Results will be announced immediately after the election ends. > > The voting period is two week long and ballots are sent out via email. > > And how do you end up on the voter list? See below. :) > > IMPORTANT: New voters will NOT be added once the election is started. > You MUST try to get on the voter list before the 16th of April 2021 > or you will NOT be able to vote. If your Email has changed please try > to make sure it is changed on the list of voters before the election > starts. > > -------------------------- > > If you were invited to vote last year you are already on the voter > list, no worries! If you are a new Squeaker and wish to vote you > should do ONE of the following: > > * Get a "known" Squeaker to vouch for you. If a known Squeaker > sends an email to voters (at) squeak.org giving me a name and email > for you, then I will add you. > > * Send an email to voters (at) squeak.org yourself (and CC to > squeak-dev if you like) with information/arguments showing me that you > are indeed serious about voting and that you are indeed a Squeaker. > > When the voting period starts all voters will receive an email with > instructions and a link to the voting website. > > If there are any further questions, just reply *in this thread* and I > will closely track it - or send email to voters (at) squeak.org which > is updated and points to me. > > ...so let's get on with it! > > All the best, > Patrick Rein > > -- John-Reed Maffeo -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Sat Apr 3 19:06:04 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 3 Apr 2021 19:06:04 0000 Subject: [squeak-dev] The Trunk: KernelTests-codefrau.395.mcz Message-ID: Vanessa Freudenberg uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz ==================== Summary ==================== Name: KernelTests-codefrau.395 Author: codefrau Time: 3 April 2021, 12:06:03.17026 pm UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc Ancestors: KernelTests-mt.394 Fix typo in CompiledMethodComparisonTest. =============== Diff against KernelTests-mt.394 =============== Item was changed: ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- testHash | ai | ai := CompiledMethod allInstances. "We assume here that if two CompiledMethods are equal then they have the same size and header." (ai groupBy: [ :method | { method size. method header } ]) values replace: [ :each | each asArray ]; do: [ :methods | 1 to: methods size do: [ :i | i to: methods size do: [ :j | (methods at: i) = (methods at: j) ifTrue: [ + self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] - self assert: (methods at: i) hash equals: (methods at: i) hash ] ] ] ] displayingProgress: 'Testing hashes'. self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! From vanessa at codefrau.net Sat Apr 3 19:11:07 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sat, 3 Apr 2021 12:11:07 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <74793F41-945B-454D-8917-44D4FDB4B687@rowledge.org> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <74793F41-945B-454D-8917-44D4FDB4B687@rowledge.org> Message-ID: On Fri, Apr 2, 2021 at 10:21 AM tim Rowledge wrote: > > On 2021-04-02, at 1:10 AM, Rein, Patrick wrote: > > > > Candidates should nominate themselves and start their campaign on the > > squeak-dev mailing list. > > Me! Me! Vote for me! > Me too. Vanessa -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Sat Apr 3 19:11:37 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sat, 3 Apr 2021 12:11:37 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <74793F41-945B-454D-8917-44D4FDB4B687@rowledge.org> Message-ID: 👀 On Fri, Apr 2, 2021 at 3:35 PM Ron Teitelbaum wrote: > That wins for the shortest nomination email! > > Ron > > On Fri, Apr 2, 2021, 1:20 PM tim Rowledge wrote: > >> >> >> > On 2021-04-02, at 1:10 AM, Rein, Patrick wrote: >> > >> > >> > Candidates should nominate themselves and start their campaign on the >> > squeak-dev mailing list. >> >> Me! Me! Vote for me! >> >> >> tim >> -- >> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim >> How come it's 'Java One' every year? Aren't they making any progress? >> >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron at usmedrec.com Sat Apr 3 19:46:56 2021 From: ron at usmedrec.com (Ron Teitelbaum) Date: Sat, 3 Apr 2021 15:46:56 -0400 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <74793F41-945B-454D-8917-44D4FDB4B687@rowledge.org> Message-ID: Hahahah! Ok ok, new winner! Ron On Sat, Apr 3, 2021 at 3:11 PM Vanessa Freudenberg wrote: > On Fri, Apr 2, 2021 at 10:21 AM tim Rowledge wrote: > >> > On 2021-04-02, at 1:10 AM, Rein, Patrick wrote: >> > >> > Candidates should nominate themselves and start their campaign on the >> > squeak-dev mailing list. >> >> Me! Me! Vote for me! >> > > Me too. > > Vanessa > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Sat Apr 3 19:55:29 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sat, 3 Apr 2021 12:55:29 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: References: Message-ID: I just fixed a typo that went unnoticed for ~9 years (see KernelTests-codefrau.395). Even when Levente revised the code in 2015, he did not spot it: [image: image.png] IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? - Vanessa - On Sat, Apr 3, 2021 at 12:06 PM wrote: > Vanessa Freudenberg uploaded a new version of KernelTests to project The > Trunk: > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > ==================== Summary ==================== > > Name: KernelTests-codefrau.395 > Author: codefrau > Time: 3 April 2021, 12:06:03.17026 pm > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > Ancestors: KernelTests-mt.394 > > Fix typo in CompiledMethodComparisonTest. > > =============== Diff against KernelTests-mt.394 =============== > > Item was changed: > ----- Method: CompiledMethodComparisonTest>>testHash (in category > 'tests') ----- > testHash > > > | ai | > ai := CompiledMethod allInstances. > "We assume here that if two CompiledMethods are equal then they > have the same size and header." > (ai groupBy: [ :method | { method size. method header } ]) values > replace: [ :each | each asArray ]; > do: [ :methods | > 1 to: methods size do: [ :i | > i to: methods size do: [ :j | > (methods at: i) = (methods at: j) > ifTrue: [ > + self assert: (methods at: > i) hash equals: (methods at: j) hash ] ] ] ] > - self assert: (methods at: > i) hash equals: (methods at: i) hash ] ] ] ] > displayingProgress: 'Testing hashes'. > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= > ai asSet size! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 71210 bytes Desc: not available URL: From Das.Linux at gmx.de Sat Apr 3 20:41:31 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Sat, 3 Apr 2021 22:41:31 +0200 Subject: [squeak-dev] Need better default code font In-Reply-To: References: Message-ID: > On 3. Apr 2021, at 21:55, Vanessa Freudenberg wrote: > > I very much like our use of a proportional font, but maybe it's time to switch to a different one? I sure do like Fira Sans, it would be great for that I think… -t From tim at rowledge.org Sat Apr 3 23:47:35 2021 From: tim at rowledge.org (tim Rowledge) Date: Sat, 3 Apr 2021 16:47:35 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: References: Message-ID: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> > On 2021-04-03, at 12:55 PM, Vanessa Freudenberg wrote: > > IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? I din't think it's anything to do with proprtional fonts per se, but we could certainly do with some better font choices. And indeed a better manner of choosing them & setting them. The FontChooserTool is decent but the whole world-menu->appearance...->system fonts... thing is awful. This a more than a bit amusing though since I'm in the middle watching Juan's excellent talk on Cuis & vector graphics - https://vimeo.com/532636234 tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SVE: Skip on Vernal Equinox From lewis at mail.msen.com Sun Apr 4 01:40:05 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Sat, 3 Apr 2021 21:40:05 -0400 Subject: [squeak-dev] VectorGraphics (was: Need better default code font) In-Reply-To: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> Message-ID: <20210404014005.GA6334@shell.msen.com> On Sat, Apr 03, 2021 at 04:47:35PM -0700, tim Rowledge wrote: > > > On 2021-04-03, at 12:55 PM, Vanessa Freudenberg wrote: > > > > IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? > > I din't think it's anything to do with proprtional fonts per se, but we could certainly do with some better font choices. And indeed a better manner of choosing them & setting them. The FontChooserTool is decent but the whole world-menu->appearance...->system fonts... thing is awful. > > This a more than a bit amusing though since I'm in the middle watching Juan's excellent talk on Cuis & vector graphics - https://vimeo.com/532636234 > Juan's VectorGraphics package is very impressive. He has written a VM plugin that provides excellent performance and that requires no external libraries at all (100% Slang). This works with our standard Squeak VMs and can be included in future releases of the VM for Squeak and Cuis (I plan to do whatever is needed to make sure this happens). I don't know what is required to make this work with SqueakJS, but that's only because I have not looked at it yet. I expect that it can and should be done. It also works on the classic interpreter VM modulo a few issues that still need sorting, so it appears to be very portable. I really love the way this works without dependence on external libraries. It's turtles all the way down. Dave From bstjean at yahoo.com Sun Apr 4 17:33:31 2021 From: bstjean at yahoo.com (Benoit St-Jean) Date: Sun, 4 Apr 2021 17:33:31 +0000 (UTC) Subject: [squeak-dev] SqueakMap packages References: <1410971243.2113190.1617557611153.ref@mail.yahoo.com> Message-ID: <1410971243.2113190.1617557611153@mail.yahoo.com> How can I show all available packages in the SqueakMap Package Loader (Menu Apps->>SqueakMap Catalog)? Right now, even after the update, it only shows 15 packages out of 817 available. P.S. Squeak 5.3 64-bit, Windows 10. -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Sun Apr 4 17:44:14 2021 From: tim at rowledge.org (tim Rowledge) Date: Sun, 4 Apr 2021 10:44:14 -0700 Subject: [squeak-dev] SqueakMap packages In-Reply-To: <1410971243.2113190.1617557611153@mail.yahoo.com> References: <1410971243.2113190.1617557611153.ref@mail.yahoo.com> <1410971243.2113190.1617557611153@mail.yahoo.com> Message-ID: <9C520641-1734-4B6B-9090-C0A2AB47FAD8@rowledge.org> > On 2021-04-04, at 10:33 AM, Benoit St-Jean via Squeak-dev wrote: > > How can I show all available packages in the SqueakMap Package Loader (Menu Apps->>SqueakMap Catalog)? > > Right now, even after the update, it only shows 15 packages out of 817 available. In the SM window pop up the menu and untick the 'new safely available packages' option. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- Not all his dogs are barking. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screen Shot 2021-04-04 at 10.43.18 AM.png Type: image/png Size: 23847 bytes Desc: not available URL: From lewis at mail.msen.com Sun Apr 4 17:53:09 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Sun, 4 Apr 2021 13:53:09 -0400 Subject: [squeak-dev] SqueakMap packages In-Reply-To: <1410971243.2113190.1617557611153@mail.yahoo.com> References: <1410971243.2113190.1617557611153.ref@mail.yahoo.com> <1410971243.2113190.1617557611153@mail.yahoo.com> Message-ID: <20210404175309.GA26516@shell.msen.com> On Sun, Apr 04, 2021 at 05:33:31PM +0000, Benoit St-Jean via Squeak-dev wrote: > How can I show all available packages in the SqueakMap Package Loader (Menu Apps->>SqueakMap Catalog)? > Right now, even after the update, it only shows 15 packages out of 817 available. > P.S. Squeak 5.3 64-bit, Windows 10. In the SqueakMap Package Loader, click for menu in one of the left hand panes, and de-select the "New safely-available packages" option. I can't explain the logic behind these options. I just turn them off. Dave From craig at blackpagedigital.com Sun Apr 4 18:18:44 2021 From: craig at blackpagedigital.com (Craig Latta) Date: Sun, 4 Apr 2021 11:18:44 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: Hi all-- Please vote for me for the Squeak Oversight Board in 2021. I've been organizing the board meetings for a few years now, and I'm coordinating a 25th anniversary celebration for Squeak in September. I'm also recording an anniversary podcast interview series; please let me know if you'd like to be part of that. I'm very excited about Squeak these days! I'm writing a webapp with SqueakJS[1], Croquet[2], and Caffeine[3] at beatshifting.org, enabling musicians to play together to a distributed beat. I'm also using Squeak as the center of my music production studio, controlling lots of sound, video, and MIDI gear. My experiments in virtual reality continue as well, with mashups of Caffeine and A-Frame on the Oculus Quest headset. I'd like to continue scheming about the future of Squeak with the board, and expanding our realtime community activity. In January, Dan Ingalls, Vanessa Freudenberg and I started the California Smalltalkers meetup group, with group video gatherings. It's been going very well, and it has inspired me to use the video technology for Squeak gatherings also. I'd like to have an online Squeakers conference in September, and regular gatherings on second and fourth Wednesdays leading up to it. Join us on squeak.slack.org to find out more. Hm, this won't be the shortest candidacy message. :) thanks! Craig [1] https://squeak.js.org [2] https://croquet.io [3] https://caffeine.js.org -- Craig Latta :: research computer scientist Black Page Digital :: Berkeley, California 663137D7940BF5C0AFC :: 1349FB2ADA32C4D5314CE From vanessa at codefrau.net Sun Apr 4 20:28:33 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sun, 4 Apr 2021 13:28:33 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> Message-ID: On Sat, Apr 3, 2021 at 4:47 PM tim Rowledge wrote: > > > On 2021-04-03, at 12:55 PM, Vanessa Freudenberg > wrote: > > > > IMHO (speaking as a typo nerd) this is due to our default code font not > having distinct enough letter shapes. I very much like our use of a > proportional font, but maybe it's time to switch to a different one? > > I din't think it's anything to do with proprtional fonts per se, Only insofar as that I do not know a single proportional font that has been optimized for coding, as opposed to dozens of monospaced fonts (there is Input Sans, granted, but that looks very much monospaced with only a few adjustments). I bet choosing the right glyph variants in some proportional font would help. Tobi suggested Fira Sans, and while I like Spiekermann fonts in general and Fira Sans in particular, the rendering of e.g. ":=" is atrocious, because that combination just does not happen in "normal" text. - Vanessa - -------------- next part -------------- An HTML attachment was scrubbed... URL: From bstjean at yahoo.com Sun Apr 4 21:53:24 2021 From: bstjean at yahoo.com (Benoit St-Jean) Date: Sun, 4 Apr 2021 21:53:24 +0000 (UTC) Subject: [squeak-dev] =?utf-8?q?Re=C2=A0=3A_Re=3A__Need_better_default_cod?= =?utf-8?q?e_font?= In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> Message-ID: <178495258.2143683.1617573204650@mail.yahoo.com> A few suggestions here... https://www.creativebloq.com/features/the-best-monospace-fonts-for-coding Envoyé à partir de Yahoo Courriel sur Android Le dim., avr. 4 2021 à 16:29, Vanessa Freudenberg a écrit : -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Sun Apr 4 22:06:12 2021 From: tim at rowledge.org (tim Rowledge) Date: Sun, 4 Apr 2021 15:06:12 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> Message-ID: <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> > On 2021-04-04, at 1:28 PM, Vanessa Freudenberg wrote: > > On Sat, Apr 3, 2021 at 4:47 PM tim Rowledge wrote: > >> On 2021-04-03, at 12:55 PM, Vanessa Freudenberg wrote: >> >> IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? > > I din't think it's anything to do with proprtional fonts per se, > > Only insofar as that I do not know a single proportional font that has been optimized for coding, as opposed to dozens of monospaced fonts (there is Input Sans, granted, but that looks very much monospaced with only a few adjustments). > > I bet choosing the right glyph variants in some proportional font would help. I quite like Roboto (perhaps in part because we use a 'Piboto' variant on Pi) Take a look at - https://fonts.google.com/specimen/Roboto?query=roboto&preview.text=%5Bself%20add:%20$4;%20add:;%20and:%5Bg:%3D%2034%5D.%20%20:%3D%20i,%20j&preview.text_type=custom#standard-styles I really wish there was a propelr left-arrow-assign for use to use. I hate ':='; it's so.... C tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Great leaders inspire by example. When that's not an option, brute intimidation works pretty well. From tim at rowledge.org Sun Apr 4 22:19:10 2021 From: tim at rowledge.org (tim Rowledge) Date: Sun, 4 Apr 2021 15:19:10 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: <178495258.2143683.1617573204650@mail.yahoo.com> References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <178495258.2143683.1617573204650@mail.yahoo.com> Message-ID: <2A821ACF-AA85-4D5F-AED3-B0461442AB7E@rowledge.org> > On 2021-04-04, at 2:53 PM, Benoit St-Jean via Squeak-dev wrote: > > A few suggestions here... > > https://www.creativebloq.com/features/the-best-monospace-fonts-for-coding I deeply dislike monospaced fonts for Smalltalk. Again, far too C. We're not programming mere machines here folks, we're having a conversation with objects. How about https://fonts.google.com/specimen/Knewave ? :-) Teko is quite nice and clear. Or go really retro with 'Press Start 2P'. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- One bit short of a word. From Das.Linux at gmx.de Mon Apr 5 06:32:43 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 5 Apr 2021 08:32:43 +0200 Subject: [squeak-dev] Need better default code font In-Reply-To: <2A821ACF-AA85-4D5F-AED3-B0461442AB7E@rowledge.org> References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <178495258.2143683.1617573204650@mail.yahoo.com> <2A821ACF-AA85-4D5F-AED3-B0461442AB7E@rowledge.org> Message-ID: > On 5. Apr 2021, at 00:19, tim Rowledge wrote: > > > >> On 2021-04-04, at 2:53 PM, Benoit St-Jean via Squeak-dev wrote: >> >> A few suggestions here... >> >> https://www.creativebloq.com/features/the-best-monospace-fonts-for-coding > > I deeply dislike monospaced fonts for Smalltalk. Again, far too C. We're not programming mere machines here folks, we're having a conversation with objects. > > How about https://fonts.google.com/specimen/Knewave ? :-) > Teko is quite nice and clear. Or go really retro with 'Press Start 2P'. I've been using Source Sans Pro (not Source Code, the mono variant) and Fira Sans for quite a while in different editors as proportional, sans-serif code fonts. The work very well. If we had ligatures, I think proper := is doable in any of these, and if we want to go all in, we can change these open source fonts to auto-mazing-ly replace them by left-arrow; and that visually only. Best regards -Tobias From kirtai+st at gmail.com Mon Apr 5 07:42:31 2021 From: kirtai+st at gmail.com (Douglas Brebner) Date: Mon, 5 Apr 2021 08:42:31 +0100 Subject: [squeak-dev] Need better default code font In-Reply-To: <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> Message-ID: On 04/04/2021 23:06, tim Rowledge wrote: > I really wish there was a propelr left-arrow-assign for use to use. I hate ':='; it's so.... C I thought it was taken from Pascal. From kirtai+st at gmail.com Mon Apr 5 07:45:44 2021 From: kirtai+st at gmail.com (Douglas Brebner) Date: Mon, 5 Apr 2021 08:45:44 +0100 Subject: [squeak-dev] Need better default code font In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <178495258.2143683.1617573204650@mail.yahoo.com> <2A821ACF-AA85-4D5F-AED3-B0461442AB7E@rowledge.org> Message-ID: <4ef0c744-168d-2deb-e2e8-bb07fdeebbe5@gmail.com> On 05/04/2021 07:32, Tobias Pape wrote: > I've been using Source Sans Pro (not Source Code, the mono variant) and Fira Sans for quite a while > in different editors as proportional, sans-serif code fonts. The work very well. I've come to like serif fonts for high dpi displays. Unfortunately, the one I want most is quite expensive (the serif version of Fira). > If we had ligatures, I think proper := is doable in any of these, and if we want to go all in, > we can change these open source fonts to auto-mazing-ly replace them by left-arrow; and that visually > only. That would be amazing. From m at jaromir.net Mon Apr 5 17:00:27 2021 From: m at jaromir.net (Jaromir Matas) Date: Mon, 5 Apr 2021 12:00:27 -0500 (CDT) Subject: [squeak-dev] Solving multiple termination bugs - summary & proposal Message-ID: <1617642027172-0.post@n4.nabble.com> Hi All, here's a summary of bugs in the current termination procedure: 1. #isTerminated and #isSuspended fail to report correctly - in [1] 2. active process termination bug causing an image crash - in [2] 3. nested unwind bug: skipping some ensure blocks - in [3] 4. likely a bug: a failure to complete nested unwind blocks halfway thru execution - also in [3] 5. Christoph's discovery: a failure to correctly close the debugger in case of error or non-local return in unwind - in [4] 6. inconsistent semantics of unwinding protected blocks during active vs. suspended process termination (not reported yet - different sets of unwind blocks are executed depending on whether a process terminates itself or whether some other process initiates its termination; the proposed solution unifies active and suspended process termination and is consistent with Visual Works semantics (and goes beyond)) [1] http://forum.world.st/The-Inbox-Kernel-jar-1376-mcz-td5127335.html#a5127336 [2] http://forum.world.st/A-bug-in-active-process-termination-crashing-image-td5128186.html [3] http://forum.world.st/Another-bug-in-Process-terminate-in-unwinding-contexts-tp5128171p5128178.html [4] http://forum.world.st/Bug-in-Process-gt-gt-terminate-Returning-from-unwind-contexts-td5127570.html#a5128095 I'd like to propose a solution - a rewrite of #terminate - addressing all of the above issues. Main points of the solution are: (i) why differentiate active and suspended process termination? I propose to unify the two: to suspend the active process and terminate it as a suspended process. As a result the semantics/outcome of the unwind algorithm will be the same in both cases. Fixes 2 and 6. (ii) the above leads to a susbstantial simplification of #isTerminated - a process is terminated when at the last instruction of its bottom context. Fixes 1. (iii) unwind algorithm for incomplete unwind blocks is extended to execute the outer-most instead of the inner-most incomplete unwind context. Fixes 3 and 4. (iv) indirect termination via #popTo is replaced with a analogue of #unwindTo: using Eliot's ingenious #runUntilErrorOrReturnFrom: the same way as in (iii). I'd very much appreciate if someone commented this part because I haven't found any clue why the indirect termination has implemented using #popTo and not #runUntilErrorOrReturnFrom. Fixes 5. I enclose a set of examples used to compare the current Squeak semantics with the proposed one (and with VW) that can be used to build test cases. Here's a commented code. I'll be happy to provide detailed step-by-step guidance if you find this whole idea interesting and worth implementing. I'm convinced at least parts of the proposal should be integrated as simple fixes of the current bugs. Thank you for your patience if you're still reading :) Any feedback extremely welcome. A changeset is enclosed for your convenience here: Fix_terminate_v2.cs Process >> terminate "Stop the process that the receiver represents so that it answers true to #isTerminated. Unwind to execute pending and unfinished ensure:/ifCurtailed: blocks before terminating. If the process is in the middle of a critical: critical section, release it properly." | ctxt unwindBlock oldList outerMost | self isActiveProcess ifTrue: [ "If terminating the active process, suspend it first and terminate it as a suspended process. Nested #terminate messages could derail the termination so let's enclose it in #ensure." [[] ensure: [self terminate]] fork. ^self suspend]. "Always suspend the process first so it doesn't accidentally get woken up. N.B. If oldList is a LinkedList then the process is runnable. If it is a Semaphore/Mutex et al then the process is blocked, and if it is nil then the process is already suspended." oldList := self suspend. suspendedContext ifNotNil: ["Release any method marked with the pragma. The argument is whether the process is runnable." self releaseCriticalSection: (oldList isNil or: [oldList class == LinkedList]). "If terminating a process halfways through an unwind, try to complete that unwind block first; if there are multiple such nested unwind blocks, try to complete the outer-most one; the inner blocks will be completed in the process." ctxt := suspendedContext. [(ctxt := ctxt findNextUnwindContextUpTo: nil) isNil] whileFalse: "Contexts under evaluation have already set their complete (tempAt: 2) to true." [(ctxt tempAt:2) ifNotNil: [outerMost := ctxt]]. outerMost ifNotNil: [ "This is the outer-most unwind context currently under evaluation; let's find an inner context executing outerMost's argument block (tempAt: 1)" (suspendedContext findContextSuchThat: [:ctx | ctx closure == (outerMost tempAt: 1)]) ifNotNil: [:inner | "Let's finish the unfinished unwind context only (i.e. up to inner) and return here" suspendedContext runUntilErrorOrReturnFrom: inner. "Update the receiver's suspendedContext (the previous step reset its sender to nil)" suspendedContext := outerMost]]. "Now all unwind blocks caught halfway through have been completed; let's execute the ones still pending. Note: #findNextUnwindContextUpTo: starts searching from the receiver's sender but the receiver itself may be an unwind context." ctxt := suspendedContext. ctxt isUnwindContext ifFalse: [ctxt := ctxt findNextUnwindContextUpTo: nil]. [ctxt isNil] whileFalse: [ (ctxt tempAt: 2) ifNil: [ ctxt tempAt: 2 put: true. unwindBlock := ctxt tempAt: 1. "Create a context for the unwind block and execute it on the unwind block's stack. Note: using #value instead of #runUntilErrorOrReturnFrom: would lead to executing the unwind on the wrong stack preventing the correct execution of non-local returns." suspendedContext := unwindBlock asContextWithSender: ctxt. suspendedContext runUntilErrorOrReturnFrom: suspendedContext]. ctxt := ctxt findNextUnwindContextUpTo: nil]. "Set the context to its endPC and its sender to nil for the benefit of isTerminated." ctxt := suspendedContext. ctxt terminateTo: nil. ctxt pc: ctxt endPC] Process >> isTerminated "Answer if the receiver is terminated. A process is considered terminated if the suspendedContext is the bottomContext and the pc is at the endPC" self isActiveProcess ifTrue: [^ false]. ^suspendedContext isNil or: [ suspendedContext isBottomContext and: [ suspendedContext isDead or: [suspendedContext atEnd]]] Process >> isSuspended "A process is suspended if it has non-nil suspendedContext (e.g. new or previously suspended with the suspend primitive) and is not terminated or waiting in a scheduler or a semaphore queue (i.e. is not runnable or blocked)." ^myList isNil and: [suspendedContext notNil and: [self isTerminated not]] Debugger >> windowIsClosing "My window is being closed; clean up. Restart the low space watcher. If the debugged process is a do-it, it may do a non-local return escaping termination so we need to insert a #terminate context under the do-it to make sure the debugged UI process will terminate." | doItContext terminateContext | (interruptedProcess == nil or: [interruptedProcess suspendedContext isNil]) ifTrue: [^ self]. "find a do-it context; answer nil if it doesn't exist in the sender chain" doItContext := interruptedProcess suspendedContext findContextSuchThat: [:ctx | ctx methodClass = UndefinedObject and: [ ctx selector = #DoIt and: [ ctx closure isNil]]]. doItContext ifNotNil: [ "it exists so let's insert a #terminate context" terminateContext := Context sender: doItContext sender receiver: interruptedProcess method: (Process>>#terminate) arguments: {}. doItContext privSender: terminateContext ]. interruptedProcess terminate. interruptedProcess := nil. contextStack := nil. receiverInspector := nil. contextVariablesInspector := nil. Smalltalk installLowSpaceWatcher. "restart low space handler" A few examples to illustrate the idea (many more enclosed here Some_examples_to_examine_terminate_bugs.txt ): Ex. 1: | p | "Suspend process inside ensure block and make sure x1 x2 and x3 are printed. Currently only x1 is printed." p := [ [ [ ] ensure: [ [ ] ensure: [ Processor activeProcess suspend. Transcript show: 'x1']. Transcript show: 'x2'] ] ensure: [ Transcript show: 'x3'] ] fork. Processor yield. p terminate ---> x1 (instead of x1 x2 x3) Ex. 2: | p | Currently only x3 is printed." p := [ [ [ ] ensure: [ [ ] ensure: [ Processor activeProcess terminate. Transcript show: 'x1']. "terminate active process inside ensure block and make sure x1 x2 and x3 are printed. Transcript show: 'x2'] ] ensure: [ Transcript show: 'x3'] ] fork. Processor yield ---> x3 (instead of x1 x2 x3) Ex. 3: "unwind after error inside ensure block and make sure x1 x2 and x3 are printed. [ [ ] ensure: [ [ ] ensure: [ self error. Transcript show: 'x1']. Transcript show: 'x2'] ] ensure: [ ^Transcript show: 'x3'] ---> x3 (instead of x1 x2 x3) Note: nested errors during unwind follow #runUntilErrorOrReturnFrom: logic, i.e. return exception and let user decide... ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From tim at rowledge.org Mon Apr 5 17:55:39 2021 From: tim at rowledge.org (tim Rowledge) Date: Mon, 5 Apr 2021 10:55:39 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> Message-ID: <99848311-8386-4520-9CE7-BA819C0C42FC@rowledge.org> > On 2021-04-05, at 12:42 AM, Douglas Brebner wrote: > > On 04/04/2021 23:06, tim Rowledge wrote: >> I really wish there was a propelr left-arrow-assign for use to use. I hate ':='; it's so.... C > > > I thought it was taken from Pascal. C, Pascal, FORTRAN.. all based on assault and pillage of memory. As Adele Goldberg used to quip "Ask, don't grab". But yeah, well spotted on an embarrassing slip. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: EROS: Erase Read-Only Storage From jecel at merlintec.com Mon Apr 5 20:36:54 2021 From: jecel at merlintec.com (Jecel Assumpcao Jr) Date: Mon, 5 Apr 2021 17:36:54 -0300 Subject: [squeak-dev] Need better default code font In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> Message-ID: <20210405203657.312818C15D5@proxy.email-ssl.com.br> Douglas Brebner wrote on Mon, 5 Apr 2021 08:42:31 +0100 > On 04/04/2021 23:06, tim Rowledge wrote: > > I really wish there was a propelr left-arrow-assign for use to use. I hate ':='; it's so.... C > > > I thought it was taken from Pascal. Digitalk introduced ":=" to Smalltalk in its Methods implementation for the IBM PC even though that machine did have a left arrow characeter (but with a very different encoding than 1963 ASCII used by Xerox). Given that the first part of the manual showed code fragments in Methods and Pascal side by side, it is clear that the choice was indeed made to make Pascal programmers (the most numerous in the early 1980s) feel at home. See chapter 2 of > http://www.wirfs-brock.com/allen/files/digitalk/methods-language-guide.pdf Note that not all PDF readers can handle this file. -- Jecel From vanessa at codefrau.net Mon Apr 5 20:37:20 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Mon, 5 Apr 2021 13:37:20 -0700 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: References: Message-ID: Since we're on the subject of how our code looks: I would 💜 love 💜 if we had elastic tabstops by default in our code editors. This would eliminate (IMHO) the biggest counter-argument to using proportional fonts. Vanessa On Sat, Apr 3, 2021 at 12:55 PM Vanessa Freudenberg wrote: > I just fixed a typo that went unnoticed for ~9 years (see KernelTests-codefrau.395). > Even when Levente revised the code in 2015, he did not spot it: > > [image: image.png] > > IMHO (speaking as a typo nerd) this is due to our default code font not > having distinct enough letter shapes. I very much like our use of a > proportional font, but maybe it's time to switch to a different one? > > - Vanessa - > > On Sat, Apr 3, 2021 at 12:06 PM wrote: > >> Vanessa Freudenberg uploaded a new version of KernelTests to project The >> Trunk: >> http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz >> >> ==================== Summary ==================== >> >> Name: KernelTests-codefrau.395 >> Author: codefrau >> Time: 3 April 2021, 12:06:03.17026 pm >> UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc >> Ancestors: KernelTests-mt.394 >> >> Fix typo in CompiledMethodComparisonTest. >> >> =============== Diff against KernelTests-mt.394 =============== >> >> Item was changed: >> ----- Method: CompiledMethodComparisonTest>>testHash (in category >> 'tests') ----- >> testHash >> >> >> | ai | >> ai := CompiledMethod allInstances. >> "We assume here that if two CompiledMethods are equal then they >> have the same size and header." >> (ai groupBy: [ :method | { method size. method header } ]) values >> replace: [ :each | each asArray ]; >> do: [ :methods | >> 1 to: methods size do: [ :i | >> i to: methods size do: [ :j | >> (methods at: i) = (methods at: j) >> ifTrue: [ >> + self assert: (methods at: >> i) hash equals: (methods at: j) hash ] ] ] ] >> - self assert: (methods at: >> i) hash equals: (methods at: i) hash ] ] ] ] >> displayingProgress: 'Testing hashes'. >> self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= >> ai asSet size! >> >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 71210 bytes Desc: not available URL: From Das.Linux at gmx.de Mon Apr 5 20:39:10 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 5 Apr 2021 22:39:10 +0200 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: References: Message-ID: > On 5. Apr 2021, at 22:37, Vanessa Freudenberg wrote: > > Since we're on the subject of how our code looks: > I would 💜 love 💜 if we had elastic tabstops by default in our code editors. > This would eliminate (IMHO) the biggest counter-argument to using proportional fonts. > +100 -t > > > Vanessa > > On Sat, Apr 3, 2021 at 12:55 PM Vanessa Freudenberg wrote: > I just fixed a typo that went unnoticed for ~9 years (see KernelTests-codefrau.395). Even when Levente revised the code in 2015, he did not spot it: > > > > IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? > > - Vanessa - > > On Sat, Apr 3, 2021 at 12:06 PM wrote: > Vanessa Freudenberg uploaded a new version of KernelTests to project The Trunk: > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > ==================== Summary ==================== > > Name: KernelTests-codefrau.395 > Author: codefrau > Time: 3 April 2021, 12:06:03.17026 pm > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > Ancestors: KernelTests-mt.394 > > Fix typo in CompiledMethodComparisonTest. > > =============== Diff against KernelTests-mt.394 =============== > > Item was changed: > ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- > testHash > > > | ai | > ai := CompiledMethod allInstances. > "We assume here that if two CompiledMethods are equal then they have the same size and header." > (ai groupBy: [ :method | { method size. method header } ]) values > replace: [ :each | each asArray ]; > do: [ :methods | > 1 to: methods size do: [ :i | > i to: methods size do: [ :j | > (methods at: i) = (methods at: j) ifTrue: [ > + self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] > - self assert: (methods at: i) hash equals: (methods at: i) hash ] ] ] ] > displayingProgress: 'Testing hashes'. > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! > > > From vanessa at codefrau.net Mon Apr 5 21:37:55 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Mon, 5 Apr 2021 14:37:55 -0700 Subject: [squeak-dev] The Trunk: KernelTests-codefrau.395.mcz In-Reply-To: References: Message-ID: Btw, I only fixed the test. Which makes the test fail in trunk. Eliot must have had a reason to create the test so Someone™️ should probably look at that. I probably don't have time for that soon. - Vanessa - On Sat, Apr 3, 2021 at 12:06 PM wrote: > Vanessa Freudenberg uploaded a new version of KernelTests to project The > Trunk: > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > ==================== Summary ==================== > > Name: KernelTests-codefrau.395 > Author: codefrau > Time: 3 April 2021, 12:06:03.17026 pm > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > Ancestors: KernelTests-mt.394 > > Fix typo in CompiledMethodComparisonTest. > > =============== Diff against KernelTests-mt.394 =============== > > Item was changed: > ----- Method: CompiledMethodComparisonTest>>testHash (in category > 'tests') ----- > testHash > > > | ai | > ai := CompiledMethod allInstances. > "We assume here that if two CompiledMethods are equal then they > have the same size and header." > (ai groupBy: [ :method | { method size. method header } ]) values > replace: [ :each | each asArray ]; > do: [ :methods | > 1 to: methods size do: [ :i | > i to: methods size do: [ :j | > (methods at: i) = (methods at: j) > ifTrue: [ > + self assert: (methods at: > i) hash equals: (methods at: j) hash ] ] ] ] > - self assert: (methods at: > i) hash equals: (methods at: i) hash ] ] ] ] > displayingProgress: 'Testing hashes'. > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= > ai asSet size! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 6 10:50:39 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 6 Apr 2021 12:50:39 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: Hi Patrick, hi Ron, hi all! :-) I would like to continue serving on the Squeak Oversight Board in 2021! Looking back on 2020, there were some noteworthy events where I was able to contribute a little something to Squeak's ecosystem and its community. First, my role as a shepherd for inbox contributions got more serious and fun, nonetheless due to Christoph's (ct) numerous ideas: http://forum.world.st/Please-try-out-Inspector-Refactoring-tp5114974.html [http://forum.world.st/Please-try-out-Inspector-Refactoring-tp5114974.html] http://forum.world.st/Please-try-out-Fixes-for-debugger-invocation-during-code-simulation-tp5127684.html [http://forum.world.st/Please-try-out-Fixes-for-debugger-invocation-during-code-simulation-tp5127684.html] In the beginning of 2020, I helped Hannes (hjh) getting the 5.3 release out into the wild: http://forum.world.st/Brief-update-on-the-Squeak-5-3-release-schedule-td5112129.html [http://forum.world.st/Brief-update-on-the-Squeak-5-3-release-schedule-td5112129.html] http://forum.world.st/ANN-Squeak-5-3-released-www-squeak-org-Trunk-open-again-tp5112795.html [http://forum.world.st/ANN-Squeak-5-3-released-www-squeak-org-Trunk-open-again-tp5112795.html] There were a few events, where I thought that it would be nice to involve the Squeak community a little bit more: http://forum.world.st/Squeak-Winter-Demos-2021-03-06-3-p-m-6-p-m-CET-virtual-tp5126913.html [http://forum.world.st/Squeak-Winter-Demos-2021-03-06-3-p-m-6-p-m-CET-virtual-tp5126913.html] http://forum.world.st/CfP-Programming-Experience-Workshop-PX-21-tp5126609.html [http://forum.world.st/CfP-Programming-Experience-Workshop-PX-21-tp5126609.html] A serious portion of my spring/summer time went into understanding and (hopefully) improving Squeak's FFI, keeping an eye on tool support. After the next iteration on FFI-Pools, I wrote my first bigger commentary on that spanning multiple class comments: http://forum.world.st/FFI-FFI-Pools-mt-18-mcz-td5117607.html [http://forum.world.st/FFI-FFI-Pools-mt-18-mcz-td5117607.html] In general, I am interested in restructuring and cleaning up the system to improve modularity and readability: http://forum.world.st/Proposal-Geometry-Classes-tp5093998p5127584.html [http://forum.world.st/Proposal-Geometry-Classes-tp5093998p5127584.html] http://forum.world.st/Proposal-Resetting-pragma-preferences-via-nil-or-reset-message-tp5123490.html [http://forum.world.st/Proposal-Resetting-pragma-preferences-via-nil-or-reset-message-tp5123490.html] http://forum.world.st/The-Trunk-Morphic-mt-1732-mcz-td5127408.html [http://forum.world.st/The-Trunk-Morphic-mt-1732-mcz-td5127408.html] Occasionally, crazy ideas and other projects pop up: http://forum.world.st/Collections-Streams-About-enumerating-a-sequence-up-to-a-matching-query-td5127541.html [http://forum.world.st/Collections-Streams-About-enumerating-a-sequence-up-to-a-matching-query-td5127541.html] http://forum.world.st/ANN-MessageSendRecorder-and-MethodWrappers-GitHub-tp5120077.html [http://forum.world.st/ANN-MessageSendRecorder-and-MethodWrappers-GitHub-tp5120077.html] *** Happy Squeaking everybody! :-) Best, Marcel Am 04.04.2021 20:19:04 schrieb Craig Latta : Hi all-- Please vote for me for the Squeak Oversight Board in 2021. I've been organizing the board meetings for a few years now, and I'm coordinating a 25th anniversary celebration for Squeak in September. I'm also recording an anniversary podcast interview series; please let me know if you'd like to be part of that. I'm very excited about Squeak these days! I'm writing a webapp with SqueakJS[1], Croquet[2], and Caffeine[3] at beatshifting.org, enabling musicians to play together to a distributed beat. I'm also using Squeak as the center of my music production studio, controlling lots of sound, video, and MIDI gear. My experiments in virtual reality continue as well, with mashups of Caffeine and A-Frame on the Oculus Quest headset. I'd like to continue scheming about the future of Squeak with the board, and expanding our realtime community activity. In January, Dan Ingalls, Vanessa Freudenberg and I started the California Smalltalkers meetup group, with group video gatherings. It's been going very well, and it has inspired me to use the video technology for Squeak gatherings also. I'd like to have an online Squeakers conference in September, and regular gatherings on second and fourth Wednesdays leading up to it. Join us on squeak.slack.org to find out more. Hm, this won't be the shortest candidacy message. :) thanks! Craig [1] https://squeak.js.org [2] https://croquet.io [3] https://caffeine.js.org -- Craig Latta :: research computer scientist Black Page Digital :: Berkeley, California 663137D7940BF5C0AFC :: 1349FB2ADA32C4D5314CE -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Tue Apr 6 16:45:22 2021 From: tim at rowledge.org (tim Rowledge) Date: Tue, 6 Apr 2021 09:45:22 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: > On 2021-04-06, at 3:50 AM, Marcel Taeumel wrote: > > Hi Patrick, hi Ron, hi all! :-) > > I would like to continue serving on the Squeak Oversight Board in 2021! An important point here - Marcel has done a *huge* amount of good work for Squeak. Long may it continue. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim All computers run at the same speed...with the power off. From asqueaker at gmail.com Tue Apr 6 18:56:59 2021 From: asqueaker at gmail.com (Chris Muller) Date: Tue, 6 Apr 2021 13:56:59 -0500 Subject: [squeak-dev] SqueakMap packages In-Reply-To: <20210404175309.GA26516@shell.msen.com> References: <1410971243.2113190.1617557611153.ref@mail.yahoo.com> <1410971243.2113190.1617557611153@mail.yahoo.com> <20210404175309.GA26516@shell.msen.com> Message-ID: > > In the SqueakMap Package Loader, click for menu in one of the left > hand panes, and de-select the "New safely-available packages" option. > > I can't explain the logic behind these options. I just turn them off. > It's been explained by the first paragraph of this page since 2011. http://wiki.squeak.org/squeak/6182 - Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: From lewis at mail.msen.com Wed Apr 7 00:26:44 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Tue, 6 Apr 2021 20:26:44 -0400 Subject: [squeak-dev] SqueakMap packages In-Reply-To: References: <1410971243.2113190.1617557611153.ref@mail.yahoo.com> <1410971243.2113190.1617557611153@mail.yahoo.com> <20210404175309.GA26516@shell.msen.com> Message-ID: <20210407002644.GA30099@shell.msen.com> On Tue, Apr 06, 2021 at 01:56:59PM -0500, Chris Muller wrote: > > > > In the SqueakMap Package Loader, click for menu in one of the left > > hand panes, and de-select the "New safely-available packages" option. > > > > I can't explain the logic behind these options. I just turn them off. > > > > It's been explained by the first paragraph of this page since 2011. > > http://wiki.squeak.org/squeak/6182 > > - Chris Hi Chris, Thanks, yes that is the proper reference. I was not clear, when I said "can't explain the logic" I was referring to the multi-select check box logic in the tool. There are five selectable options ("Auto-installable packages", "new available packages", etc) so my expectation would be that selecting two options would result in the list displaying the OR of the two selections. As implemented it is the AND of the selections, which does not produce a very useful result. That's why I just turn them all off when I want to look for packages on SqueakMap. I also tend to work in a trunk image, for which there are no new safely available packages. So again, I just turn off all of the options in the tool. Dave From ma.chris.m at gmail.com Wed Apr 7 01:53:20 2021 From: ma.chris.m at gmail.com (Chris Muller) Date: Tue, 6 Apr 2021 20:53:20 -0500 Subject: [squeak-dev] SqueakMap packages In-Reply-To: <20210407002644.GA30099@shell.msen.com> References: <1410971243.2113190.1617557611153.ref@mail.yahoo.com> <1410971243.2113190.1617557611153@mail.yahoo.com> <20210404175309.GA26516@shell.msen.com> <20210407002644.GA30099@shell.msen.com> Message-ID: > I was not clear, when I said "can't explain the logic" I was referring > to the multi-select check box logic in the tool. There are five selectable > options ("Auto-installable packages", "new available packages", etc) so > my expectation would be that selecting two options would result in the > list displaying the OR of the two selections. As implemented it is the > AND of the selections, which does not produce a very useful result. That's > why I just turn them all off when I want to look for packages on SqueakMap. Oh yeah, I totally agree, those UI toggles are confusing, and clumsy even when you know what they mean. > I also tend to work in a trunk image, for which there are no new safely > available packages. So again, I just turn off all of the options in the tool. I hope to have a client streamlined for all the use-cases, hopefully it can be done fairly easily from scratch. Something like the SystemBrowser, with middle row of two buttons that toggle the list between [ 5.3 | All ], where "5.3" is the one detected from the SmalltalkImage field(s), and then a row of "Browse" and "Install" buttons. Everything just, there. From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 14:55:03 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 14:55:03 +0000 Subject: [squeak-dev] The Trunk: KernelTests-codefrau.395.mcz In-Reply-To: References: , Message-ID: <54989ee87467405f96cba462d63409b7@student.hpi.uni-potsdam.de> The reason appears to be that CompiledCode >> #hash takes the receiver class into consideration whereas CompiledCode >> #= doesn't. So what behavior do we actually want? If you remove the "+ self methodClass hash" from CompiledCode >> #hash, #testHash fails in the last statement instead because there are too many double hashes. Should we respect the methodClass in CompiledCode >> #= as well? I think this could actually make sense because the byte codes for inst var access are only meaningful in combination with the definition of the receiver class. Opinions? :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Vanessa Freudenberg Gesendet: Montag, 5. April 2021 23:37:55 An: The general-purpose Squeak developers list Cc: packages at lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: KernelTests-codefrau.395.mcz Btw, I only fixed the test. Which makes the test fail in trunk. Eliot must have had a reason to create the test so Someone™️ should probably look at that. I probably don't have time for that soon. - Vanessa - On Sat, Apr 3, 2021 at 12:06 PM > wrote: Vanessa Freudenberg uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz ==================== Summary ==================== Name: KernelTests-codefrau.395 Author: codefrau Time: 3 April 2021, 12:06:03.17026 pm UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc Ancestors: KernelTests-mt.394 Fix typo in CompiledMethodComparisonTest. =============== Diff against KernelTests-mt.394 =============== Item was changed: ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- testHash | ai | ai := CompiledMethod allInstances. "We assume here that if two CompiledMethods are equal then they have the same size and header." (ai groupBy: [ :method | { method size. method header } ]) values replace: [ :each | each asArray ]; do: [ :methods | 1 to: methods size do: [ :i | i to: methods size do: [ :j | (methods at: i) = (methods at: j) ifTrue: [ + self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] - self assert: (methods at: i) hash equals: (methods at: i) hash ] ] ] ] displayingProgress: 'Testing hashes'. self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 7 15:20:16 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 7 Apr 2021 15:20:16 0000 Subject: [squeak-dev] The Inbox: ShoutTests-ct.34.mcz Message-ID: A new version of ShoutTests was added to project The Inbox: http://source.squeak.org/inbox/ShoutTests-ct.34.mcz ==================== Summary ==================== Name: ShoutTests-ct.34 Author: ct Time: 7 April 2021, 5:20:15.847598 pm UUID: a7f39f26-a6fb-f44e-aabb-931714b56ed8 Ancestors: ShoutTests-mt.33 Document a present bug that occurs when styling a method that contains multiple unary selectors after a cascade. =============== Diff against ShoutTests-mt.33 =============== Item was added: + ----- Method: SHParserST80Test>>testChainAfterCascade (in category 'tests') ----- + testChainAfterCascade + + | types s | + s := 'x 1 positive; negative not'. + + types := self tokenTypesIn: s. + + self + assert: #(patternUnary number unary cascadeSeparator unary excessCode) + equals: types.! From commits at source.squeak.org Wed Apr 7 15:21:00 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 7 Apr 2021 15:21:00 0000 Subject: [squeak-dev] The Inbox: ShoutCore-ct.85.mcz Message-ID: A new version of ShoutCore was added to project The Inbox: http://source.squeak.org/inbox/ShoutCore-ct.85.mcz ==================== Summary ==================== Name: ShoutCore-ct.85 Author: ct Time: 7 April 2021, 5:21:00.504598 pm UUID: 555b2e6b-ef80-e842-85ee-aa1276ccddbf Ancestors: ShoutCore-eem.84 Fixes a present bug that occured when styling a method that contains multiple unary selectors after a cascade. See ShoutTests-ct.34. =============== Diff against ShoutCore-eem.84 =============== Item was changed: ----- Method: SHParserST80>>parseCascade (in category 'parse') ----- parseCascade self parseKeyword. [currentTokenFirst == $;] whileTrue: [ + | oldRangesLength | self scanPast: #cascadeSeparator. + oldRangesLength := ranges size. + self parseKeyword. + (ranges size > (oldRangesLength + 1) + and: [(ranges at: oldRangesLength + 1) type = #unary]) + ifTrue: [ + ranges removeLast: ranges size - (oldRangesLength + 1). + self fail ": 'Nothing more expected'"]]! - self parseKeyword]! From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 15:31:15 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 15:31:15 +0000 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: References: , Message-ID: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de> > I would 💜 love 💜 if we had elastic tabstops by default in our code editors. -1 for making this default behavior. :-) I think this is a matter of taste, but personally, I am not a friend of code that is not strictly left-justified, it just feels like wasted space to me. Please let's make it an optional preference. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Tobias Pape Gesendet: Montag, 5. April 2021 22:39:10 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) > On 5. Apr 2021, at 22:37, Vanessa Freudenberg wrote: > > Since we're on the subject of how our code looks: > I would 💜 love 💜 if we had elastic tabstops by default in our code editors. > This would eliminate (IMHO) the biggest counter-argument to using proportional fonts. > +100 -t > > > Vanessa > > On Sat, Apr 3, 2021 at 12:55 PM Vanessa Freudenberg wrote: > I just fixed a typo that went unnoticed for ~9 years (see KernelTests-codefrau.395). Even when Levente revised the code in 2015, he did not spot it: > > > > IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? > > - Vanessa - > > On Sat, Apr 3, 2021 at 12:06 PM wrote: > Vanessa Freudenberg uploaded a new version of KernelTests to project The Trunk: > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > ==================== Summary ==================== > > Name: KernelTests-codefrau.395 > Author: codefrau > Time: 3 April 2021, 12:06:03.17026 pm > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > Ancestors: KernelTests-mt.394 > > Fix typo in CompiledMethodComparisonTest. > > =============== Diff against KernelTests-mt.394 =============== > > Item was changed: > ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- > testHash > > > | ai | > ai := CompiledMethod allInstances. > "We assume here that if two CompiledMethods are equal then they have the same size and header." > (ai groupBy: [ :method | { method size. method header } ]) values > replace: [ :each | each asArray ]; > do: [ :methods | > 1 to: methods size do: [ :i | > i to: methods size do: [ :j | > (methods at: i) = (methods at: j) ifTrue: [ > + self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] > - self assert: (methods at: i) hash equals: (methods at: i) hash ] ] ] ] > displayingProgress: 'Testing hashes'. > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 15:37:43 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 15:37:43 +0000 Subject: [squeak-dev] The Inbox: Chronology-Core-dtl.66.mcz In-Reply-To: <20210330202128.GA24434@shell.msen.com> References: <1616948017696-0.post@n4.nabble.com> <20210328185556.GA75142@shell.msen.com> , <20210330202128.GA24434@shell.msen.com> Message-ID: <470bc752d151460fa39fa5d76e407a69@student.hpi.uni-potsdam.de> The Oxford Dictionary lists "millisecond" as a single word, so it would just be consistent to name our selectors #milliseconds. At some places, we already write it in one word, i.e. in Time class, Monitor, Sound. Duration appears to be the only protocol with #milliSeconds. If it's not too complicated, personally, I would vote for renaming it into #milliseconds. If no one else feels like doing so, I could prepare a changeset. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von David T. Lewis Gesendet: Dienstag, 30. März 2021 22:21:28 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: Chronology-Core-dtl.66.mcz On Tue, Mar 30, 2021 at 10:10:22PM +0200, Levente Uzonyi wrote: > Hi David, > > On Sun, 28 Mar 2021, David T. Lewis wrote: > > >On Sun, Mar 28, 2021 at 11:13:37AM -0500, Jaromir Matas wrote: > >>Hi, > >>great! > >> > >>Would it be a bad idea to have milliseconds instead (or on top) of > >>milliSeconds? Etc. > >> > > > >I would not want to bother with that. It would just add more stuff > >to the API, and the existing selector names are good enough. > > I find the existing names annoying. I think the author of those > methods was not familiar with the SI system. > I have no strong opinion one way or the other. It's a bit of aggrivation to manage the deprecation process, but aside from that I guess there is no reason not to fix the selector names. Should we do that? Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 15:42:50 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 15:42:50 +0000 Subject: [squeak-dev] Nested Environments demo In-Reply-To: References: Message-ID: <81a1f492ad4e4628940211d8ed5a38fc@student.hpi.uni-potsdam.de> Very cool implementation, Tony! I admit that I did not watch the entire video, but what I could see from the screenshots looks great. It feels kind of something that has always been missing in Smalltalk for eternities. How large is your entire patch? Provided it's not huge, I would vote for introducing these changes into the Trunk. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Tony Garnock-Jones Gesendet: Dienstag, 30. März 2021 14:12:45 An: The general-purpose Squeak developers list Betreff: [squeak-dev] Nested Environments demo Hi all, I recorded a little screencast of the EnvironmentBrowser I've been playing with: https://www.youtube.com/watch?v=1UOyca5-72Y it's ~11 minutes long if you watch it at 1:1. In the description of the video is the outline that I was following as I recorded the talk. I'll paste it below as well. Cheers, Tony -=-=-=-=- [Here's the outline I was following as I recorded this talk.] Hi everyone. I'm Tony Garnock-Jones, it's March 30th 2021, and I'm going to walk through the experimentation I've been doing on nested Namespaces in Squeak Smalltalk. This work builds on Squeak's Environments, which I think are originally due to Colin Putney with some recent work by Jakob Reschke. I've made some small additions to Environment, and a little subclass called Namespace, which allows one to expose Environments via ordinary variable reference, if one so chooses. It doesn't change anything about how Environments work otherwise, so existing uses should remain unchanged. I've also added a variant of Browser that shows these accessible Environments in a hierarchy, and allows you to manage their imports and exports. Here it is. [Open an EnvironmentBrowser] [Navigate to EnvironmentBrowser] The tool is called EnvironmentBrowser, and it's a very thin veneer over the existing underlying Environment machinery. You can see that compared to the default browser, it has a couple of extra panels. This one [on the left] is a tree of environments. The idea is to take Environment's Instances as "well-known" roots for this tree: Environment wellKnownInstances Smalltalk is already in there, and at the moment there are no others. From the roots, we recursively scan each environment for globals that are also Environments. This scan is a part of Environment itself: [Navigate to Environment's namespaceTreeDo: method] This other panel [on the left, just below the tree of environments] shows the imports and exports of this environment. Here you can see that the default environment, Smalltalk, imports all its own bindings, so they're visible to its own classes, and exports all its bindings to other Environments that import from Smalltalk. [Create namespace NS1] [Create class String, extends Object, inst var length, category Demo] [Create accessors] printOn: aStream aStream nextPutAll: 'I am a ball of wool ', length, ' metres long' [class side] new: size ^ self new length: size [Proceed on the warning] [Open workspace in Smalltalk] String new: 3 [Open workspace in NS1] String new: 3 [Rename NS1 to Fabric] [Create namespace NS2] [Import Fabric with prefix Fabric] [Open workspace in NS2] String new: 3 FabricString new: 3 "Oh! It didn't work! We didn't export it from Fabric." [Export all from Fabric] [Try again - still doesn't work] [Redo the import] [Try again - works now!] There are still some issues with, I think, Environments themselves propagating changes to each other. Fabric String new: 3 [Unlink Fabric] Now we see: String new: 3 FabricString new: 3 Fabric String new: 3 "error on this, Fabric is missing" [Remove the policy importing Fabric to NS2] Didn't remove it. Still some bugs. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 15:53:27 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 15:53:27 +0000 Subject: [squeak-dev] #identityCaseOf: In-Reply-To: References: <9d7b625fce5847c187d77d373430ceb9@student.hpi.uni-potsdam.de>, Message-ID: <66bbc643fbea41c088a15e9b5497c19d@student.hpi.uni-potsdam.de> Woah, I didn't know that this topic has been such a hot potato. :-) In my opinion, people can always abuse a (domain-specific) language to write bad code and you cannot really stop them from doing so by limiting the features of the language. Instead of banning a protocol, people should understand *why* and *when* it is a bad idea to use them. #caseOf: & Co. can be used and can be abused, so I vote for keeping and legalizing it (otherwise we have to destroy every bread knife, too). If we stigmatize #caseOf:, we could also stigmatize or even deprecate #isKindOf: because very often, it is abused - but still, it can be useful in many situations where you need metaprogramming indeed, for example, Exception class >> #handles:. LBNL, I often consider both concepts as the first step of a larger refactoring. Alone for this purpose, I would like to keep these selectors. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von tim Rowledge Gesendet: Sonntag, 28. März 2021 19:07:58 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] #identityCaseOf: > On 2021-03-28, at 4:09 AM, Thiede, Christoph wrote: > > @Tim: > > > Far too like C. > > Again, why please? :-) I'm not a big fan of C either, but IMO switch/select/case is not the worst concept when it allows you to eliminate some duplication. It (both C and caseOf*) has its uses but my practical issue with caseOf* in Smalltalk is that I keep (very subjective and personal experience dependant) seeing it get used in ways that completely sidestep Smalltalk and implement bad C idiom. A bit like isKindOf: and isBlahClass. e.g. foo class caseOf: { [Rabbit] -> [foo doRabbitThing]. [Fox] -> [foo doFoxThing]} ... which of course merely (badly) replicates class lookup/inheritance/message-sending. It suggests a writer that cannot escape the mental prison of C-like assault coding. isKindOf: is a useful meta-programming idiom that I've seen used inside inner loops to do the same sort of not-message-sending. I've even had people try to justify is on the grounds that "sending messages is so slow and I want ot avoid it", which is just nuts. isBlahClass is almost as horrible but at least has the excuse of (hopefully) being part of a not yet completed cleaning of other nastiness. Part of the problem is that language flexibility always ends up being a tool that lets annoying people write bad FORTRAN in any language. And then somebody has to spend a too large fraction of their life trying to fix it. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- Not enough sense to come in out of the rain. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 15:56:19 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 15:56:19 +0000 Subject: [squeak-dev] Extending the functionality of caseOf: (was: #identityCaseOf:) In-Reply-To: <20210328233226.GA22906@shell.msen.com> References: <20210328202253.GA99661@shell.msen.com> , <20210328233226.GA22906@shell.msen.com> Message-ID: <300ccb21be7044f2ab452c20ee68a0c0@student.hpi.uni-potsdam.de> I like these proposals, too. At the moment, it is very hard to implement any change in #caseOf:[otherwise:] because the Compiler optimization has to be adjusted. We should make this optimization selective analogously to #ifTrue:, #whileTrue:. etc., so that all the fancy examples you have mentioned before will be compiled as regular message sends unless someone feels like optimizing them. What do you think? :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von David T. Lewis Gesendet: Montag, 29. März 2021 01:32:26 An: ma.chris.m at gmail.com; The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Extending the functionality of caseOf: (was: #identityCaseOf:) On Sun, Mar 28, 2021 at 05:26:42PM -0500, Chris Muller wrote: > > Here's the version using a temporary and existing API (with an added > identity-check). > > result := self someComplexExpression. > true caseOf: > { [result=1] -> [self success]. > [result odd] -> [self processEvenValue: result-1]. > [ result == identityValue ] -> [self processSomethingElse ]. > [true] -> [self processEvenValue] } > > "true caseOf:" is my sneaky way to improve its flexibility. The suggested > expansion of the API seems too dilute, not enough bang. > I really like the true caseOf: approach. It seems obvious now that you point it out, but I never would have thought of it. Thanks :-) Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Wed Apr 7 16:04:32 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Wed, 7 Apr 2021 18:04:32 +0200 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de> References: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de> Message-ID: Hi, The problem is, if it were a preference, for which setting will you write the Squeak Trunk code? A per-package setting dictated by the package maintainer sounds more practical to me, though it tends towards overengineering already. The idea of elastic tabstops sounds good to me, but I have no practical experience with it. For the left-side-only indentation, I guess it will only make a difference if somebody wants a block with hanging indent like this: | sum count | sum := anInteger. count := 0. aCollection do: [:each | sum := sum + each. count := count + 1]. "The first occurrences of sum and count are supposed to be left-aligned on the two lines above." The example applies analogously if you want to start the remaining lines of the block at or just right of the [ of its first line and put the sum-mation on its own line. Do you see other practical differences for our coding habits, everyone? Kind regards, Jakob Am Mi., 7. Apr. 2021 um 17:31 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > > I would 💜 love 💜 if we had elastic tabstops by default in our code > editors. > > -1 for making this default behavior. :-) I think this is a matter of > taste, but personally, I am not a friend of code that is not strictly > left-justified, it just feels like wasted space to me. > Please let's make it an optional preference. > > Best, > Christoph > > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Tobias Pape > *Gesendet:* Montag, 5. April 2021 22:39:10 > *An:* The general-purpose Squeak developers list > *Betreff:* Re: [squeak-dev] Elastic Tabstops (was Re: Need better default > code font) > > > > > On 5. Apr 2021, at 22:37, Vanessa Freudenberg > wrote: > > > > Since we're on the subject of how our code looks: > > I would 💜 love 💜 if we had elastic tabstops by default in our code > editors. > > This would eliminate (IMHO) the biggest counter-argument to using > proportional fonts. > > > > +100 > -t > > > > > > Vanessa > > > > On Sat, Apr 3, 2021 at 12:55 PM Vanessa Freudenberg < > vanessa at codefrau.net> wrote: > > I just fixed a typo that went unnoticed for ~9 years (see > KernelTests-codefrau.395). Even when Levente revised the code in 2015, he > did not spot it: > > > > > > > > IMHO (speaking as a typo nerd) this is due to our default code font not > having distinct enough letter shapes. I very much like our use of a > proportional font, but maybe it's time to switch to a different one? > > > > - Vanessa - > > > > On Sat, Apr 3, 2021 at 12:06 PM wrote: > > Vanessa Freudenberg uploaded a new version of KernelTests to project The > Trunk: > > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > > > ==================== Summary ==================== > > > > Name: KernelTests-codefrau.395 > > Author: codefrau > > Time: 3 April 2021, 12:06:03.17026 pm > > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > > Ancestors: KernelTests-mt.394 > > > > Fix typo in CompiledMethodComparisonTest. > > > > =============== Diff against KernelTests-mt.394 =============== > > > > Item was changed: > > ----- Method: CompiledMethodComparisonTest>>testHash (in category > 'tests') ----- > > testHash > > > > > > | ai | > > ai := CompiledMethod allInstances. > > "We assume here that if two CompiledMethods are equal then they > have the same size and header." > > (ai groupBy: [ :method | { method size. method header } ]) values > > replace: [ :each | each asArray ]; > > do: [ :methods | > > 1 to: methods size do: [ :i | > > i to: methods size do: [ :j | > > (methods at: i) = (methods at: > j) ifTrue: [ > > + self assert: (methods > at: i) hash equals: (methods at: j) hash ] ] ] ] > > - self assert: (methods > at: i) hash equals: (methods at: i) hash ] ] ] ] > > displayingProgress: 'Testing hashes'. > > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= > ai asSet size! > > > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 16:06:28 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 16:06:28 +0000 Subject: [squeak-dev] X Server implementation for Squeak In-Reply-To: References: <20210324190810.GA73495@shell.msen.com>, Message-ID: <328e06afe22441ab887ef3af40bab7ee@student.hpi.uni-potsdam.de> This was very interesting, thanks for all the impressions! I don't think I will write an X11 server for Squeak these days if it's so complicated. But still, this could be an exciting project for someone or somewhen else ... :-) > Squeak hosts already have X display server software, so there is no incentive to build one for Squeak. Squeak makes more sense as a Xclient than an Xserver. It depends on your perspective. You could either say "Squeak is one of many applications on your computer", then an Xclient makes much more sense, of course. But you can also consider Squeak as a separate operating system that only requires an outer OS "for compatibility reasons", and from this PoV, it would be very useful to include applications from the outside into your image. Thankfully, with Squeak, we have a system that does not require you to decide on one of both perspectives. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von K K Subbu Gesendet: Donnerstag, 25. März 2021 11:53:35 An: squeak-dev at lists.squeakfoundation.org Betreff: Re: [squeak-dev] X Server implementation for Squeak On 25/03/21 12:38 am, David T. Lewis wrote: > However, as a practical matter, this would be a big project. The protocols > are complex, and modern X11 servers have accumulated a lot of fancy > features that would be difficult to reproduce from scratch. > > Here is another way to look at it: Once apon a time, web browsers were > simple and we had browser functionality written in Smalltalk, and running > in the Squeak image. But as time went on, browsers got more complicated, > and it became infeasible to keep up with the feature creep. > > I think you would find a similar situation with X11 servers. In theory > you can write one, but it would be difficult to implement enough > functionality to make it seem acceptable to users today. Well said! Squeak hosts already have X display server software, so there is no incentive to build one for Squeak. Squeak makes more sense as a Xclient than an Xserver. There is an fascinating Squeak package called NetMorph circa 2002. Morphic objects could move along on a virtual display, like a multi-monitor video wall, spanning multiple Squeak nodes. It required a fast network and lots of RAM, so it may be a better fit for today's world. A NetMorphed Squeak image, running as Xclient on all nodes, can offer a much richer environment than just a plain display. Imagine live object migrations and collaborations! Sorry if this is off-topic. Regards .. Subbu -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 16:12:47 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 16:12:47 +0000 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: References: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de>, Message-ID: <7d965bbc7d78428391dab1029b5f6486@student.hpi.uni-potsdam.de> The only other example I was thinking of would be multi-line comments, but I dislike them anyway. :-) Yes, speaking generally, subjective coding style preferences are a problem when writing or maintaining code in a community. I am still convinced that it would be the best solution to remove specific styling information from the Trunk code base and apply it on everyone's end only according to their personal preferences. With prettyDiff, which is already fairly well supported, and a good pretty-printer, this should be a feasible endeavor. PoppyPrint looks very promising to me in this regard. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Jakob Reschke Gesendet: Mittwoch, 7. April 2021 18:04:32 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) Hi, The problem is, if it were a preference, for which setting will you write the Squeak Trunk code? A per-package setting dictated by the package maintainer sounds more practical to me, though it tends towards overengineering already. The idea of elastic tabstops sounds good to me, but I have no practical experience with it. For the left-side-only indentation, I guess it will only make a difference if somebody wants a block with hanging indent like this: | sum count | sum := anInteger. count := 0. aCollection do: [:each | sum := sum + each. count := count + 1]. "The first occurrences of sum and count are supposed to be left-aligned on the two lines above." The example applies analogously if you want to start the remaining lines of the block at or just right of the [ of its first line and put the sum-mation on its own line. Do you see other practical differences for our coding habits, everyone? Kind regards, Jakob Am Mi., 7. Apr. 2021 um 17:31 Uhr schrieb Thiede, Christoph >: > I would 💜 love 💜 if we had elastic tabstops by default in our code editors. -1 for making this default behavior. :-) I think this is a matter of taste, but personally, I am not a friend of code that is not strictly left-justified, it just feels like wasted space to me. Please let's make it an optional preference. Best, Christoph ________________________________ Von: Squeak-dev > im Auftrag von Tobias Pape > Gesendet: Montag, 5. April 2021 22:39:10 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) > On 5. Apr 2021, at 22:37, Vanessa Freudenberg > wrote: > > Since we're on the subject of how our code looks: > I would 💜 love 💜 if we had elastic tabstops by default in our code editors. > This would eliminate (IMHO) the biggest counter-argument to using proportional fonts. > +100 -t > > > Vanessa > > On Sat, Apr 3, 2021 at 12:55 PM Vanessa Freudenberg > wrote: > I just fixed a typo that went unnoticed for ~9 years (see KernelTests-codefrau.395). Even when Levente revised the code in 2015, he did not spot it: > > > > IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? > > - Vanessa - > > On Sat, Apr 3, 2021 at 12:06 PM > wrote: > Vanessa Freudenberg uploaded a new version of KernelTests to project The Trunk: > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > ==================== Summary ==================== > > Name: KernelTests-codefrau.395 > Author: codefrau > Time: 3 April 2021, 12:06:03.17026 pm > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > Ancestors: KernelTests-mt.394 > > Fix typo in CompiledMethodComparisonTest. > > =============== Diff against KernelTests-mt.394 =============== > > Item was changed: > ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- > testHash > > > | ai | > ai := CompiledMethod allInstances. > "We assume here that if two CompiledMethods are equal then they have the same size and header." > (ai groupBy: [ :method | { method size. method header } ]) values > replace: [ :each | each asArray ]; > do: [ :methods | > 1 to: methods size do: [ :i | > i to: methods size do: [ :j | > (methods at: i) = (methods at: j) ifTrue: [ > + self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] > - self assert: (methods at: i) hash equals: (methods at: i) hash ] ] ] ] > displayingProgress: 'Testing hashes'. > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 16:15:57 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 16:15:57 +0000 Subject: [squeak-dev] Extending the functionality of caseOf: (was: #identityCaseOf:) In-Reply-To: References: <20210328202253.GA99661@shell.msen.com> , Message-ID: <6c27374c93a1431f89303bd6f10557e9@student.hpi.uni-potsdam.de> Hi Levente, IMHO a DSL is very much about syntactic sugar. If we obviate it, we impede the development of richer and higher-level language concepts that abstract from repetitive and uninteresting basics such as the temporary variable in your example. Just my two cents. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Levente Uzonyi Gesendet: Dienstag, 30. März 2021 22:21:00 An: ma.chris.m at gmail.com; The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Extending the functionality of caseOf: (was: #identityCaseOf:) Hi Chris, On Sun, 28 Mar 2021, Chris Muller wrote: > > For example, passing the object to the condition block (or even the result > > block) could be useful: > > > > self someComplexExpression caseOf: { > > [ 1 ] -> [ self success ] > > [ :value | value odd ] -> [ :value | self processEvenValue: value - > > 1 ]. > > [ :value | true "it's even ] -> [ :value | self processEvenValue ] } > > > > > There are two new things in the example: > > - the value of self someComplexExpression is optionally passed to the > > blocks. Yes, that could be done by creating a temporary variable. > > > Here's the version using a temporary and existing API (with an added identity-check). > > result := self someComplexExpression. > true caseOf: > { [result=1] -> [self success]. > [result odd] -> [self processEvenValue: result-1]. > [ result == identityValue ] -> [self processSomethingElse ]. > [true] -> [self processEvenValue] } > > "true caseOf:" is my sneaky way to improve its flexibility. The suggested expansion of the API seems too dilute, not enough bang. Yes, it does the job, but it's a bit more verbose and probably less efficient: you have to declare the variable yourself, and you have to write result=1 instead of just 1. > > The > > compiler could do exactly that behind the scenes. > > - when the value is passed to the matcher block, possibilities are greatly > > extended. > > > The evaluation is done before any of the caseOf tests, so is it really extended with more expressive power? Or just a different syntax that moves the variable declaration from a temporary to the block arg? It's just syntactic sugar. The optimized evaluation would just reuse the existing temporary instead of creating a new one all the time. The default implementation would be Object >> caseOf: aBlockAssociationCollection otherwise: aBlock aBlockAssociationCollection associationsDo: [:assoc | (assoc key numArgs = 0 ifTrue: [ assoc key value = self ] ifFalse: [ assoc key value: self ]) ifTrue: [^assoc value cull: self]]. ^ aBlock cull: self Levente > > For example, it could even reproduce #identityCaseOf: > > > > foo caseOf: { > > [ :o | o == #foo ] -> [ self foo ]. > > [ :o | o == #bar ] -> [ self bar ] } > > > > The same thing could be done with the otherwise block too: > > > > self foo > > caseOf: { ... } > > otherwise: [ :value | value ] > > > > > > Levente > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Wed Apr 7 16:22:16 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Wed, 7 Apr 2021 09:22:16 -0700 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de> References: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de> Message-ID: Guess you misunderstood - this does not affect indentation at all, it only affects the rendering of tabs following non-space characters in a line. And indeed there could be a preference to render those tabs as a space instead, however, that would probably lead to those text blocks being messed up accidentally. The Smalltalk environment was meant to provide rich text rendering. We had text that could flow around objects at some point, that could flow along a curve, that could embed bitmaps and even arbitrary morphs. For some reason we went back to more or less plain text at least for code. I partly blame Monticello which did not preserve the rich formatting that the style chunks in the fileout format supported. I do find that unfortunate, however, and would love to get some richness back. Tabbed comments are similar to traditional type-setting’s margin notes, that can be used to write table-like data, etc. You don’t have to use them, but I’m convinced it would make our codebase look a lot better. Similarly, there’s no need for double quotes around comments. Comments should simply use a different font. Not coincidentally, that is exactly how commented code used to be printed in books. We only need the quotes for typing, and maybe for exporting, but otherwise I wouldn’t mind to never see them again. My point being that Smalltalk source code is not plain text. Never has been. It shouldn’t be treated as such. IMHO. Vanessa On Wed, Apr 7, 2021 at 08:31 Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de> wrote: > > I would 💜 love 💜 if we had elastic tabstops by default in our code > editors. > > -1 for making this default behavior. :-) I think this is a matter of > taste, but personally, I am not a friend of code that is not strictly > left-justified, it just feels like wasted space to me. > Please let's make it an optional preference. > > Best, > Christoph > > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Tobias Pape > *Gesendet:* Montag, 5. April 2021 22:39:10 > *An:* The general-purpose Squeak developers list > *Betreff:* Re: [squeak-dev] Elastic Tabstops (was Re: Need better default > code font) > > > > > On 5. Apr 2021, at 22:37, Vanessa Freudenberg > wrote: > > > > Since we're on the subject of how our code looks: > > I would 💜 love 💜 if we had elastic tabstops by default in our code > editors. > > This would eliminate (IMHO) the biggest counter-argument to using > proportional fonts. > > > > +100 > -t > > > > > > Vanessa > > > > On Sat, Apr 3, 2021 at 12:55 PM Vanessa Freudenberg < > vanessa at codefrau.net> wrote: > > I just fixed a typo that went unnoticed for ~9 years (see > KernelTests-codefrau.395). Even when Levente revised the code in 2015, he > did not spot it: > > > > > > > > IMHO (speaking as a typo nerd) this is due to our default code font not > having distinct enough letter shapes. I very much like our use of a > proportional font, but maybe it's time to switch to a different one? > > > > - Vanessa - > > > > On Sat, Apr 3, 2021 at 12:06 PM wrote: > > Vanessa Freudenberg uploaded a new version of KernelTests to project The > Trunk: > > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > > > ==================== Summary ==================== > > > > Name: KernelTests-codefrau.395 > > Author: codefrau > > Time: 3 April 2021, 12:06:03.17026 pm > > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > > Ancestors: KernelTests-mt.394 > > > > Fix typo in CompiledMethodComparisonTest. > > > > =============== Diff against KernelTests-mt.394 =============== > > > > Item was changed: > > ----- Method: CompiledMethodComparisonTest>>testHash (in category > 'tests') ----- > > testHash > > > > > > | ai | > > ai := CompiledMethod allInstances. > > "We assume here that if two CompiledMethods are equal then they > have the same size and header." > > (ai groupBy: [ :method | { method size. method header } ]) values > > replace: [ :each | each asArray ]; > > do: [ :methods | > > 1 to: methods size do: [ :i | > > i to: methods size do: [ :j | > > (methods at: i) = (methods at: > j) ifTrue: [ > > + self assert: (methods > at: i) hash equals: (methods at: j) hash ] ] ] ] > > - self assert: (methods > at: i) hash equals: (methods at: i) hash ] ] ] ] > > displayingProgress: 'Testing hashes'. > > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= > ai asSet size! > > > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Wed Apr 7 16:30:21 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Wed, 7 Apr 2021 18:30:21 +0200 Subject: [squeak-dev] Nested Environments demo In-Reply-To: References: Message-ID: Hi Tony, This looks great and like the tool support that Environments have been missing for some time. I had expected that the Namespace concept would spawn more controversial discussion. Anyway, just the availability of the tool would be a welcome addition in my opinion. As for those bugs, I guess the community needs to have some discussion and agreement about what the expected behavior would be, though Environments does not seem to be the most favorite topic around. From the comprehensibility perspective, I agree with you that it should behave in less surprising ways than it currently does. Also thank you for the mention, although I'm humbly not sure whether I deserve the naming next to Colin on that matter. ;-) Kind regards, Jakob Am Di., 30. März 2021 um 14:12 Uhr schrieb Tony Garnock-Jones < tonyg at leastfixedpoint.com>: > Hi all, > > I recorded a little screencast of the EnvironmentBrowser I've been > playing with: > > https://www.youtube.com/watch?v=1UOyca5-72Y > > it's ~11 minutes long if you watch it at 1:1. In the description of the > video is the outline that I was following as I recorded the talk. > > I'll paste it below as well. > > Cheers, > Tony > > -=-=-=-=- > > [Here's the outline I was following as I recorded this talk.] > > Hi everyone. > > I'm Tony Garnock-Jones, it's March 30th 2021, and I'm going to walk > through the experimentation I've been doing on nested Namespaces in > Squeak Smalltalk. > > This work builds on Squeak's Environments, which I think are originally > due to Colin Putney with some recent work by Jakob Reschke. > > I've made some small additions to Environment, and a little subclass > called Namespace, which allows one to expose Environments via ordinary > variable reference, if one so chooses. It doesn't change anything about > how Environments work otherwise, so existing uses should remain unchanged. > > I've also added a variant of Browser that shows these accessible > Environments in a hierarchy, and allows you to manage their imports and > exports. Here it is. > > [Open an EnvironmentBrowser] > [Navigate to EnvironmentBrowser] > > The tool is called EnvironmentBrowser, and it's a very thin veneer over > the existing underlying Environment machinery. > > You can see that compared to the default browser, it has a couple of > extra panels. > > This one [on the left] is a tree of environments. The idea is to take > Environment's Instances as "well-known" roots for this tree: > > Environment wellKnownInstances > > Smalltalk is already in there, and at the moment there are no others. > > From the roots, we recursively scan each environment for globals that > are also Environments. This scan is a part of Environment itself: > > [Navigate to Environment's namespaceTreeDo: method] > > This other panel [on the left, just below the tree of environments] > shows the imports and exports of this environment. > > Here you can see that the default environment, Smalltalk, imports all > its own bindings, so they're visible to its own classes, and exports all > its bindings to other Environments that import from Smalltalk. > > [Create namespace NS1] > [Create class String, extends Object, inst var length, category Demo] > [Create accessors] > > printOn: aStream > aStream nextPutAll: 'I am a ball of wool ', length, ' metres long' > > [class side] > new: size > ^ self new length: size > [Proceed on the warning] > > [Open workspace in Smalltalk] > String new: 3 > > [Open workspace in NS1] > String new: 3 > > [Rename NS1 to Fabric] > [Create namespace NS2] > [Import Fabric with prefix Fabric] > > [Open workspace in NS2] > String new: 3 > FabricString new: 3 > "Oh! It didn't work! We didn't export it from Fabric." > > [Export all from Fabric] > [Try again - still doesn't work] > [Redo the import] > [Try again - works now!] > > There are still some issues with, I think, Environments themselves > propagating changes to each other. > > Fabric String new: 3 > > [Unlink Fabric] > > Now we see: > > String new: 3 > FabricString new: 3 > Fabric String new: 3 "error on this, Fabric is missing" > > [Remove the policy importing Fabric to NS2] > > Didn't remove it. Still some bugs. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 16:31:29 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 16:31:29 +0000 Subject: [squeak-dev] EnvironmentBrowser and nested Namespaces (was Re: The Inbox: Environments-tonyg.78.mcz) In-Reply-To: References: <8de91609-2662-2bda-6771-c05cc095aee8@leastfixedpoint.com>, Message-ID: <32b66157c2144031beb1e4a72099e7f7@student.hpi.uni-potsdam.de> -1 on the #doesNotUnderstand: proposal. JsonObject is already questionable depending on the use case - IMHO message forwarding is easy to abuse, and using it for any kind of lookup appears kind of abusive to me. However, only my 2 cents. :-) A big +1 for the rest of the proposed changes! :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Freitag, 26. März 2021 11:42:24 An: squeak-dev Betreff: Re: [squeak-dev] EnvironmentBrowser and nested Namespaces (was Re: The Inbox: Environments-tonyg.78.mcz) Hi Tony, if I would implement a hierarchy of environments, I would not exploit "globals" or "declarations" but add "outer" and/or "inner" as instance variables. Then #classNamed: needs to be changed to also look in outer environments. -- I think that environments are already "namespaces". Thus, I would not add an extra subclass "Namespace" for it. The second proposal in here is that new syntax via #doesNotUnderstand:. Hmm... I do not like it. :-) Maybe a Environment class >> #fromPath: would work. Then tools can support such a path syntax. In source code I would rather not use it to not create any more "spaghetti code" than we already have. Feels like a "pandoras box" to allow an easy way for arbitrary environments in any piece of code. Best, Marcel Am 25.03.2021 13:58:51 schrieb Tony Garnock-Jones : Hi all, This message is about the in-inbox EXPERIMENTAL DRAFT packages - http://source.squeak.org/inbox/Environments-tonyg.78.mcz and - http://source.squeak.org/inbox/Tools-tonyg.1033.mcz The two packages go together. Screenshot of EnvironmentBrowser in action attached. The idea here is a kind of Self-like "namespacing" facility, based around placing Environment instances into another Environment's globals table. The EnvironmentBrowser class in Tools 1033 is a sketch of UI for the core functionality I've identified so far. If I have the following setup of nested Environments... Smalltalk -- the normal Environment default / Environment current - A - B - C - D with class X in A, class Y in B, a *different* class Y in C, and class Z in D, then - In a workspace whose environment is Smalltalk, `A` evaluates to the environment A. `A B` evaluates to the environment B. `A B Y` evaluates to B's Y. `A C Y` evaluates to C's Y. etc. - In a workspace whose environment is A, all of the examples from the Smalltalk paragraph above are unchanged `B` evaluates to the environment B, `B Y` yields B's Y `C Y` yields C's Y `D` is an undefined name - In a workspace whose environment is B, all of the examples from the Smalltalk paragraph above are unchanged `Y` is B's Y `C` and `D` are undefined names The ability of Environments to import/export is unused (!) at present, other than Namespace instances default to importing self and Smalltalk. I'm looking at Monticello now. The major difficulty is that it hardcodes `Environment current` and expects a single environment to apply. I imagine the following: - the nested namespaces are analogous to nested folders in a Unix file system - packages are like Debian packages, and may have entries in multiple namespaces - `Environment current` at load time acts like a chroot Given those guesses/assumptions, MC might need to learn about the idea of classes living in a particular (or more than one!) Environment, and the necessity of creating Namespaces as needed. Here's an interesting method on PackageInfo I've been messing around with: classesAndEnvironments | cs | cs := IdentityDictionary new. self systemCategories do: [:cat | Environment current namespaceTreeDo: [:environment | (environment organization listAtCategoryNamed: cat) do: [:className | | envs | envs := cs at: (environment valueOf: className) ifAbsentPut: [Set new]. envs add: environment]]]. ^ cs Does anyone have thoughts on this whole approach? On how MC's model could profitably be altered to include a notion of namespace/environment? Regards, Tony -------------- next part -------------- An HTML attachment was scrubbed... URL: From kirtai+st at gmail.com Wed Apr 7 16:39:20 2021 From: kirtai+st at gmail.com (Douglas Brebner) Date: Wed, 7 Apr 2021 17:39:20 +0100 Subject: [squeak-dev] X Server implementation for Squeak In-Reply-To: <328e06afe22441ab887ef3af40bab7ee@student.hpi.uni-potsdam.de> References: <20210324190810.GA73495@shell.msen.com> <328e06afe22441ab887ef3af40bab7ee@student.hpi.uni-potsdam.de> Message-ID: <420e8cbc-58a0-1637-e2cf-522611c90443@gmail.com> On 07/04/2021 17:06, Thiede, Christoph wrote: > > This was very interesting, thanks for all the impressions! I don't > think I will write an X11 server for Squeak these days if it's so > complicated. But still, this could be an exciting project for someone > or somewhen else ... :-) > > > > Squeak hosts already have X display server software, so there is no > incentive to build one for Squeak. Squeak makes more sense as a > Xclient than an Xserver. > > > It depends on your perspective. You could either say "Squeak is one of > many applications on your computer", then an Xclient makes much more > sense, of course. But you can also consider Squeak as a separate > operating system that only requires an outer OS "for compatibility > reasons", and from this PoV, it would be very useful to include > applications from the outside into your image. Thankfully, with > Squeak, we have a system that does not require you to decide on one of > both perspectives. :-) > On a somewhat belated note, the xcb project has descriptions of the X11 protocols in XML format, which may make it significantly easier to create an X server. https://xcb.freedesktop.org/ From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 16:41:46 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 16:41:46 +0000 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: References: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de>, Message-ID: <073ead29274b430ba1415c01bede1e20@student.hpi.uni-potsdam.de> Alright, if it only affects rendering, then it should not be a big deal to make a preference for it. :-) > Tabbed comments are similar to traditional type-setting’s margin notes, that can be used to write table-like data, etc. That's indeed an interesting use case for that I would like elastic tabstops, too! And here is another one: PasteUpMorph >> #defaultDesktopCommandKeyTriplets ... I would only dislike to indent blocks in this style. :-) > My point being that Smalltalk source code is not plain text. Never has been. It shouldn’t be treated as such. IMHO. Well, my perspective on this question is that Smalltalk is literally small talk without all this nasty and complicated syntactic stuff you are used to from C-like languages and many others. So it's still not exactly plain text, but at least very near to it. You can just read (good) Smalltalk code like a book (and I have to say that I *love* this book :D). That's why in my personal opinion, Smalltalk code does not deserve a separate font compared to comments. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Vanessa Freudenberg Gesendet: Mittwoch, 7. April 2021 18:22:16 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) Guess you misunderstood - this does not affect indentation at all, it only affects the rendering of tabs following non-space characters in a line. And indeed there could be a preference to render those tabs as a space instead, however, that would probably lead to those text blocks being messed up accidentally. The Smalltalk environment was meant to provide rich text rendering. We had text that could flow around objects at some point, that could flow along a curve, that could embed bitmaps and even arbitrary morphs. For some reason we went back to more or less plain text at least for code. I partly blame Monticello which did not preserve the rich formatting that the style chunks in the fileout format supported. I do find that unfortunate, however, and would love to get some richness back. Tabbed comments are similar to traditional type-setting’s margin notes, that can be used to write table-like data, etc. You don’t have to use them, but I’m convinced it would make our codebase look a lot better. Similarly, there’s no need for double quotes around comments. Comments should simply use a different font. Not coincidentally, that is exactly how commented code used to be printed in books. We only need the quotes for typing, and maybe for exporting, but otherwise I wouldn’t mind to never see them again. My point being that Smalltalk source code is not plain text. Never has been. It shouldn’t be treated as such. IMHO. Vanessa On Wed, Apr 7, 2021 at 08:31 Thiede, Christoph > wrote: > I would 💜 love 💜 if we had elastic tabstops by default in our code editors. -1 for making this default behavior. :-) I think this is a matter of taste, but personally, I am not a friend of code that is not strictly left-justified, it just feels like wasted space to me. Please let's make it an optional preference. Best, Christoph ________________________________ Von: Squeak-dev > im Auftrag von Tobias Pape > Gesendet: Montag, 5. April 2021 22:39:10 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) > On 5. Apr 2021, at 22:37, Vanessa Freudenberg > wrote: > > Since we're on the subject of how our code looks: > I would 💜 love 💜 if we had elastic tabstops by default in our code editors. > This would eliminate (IMHO) the biggest counter-argument to using proportional fonts. > +100 -t > > > Vanessa > > On Sat, Apr 3, 2021 at 12:55 PM Vanessa Freudenberg > wrote: > I just fixed a typo that went unnoticed for ~9 years (see KernelTests-codefrau.395). Even when Levente revised the code in 2015, he did not spot it: > > > > IMHO (speaking as a typo nerd) this is due to our default code font not having distinct enough letter shapes. I very much like our use of a proportional font, but maybe it's time to switch to a different one? > > - Vanessa - > > On Sat, Apr 3, 2021 at 12:06 PM > wrote: > Vanessa Freudenberg uploaded a new version of KernelTests to project The Trunk: > http://source.squeak.org/trunk/KernelTests-codefrau.395.mcz > > ==================== Summary ==================== > > Name: KernelTests-codefrau.395 > Author: codefrau > Time: 3 April 2021, 12:06:03.17026 pm > UUID: 062e8b73-a62e-46ce-af80-0dbb34c2f8dc > Ancestors: KernelTests-mt.394 > > Fix typo in CompiledMethodComparisonTest. > > =============== Diff against KernelTests-mt.394 =============== > > Item was changed: > ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- > testHash > > > | ai | > ai := CompiledMethod allInstances. > "We assume here that if two CompiledMethods are equal then they have the same size and header." > (ai groupBy: [ :method | { method size. method header } ]) values > replace: [ :each | each asArray ]; > do: [ :methods | > 1 to: methods size do: [ :i | > i to: methods size do: [ :j | > (methods at: i) = (methods at: j) ifTrue: [ > + self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] > - self assert: (methods at: i) hash equals: (methods at: i) hash ] ] ] ] > displayingProgress: 'Testing hashes'. > self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 17:37:50 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 17:37:50 +0000 Subject: [squeak-dev] Regular Expressions are not limited to Strings Message-ID: <0d42ee73525645599de63902aec3529b@student.hpi.uni-potsdam.de> Hi all, just a small goody for all those interested: It turns out that, thanks to the great polymorphy in Squeak, regular expressions (as implemented in the Regex package of Trunk originally developed by Vassili Bykov) are not limited to collections that are actually strings. Here is a short counter-example: regex := RxParser new parse: #(1 2 $+ 1). matcher := RxParser preferredMatcherClass for: regex. matcher matches: #(1 2 2 2 1). "true!" To make the example work, only a small number of hard-coded class names have to be adjusted, see the attached changeset, it's really tiny. Here's another example: matcher copy: #(1 2 2 1 0 1 2 1) translatingMatchesUsing: [:match | match negated]. "#(-1 -2 -2 -1 0 -1 -2 -1)" This also allows us to style texts using regexes: matcher := 'ab+a' asRegex. matcher copy: ' aa-aba-abba ' asText translatingMatchesUsing: [:match | match allBold]. " aa-aba-abba " However, if the original text attributes should be preserved, we would need to hack TextStream >> #withAttributes:do: into the copy methods, analogously to Text >> #format:. I guess this limitation could only be resolved by redesigning Text as a collection of TextCharacters, which might be very slow. Nevertheless, I think this insight opens great possibilities for other forms of parsing. Maybe one could also process binary streams using polymorphic regex patterns, or even process sequences of domain-specific objects. Because RxsPredicate is so generic, you could also simply define custom predicates for these objects. Later, the next step could be adding support for nested collections (RxsNested?) so that you could parse entire trees of objects ... Ah, so beautiful dreams :-) Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: regex-polymorphy.2.cs URL: From jakres+squeak at gmail.com Wed Apr 7 17:42:48 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Wed, 7 Apr 2021 19:42:48 +0200 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: <073ead29274b430ba1415c01bede1e20@student.hpi.uni-potsdam.de> References: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de> <073ead29274b430ba1415c01bede1e20@student.hpi.uni-potsdam.de> Message-ID: Am Mi., 7. Apr. 2021 um 18:41 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > Alright, if it only affects rendering, then it should not be a big deal to > make a preference for it. :-) > > > Well, it depends. In my hanging indent example with elastic tabstops you would write less tab stops on the hanging lines and at least one additional tab stop on the first line of the block. Whereas without elastic tabstops you would push tab or space repeatedly until you are somewhat satisfied with the results for your particular font setting, to achieve the same looks. One source code will contain different characters (tabs) than the other. Some intelligent rendering that makes both codes look like indented in the same, properly aligned way might be nice. As a compromise between unformatted and pretty-printed browsing. With these additional ideas like not showing the quotes, there will be at least two meanings of "pretty print" in the future. > My point being that Smalltalk source code is not plain text. Never has > been. It shouldn’t be treated as such. IMHO. > > Well, my perspective on this question is that Smalltalk is literally small > talk without all this nasty and complicated syntactic stuff you are used to > from C-like languages and many others. So it's still not exactly plain > text, but at least very near to it. You can just read (good) Smalltalk code > like a book (and I have to say that I *love* this book :D). That's why in > my personal opinion, Smalltalk code does not deserve a separate font > compared to comments. :-) > (It is certainly better than typedef char (*pointerToArrays)[6]; but Smalltalk, too, has its unnatural plain text/keyboard quirks/compromises like ~= or historical syntax artifacts like the colon in block arguments—if I remember that correctly from the evolution of Smalltalk article from last year. And there was already a remark about the looks of := with certain fonts.) Comments looking like sticky notes in PDFs would be fancy. And less portable, of course. ;-) "This package is best browsed with Squeak 5.4, standard system browser, elastic tabstops and automatic rendering of ←, ↑ enabled, quotes disabled, and a display size of at least 1024x768. What do you mean, you are still using Internet Explorer?" Kidding aside, preferences and rendering fragmentation might, here too, be a problem for authors and readers. No objections from me personally against improving the tools and rendering. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Wed Apr 7 18:13:23 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Wed, 7 Apr 2021 20:13:23 +0200 Subject: [squeak-dev] #identityCaseOf: In-Reply-To: <66bbc643fbea41c088a15e9b5497c19d@student.hpi.uni-potsdam.de> References: <9d7b625fce5847c187d77d373430ceb9@student.hpi.uni-potsdam.de> <66bbc643fbea41c088a15e9b5497c19d@student.hpi.uni-potsdam.de> Message-ID: Having started out with Delphi, I do not mind caseOf:. But I more often wish for Lisp's cond. true caseOf: looks somehow strange and like a hack to me—just a feeling—though I admit it does make sense when I force myself to read it as English: "For the true case of the following, do..." Regarding letting people choose their protocols, just make sure that Smalltalk does not end up being a write-only-for-me language like Perl. :-) I think there has already been this discussion about how many shortcuts and utility methods should be in the language and which should rather stay out. Am Mi., 7. Apr. 2021 um 17:53 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > Woah, I didn't know that this topic has been such a hot potato. :-) > > > In my opinion, people can always abuse a (domain-specific) language to > write bad code and you cannot really stop them from doing so by limiting > the features of the language. Instead of banning a protocol, people should > understand *why* and *when* it is a bad idea to use them. #caseOf: & Co. > can be used and can be abused, so I vote for keeping and legalizing it > (otherwise we have to destroy every bread knife, too). > If we stigmatize #caseOf:, we could also stigmatize or even deprecate > #isKindOf: because very often, it is abused - but still, it can be useful > in many situations where you need metaprogramming indeed, for example, > Exception class >> #handles:. > LBNL, I often consider both concepts as the first step of a > larger refactoring. Alone for this purpose, I would like to keep these > selectors. > > Best, > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von tim Rowledge > *Gesendet:* Sonntag, 28. März 2021 19:07:58 > *An:* The general-purpose Squeak developers list > *Betreff:* Re: [squeak-dev] #identityCaseOf: > > > > > On 2021-03-28, at 4:09 AM, Thiede, Christoph < > Christoph.Thiede at student.hpi.uni-potsdam.de> wrote: > > > > @Tim: > > > > > Far too like C. > > > > Again, why please? :-) I'm not a big fan of C either, but IMO > switch/select/case is not the worst concept when it allows you to eliminate > some duplication. > > It (both C and caseOf*) has its uses but my practical issue with caseOf* > in Smalltalk is that I keep (very subjective and personal experience > dependant) seeing it get used in ways that completely sidestep Smalltalk > and implement bad C idiom. A bit like isKindOf: and isBlahClass. > > e.g. > foo class > caseOf: { > [Rabbit] -> [foo doRabbitThing]. > [Fox] -> [foo doFoxThing]} > ... which of course merely (badly) replicates class > lookup/inheritance/message-sending. It suggests a writer that cannot escape > the mental prison of C-like assault coding. > > isKindOf: is a useful meta-programming idiom that I've seen used inside > inner loops to do the same sort of not-message-sending. I've even had > people try to justify is on the grounds that "sending messages is so slow > and I want ot avoid it", which is just nuts. > > isBlahClass is almost as horrible but at least has the excuse of > (hopefully) being part of a not yet completed cleaning of other nastiness. > > Part of the problem is that language flexibility always ends up being a > tool that lets annoying people write bad FORTRAN in any language. And then > somebody has to spend a too large fraction of their life trying to fix it. > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > Useful random insult:- Not enough sense to come in out of the rain. > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 7 18:40:25 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 7 Apr 2021 18:40:25 0000 Subject: [squeak-dev] The Trunk: EToys-nice.438.mcz Message-ID: Nicolas Cellier uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-nice.438.mcz ==================== Summary ==================== Name: EToys-nice.438 Author: nice Time: 7 April 2021, 8:40:21.068323 pm UUID: d28ff6d4-e638-483f-b11b-7c3a9f5c7283 Ancestors: EToys-mt.437 Nuke usage of #parserClass: because redundant with definition of ScriptCompiler class>>parserClass. Fix evaluate:in:to:notifying:ifFail:logged: (self parser) already answers an instance, (self parser new) fails. Simplify: ScriptCompiler new parserClass new -> ScriptCompiler newParser =============== Diff against EToys-mt.437 =============== Item was removed: - ----- Method: ScriptCompiler>>compile:in:notifying:ifFail: (in category 'as yet unclassified') ----- - compile: textOrStream in: aClass notifying: aRequestor ifFail: failBlock - - self parserClass: ScriptParser. - ^ super compile: textOrStream in: aClass notifying: aRequestor ifFail: failBlock! Item was changed: ----- Method: ScriptCompiler>>compile:in:notifying:ifFail:for: (in category 'as yet unclassified') ----- compile: textOrStream in: aClass notifying: aRequestor ifFail: failBlock for: anInstance "Answer a MethodNode for the argument, textOrStream. If the MethodNode can not be created, notify the argument, aRequestor; if aRequestor is nil, evaluate failBlock instead. The MethodNode is the root of a parse tree. It can be told to generate a CompiledMethod to be installed in the method dictionary of the argument, aClass." - self parserClass: ScriptParser. ^ self parser parse: textOrStream readStream class: aClass noPattern: false context: nil notifying: aRequestor ifFail: [^ failBlock value] for: anInstance. ! Item was changed: ----- Method: ScriptCompiler>>evaluate:in:to:notifying:ifFail:logged: (in category 'as yet unclassified') ----- evaluate: textOrStream in: aContext to: receiver notifying: aRequestor ifFail: failBlock logged: logFlag "Compiles the sourceStream into a parse tree, then generates code into a method. This method is then installed in the receiver's class so that it can be invoked. In other words, if receiver is not nil, then the text can refer to instance variables of that receiver (the Inspector uses this). If aContext is not nil, the text can refer to temporaries in that context (the Debugger uses this). If aRequestor is not nil, then it will receive a notify:at: message before the attempt to evaluate is aborted." | methodNode method value toLog itsSelectionString itsSelection | + methodNode := self parser - methodNode := self parser new parse: textOrStream readStream class: (self classForReceiver: receiver context: aContext) noPattern: true context: aContext notifying: aRequestor ifFail: [^ failBlock value] for: receiver. method := methodNode generate: (CompiledMethodTrailer empty sourceCode: methodNode sourceText; yourself). self interactive ifTrue: [method := method copyWithTempNames: methodNode tempNames]. value := receiver withArgs: (aContext ifNil: [#()] ifNotNil: [{aContext}]) executeMethod: method. logFlag ifTrue: [toLog := ((aRequestor respondsTo: #selection) and: [(itsSelection := aRequestor selection) notNil] and: [(itsSelectionString := itsSelection asString) isEmptyOrNil not] ) ifTrue: [itsSelectionString] ifFalse: [textOrStream readStream contents]. SystemChangeNotifier uniqueInstance evaluated: toLog context: aContext]. ^value! Item was changed: ----- Method: TileMorph>>parseNodeWith: (in category '*Etoys-Squeakland-code generation') ----- parseNodeWith: encoder | op playerBearingCode | playerBearingCode := self playerBearingCode. "Must determine whom is scripted for what follows to work; if it's ever nil, we've got trouble" type = #expression ifTrue: + [^ (ScriptCompiler newParser parse: 'xxx ', operatorOrExpression class: UndefinedObject) block statements first]. - [^ (ScriptCompiler new parserClass new parse: 'xxx ', operatorOrExpression class: UndefinedObject) block statements first]. type = #literal ifTrue: [^ encoder encodeLiteral: literal]. type == #objRef ifTrue: [^playerBearingCode == actualObject ifTrue: ["If the object is the method's own 'self' then we MUST, rather than just MAY, put out 'self' rather than the referencer call, though the latter will temporarily work if only one instance of the uniclass exists." ^ encoder encodeVariable: 'self'] ifFalse: [(actualObject isPlayerLike and: [actualObject isSequentialStub]) ifTrue: [ ^ actualObject parseNodeWith: encoder. ] ifFalse: [ ^ encoder encodePlayer: actualObject]]]. type = #operator ifTrue: [op := ((UpdatingOperators includesKey: operatorOrExpression) and: [self precedingTileType = #slotRef]) ifTrue: [UpdatingOperators at: operatorOrExpression] ifFalse: [operatorOrExpression]. ^op isEmpty ifTrue: [self halt.] ifFalse: [^ encoder encodeSelector: (EqualityOperators at: op ifAbsent: [op])]]. ! From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 7 19:33:01 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 7 Apr 2021 19:33:01 +0000 Subject: [squeak-dev] Regular Expressions are not limited to Strings In-Reply-To: <0d42ee73525645599de63902aec3529b@student.hpi.uni-potsdam.de> References: <0d42ee73525645599de63902aec3529b@student.hpi.uni-potsdam.de> Message-ID: <08a5884fa66e4df7b5d86053b8448f4a@student.hpi.uni-potsdam.de> Woohoo, nested regular expressions are even easier than I thought! innerRegex := RxParser new parse: #(3 4 $* 5). innerMatcher := RxParser preferredMatcherClass for: innerRegex. regex := RxParser new parse: {#(1 2). innerMatcher. ${.$,.$3.$}. #(6 7)}. matcher := RxParser preferredMatcherClass for: regex. matcher matches: #((1 2) (3 4 5) (6 7)). "true" matcher matches: #((1 2) (3 4 5) (3 5) (6 7)). "true" matcher matches: #((1 2) (3 4 5) (3 5) (3 4 4 5) (6 7)). "true" matcher matches: #((1 2) (3 4 5) (3 5) (3 4 4 5) (3 5) (6 7)). "false" matcher matches: #((1 2) (3 4 5) (3 2 5) (3 4 4 5) (6 7)). "false" I'll share my changeset upon request. This is really exciting stuff. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Thiede, Christoph Gesendet: Mittwoch, 7. April 2021 19:37 Uhr An: Squeak Dev Betreff: [squeak-dev] Regular Expressions are not limited to Strings Hi all, just a small goody for all those interested: It turns out that, thanks to the great polymorphy in Squeak, regular expressions (as implemented in the Regex package of Trunk originally developed by Vassili Bykov) are not limited to collections that are actually strings. Here is a short counter-example: regex := RxParser new parse: #(1 2 $+ 1). matcher := RxParser preferredMatcherClass for: regex. matcher matches: #(1 2 2 2 1). "true!" To make the example work, only a small number of hard-coded class names have to be adjusted, see the attached changeset, it's really tiny. Here's another example: matcher copy: #(1 2 2 1 0 1 2 1) translatingMatchesUsing: [:match | match negated]. "#(-1 -2 -2 -1 0 -1 -2 -1)" This also allows us to style texts using regexes: matcher := 'ab+a' asRegex. matcher copy: ' aa-aba-abba ' asText translatingMatchesUsing: [:match | match allBold]. " aa-aba-abba " However, if the original text attributes should be preserved, we would need to hack TextStream >> #withAttributes:do: into the copy methods, analogously to Text >> #format:. I guess this limitation could only be resolved by redesigning Text as a collection of TextCharacters, which might be very slow. Nevertheless, I think this insight opens great possibilities for other forms of parsing. Maybe one could also process binary streams using polymorphic regex patterns, or even process sequences of domain-specific objects. Because RxsPredicate is so generic, you could also simply define custom predicates for these objects. Later, the next step could be adding support for nested collections (RxsNested?) so that you could parse entire trees of objects ... Ah, so beautiful dreams :-) Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Wed Apr 7 22:03:27 2021 From: tim at rowledge.org (tim Rowledge) Date: Wed, 7 Apr 2021 15:03:27 -0700 Subject: [squeak-dev] Elastic Tabstops (was Re: Need better default code font) In-Reply-To: References: <690fbcd4932f42f1972f01ae68949a22@student.hpi.uni-potsdam.de> <073ead29274b430ba1415c01bede1e20@student.hpi.uni-potsdam.de> Message-ID: <58DD4828-0B51-402C-8002-AEDFB102EE85@rowledge.org> It seems to me that Shout obviates rather a lot of the concerns about formatting and elastic tabs and comments in different fonts etc. Make Shout render the comments in a different font - it already does the colouring - and drop the " if you want. Keep the " as part of the raw markup. That leaves filed out code untouched. So far as I can see from a quick dig the Shout code works through the Themes stuff and can already cope with a font or emphasis being specified, so that just leaves the not-display of the ". Make Shout handle the aligning of tabby-things. No need for any change in the raw code. Way past time the pretty print was integrated with Shout too; better yet, time to allow some profiles of what is considered 'pretty'. I've been trying to use the Kent Beck blocky layout format recently; it's not terrible. I'm probably going a bit far with it right now but we learn as we go. Also probably past time to drop the background shouting and redisplay thing; we're probably just wasting cycles here. Even a Pi2 didn't really have any problem...hmm, maybe for really big methods where some huge literal bitmap is defined? tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim "Bother!" said Pooh, as he stood up to his waist in a cow pat. From commits at source.squeak.org Thu Apr 8 20:30:32 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 8 Apr 2021 20:30:32 0000 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz Message-ID: A new version of MonticelloConfigurations was added to project The Inbox: http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz ==================== Summary ==================== Name: MonticelloConfigurations-ct.166 Author: ct Time: 8 April 2021, 10:30:30.702818 pm UUID: 6d887a86-fe0f-8e4c-a878-e40e8e612918 Ancestors: MonticelloConfigurations-mt.165 Adds support in MCMcmUpdater to install updates up to a specified system version number. This can be helpful when you want to bring an image into an exact state of an alpha version. I.e., a bug report or a tool can refer to Squeak6.0 Alpha #19570. Now it's possible to bring your 5.3 image into this state by evaluating: MCMcmUpdater default doUpdate: true upToUpdate: 19570. Still, it is possible to install all updates or navigate forward to a certain upstream version using the existing protocol: MCMcmUpdater default doUpdate: true. MCMcmUpdater default doUpdate: true upTo: 470. Detailed changelog (anticlimax): - Added 'upToUpdate:' variant of update selectors on MCMcmUpdater. - Refactored existing update selectors to deduplicate the logic for doing a complete update (#doUpdate: etc.) versus installing all updates up to an upstream version (#doUpdate:upTo: etc.). - Added #currentSystemVersion and #totalSystemVersion on MCConfiguration to determine the current resp. eventual system version as implied by the update stream. - Renamed (+ deprecated) #depsSatisfying:version(s)Do:displayingProgress: due to misleading use of singular in the block keyword. - Improved multilingual support for the updater. - Improved documentation of the update protocol. Note that in some situations, a small number of follow-up updates will be installed that go beyond the specified system version number. This is caused by interdependencies between the target version and its postdecessors when a definiton was moved from one package into another one. See sender of MCReorganizationPreloader. =============== Diff against MonticelloConfigurations-mt.165 =============== Item was added: + ----- Method: MCConfiguration class>>ensureOpenTranscript:during: (in category 'preferences') ----- + ensureOpenTranscript: aBoolean during: aBlock + + | previous | + previous := self ensureOpenTranscript. + self ensureOpenTranscript: aBoolean. + ^ aBlock ensure: [ + self ensureOpenTranscript: previous]! Item was added: + ----- Method: MCConfiguration>>currentSystemVersion (in category 'updating') ----- + currentSystemVersion + "Answer the current system version found in my configuration (or the associated working copy)." + + ^ self systemVersionForDeps: (self dependencies + collect: [:dep | + dep isFulfilledByAncestors + ifTrue: [dep versionInfo] + ifFalse: [dep package workingCopy ancestors] ] )! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:upToUpdate:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock upToUpdate: anIntegerOrNil versionsDo: versionBlock displayingProgress: progressString + + | count selectedVersions cleanWorkingCopies | + self cacheAllFileNamesDuring: [ + self repositories do: [ :eachRepository | + MCRepositoryGroup default addRepository: eachRepository ]. + + "First, download selected versions" + count := 0. + selectedVersions := OrderedCollection new. + self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | + verName := dep versionInfo name. + self class extraProgressInfo ifTrue: + [ ProgressNotification signal: '' extra: ('Downloading {1}' translated format: {verName}) ]. + repo := self repositories + detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] + ifNone: [ self logError: ('Version {1} not found in any repository' translated format: {verName}). + self logError: 'Aborting' translated. + ^ count ]. + (selectBlock value: dep) ifTrue: [ | version | + version := self versionNamed: verName for: dep from: repo. + version ifNil: [ self logError: ('Could not download version {1} from {2}' translated format: {verName. repo description}). + self logError: 'Aborting' translated. + ^ count ]. + dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" + dep package workingCopy repositoryGroup addRepository: repo. + selectedVersions add: version ] ]. + + "Then, process only those definitions that moved from one package to another, to avoid order dependence" + cleanWorkingCopies := MCWorkingCopy allManagers select: + [ :wc | wc modified not and: + [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. + MCReorganizationPreloader preloadMovesBetween: selectedVersions. + + "Finally, load/merge selected versions" + [:exit | self withProgress: progressString in: selectedVersions do: [ :version | + self logUpdate: version package with: version. + self class extraProgressInfo ifTrue: + [ ProgressNotification signal: '' extra: ('Installing {1}' translated format: {version info name}) ]. + versionBlock value: version. + count := count + 1. + anIntegerOrNil ifNotNil: [ + self currentSystemVersion highestUpdate < anIntegerOrNil ifFalse: exit. + self flag: #optimization. "ct: By customizing the system version computation, we could save redundant version downloads above. However, because of the preloading stage, this might become a bit more sophisticated." ] ]. + ] valueWithExit. + + "Clean up packages made dirty by MCReorganizationPreloader" + cleanWorkingCopies + select: [ :wc | wc modified ] + thenDo: [ :wc | wc checkModified ]. + ]. + ^ count! Item was changed: ----- Method: MCConfiguration>>depsSatisfying:versionDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionDo: versionBlock displayingProgress: progressString + + self deprecated. + ^ self + depsSatisfying: selectBlock + versionsDo: versionBlock + displayingProgress: progressString! - depsSatisfying: selectBlock versionDo: verBlock displayingProgress: progressString - | count selectedVersions cleanWorkingCopies | - self cacheAllFileNamesDuring: [ - self repositories do: [ :eachRepository | - MCRepositoryGroup default addRepository: eachRepository ]. - "First, download selected versions" - count := 0. - selectedVersions := OrderedCollection new. - self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | - verName := dep versionInfo name. - self class extraProgressInfo ifTrue: - [ ProgressNotification signal: '' extra: 'Downloading ' , verName ]. - repo := self repositories - detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] - ifNone: [ self logError: 'Version ' , verName , ' not found in any repository'. - self logError: 'Aborting'. - ^ count ]. - (selectBlock value: dep) ifTrue: [ | version | - version := self versionNamed: verName for: dep from: repo. - version ifNil: [ self logError: 'Could not download version ' , verName , ' from ' , repo description. - self logError: 'Aborting'. - ^ count ]. - dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" - dep package workingCopy repositoryGroup addRepository: repo. - selectedVersions add: version]]. - "Then, process only those definitions that moved from one package to another, to avoid order dependence" - cleanWorkingCopies := MCWorkingCopy allManagers select: - [ :wc | wc modified not and: - [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. - MCReorganizationPreloader preloadMovesBetween: selectedVersions. - "Finally, load/merge selected versions" - self withProgress: progressString in: selectedVersions do: [ :version | - self logUpdate: version package with: version. - self class extraProgressInfo ifTrue: - [ ProgressNotification signal: '' extra: 'Installing ' , version info name ]. - verBlock value: version. - count := count + 1 ]. - "Clean up packages made dirty by MCReorganizationPreloader" - cleanWorkingCopies - select: [ :wc | wc modified ] - thenDo: [ :wc | wc checkModified ]. - ]. - ^ count! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionsDo: versionBlock displayingProgress: progressString + + ^ self + depsSatisfying: selectBlock + upToUpdate: nil + versionsDo: versionBlock + displayingProgress: progressString! Item was changed: ----- Method: MCConfiguration>>load (in category 'actions') ----- load ^self depsSatisfying: [:dep | dep isCurrent not] + versionsDo: [:ver | ver load] + displayingProgress: 'loading packages' translated! - versionDo: [:ver | ver load] - displayingProgress: 'loading packages' - ! Item was changed: ----- Method: MCConfiguration>>merge (in category 'actions') ----- merge ^self depsSatisfying: [:dep | dep isFulfilledByAncestors not] + versionsDo: [:ver | ver merge] + displayingProgress: 'merging packages' translated! - versionDo: [:ver | ver merge] - displayingProgress: 'merging packages' - ! Item was changed: ----- Method: MCConfiguration>>setSystemVersion (in category 'updating') ----- setSystemVersion - "Set the current system version date to the latest date found in my configuration (or the associated working copy). Also set the highest update number to the sum of version numbers in my configuration." + | newVersion | + newVersion := self currentSystemVersion. - | versionNumbers versionDates | - versionNumbers := self dependencies collect: [:d | - (d versionInfo name copyAfterLast: $.) asInteger]. - versionDates := self dependencies collect: [:d | - d versionInfo date - ifNil: [d package workingCopy ancestors first date]]. SystemVersion current + date: newVersion date; + highestUpdate: newVersion highestUpdate.! - date: versionDates max; - highestUpdate: versionNumbers sum.! Item was added: + ----- Method: MCConfiguration>>systemVersionForDeps: (in category 'updating') ----- + systemVersionForDeps: dependencies + "Answer the system version that will be reached by loading the passed dependencies." + + | versionNumbers versionDates | + versionNumbers := dependencies collect: [:dep | + dep isCollection + ifFalse: [dep name versionNumber] + ifTrue: [(dep collect: [:version | + version name versionNumber]) + ifEmpty: [0] + ifNotEmpty: #max]]. + versionDates := dependencies with: self dependencies collect: [:dep :originalDep | + (dep isCollection ifFalse: [dep date]) + ifNil: [originalDep package workingCopy ancestors + ifEmpty: [nil] + ifNotEmpty: [:ancestors | ancestors first date]]]. + + ^ SystemVersion new + date: ((versionDates copyWithout: nil) + ifEmpty: [nil] + ifNotEmpty: #max); + highestUpdate: versionNumbers sum! Item was added: + ----- Method: MCConfiguration>>totalSystemVersion (in category 'updating') ----- + totalSystemVersion + "Answer the total system version that will be reached by upgrading the receiver." + + ^ self systemVersionForDeps: (self dependencies collect: #versionInfo)! Item was changed: ----- Method: MCConfiguration>>upgrade (in category 'actions') ----- upgrade + + ^ self upgradeUpToUpdate: nil! - ^self depsSatisfying: - [:dep | dep isFulfilledByAncestors not] - versionDo: - [:ver | - (self class upgradeIsMerge and: [ver shouldMerge]) - ifFalse: [ver load] - ifTrue: - [[ver merge] - on: MCNoChangesException - do: [:req| req resume ] - on: MCMergeResolutionRequest - do: [:request | - request merger conflicts isEmpty - ifTrue: [request resume: true] - ifFalse: [request pass]] - on: Deprecation - do: [:req| req resume ]]] - displayingProgress: 'upgrading packages'! Item was added: + ----- Method: MCConfiguration>>upgradeUpToUpdate: (in category 'actions') ----- + upgradeUpToUpdate: anIntegerOrNil + + ^ self + depsSatisfying: [:dep | + dep isFulfilledByAncestors not] + upToUpdate: anIntegerOrNil + versionsDo: [:ver | + (self class upgradeIsMerge and: [ver shouldMerge]) + ifFalse: [ver load] + ifTrue: + [[ver merge] + on: MCNoChangesException + do: [:req | req resume ] + on: MCMergeResolutionRequest + do: [:request | + request merger conflicts isEmpty + ifTrue: [request resume: true] + ifFalse: [request pass]] + on: Deprecation + do: [:req | req resume ]]] + displayingProgress: 'upgrading packages' translated! Item was added: + ----- Method: MCMcmUpdater>>basicDoUpdate:do: (in category 'updating') ----- + basicDoUpdate: interactive do: aBlock + "Update the image by evaluating aBlock. If this is the default updater for the system, update the system version when complete. If interactive, use a modal notifier, otherwise only update the transcript. Flush all caches. If a previous download failed, this is often helpful." + + | config previousUpdateLevel | + previousUpdateLevel := SystemVersion current highestUpdate. + MCFileBasedRepository flushAllCaches. + + MCConfiguration ensureOpenTranscript: interactive during: [ + config := aBlock value. + + config ifNil: [ + interactive ifTrue: [^ self inform: 'Unable to retrieve updates from remote repository.' translated]. + Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. + ^ self ]. + + MCMcmUpdater default == self + ifTrue: [ + config setSystemVersion. + interactive ifTrue: [ + self inform: (self updateMessageFor: previousUpdateLevel)]. + Transcript cr; + show: '========== Update completed: ' translated; + show: previousUpdateLevel; + show: ' -> ' ; + show: SystemVersion current highestUpdate; + show: ' =========='; cr ] + ifFalse: [ + interactive + ifTrue: [ self inform: 'Update completed.' ]. + Transcript cr; show: '========== Update completed. ==========' translated; cr ] ].! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepositories:do: (in category 'updating') ----- + basicUpdateFromRepositories: repositoryUrls do: repositoryBlock + + | repos config | + MCConfiguration upgradeIsMerge: true. + "The list of repositories to consult in order" + repos := repositoryUrls collect: [:url| + MCRepositoryGroup default repositories + detect: [:repo | repo description = url] + ifNone: [ | repo | + repo := MCHttpRepository location: url. + MCRepositoryGroup default addRepository: repo. + repo]]. + + "The list of updates-author.version.mcm sorted by version" + repos do: [:repo | + config := repositoryBlock value: repo]. + ^ config! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository thenDo: configBlock + + ^ self + basicUpdateFromRepository: aRepository + whileUpdatesSatisfy: [true] + upToUpdate: nil + thenDo: configBlock! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:whileUpdatesSatisfy:upToUpdate:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository whileUpdatesSatisfy: updateBlock upToUpdate: anIntegerOrNil thenDo: configBlock + + | config | + aRepository cacheAllFileNamesDuring: [ | updateList | + updateList := self updateListFor: aRepository. + "Proceed only if there are updates available at all." + updateList ifNotEmpty: [ + updateList := self refreshUpdateMapFor: aRepository with: updateList. + "Now process each update file. Check if we have all dependencies and if not, load the entire configuration (this is mostly to skip older updates quickly)" + [:exit | updateList + do: [:assoc | + (updateBlock cull: assoc key cull: assoc value) ifFalse: exit. + ProgressNotification signal: '' extra: ('Processing {1}' translated format: {assoc value}). + config := aRepository versionNamed: assoc value. + anIntegerOrNil ifNotNil: [ + config currentSystemVersion highestUpdate <= anIntegerOrNil ifFalse: exit]. + self updateFromConfig: config upToUpdate: anIntegerOrNil. + anIntegerOrNil ifNotNil: [ + config currentSystemVersion highestUpdate < config totalSystemVersion highestUpdate ifTrue: exit]. + self lastUpdateMap at: aRepository description put: assoc key] + displayingProgress: 'Processing configurations' translated] valueWithExit. + configBlock cull: config]]. + ^ config! Item was changed: ----- Method: MCMcmUpdater>>doUpdate: (in category 'updating') ----- doUpdate: interactive + "Update the image by loading all pending updates from the server." - "Update the image by loading all pending updates from the server. If this is - the default updater for the system, update the system version when complete. - If interteractive use a modal notifier, otherwise only update the transcript. - Flush all caches. If a previous download failed this is often helpful" + ^ self basicDoUpdate: interactive do: [ + self updateFromRepository ]! - | config previousUpdateLevel ensureTranscriptSetting | - previousUpdateLevel := SystemVersion current highestUpdate. - MCFileBasedRepository flushAllCaches. - ensureTranscriptSetting := MCConfiguration ensureOpenTranscript. - [ MCConfiguration ensureOpenTranscript: interactive. - config := self updateFromRepository. - config ifNil: [ - interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. - Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. - ^ self ]. - MCMcmUpdater default == self - ifTrue: [ - config setSystemVersion. - interactive ifTrue: [ - self inform: (self updateMessageFor: previousUpdateLevel)]. - Transcript cr; - show: '========== Update completed: ' translated; - show: previousUpdateLevel; - show: ' -> ' ; - show: SystemVersion current highestUpdate; - show: ' =========='; cr ] - ifFalse: [ - interactive - ifTrue: [ self inform: 'Update completed.' ]. - Transcript cr; show: '========== Update completed. ==========' translated; cr ] ] - ensure: [ MCConfiguration ensureOpenTranscript: ensureTranscriptSetting]. - - ! Item was changed: ----- Method: MCMcmUpdater>>doUpdate:upTo: (in category 'updating') ----- doUpdate: interactive upTo: versionNumber + "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." - "Update the image by loading all pending updates from the server. If this is - the default updater for the system, update the system version when complete. - If interteractive use a modal notifier, otherwise only update the transcript. - Flush all caches. If a previous download failed this is often helpful" + ^ self basicDoUpdate: interactive do: [ + self updateFromRepositories: {self repository} upTo: versionNumber ]! - | config previousUpdateLevel | - previousUpdateLevel := SystemVersion current highestUpdate. - MCFileBasedRepository flushAllCaches. - config := self updateFromRepositories: { self repository } upTo: versionNumber. - config ifNil: [ - interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. - Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. - ^ self ]. - MCMcmUpdater default == self - ifTrue: [ - config setSystemVersion. - interactive ifTrue: [ - self inform: (self updateMessageFor: previousUpdateLevel)]. - Transcript cr; - show: '========== Update completed: ' translated; - show: previousUpdateLevel; - show: ' -> ' ; - show: SystemVersion current highestUpdate; - show: ' =========='; cr ] - ifFalse: [ - interactive - ifTrue: [ self inform: 'Update completed.' ]. - Transcript cr; show: '========== Update completed. ==========' translated; cr ] - ! Item was added: + ----- Method: MCMcmUpdater>>doUpdate:upToUpdate: (in category 'updating') ----- + doUpdate: interactive upToUpdate: anIntegerOrNil + "Update the image by loading all pending updates from the server until the system version has reached at least anInteger. If anInteger is nil, install all available updates." + + ^ self basicDoUpdate: interactive do: [ + self updateFromRepositories: {self repository} upToUpdate: anIntegerOrNil ]! Item was changed: ----- Method: MCMcmUpdater>>doUpdateUpTo: (in category 'updating') ----- doUpdateUpTo: versionNumber + "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." - "Update the image by loading all pending updates from the server. If this is - the default updater for the system, update the system version when complete. - Flush all caches. If a previous download failed this is often helpful" ^self doUpdate: true upTo: versionNumber ! Item was changed: ----- Method: MCMcmUpdater>>updateFromConfig: (in category 'updating') ----- updateFromConfig: config + ^ self updateFromConfig: config upToUpdate: nil! - "Skip packages that were specifically unloaded" - config dependencies: (config dependencies - reject: [:dep| self class skipPackages includes: dep package name]). - self class updateMissingPackages ifFalse:[ - "Skip packages that are not in the image" - config dependencies: (config dependencies - select: [:dep| dep package hasWorkingCopy])]. - (config dependencies allSatisfy:[:dep| dep isFulfilled]) - ifFalse:[config upgrade]. - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromConfig:upToUpdate: (in category 'updating') ----- + updateFromConfig: config upToUpdate: anIntegerOrNil + + "Skip packages that were specifically unloaded" + config dependencies: (config dependencies + reject: [:dep | self class skipPackages includes: dep package name]). + self class updateMissingPackages ifFalse: [ + "Skip packages that are not in the image" + config dependencies: (config dependencies + select: [:dep | dep package hasWorkingCopy])]. + (config dependencies allSatisfy: [:dep | dep isFulfilled]) + ifFalse: [config upgradeUpToUpdate: anIntegerOrNil].! Item was changed: ----- Method: MCMcmUpdater>>updateFromRepositories:upTo: (in category 'updating') ----- updateFromRepositories: repositoryUrls upTo: versionNumber + " + MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest') upTo: 3 + " - "MCMcmUpdater updateFromRepositories: #( - 'http://squeaksource.com/MCUpdateTest' - )" + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | + self updateFromRepository: repo upTo: versionNumber]! - | repos config | - MCConfiguration upgradeIsMerge: true. - "The list of repositories to consult in order" - repos := repositoryUrls collect:[:url| - MCRepositoryGroup default repositories - detect:[:r| r description = url] - ifNone:[ | r | - r := MCHttpRepository location: url user: '' password: ''. - MCRepositoryGroup default addRepository: r. - r]]. - - "The list of updates-author.version.mcm sorted by version" - repos do:[ :r | config := self updateFromRepository: r upTo: versionNumber]. - ^config! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepositories:upToUpdate: (in category 'updating') ----- + updateFromRepositories: repositoryUrls upToUpdate: anIntegerOrNil + " + MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest') upToUpdate: 2130 + " + + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | + self updateFromRepository: repo upToUpdate: anIntegerOrNil ]! Item was changed: ----- Method: MCMcmUpdater>>updateFromRepository (in category 'updating') ----- updateFromRepository + ^ self updateFromRepository: self getRepositoryFromRepositoryGroup! - | config repo | - repo := self getRepositoryFromRepositoryGroup. - repo cacheAllFileNamesDuring: [ | updateList | - updateList := self updateListFor: repo. - "Proceed only if there are updates available at all." - updateList ifNotEmpty: [ - updateList := self refreshUpdateMapFor: repo with: updateList. - "Now process each update file. Check if we have all dependencies and if not, - load the entire configuration (this is mostly to skip older updates quickly)" - updateList do:[:assoc| - ProgressNotification signal: '' extra: 'Processing ', assoc value. - config := repo versionNamed: assoc value. - self updateFromConfig: config. - self lastUpdateMap at: repo description put: assoc key. - ] displayingProgress: 'Processing configurations'. - "We've loaded all the provided update configurations. - Use the latest configuration to update all the remaining packages." - (self useLatestPackagesFrom: repo) ifTrue: [ - config updateFromRepositories. - config upgrade]. - ]]. - ^ config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository: (in category 'updating') ----- + updateFromRepository: aRepository + + ^ self basicUpdateFromRepository: aRepository thenDo: [:config | + "We've loaded all the provided update configurations. Use the latest configuration to update all the remaining packages." + (self useLatestPackagesFrom: aRepository) ifTrue: [ + config updateFromRepositories. + config upgrade]]! Item was changed: ----- Method: MCMcmUpdater>>updateFromRepository:upTo: (in category 'updating') ----- + updateFromRepository: aRepository upTo: versionNumber - updateFromRepository: repository upTo: versionNumber + ^ self + basicUpdateFromRepository: aRepository + whileUpdatesSatisfy: [:updateVersion | updateVersion <= versionNumber] + upToUpdate: nil + thenDo: []! - | config | - repository cacheAllFileNamesDuring: [ | updateList | - updateList := self updateListFor: repository. - "Proceed only if there are updates available at all." - updateList ifNotEmpty: [ - updateList := self refreshUpdateMapFor: repository with: updateList. - "Now process each update file. Check if we have all dependencies and if not, - load the entire configuration (this is mostly to skip older updates quickly)" - updateList do:[:assoc| - assoc key > versionNumber ifTrue: [^config]. - ProgressNotification signal: '' extra: 'Processing ', assoc value. - config := repository versionNamed: assoc value. - self updateFromConfig: config. - self lastUpdateMap at: repository description put: assoc key. - ] displayingProgress: 'Processing configurations'. - ]]. - ^config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository:upToUpdate: (in category 'updating') ----- + updateFromRepository: aRepository upToUpdate: anIntegerOrNil + + ^ self + basicUpdateFromRepository: aRepository + whileUpdatesSatisfy: [true] + upToUpdate: anIntegerOrNil + thenDo: []! From Christoph.Thiede at student.hpi.uni-potsdam.de Thu Apr 8 20:37:06 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Thu, 8 Apr 2021 20:37:06 +0000 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz In-Reply-To: References: Message-ID: <53352cd9abea4ff999373cc0b798f00c@student.hpi.uni-potsdam.de> Please review! :-) A concrete use case I was having in mind for this feature is to allow arbitrary Squeak Trunk version numbers in smalltalkCI, see: https://github.com/hpi-swa/smalltalkCI/pull/506 At the moment, it is WIP - an unpolished prototype only, but the idea is that you could specify something like Squeak64-18242 instead of Squeak64-trunk in the CI/CLI args. Nevertheless, even if the proposal for SCI should get rejected, I think this is a helpful feature because releases are quite rare in Squeak and I find it important to tag certain states in the Trunk evolution. To improve support for the SCI PR, I would also like to backport these changes to 5.3 - there was only a single merge conflict, so if you agree with this proposal, I can send you a changeset for 5.3. Thanks in advance! :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Donnerstag, 8. April 2021 22:30:32 An: squeak-dev at lists.squeakfoundation.org Betreff: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz A new version of MonticelloConfigurations was added to project The Inbox: http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz ==================== Summary ==================== Name: MonticelloConfigurations-ct.166 Author: ct Time: 8 April 2021, 10:30:30.702818 pm UUID: 6d887a86-fe0f-8e4c-a878-e40e8e612918 Ancestors: MonticelloConfigurations-mt.165 Adds support in MCMcmUpdater to install updates up to a specified system version number. This can be helpful when you want to bring an image into an exact state of an alpha version. I.e., a bug report or a tool can refer to Squeak6.0 Alpha #19570. Now it's possible to bring your 5.3 image into this state by evaluating: MCMcmUpdater default doUpdate: true upToUpdate: 19570. Still, it is possible to install all updates or navigate forward to a certain upstream version using the existing protocol: MCMcmUpdater default doUpdate: true. MCMcmUpdater default doUpdate: true upTo: 470. Detailed changelog (anticlimax): - Added 'upToUpdate:' variant of update selectors on MCMcmUpdater. - Refactored existing update selectors to deduplicate the logic for doing a complete update (#doUpdate: etc.) versus installing all updates up to an upstream version (#doUpdate:upTo: etc.). - Added #currentSystemVersion and #totalSystemVersion on MCConfiguration to determine the current resp. eventual system version as implied by the update stream. - Renamed (+ deprecated) #depsSatisfying:version(s)Do:displayingProgress: due to misleading use of singular in the block keyword. - Improved multilingual support for the updater. - Improved documentation of the update protocol. Note that in some situations, a small number of follow-up updates will be installed that go beyond the specified system version number. This is caused by interdependencies between the target version and its postdecessors when a definiton was moved from one package into another one. See sender of MCReorganizationPreloader. =============== Diff against MonticelloConfigurations-mt.165 =============== Item was added: + ----- Method: MCConfiguration class>>ensureOpenTranscript:during: (in category 'preferences') ----- + ensureOpenTranscript: aBoolean during: aBlock + + | previous | + previous := self ensureOpenTranscript. + self ensureOpenTranscript: aBoolean. + ^ aBlock ensure: [ + self ensureOpenTranscript: previous]! Item was added: + ----- Method: MCConfiguration>>currentSystemVersion (in category 'updating') ----- + currentSystemVersion + "Answer the current system version found in my configuration (or the associated working copy)." + + ^ self systemVersionForDeps: (self dependencies + collect: [:dep | + dep isFulfilledByAncestors + ifTrue: [dep versionInfo] + ifFalse: [dep package workingCopy ancestors] ] )! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:upToUpdate:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock upToUpdate: anIntegerOrNil versionsDo: versionBlock displayingProgress: progressString + + | count selectedVersions cleanWorkingCopies | + self cacheAllFileNamesDuring: [ + self repositories do: [ :eachRepository | + MCRepositoryGroup default addRepository: eachRepository ]. + + "First, download selected versions" + count := 0. + selectedVersions := OrderedCollection new. + self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | + verName := dep versionInfo name. + self class extraProgressInfo ifTrue: + [ ProgressNotification signal: '' extra: ('Downloading {1}' translated format: {verName}) ]. + repo := self repositories + detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] + ifNone: [ self logError: ('Version {1} not found in any repository' translated format: {verName}). + self logError: 'Aborting' translated. + ^ count ]. + (selectBlock value: dep) ifTrue: [ | version | + version := self versionNamed: verName for: dep from: repo. + version ifNil: [ self logError: ('Could not download version {1} from {2}' translated format: {verName. repo description}). + self logError: 'Aborting' translated. + ^ count ]. + dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" + dep package workingCopy repositoryGroup addRepository: repo. + selectedVersions add: version ] ]. + + "Then, process only those definitions that moved from one package to another, to avoid order dependence" + cleanWorkingCopies := MCWorkingCopy allManagers select: + [ :wc | wc modified not and: + [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. + MCReorganizationPreloader preloadMovesBetween: selectedVersions. + + "Finally, load/merge selected versions" + [:exit | self withProgress: progressString in: selectedVersions do: [ :version | + self logUpdate: version package with: version. + self class extraProgressInfo ifTrue: + [ ProgressNotification signal: '' extra: ('Installing {1}' translated format: {version info name}) ]. + versionBlock value: version. + count := count + 1. + anIntegerOrNil ifNotNil: [ + self currentSystemVersion highestUpdate < anIntegerOrNil ifFalse: exit. + self flag: #optimization. "ct: By customizing the system version computation, we could save redundant version downloads above. However, because of the preloading stage, this might become a bit more sophisticated." ] ]. + ] valueWithExit. + + "Clean up packages made dirty by MCReorganizationPreloader" + cleanWorkingCopies + select: [ :wc | wc modified ] + thenDo: [ :wc | wc checkModified ]. + ]. + ^ count! Item was changed: ----- Method: MCConfiguration>>depsSatisfying:versionDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionDo: versionBlock displayingProgress: progressString + + self deprecated. + ^ self + depsSatisfying: selectBlock + versionsDo: versionBlock + displayingProgress: progressString! - depsSatisfying: selectBlock versionDo: verBlock displayingProgress: progressString - | count selectedVersions cleanWorkingCopies | - self cacheAllFileNamesDuring: [ - self repositories do: [ :eachRepository | - MCRepositoryGroup default addRepository: eachRepository ]. - "First, download selected versions" - count := 0. - selectedVersions := OrderedCollection new. - self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | - verName := dep versionInfo name. - self class extraProgressInfo ifTrue: - [ ProgressNotification signal: '' extra: 'Downloading ' , verName ]. - repo := self repositories - detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] - ifNone: [ self logError: 'Version ' , verName , ' not found in any repository'. - self logError: 'Aborting'. - ^ count ]. - (selectBlock value: dep) ifTrue: [ | version | - version := self versionNamed: verName for: dep from: repo. - version ifNil: [ self logError: 'Could not download version ' , verName , ' from ' , repo description. - self logError: 'Aborting'. - ^ count ]. - dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" - dep package workingCopy repositoryGroup addRepository: repo. - selectedVersions add: version]]. - "Then, process only those definitions that moved from one package to another, to avoid order dependence" - cleanWorkingCopies := MCWorkingCopy allManagers select: - [ :wc | wc modified not and: - [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. - MCReorganizationPreloader preloadMovesBetween: selectedVersions. - "Finally, load/merge selected versions" - self withProgress: progressString in: selectedVersions do: [ :version | - self logUpdate: version package with: version. - self class extraProgressInfo ifTrue: - [ ProgressNotification signal: '' extra: 'Installing ' , version info name ]. - verBlock value: version. - count := count + 1 ]. - "Clean up packages made dirty by MCReorganizationPreloader" - cleanWorkingCopies - select: [ :wc | wc modified ] - thenDo: [ :wc | wc checkModified ]. - ]. - ^ count! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionsDo: versionBlock displayingProgress: progressString + + ^ self + depsSatisfying: selectBlock + upToUpdate: nil + versionsDo: versionBlock + displayingProgress: progressString! Item was changed: ----- Method: MCConfiguration>>load (in category 'actions') ----- load ^self depsSatisfying: [:dep | dep isCurrent not] + versionsDo: [:ver | ver load] + displayingProgress: 'loading packages' translated! - versionDo: [:ver | ver load] - displayingProgress: 'loading packages' - ! Item was changed: ----- Method: MCConfiguration>>merge (in category 'actions') ----- merge ^self depsSatisfying: [:dep | dep isFulfilledByAncestors not] + versionsDo: [:ver | ver merge] + displayingProgress: 'merging packages' translated! - versionDo: [:ver | ver merge] - displayingProgress: 'merging packages' - ! Item was changed: ----- Method: MCConfiguration>>setSystemVersion (in category 'updating') ----- setSystemVersion - "Set the current system version date to the latest date found in my configuration (or the associated working copy). Also set the highest update number to the sum of version numbers in my configuration." + | newVersion | + newVersion := self currentSystemVersion. - | versionNumbers versionDates | - versionNumbers := self dependencies collect: [:d | - (d versionInfo name copyAfterLast: $.) asInteger]. - versionDates := self dependencies collect: [:d | - d versionInfo date - ifNil: [d package workingCopy ancestors first date]]. SystemVersion current + date: newVersion date; + highestUpdate: newVersion highestUpdate.! - date: versionDates max; - highestUpdate: versionNumbers sum.! Item was added: + ----- Method: MCConfiguration>>systemVersionForDeps: (in category 'updating') ----- + systemVersionForDeps: dependencies + "Answer the system version that will be reached by loading the passed dependencies." + + | versionNumbers versionDates | + versionNumbers := dependencies collect: [:dep | + dep isCollection + ifFalse: [dep name versionNumber] + ifTrue: [(dep collect: [:version | + version name versionNumber]) + ifEmpty: [0] + ifNotEmpty: #max]]. + versionDates := dependencies with: self dependencies collect: [:dep :originalDep | + (dep isCollection ifFalse: [dep date]) + ifNil: [originalDep package workingCopy ancestors + ifEmpty: [nil] + ifNotEmpty: [:ancestors | ancestors first date]]]. + + ^ SystemVersion new + date: ((versionDates copyWithout: nil) + ifEmpty: [nil] + ifNotEmpty: #max); + highestUpdate: versionNumbers sum! Item was added: + ----- Method: MCConfiguration>>totalSystemVersion (in category 'updating') ----- + totalSystemVersion + "Answer the total system version that will be reached by upgrading the receiver." + + ^ self systemVersionForDeps: (self dependencies collect: #versionInfo)! Item was changed: ----- Method: MCConfiguration>>upgrade (in category 'actions') ----- upgrade + + ^ self upgradeUpToUpdate: nil! - ^self depsSatisfying: - [:dep | dep isFulfilledByAncestors not] - versionDo: - [:ver | - (self class upgradeIsMerge and: [ver shouldMerge]) - ifFalse: [ver load] - ifTrue: - [[ver merge] - on: MCNoChangesException - do: [:req| req resume ] - on: MCMergeResolutionRequest - do: [:request | - request merger conflicts isEmpty - ifTrue: [request resume: true] - ifFalse: [request pass]] - on: Deprecation - do: [:req| req resume ]]] - displayingProgress: 'upgrading packages'! Item was added: + ----- Method: MCConfiguration>>upgradeUpToUpdate: (in category 'actions') ----- + upgradeUpToUpdate: anIntegerOrNil + + ^ self + depsSatisfying: [:dep | + dep isFulfilledByAncestors not] + upToUpdate: anIntegerOrNil + versionsDo: [:ver | + (self class upgradeIsMerge and: [ver shouldMerge]) + ifFalse: [ver load] + ifTrue: + [[ver merge] + on: MCNoChangesException + do: [:req | req resume ] + on: MCMergeResolutionRequest + do: [:request | + request merger conflicts isEmpty + ifTrue: [request resume: true] + ifFalse: [request pass]] + on: Deprecation + do: [:req | req resume ]]] + displayingProgress: 'upgrading packages' translated! Item was added: + ----- Method: MCMcmUpdater>>basicDoUpdate:do: (in category 'updating') ----- + basicDoUpdate: interactive do: aBlock + "Update the image by evaluating aBlock. If this is the default updater for the system, update the system version when complete. If interactive, use a modal notifier, otherwise only update the transcript. Flush all caches. If a previous download failed, this is often helpful." + + | config previousUpdateLevel | + previousUpdateLevel := SystemVersion current highestUpdate. + MCFileBasedRepository flushAllCaches. + + MCConfiguration ensureOpenTranscript: interactive during: [ + config := aBlock value. + + config ifNil: [ + interactive ifTrue: [^ self inform: 'Unable to retrieve updates from remote repository.' translated]. + Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. + ^ self ]. + + MCMcmUpdater default == self + ifTrue: [ + config setSystemVersion. + interactive ifTrue: [ + self inform: (self updateMessageFor: previousUpdateLevel)]. + Transcript cr; + show: '========== Update completed: ' translated; + show: previousUpdateLevel; + show: ' -> ' ; + show: SystemVersion current highestUpdate; + show: ' =========='; cr ] + ifFalse: [ + interactive + ifTrue: [ self inform: 'Update completed.' ]. + Transcript cr; show: '========== Update completed. ==========' translated; cr ] ].! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepositories:do: (in category 'updating') ----- + basicUpdateFromRepositories: repositoryUrls do: repositoryBlock + + | repos config | + MCConfiguration upgradeIsMerge: true. + "The list of repositories to consult in order" + repos := repositoryUrls collect: [:url| + MCRepositoryGroup default repositories + detect: [:repo | repo description = url] + ifNone: [ | repo | + repo := MCHttpRepository location: url. + MCRepositoryGroup default addRepository: repo. + repo]]. + + "The list of updates-author.version.mcm sorted by version" + repos do: [:repo | + config := repositoryBlock value: repo]. + ^ config! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository thenDo: configBlock + + ^ self + basicUpdateFromRepository: aRepository + whileUpdatesSatisfy: [true] + upToUpdate: nil + thenDo: configBlock! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:whileUpdatesSatisfy:upToUpdate:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository whileUpdatesSatisfy: updateBlock upToUpdate: anIntegerOrNil thenDo: configBlock + + | config | + aRepository cacheAllFileNamesDuring: [ | updateList | + updateList := self updateListFor: aRepository. + "Proceed only if there are updates available at all." + updateList ifNotEmpty: [ + updateList := self refreshUpdateMapFor: aRepository with: updateList. + "Now process each update file. Check if we have all dependencies and if not, load the entire configuration (this is mostly to skip older updates quickly)" + [:exit | updateList + do: [:assoc | + (updateBlock cull: assoc key cull: assoc value) ifFalse: exit. + ProgressNotification signal: '' extra: ('Processing {1}' translated format: {assoc value}). + config := aRepository versionNamed: assoc value. + anIntegerOrNil ifNotNil: [ + config currentSystemVersion highestUpdate <= anIntegerOrNil ifFalse: exit]. + self updateFromConfig: config upToUpdate: anIntegerOrNil. + anIntegerOrNil ifNotNil: [ + config currentSystemVersion highestUpdate < config totalSystemVersion highestUpdate ifTrue: exit]. + self lastUpdateMap at: aRepository description put: assoc key] + displayingProgress: 'Processing configurations' translated] valueWithExit. + configBlock cull: config]]. + ^ config! Item was changed: ----- Method: MCMcmUpdater>>doUpdate: (in category 'updating') ----- doUpdate: interactive + "Update the image by loading all pending updates from the server." - "Update the image by loading all pending updates from the server. If this is - the default updater for the system, update the system version when complete. - If interteractive use a modal notifier, otherwise only update the transcript. - Flush all caches. If a previous download failed this is often helpful" + ^ self basicDoUpdate: interactive do: [ + self updateFromRepository ]! - | config previousUpdateLevel ensureTranscriptSetting | - previousUpdateLevel := SystemVersion current highestUpdate. - MCFileBasedRepository flushAllCaches. - ensureTranscriptSetting := MCConfiguration ensureOpenTranscript. - [ MCConfiguration ensureOpenTranscript: interactive. - config := self updateFromRepository. - config ifNil: [ - interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. - Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. - ^ self ]. - MCMcmUpdater default == self - ifTrue: [ - config setSystemVersion. - interactive ifTrue: [ - self inform: (self updateMessageFor: previousUpdateLevel)]. - Transcript cr; - show: '========== Update completed: ' translated; - show: previousUpdateLevel; - show: ' -> ' ; - show: SystemVersion current highestUpdate; - show: ' =========='; cr ] - ifFalse: [ - interactive - ifTrue: [ self inform: 'Update completed.' ]. - Transcript cr; show: '========== Update completed. ==========' translated; cr ] ] - ensure: [ MCConfiguration ensureOpenTranscript: ensureTranscriptSetting]. - - ! Item was changed: ----- Method: MCMcmUpdater>>doUpdate:upTo: (in category 'updating') ----- doUpdate: interactive upTo: versionNumber + "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." - "Update the image by loading all pending updates from the server. If this is - the default updater for the system, update the system version when complete. - If interteractive use a modal notifier, otherwise only update the transcript. - Flush all caches. If a previous download failed this is often helpful" + ^ self basicDoUpdate: interactive do: [ + self updateFromRepositories: {self repository} upTo: versionNumber ]! - | config previousUpdateLevel | - previousUpdateLevel := SystemVersion current highestUpdate. - MCFileBasedRepository flushAllCaches. - config := self updateFromRepositories: { self repository } upTo: versionNumber. - config ifNil: [ - interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. - Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. - ^ self ]. - MCMcmUpdater default == self - ifTrue: [ - config setSystemVersion. - interactive ifTrue: [ - self inform: (self updateMessageFor: previousUpdateLevel)]. - Transcript cr; - show: '========== Update completed: ' translated; - show: previousUpdateLevel; - show: ' -> ' ; - show: SystemVersion current highestUpdate; - show: ' =========='; cr ] - ifFalse: [ - interactive - ifTrue: [ self inform: 'Update completed.' ]. - Transcript cr; show: '========== Update completed. ==========' translated; cr ] - ! Item was added: + ----- Method: MCMcmUpdater>>doUpdate:upToUpdate: (in category 'updating') ----- + doUpdate: interactive upToUpdate: anIntegerOrNil + "Update the image by loading all pending updates from the server until the system version has reached at least anInteger. If anInteger is nil, install all available updates." + + ^ self basicDoUpdate: interactive do: [ + self updateFromRepositories: {self repository} upToUpdate: anIntegerOrNil ]! Item was changed: ----- Method: MCMcmUpdater>>doUpdateUpTo: (in category 'updating') ----- doUpdateUpTo: versionNumber + "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." - "Update the image by loading all pending updates from the server. If this is - the default updater for the system, update the system version when complete. - Flush all caches. If a previous download failed this is often helpful" ^self doUpdate: true upTo: versionNumber ! Item was changed: ----- Method: MCMcmUpdater>>updateFromConfig: (in category 'updating') ----- updateFromConfig: config + ^ self updateFromConfig: config upToUpdate: nil! - "Skip packages that were specifically unloaded" - config dependencies: (config dependencies - reject: [:dep| self class skipPackages includes: dep package name]). - self class updateMissingPackages ifFalse:[ - "Skip packages that are not in the image" - config dependencies: (config dependencies - select: [:dep| dep package hasWorkingCopy])]. - (config dependencies allSatisfy:[:dep| dep isFulfilled]) - ifFalse:[config upgrade]. - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromConfig:upToUpdate: (in category 'updating') ----- + updateFromConfig: config upToUpdate: anIntegerOrNil + + "Skip packages that were specifically unloaded" + config dependencies: (config dependencies + reject: [:dep | self class skipPackages includes: dep package name]). + self class updateMissingPackages ifFalse: [ + "Skip packages that are not in the image" + config dependencies: (config dependencies + select: [:dep | dep package hasWorkingCopy])]. + (config dependencies allSatisfy: [:dep | dep isFulfilled]) + ifFalse: [config upgradeUpToUpdate: anIntegerOrNil].! Item was changed: ----- Method: MCMcmUpdater>>updateFromRepositories:upTo: (in category 'updating') ----- updateFromRepositories: repositoryUrls upTo: versionNumber + " + MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest') upTo: 3 + " - "MCMcmUpdater updateFromRepositories: #( - 'http://squeaksource.com/MCUpdateTest' - )" + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | + self updateFromRepository: repo upTo: versionNumber]! - | repos config | - MCConfiguration upgradeIsMerge: true. - "The list of repositories to consult in order" - repos := repositoryUrls collect:[:url| - MCRepositoryGroup default repositories - detect:[:r| r description = url] - ifNone:[ | r | - r := MCHttpRepository location: url user: '' password: ''. - MCRepositoryGroup default addRepository: r. - r]]. - - "The list of updates-author.version.mcm sorted by version" - repos do:[ :r | config := self updateFromRepository: r upTo: versionNumber]. - ^config! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepositories:upToUpdate: (in category 'updating') ----- + updateFromRepositories: repositoryUrls upToUpdate: anIntegerOrNil + " + MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest') upToUpdate: 2130 + " + + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | + self updateFromRepository: repo upToUpdate: anIntegerOrNil ]! Item was changed: ----- Method: MCMcmUpdater>>updateFromRepository (in category 'updating') ----- updateFromRepository + ^ self updateFromRepository: self getRepositoryFromRepositoryGroup! - | config repo | - repo := self getRepositoryFromRepositoryGroup. - repo cacheAllFileNamesDuring: [ | updateList | - updateList := self updateListFor: repo. - "Proceed only if there are updates available at all." - updateList ifNotEmpty: [ - updateList := self refreshUpdateMapFor: repo with: updateList. - "Now process each update file. Check if we have all dependencies and if not, - load the entire configuration (this is mostly to skip older updates quickly)" - updateList do:[:assoc| - ProgressNotification signal: '' extra: 'Processing ', assoc value. - config := repo versionNamed: assoc value. - self updateFromConfig: config. - self lastUpdateMap at: repo description put: assoc key. - ] displayingProgress: 'Processing configurations'. - "We've loaded all the provided update configurations. - Use the latest configuration to update all the remaining packages." - (self useLatestPackagesFrom: repo) ifTrue: [ - config updateFromRepositories. - config upgrade]. - ]]. - ^ config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository: (in category 'updating') ----- + updateFromRepository: aRepository + + ^ self basicUpdateFromRepository: aRepository thenDo: [:config | + "We've loaded all the provided update configurations. Use the latest configuration to update all the remaining packages." + (self useLatestPackagesFrom: aRepository) ifTrue: [ + config updateFromRepositories. + config upgrade]]! Item was changed: ----- Method: MCMcmUpdater>>updateFromRepository:upTo: (in category 'updating') ----- + updateFromRepository: aRepository upTo: versionNumber - updateFromRepository: repository upTo: versionNumber + ^ self + basicUpdateFromRepository: aRepository + whileUpdatesSatisfy: [:updateVersion | updateVersion <= versionNumber] + upToUpdate: nil + thenDo: []! - | config | - repository cacheAllFileNamesDuring: [ | updateList | - updateList := self updateListFor: repository. - "Proceed only if there are updates available at all." - updateList ifNotEmpty: [ - updateList := self refreshUpdateMapFor: repository with: updateList. - "Now process each update file. Check if we have all dependencies and if not, - load the entire configuration (this is mostly to skip older updates quickly)" - updateList do:[:assoc| - assoc key > versionNumber ifTrue: [^config]. - ProgressNotification signal: '' extra: 'Processing ', assoc value. - config := repository versionNamed: assoc value. - self updateFromConfig: config. - self lastUpdateMap at: repository description put: assoc key. - ] displayingProgress: 'Processing configurations'. - ]]. - ^config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository:upToUpdate: (in category 'updating') ----- + updateFromRepository: aRepository upToUpdate: anIntegerOrNil + + ^ self + basicUpdateFromRepository: aRepository + whileUpdatesSatisfy: [true] + upToUpdate: anIntegerOrNil + thenDo: []! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Apr 8 20:59:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 8 Apr 2021 20:59:46 0000 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.167.mcz Message-ID: A new version of MonticelloConfigurations was added to project The Inbox: http://source.squeak.org/inbox/MonticelloConfigurations-ct.167.mcz ==================== Summary ==================== Name: MonticelloConfigurations-ct.167 Author: ct Time: 8 April 2021, 10:59:45.930314 pm UUID: 99193dce-93ca-0f46-82ab-ca64f2641b16 Ancestors: MonticelloConfigurations-ct.166 Improves backward compatibility of MonticelloConfigurations-ct.166 for Squeak 5.2. =============== Diff against MonticelloConfigurations-ct.166 =============== Item was changed: ----- Method: MCConfiguration>>systemVersionForDeps: (in category 'updating') ----- systemVersionForDeps: dependencies "Answer the system version that will be reached by loading the passed dependencies." | versionNumbers versionDates | versionNumbers := dependencies collect: [:dep | dep isCollection ifFalse: [dep name versionNumber] ifTrue: [(dep collect: [:version | version name versionNumber]) ifEmpty: [0] + ifNotEmpty: [:numbers | numbers max]]]. - ifNotEmpty: #max]]. versionDates := dependencies with: self dependencies collect: [:dep :originalDep | (dep isCollection ifFalse: [dep date]) ifNil: [originalDep package workingCopy ancestors ifEmpty: [nil] ifNotEmpty: [:ancestors | ancestors first date]]]. ^ SystemVersion new date: ((versionDates copyWithout: nil) ifEmpty: [nil] + ifNotEmpty: [:dates | dates max]); - ifNotEmpty: #max); highestUpdate: versionNumbers sum! From dev at stlutz.net Fri Apr 9 11:27:09 2021 From: dev at stlutz.net (Stephan Lutz) Date: Fri, 9 Apr 2021 13:27:09 +0200 Subject: [squeak-dev] Methods with more than 15 arguments? Message-ID: At the moment methods are limited to 15 arguments at most. Trying to compile a method with more arguments fails: with: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 with: arg7 with: arg8 with: arg9 with: arg10 with: arg11 with: arg12 with: arg13 with: arg14 with: arg15 with:  "Too many arguments ->"arg16     ^ 42 This limitation is enforced in Encoder >> bindArg: bindArg: name     "Declare an argument."     | node |     nTemps >= 15         ifTrue: [^self notify: 'Too many arguments'].     node := self bindTemp: name.     ^ node nowHasDef nowHasRef Looking at where this limitation comes from, I noticed that a method header only has 4 bits reserved for the number of arguments: header     "Answer the word containing the information about the form of the      receiver and the form of the context needed to run the receiver.         sign:1 29-28:accessModifier 27-24:numArgs 23-18:numTemps 17:largeFrameFlag 16:hasPrimitive 15:isOptimized 14-0:numLits"     ^self objectAt: 1 This, however, only uses 32 bits in total. In a 64bit image, the other 32 bits seem to be unused. Question: Is the limit of 15 arguments still accurate on modern VMs & bytecode sets? Stephan Disclaimer: No, I do not want to pass every single pixel of my bitmap as an argument ^^. But apparently other people's C-style libraries do, and I need to interface with one through FFI. Yes, I could build and invoke ExternalFunctions manually, but I would reeeaaally prefer not to if given a choice. -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Fri Apr 9 14:01:49 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 9 Apr 2021 16:01:49 +0200 Subject: [squeak-dev] Methods with more than 15 arguments? In-Reply-To: References: Message-ID: You can see a workaround at http://www.squeaksource.com/Smallapack.html See package Smallapack-Compiler.trunk-nice.6.mcz Le ven. 9 avr. 2021 à 13:28, Stephan Lutz a écrit : > > At the moment methods are limited to 15 arguments at most. > > Trying to compile a method with more arguments fails: > > with: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 with: arg7 with: arg8 with: arg9 with: arg10 with: arg11 with: arg12 with: arg13 with: arg14 with: arg15 with: "Too many arguments ->"arg16 > > ^ 42 > > This limitation is enforced in Encoder >> bindArg: > > bindArg: name > "Declare an argument." > | node | > nTemps >= 15 > ifTrue: [^self notify: 'Too many arguments']. > node := self bindTemp: name. > ^ node nowHasDef nowHasRef > > Looking at where this limitation comes from, I noticed that a method header only has 4 bits reserved for the number of arguments: > > header > "Answer the word containing the information about the form of the > receiver and the form of the context needed to run the receiver. > > sign:1 29-28:accessModifier 27-24:numArgs 23-18:numTemps 17:largeFrameFlag 16:hasPrimitive 15:isOptimized 14-0:numLits" > > ^self objectAt: 1 > > This, however, only uses 32 bits in total. In a 64bit image, the other 32 bits seem to be unused. > > Question: Is the limit of 15 arguments still accurate on modern VMs & bytecode sets? > > Stephan > > > Disclaimer: No, I do not want to pass every single pixel of my bitmap as an argument ^^. But apparently other people's C-style libraries do, and I need to interface with one through FFI. Yes, I could build and invoke ExternalFunctions manually, but I would reeeaaally prefer not to if given a choice. > > From nicolas.cellier.aka.nice at gmail.com Fri Apr 9 14:13:56 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 9 Apr 2021 16:13:56 +0200 Subject: [squeak-dev] Methods with more than 15 arguments? In-Reply-To: References: Message-ID: Note that Smallapack passes all arguments into a single array. Eliot Miranda suggested to pass first 14 arguments as usual, and only the last+excess arguments into an array, but nobody did work on such implementation. I do not remember pros and cons either, need to various scan mailing lists (squeak or vm-dev ?)... Le ven. 9 avr. 2021 à 16:01, Nicolas Cellier a écrit : > > You can see a workaround at http://www.squeaksource.com/Smallapack.html > See package > > Smallapack-Compiler.trunk-nice.6.mcz > > Le ven. 9 avr. 2021 à 13:28, Stephan Lutz a écrit : > > > > At the moment methods are limited to 15 arguments at most. > > > > Trying to compile a method with more arguments fails: > > > > with: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 with: arg7 with: arg8 with: arg9 with: arg10 with: arg11 with: arg12 with: arg13 with: arg14 with: arg15 with: "Too many arguments ->"arg16 > > > > ^ 42 > > > > This limitation is enforced in Encoder >> bindArg: > > > > bindArg: name > > "Declare an argument." > > | node | > > nTemps >= 15 > > ifTrue: [^self notify: 'Too many arguments']. > > node := self bindTemp: name. > > ^ node nowHasDef nowHasRef > > > > Looking at where this limitation comes from, I noticed that a method header only has 4 bits reserved for the number of arguments: > > > > header > > "Answer the word containing the information about the form of the > > receiver and the form of the context needed to run the receiver. > > > > sign:1 29-28:accessModifier 27-24:numArgs 23-18:numTemps 17:largeFrameFlag 16:hasPrimitive 15:isOptimized 14-0:numLits" > > > > ^self objectAt: 1 > > > > This, however, only uses 32 bits in total. In a 64bit image, the other 32 bits seem to be unused. > > > > Question: Is the limit of 15 arguments still accurate on modern VMs & bytecode sets? > > > > Stephan > > > > > > Disclaimer: No, I do not want to pass every single pixel of my bitmap as an argument ^^. But apparently other people's C-style libraries do, and I need to interface with one through FFI. Yes, I could build and invoke ExternalFunctions manually, but I would reeeaaally prefer not to if given a choice. > > > > From lewis at mail.msen.com Fri Apr 9 16:40:32 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Fri, 9 Apr 2021 12:40:32 -0400 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: <20210409164032.GA88364@shell.msen.com> On Fri, Apr 02, 2021 at 08:10:25AM +0000, Rein, Patrick wrote: > Hi All, > > It's that time again (although with a new person telling you this). > Time to raise your voices and elect your leaders! Can you believe > it's been over a year already? > > It's a time for you to stand up, help your community and volunteer to serve! > > Squeak wants you! > I am running for the Squeak Oversight Board again this year. I am a hobby programmer and long-time participant in the Squeak community. I have contriibuted to some of the technical aspects of Squeak, but I am most enthusiatic about using Squeak for learning and exploration, and for music, arts, and thought experiments. Although my personal focus is mainly on Squeak as a tool for individual use, I am also committed to ensuring that Squeak continues to be a preferred medium for advanced virtual machine development, computer science, and software development. I expect some fundamental challenges in the coming years: We will be challenged to evolve Squeak to be useful and relevant in an internet-based world of smart devices and new ways of human interaction with those devices. We need to manage the tension between simplicity and adding functionality. To me, it is essential to keep things simple and clean enough that a single person can understand and explore any and all parts of the system. But we also need to enhance and evolve the system. Balancing these goals is not easy, but it is the job of the Squeak board to make it happen. I am an enthusiastic user of git, and an extremely cautious advocate of finding a simple and effective way to use it to support our Monticello tools in the image. But see above concerning the tension between simplicity and function, whatever we do needs to be easy to understand and explore for a wide range of Squeak users. Finally, we are a small community, and we need to find ways to make the system and the community supportive of the creative work of evolving the system and the virtual machine that supports it. I have no easy solutions here, but this is critical for the well-being of both Squeak and of the people who are contributing to it. Please vote for me, and please also consider running for the board yourself if you have not yet done so. We need people of diverse backgrounds who have an interest in the progress of Squeak! Dave From vanessa at codefrau.net Fri Apr 9 16:43:13 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Fri, 9 Apr 2021 09:43:13 -0700 Subject: [squeak-dev] Methods with more than 15 arguments? In-Reply-To: References: Message-ID: Yep, that’s how it should work (array as 15th arg). I guess it would be relatively simple to make the encoder do that. Vanessa On Fri, Apr 9, 2021 at 07:14 Nicolas Cellier < nicolas.cellier.aka.nice at gmail.com> wrote: > Note that Smallapack passes all arguments into a single array. > Eliot Miranda suggested to pass first 14 arguments as usual, and only > the last+excess arguments into an array, but nobody did work on such > implementation. I do not remember pros and cons either, need to > various scan mailing lists (squeak or vm-dev ?)... > > Le ven. 9 avr. 2021 à 16:01, Nicolas Cellier > a écrit : > > > > You can see a workaround at http://www.squeaksource.com/Smallapack.html > > See package > > > > Smallapack-Compiler.trunk-nice.6.mcz > > > > Le ven. 9 avr. 2021 à 13:28, Stephan Lutz a écrit : > > > > > > At the moment methods are limited to 15 arguments at most. > > > > > > Trying to compile a method with more arguments fails: > > > > > > with: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 > with: arg7 with: arg8 with: arg9 with: arg10 with: arg11 with: arg12 with: > arg13 with: arg14 with: arg15 with: "Too many arguments ->"arg16 > > > > > > ^ 42 > > > > > > This limitation is enforced in Encoder >> bindArg: > > > > > > bindArg: name > > > "Declare an argument." > > > | node | > > > nTemps >= 15 > > > ifTrue: [^self notify: 'Too many arguments']. > > > node := self bindTemp: name. > > > ^ node nowHasDef nowHasRef > > > > > > Looking at where this limitation comes from, I noticed that a method > header only has 4 bits reserved for the number of arguments: > > > > > > header > > > "Answer the word containing the information about the form of the > > > receiver and the form of the context needed to run the receiver. > > > > > > sign:1 29-28:accessModifier 27-24:numArgs 23-18:numTemps > 17:largeFrameFlag 16:hasPrimitive 15:isOptimized 14-0:numLits" > > > > > > ^self objectAt: 1 > > > > > > This, however, only uses 32 bits in total. In a 64bit image, the other > 32 bits seem to be unused. > > > > > > Question: Is the limit of 15 arguments still accurate on modern VMs & > bytecode sets? > > > > > > Stephan > > > > > > > > > Disclaimer: No, I do not want to pass every single pixel of my bitmap > as an argument ^^. But apparently other people's C-style libraries do, and > I need to interface with one through FFI. Yes, I could build and invoke > ExternalFunctions manually, but I would reeeaaally prefer not to if given a > choice. > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Fri Apr 9 16:52:38 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Fri, 9 Apr 2021 09:52:38 -0700 Subject: [squeak-dev] Methods with more than 15 arguments? In-Reply-To: References: Message-ID: ... and the FFI compiler could then compile that into a proper external function call. Which is probably better than trying to make the FFI plugin understand the 14+array convention, but I might be mistaken. Incidentally, which library/function specifically do you want to call? Vanessa On Fri, Apr 9, 2021 at 09:43 Vanessa Freudenberg wrote: > Yep, that’s how it should work (array as 15th arg). I guess it would be > relatively simple to make the encoder do that. > > Vanessa > > On Fri, Apr 9, 2021 at 07:14 Nicolas Cellier < > nicolas.cellier.aka.nice at gmail.com> wrote: > >> Note that Smallapack passes all arguments into a single array. >> Eliot Miranda suggested to pass first 14 arguments as usual, and only >> the last+excess arguments into an array, but nobody did work on such >> implementation. I do not remember pros and cons either, need to >> various scan mailing lists (squeak or vm-dev ?)... >> >> Le ven. 9 avr. 2021 à 16:01, Nicolas Cellier >> a écrit : >> > >> > You can see a workaround at http://www.squeaksource.com/Smallapack.html >> > See package >> > >> > Smallapack-Compiler.trunk-nice.6.mcz >> > >> > Le ven. 9 avr. 2021 à 13:28, Stephan Lutz a écrit : >> > > >> > > At the moment methods are limited to 15 arguments at most. >> > > >> > > Trying to compile a method with more arguments fails: >> > > >> > > with: arg1 with: arg2 with: arg3 with: arg4 with: arg5 with: arg6 >> with: arg7 with: arg8 with: arg9 with: arg10 with: arg11 with: arg12 with: >> arg13 with: arg14 with: arg15 with: "Too many arguments ->"arg16 >> > > >> > > ^ 42 >> > > >> > > This limitation is enforced in Encoder >> bindArg: >> > > >> > > bindArg: name >> > > "Declare an argument." >> > > | node | >> > > nTemps >= 15 >> > > ifTrue: [^self notify: 'Too many arguments']. >> > > node := self bindTemp: name. >> > > ^ node nowHasDef nowHasRef >> > > >> > > Looking at where this limitation comes from, I noticed that a method >> header only has 4 bits reserved for the number of arguments: >> > > >> > > header >> > > "Answer the word containing the information about the form of the >> > > receiver and the form of the context needed to run the receiver. >> > > >> > > sign:1 29-28:accessModifier 27-24:numArgs 23-18:numTemps >> 17:largeFrameFlag 16:hasPrimitive 15:isOptimized 14-0:numLits" >> > > >> > > ^self objectAt: 1 >> > > >> > > This, however, only uses 32 bits in total. In a 64bit image, the >> other 32 bits seem to be unused. >> > > >> > > Question: Is the limit of 15 arguments still accurate on modern VMs & >> bytecode sets? >> > > >> > > Stephan >> > > >> > > >> > > Disclaimer: No, I do not want to pass every single pixel of my bitmap >> as an argument ^^. But apparently other people's C-style libraries do, and >> I need to interface with one through FFI. Yes, I could build and invoke >> ExternalFunctions manually, but I would reeeaaally prefer not to if given a >> choice. >> > > >> > > >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From tomjonabc at gmail.com Fri Apr 9 18:27:29 2021 From: tomjonabc at gmail.com (Tom Beckmann) Date: Fri, 9 Apr 2021 20:27:29 +0200 Subject: [squeak-dev] Need better default code font In-Reply-To: <20210405203657.312818C15D5@proxy.email-ssl.com.br> References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> <20210405203657.312818C15D5@proxy.email-ssl.com.br> Message-ID: Hi everyone, I went ahead and loaded some of the fonts mentioned in this thread and gave them a spin in the image. Note that these are rendered with freetype, so if you use Balloon2D you may get different results. If you have other favorites or a preferred method to "benchmark" the looks, let me know. Input Sans, 10 [image: Screenshot from 2021-04-09 20-11-34.png] Ubuntu Mono, 11 [image: Screenshot from 2021-04-09 20-13-04.png] Roboto, 11 [image: Screenshot from 2021-04-09 20-15-36.png] Fira Sans, 11 [image: Screenshot from 2021-04-09 20-17-34.png] Source Sans Pro, 12 [image: Screenshot from 2021-04-09 20-25-12.png] Best, Tom On Mon, Apr 5, 2021 at 10:37 PM Jecel Assumpcao Jr wrote: > Douglas Brebner wrote on Mon, 5 Apr 2021 08:42:31 +0100 > > On 04/04/2021 23:06, tim Rowledge wrote: > > > I really wish there was a propelr left-arrow-assign for use to use. I > hate ':='; it's so.... C > > > > > > I thought it was taken from Pascal. > > Digitalk introduced ":=" to Smalltalk in its Methods implementation for > the IBM PC even though that machine did have a left arrow characeter > (but with a very different encoding than 1963 ASCII used by Xerox). > Given that the first part of the manual showed code fragments in Methods > and Pascal side by side, it is clear that the choice was indeed made to > make Pascal programmers (the most numerous in the early 1980s) feel at > home. > > See chapter 2 of > > > http://www.wirfs-brock.com/allen/files/digitalk/methods-language-guide.pdf > > Note that not all PDF readers can handle this file. > > -- Jecel > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2021-04-09 20-11-34.png Type: image/png Size: 27100 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2021-04-09 20-13-04.png Type: image/png Size: 25590 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2021-04-09 20-15-36.png Type: image/png Size: 25293 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2021-04-09 20-17-34.png Type: image/png Size: 25946 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot from 2021-04-09 20-25-12.png Type: image/png Size: 24995 bytes Desc: not available URL: From Das.Linux at gmx.de Fri Apr 9 18:35:14 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri, 9 Apr 2021 20:35:14 +0200 Subject: [squeak-dev] Need better default code font In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> <20210405203657.312818C15D5@proxy.email-ssl.com.br> Message-ID: <6A4FEF27-13B6-4C5D-BFDB-9BD850524322@gmx.de> > On 9. Apr 2021, at 20:27, Tom Beckmann wrote: > > Fira Sans, 11 note that Fira Sans also has a slashed-Zero variant, which could come in handy… (still my favourite…) -t -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Bildschirmfoto 2021-04-09 um 20.33.51.PNG Type: image/png Size: 32751 bytes Desc: not available URL: From commits at source.squeak.org Fri Apr 9 22:34:33 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 9 Apr 2021 22:34:33 0000 Subject: [squeak-dev] The Inbox: Environments-jr.82.mcz Message-ID: A new version of Environments was added to project The Inbox: http://source.squeak.org/inbox/Environments-jr.82.mcz ==================== Summary ==================== Name: Environments-jr.82 Author: jr Time: 10 April 2021, 12:34:34.717998 am UUID: 2935eb63-046e-c344-8fba-771fb62fb5c2 Ancestors: Environments-tonyg.81 Sending resume: from defaultAction is erroneous in the ANSI standard. In Squeak, unhandled exceptions are resumed with the answer to the defaultAction message. =============== Diff against Environments-tonyg.81 =============== Item was changed: ----- Method: EnvironmentRequest>>defaultAction (in category 'exceptionDescription') ----- defaultAction | all environment | all := Environment allInstances. environment := UIManager default chooseFrom: (all collect: [:ea | ea printString]) values: all. + ^ environment! - self resume: environment.! From vanessa at codefrau.net Sat Apr 10 03:32:44 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Fri, 9 Apr 2021 20:32:44 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: <6A4FEF27-13B6-4C5D-BFDB-9BD850524322@gmx.de> References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> <20210405203657.312818C15D5@proxy.email-ssl.com.br> <6A4FEF27-13B6-4C5D-BFDB-9BD850524322@gmx.de> Message-ID: Thanks Tom, those look great! Kinda hard to pick a favorite really. Tobias: how hard is it to pick a glyph variant when importing the font? —Vanessa— On Fri, Apr 9, 2021 at 11:35 AM Tobias Pape wrote: > > > On 9. Apr 2021, at 20:27, Tom Beckmann wrote: > > Fira Sans, 11 > > > note that Fira Sans also has a slashed-Zero variant, which could come in > handy… > > (still my favourite…) > -t > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Bildschirmfoto 2021-04-09 um 20.33.51.PNG Type: image/png Size: 32751 bytes Desc: not available URL: From Das.Linux at gmx.de Sat Apr 10 07:01:57 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Sat, 10 Apr 2021 09:01:57 +0200 Subject: [squeak-dev] Need better default code font In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> <20210405203657.312818C15D5@proxy.email-ssl.com.br> <6A4FEF27-13B6-4C5D-BFDB-9BD850524322@gmx.de> Message-ID: Hi > On 10. Apr 2021, at 05:32, Vanessa Freudenberg wrote: > > Thanks Tom, those look great! Kinda hard to pick a favorite really. > > Tobias: how hard is it to pick a glyph variant when importing the font? At the moment, impossible -.- But if we pre-render, as with the bitmap-dejavu, we have all control… best regards -tobias > > —Vanessa— > > On Fri, Apr 9, 2021 at 11:35 AM Tobias Pape wrote: > > >> On 9. Apr 2021, at 20:27, Tom Beckmann wrote: >> >> Fira Sans, 11 > > note that Fira Sans also has a slashed-Zero variant, which could come in handy… > > (still my favourite…) > -t > > > From m at jaromir.net Sat Apr 10 08:58:13 2021 From: m at jaromir.net (Jaromir Matas) Date: Sat, 10 Apr 2021 03:58:13 -0500 (CDT) Subject: [squeak-dev] Solving multiple termination bugs - summary & proposal In-Reply-To: <1617642027172-0.post@n4.nabble.com> References: <1617642027172-0.post@n4.nabble.com> Message-ID: <1618045093475-0.post@n4.nabble.com> Hi, The enclosed changeset fixes all bugs/inconsistencies concerning process termination listed below. It's a simplified version of the previous proposal. Feedback very welcome indeed! The idea is to simply extend the existing mechanism for completing halfway-through unwind blocks and let it deal with *all* unwind blocks. best, Fix_terminate_v3.cs Jaromir Matas wrote > Hi All, > > here's a summary of bugs in the current termination procedure: > > 1. #isTerminated and #isSuspended fail to report correctly - in [1] > > 2. active process termination bug causing an image crash - in [2] > > 3. nested unwind bug: skipping some ensure blocks - in [3] > > 4. likely a bug: a failure to complete nested unwind blocks halfway thru > execution - also in [3] > > 5. Christoph's discovery: a failure to correctly close the debugger in > case > of error or non-local return in unwind - in [4] > > 6. inconsistent semantics of unwinding protected blocks during active vs. > suspended process termination ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From commits at source.squeak.org Sat Apr 10 13:16:30 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 10 Apr 2021 13:16:30 0000 Subject: [squeak-dev] The Trunk: Network-ct.244.mcz Message-ID: Nicolas Cellier uploaded a new version of Network to project The Trunk: http://source.squeak.org/trunk/Network-ct.244.mcz ==================== Summary ==================== Name: Network-ct.244 Author: ct Time: 14 November 2020, 7:46:21.777394 pm UUID: a88f27af-c0a0-c340-9d0d-60c432537f47 Ancestors: Network-mt.243 Fixes FileUrl >> #retrieveContents which did not work for certain contentTypes because of an intermediary invalid content specification. See NetworkTests-ct.61 (inbox). =============== Diff against Network-mt.243 =============== Item was added: + ----- Method: MIMEDocument class>>contentType: (in category 'private') ----- + contentType: aString + + ^ self new + contentTypeHeaderValue: (MIMEHeaderValue fromMIMEHeader: aString); + yourself! Item was changed: ----- Method: MIMEDocument class>>contentType:content: (in category 'instance creation') ----- contentType: aString content: content "create a MIMEObject with the given content-type and content" "MIMEDocument contentType: 'text/plain' content: 'This is a test'" | ans | + ans := self contentType: aString. - ans := self new. - - ans contentTypeHeaderValue: (MIMEHeaderValue fromMIMEHeader: aString). - (ans isPlaintext or: [ans isHTML]) ifTrue: [ans content: (self tryToDecodeBody: content as: ans charset)] ifFalse: [ans isMultipart ifTrue: [| separator | separator := ans attachmentSeparator asLowercase. separator ifNil: [self error: 'Bad attachment separater']. separator := '--', separator withoutTrailingBlanks. ans addAllParts: (self parseParts: content withSeparator:separator).] ifFalse: [ans content: content]]. + + ^ ans! - - ^ ans - ! Item was changed: ----- Method: MIMELocalFileDocument class>>contentType:contentStream: (in category 'instance creation') ----- contentType: aString contentStream: aStream + + ^ (self contentType: aString) + contentStream: aStream; + yourself! - ^(self contentType: aString content: nil) contentStream: aStream! From commits at source.squeak.org Sat Apr 10 13:18:27 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 10 Apr 2021 13:18:27 0000 Subject: [squeak-dev] The Trunk: NetworkTests-ct.61.mcz Message-ID: Nicolas Cellier uploaded a new version of NetworkTests to project The Trunk: http://source.squeak.org/trunk/NetworkTests-ct.61.mcz ==================== Summary ==================== Name: NetworkTests-ct.61 Author: ct Time: 14 November 2020, 7:44:22.440394 pm UUID: d2c5f22e-ee31-3a4b-aaf9-eec14d08a7b8 Ancestors: NetworkTests-eem.60 Document bug in FileUrl >> #retrieveContents. A fix is arriving soon at the inbox! =============== Diff against NetworkTests-eem.60 =============== Item was added: + ----- Method: FileUrlTest>>testRetrieveContents (in category 'tests') ----- + testRetrieveContents + + | content name | + name := '{1}-{2}.txt' format: {self className. self selector}. + content := self identityHash asString. + + FileStream newFileNamed: name do: [:stream | + stream nextPutAll: content]. + [self assert: content equals: + (FileUrl absoluteFromFileNameOrUrlString: name) retrieveContents content] + ensure: [FileDirectory default deleteFileNamed: name].! From commits at source.squeak.org Sat Apr 10 13:19:38 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 10 Apr 2021 13:19:38 0000 Subject: [squeak-dev] The Trunk: Regex-Core-ct.58.mcz Message-ID: Nicolas Cellier uploaded a new version of Regex-Core to project The Trunk: http://source.squeak.org/trunk/Regex-Core-ct.58.mcz ==================== Summary ==================== Name: Regex-Core-ct.58 Author: ct Time: 8 September 2020, 5:07:32.229336 pm UUID: 66a3d373-fd7a-fc41-ba4f-7233d60a5ec4 Ancestors: Regex-Core-ul.57 Fixes capturing-like behavior of lookaround expressions. Complements Regex-Tests-Core-ct.11. Thanks to Levente (ul) for the bug report! [1] [1] http://forum.world.st/The-Inbox-Regex-Core-ct-56-mcz-tp5113011p5114971.html =============== Diff against Regex-Core-ul.57 =============== Item was added: + ----- Method: RxsLookaround>>isNullable (in category 'testing') ----- + isNullable + + ^ true! From commits at source.squeak.org Sat Apr 10 13:20:11 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 10 Apr 2021 13:20:11 0000 Subject: [squeak-dev] The Trunk: Regex-Tests-Core-ct.11.mcz Message-ID: Nicolas Cellier uploaded a new version of Regex-Tests-Core to project The Trunk: http://source.squeak.org/trunk/Regex-Tests-Core-ct.11.mcz ==================== Summary ==================== Name: Regex-Tests-Core-ct.11 Author: ct Time: 8 September 2020, 5:06:20.887336 pm UUID: 6d0bb586-18f2-1045-ba9c-6b288515c123 Ancestors: Regex-Tests-Core-nice.10 Adds regression test for capturing-like behavior of lookaround expressions See also: http://forum.world.st/The-Inbox-Regex-Core-ct-56-mcz-tp5113011p5114971.html =============== Diff against Regex-Tests-Core-nice.10 =============== Item was added: + ----- Method: RxParserTest>>testLookaroundNullable (in category 'tests') ----- + testLookaroundNullable + + self should: ['(?<=a)?b' asRegex] raise: RegexSyntaxError.! From commits at source.squeak.org Sat Apr 10 19:17:49 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 10 Apr 2021 19:17:49 0000 Subject: [squeak-dev] The Trunk: Collections-nice.933.mcz Message-ID: Nicolas Cellier uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-nice.933.mcz ==================== Summary ==================== Name: Collections-nice.933 Author: nice Time: 10 April 2021, 9:16:54.312889 pm UUID: c066bf52-b7a5-474a-9614-90bbc3212e07 Ancestors: Collections-ul.932 Quick fix for double utf8->squeak conversion via nextChunk. (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: '�'; close. � � (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. =============== Diff against Collections-ul.932 =============== Item was changed: ----- Method: PositionableStream>>basicUpTo: (in category 'private basic') ----- basicUpTo: anObject "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of anObject in the receiver. If anObject is not in the collection, answer the entire rest of the receiver." | newStream element | newStream := WriteStream on: (self collectionSpecies new: 100). + [self atEnd or: [(element := self basicNext) = anObject]] - [self atEnd or: [(element := self next) = anObject]] whileFalse: [newStream nextPut: element]. ^newStream contents! From commits at source.squeak.org Sat Apr 10 19:20:28 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 10 Apr 2021 19:20:28 0000 Subject: [squeak-dev] The Trunk: Multilingual-nice.257.mcz Message-ID: Nicolas Cellier uploaded a new version of Multilingual to project The Trunk: http://source.squeak.org/trunk/Multilingual-nice.257.mcz ==================== Summary ==================== Name: Multilingual-nice.257 Author: nice Time: 10 April 2021, 9:20:24.355472 pm UUID: 15c77243-37af-405d-a376-698735f542e8 Ancestors: Multilingual-mt.256 Quick fix for double utf8->squeak conversion via nextChunk. (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: '�'; close. (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. =============== Diff against Multilingual-mt.256 =============== Item was removed: - ----- Method: MultiByteFileStream>>basicUpTo: (in category 'private basic') ----- - basicUpTo: delim - - ^ super upTo: delim. - ! From nicolas.cellier.aka.nice at gmail.com Sat Apr 10 19:22:04 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 10 Apr 2021 21:22:04 +0200 Subject: [squeak-dev] The Trunk: Collections-nice.933.mcz In-Reply-To: References: Message-ID: Hi all, currently, MultiByteFileStream nextChunk is incorrect for utf8 stream: it attempts to decode utf8 twice. This crafted example will raise an error: (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: 'À'; close. (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. nextChunk sends basicUpTo: with the intention to get an un-converted string, then sends decodeString: to have fast (bulk) decoding. Unfortunately basicUpTo: sends next instead of basicNext... This makes the utf8 decoded twice, which can falsify the source code in some cases, or even fail with an Error like in the crafted example above. an accelerated version of basicUpTo: was provided by Levente in Multilingual-ul.85.mcz but was removed in Multilingual-ar.119.mcz, and I didn't understand the intention by reading the commit message... basicUpTo: was then broken in Collections-ul.438.mcz, and fixed in Collections-eem.684.mcz with the double decoding problem. Le sam. 10 avr. 2021 à 21:17, a écrit : > > Nicolas Cellier uploaded a new version of Collections to project The Trunk: > http://source.squeak.org/trunk/Collections-nice.933.mcz > > ==================== Summary ==================== > > Name: Collections-nice.933 > Author: nice > Time: 10 April 2021, 9:16:54.312889 pm > UUID: c066bf52-b7a5-474a-9614-90bbc3212e07 > Ancestors: Collections-ul.932 > > Quick fix for double utf8->squeak conversion via nextChunk. > > (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: 'À'; close. > (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. > > =============== Diff against Collections-ul.932 =============== > > Item was changed: > ----- Method: PositionableStream>>basicUpTo: (in category 'private basic') ----- > basicUpTo: anObject > "Answer a subcollection from the current access position to the > occurrence (if any, but not inclusive) of anObject in the receiver. If > anObject is not in the collection, answer the entire rest of the receiver." > | newStream element | > newStream := WriteStream on: (self collectionSpecies new: 100). > + [self atEnd or: [(element := self basicNext) = anObject]] > - [self atEnd or: [(element := self next) = anObject]] > whileFalse: [newStream nextPut: element]. > ^newStream contents! > > From leves at caesar.elte.hu Sat Apr 10 20:13:13 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Sat, 10 Apr 2021 22:13:13 +0200 (CEST) Subject: [squeak-dev] The Trunk: Collections-nice.933.mcz In-Reply-To: References: Message-ID: Hi Nicolas, Nice analysis. I'm surprised I didn't notice either me making the copy-paste mistake in PositionableStream >> #basicUpTo: and Andreas removing the optimized version from MultiByteFileStream. As with all basic* methods, PositionableStream >> #basicUpTo: should simply be ^self upTo: anObject I restored the removed version of MultiByteFileStream >> #basicUpTo: in my image. It makes reading the sources file 3x faster using the following "benchmark": | file | [ | hash | file := (SourceFiles at: 1) readOnlyCopy. hash := 0. { [ [ file atEnd ] whileFalse: [ hash := (hash bitXor: file nextChunk hash) hashMultiply ] ] timeToRun. hash } ] ensure: [ file ifNotNil: [ file close ] ]. "#(1414 265702489) naive" "#(469 265702489) optimized" So, I suggest restoring MultiByteFileStream >> #basicUpTo:, and changing PositionableStream >> #basicUpTo: to the version suggested above. Also, PositionableStream >> #upTo: could use #streamContents: instead of duplicating its behavior. Levente On Sat, 10 Apr 2021, Nicolas Cellier wrote: > Hi all, > currently, MultiByteFileStream nextChunk is incorrect for utf8 stream: > it attempts to decode utf8 twice. > > This crafted example will raise an error: > > (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: 'À'; close. > (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. > > nextChunk sends basicUpTo: with the intention to get an un-converted > string, then sends decodeString: to have fast (bulk) decoding. > > Unfortunately basicUpTo: sends next instead of basicNext... This makes > the utf8 decoded twice, which can falsify the source code in some > cases, or even fail with an Error like in the crafted example above. > > an accelerated version of basicUpTo: was provided by Levente in > Multilingual-ul.85.mcz > but was removed in Multilingual-ar.119.mcz, and I didn't understand > the intention by reading the commit message... > basicUpTo: was then broken in Collections-ul.438.mcz, and fixed in > Collections-eem.684.mcz with the double decoding problem. > > > Le sam. 10 avr. 2021 à 21:17, a écrit : >> >> Nicolas Cellier uploaded a new version of Collections to project The Trunk: >> http://source.squeak.org/trunk/Collections-nice.933.mcz >> >> ==================== Summary ==================== >> >> Name: Collections-nice.933 >> Author: nice >> Time: 10 April 2021, 9:16:54.312889 pm >> UUID: c066bf52-b7a5-474a-9614-90bbc3212e07 >> Ancestors: Collections-ul.932 >> >> Quick fix for double utf8->squeak conversion via nextChunk. >> >> (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: 'À'; close. >> (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. >> >> =============== Diff against Collections-ul.932 =============== >> >> Item was changed: >> ----- Method: PositionableStream>>basicUpTo: (in category 'private basic') ----- >> basicUpTo: anObject >> "Answer a subcollection from the current access position to the >> occurrence (if any, but not inclusive) of anObject in the receiver. If >> anObject is not in the collection, answer the entire rest of the receiver." >> | newStream element | >> newStream := WriteStream on: (self collectionSpecies new: 100). >> + [self atEnd or: [(element := self basicNext) = anObject]] >> - [self atEnd or: [(element := self next) = anObject]] >> whileFalse: [newStream nextPut: element]. >> ^newStream contents! >> >> From commits at source.squeak.org Sat Apr 10 20:41:28 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 10 Apr 2021 20:41:28 0000 Subject: [squeak-dev] The Trunk: Tools-nice.1034.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-nice.1034.mcz ==================== Summary ==================== Name: Tools-nice.1034 Author: nice Time: 10 April 2021, 10:41:23.083509 pm UUID: fe72aa70-5707-479b-a576-e2950cfcf6a3 Ancestors: Tools-mt.1033 Quick fix for enabling search of references to a number or other literal from within a message list Example: 86400 cmd+n $a cmd+n #(0) cmd+n Note: it won't necessarily highlight numbers formatted differently like 16rFF for 255... This would probably require AST based search. =============== Diff against Tools-mt.1033 =============== Item was changed: ----- Method: MessageTrace>>addParentMethodsSending: (in category 'building') ----- addParentMethodsSending: selectorSymbol | methodsList | (methodsList := self systemNavigation allCallsOn: selectorSymbol) isEmpty ifTrue: [ ^(PopUpMenu labels: ' OK ') startUpWithCaption: 'There are no methods that send ', selectorSymbol ] ifFalse: [ self addParentMessages: methodsList + autoSelectString: selectorSymbol asString]! - autoSelectString: selectorSymbol ] - ! From nicolas.cellier.aka.nice at gmail.com Sat Apr 10 20:51:30 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 10 Apr 2021 22:51:30 +0200 Subject: [squeak-dev] The Trunk: Collections-nice.933.mcz In-Reply-To: References: Message-ID: Hi Levente, feel free to publish those changes, this was just a quick fix. I only detected this by inspecting inbox submissions (http://source.squeak.org/treated/Collections-cbc.581.diff) and started to wonder why we would need basicUpTo: at all. In the mid-term I would prefer that we start using stream composition rather than basic* protocol, but that's at the risk of bugs and regressions Le sam. 10 avr. 2021 à 22:13, Levente Uzonyi a écrit : > > Hi Nicolas, > > Nice analysis. I'm surprised I didn't notice either me making the > copy-paste mistake in PositionableStream >> #basicUpTo: and Andreas > removing the optimized version from MultiByteFileStream. > As with all basic* methods, PositionableStream >> #basicUpTo: > should simply be > > ^self upTo: anObject > > I restored the removed version of MultiByteFileStream >> #basicUpTo: in my > image. It makes reading the sources file 3x faster using the following > "benchmark": > > | file | > [ > | hash | > file := (SourceFiles at: 1) readOnlyCopy. > hash := 0. > { > [ [ file atEnd ] whileFalse: [ > hash := (hash bitXor: file nextChunk hash) hashMultiply ] ] timeToRun. > hash } ] > ensure: [ file ifNotNil: [ file close ] ]. > > "#(1414 265702489) naive" > "#(469 265702489) optimized" > > So, I suggest restoring MultiByteFileStream >> #basicUpTo:, and changing > PositionableStream >> #basicUpTo: to the version suggested above. > Also, PositionableStream >> #upTo: could use #streamContents: instead of > duplicating its behavior. > > > Levente > > On Sat, 10 Apr 2021, Nicolas Cellier wrote: > > > Hi all, > > currently, MultiByteFileStream nextChunk is incorrect for utf8 stream: > > it attempts to decode utf8 twice. > > > > This crafted example will raise an error: > > > > (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: 'À'; close. > > (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. > > > > nextChunk sends basicUpTo: with the intention to get an un-converted > > string, then sends decodeString: to have fast (bulk) decoding. > > > > Unfortunately basicUpTo: sends next instead of basicNext... This makes > > the utf8 decoded twice, which can falsify the source code in some > > cases, or even fail with an Error like in the crafted example above. > > > > an accelerated version of basicUpTo: was provided by Levente in > > Multilingual-ul.85.mcz > > but was removed in Multilingual-ar.119.mcz, and I didn't understand > > the intention by reading the commit message... > > basicUpTo: was then broken in Collections-ul.438.mcz, and fixed in > > Collections-eem.684.mcz with the double decoding problem. > > > > > > Le sam. 10 avr. 2021 à 21:17, a écrit : > >> > >> Nicolas Cellier uploaded a new version of Collections to project The Trunk: > >> http://source.squeak.org/trunk/Collections-nice.933.mcz > >> > >> ==================== Summary ==================== > >> > >> Name: Collections-nice.933 > >> Author: nice > >> Time: 10 April 2021, 9:16:54.312889 pm > >> UUID: c066bf52-b7a5-474a-9614-90bbc3212e07 > >> Ancestors: Collections-ul.932 > >> > >> Quick fix for double utf8->squeak conversion via nextChunk. > >> > >> (MultiByteFileStream newFileNamed: 'foo.utf8') nextPutAll: 'À'; close. > >> (MultiByteFileStream oldFileNamed: 'foo.utf8') nextChunk. > >> > >> =============== Diff against Collections-ul.932 =============== > >> > >> Item was changed: > >> ----- Method: PositionableStream>>basicUpTo: (in category 'private basic') ----- > >> basicUpTo: anObject > >> "Answer a subcollection from the current access position to the > >> occurrence (if any, but not inclusive) of anObject in the receiver. If > >> anObject is not in the collection, answer the entire rest of the receiver." > >> | newStream element | > >> newStream := WriteStream on: (self collectionSpecies new: 100). > >> + [self atEnd or: [(element := self basicNext) = anObject]] > >> - [self atEnd or: [(element := self next) = anObject]] > >> whileFalse: [newStream nextPut: element]. > >> ^newStream contents! > >> > >> From nicolas.cellier.aka.nice at gmail.com Sat Apr 10 21:21:33 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 10 Apr 2021 23:21:33 +0200 Subject: [squeak-dev] Solving multiple termination bugs - summary & proposal In-Reply-To: <1618045093475-0.post@n4.nabble.com> References: <1617642027172-0.post@n4.nabble.com> <1618045093475-0.post@n4.nabble.com> Message-ID: Hi Jaromir, many thanks for those efforts and for perseverating. It must be a bit frustrating to not receive any answer to this good work and deep investment, but there is a good reason for that: the subject is tough, and not everyone is able to give you a quick answer without reinvesting an equivalent slot of time as you personally did. This change-set looks good to my eyes, the level of comment is good too and gives me some additional confidence. I'm probably not at your level of expertise yet, but I vote for integrating this in trunk. In the meantime, I'll leave with it in my image(s) for a few days. You can as well submit an inbox contribution as you did previously, this is the preferred way, unless the changes span many packages. cheers Nicolas Le sam. 10 avr. 2021 à 10:58, Jaromir Matas a écrit : > > Hi, > > The enclosed changeset fixes all bugs/inconsistencies concerning process > termination listed below. It's a simplified version of the previous > proposal. Feedback very welcome indeed! > > The idea is to simply extend the existing mechanism for completing > halfway-through unwind blocks and let it deal with *all* unwind blocks. > > best, > > Fix_terminate_v3.cs > > > Jaromir Matas wrote > > Hi All, > > > > here's a summary of bugs in the current termination procedure: > > > > 1. #isTerminated and #isSuspended fail to report correctly - in [1] > > > > 2. active process termination bug causing an image crash - in [2] > > > > 3. nested unwind bug: skipping some ensure blocks - in [3] > > > > 4. likely a bug: a failure to complete nested unwind blocks halfway thru > > execution - also in [3] > > > > 5. Christoph's discovery: a failure to correctly close the debugger in > > case > > of error or non-local return in unwind - in [4] > > > > 6. inconsistent semantics of unwinding protected blocks during active vs. > > suspended process termination > > > > > > ----- > ^[^ Jaromir > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > From nicolas.cellier.aka.nice at gmail.com Sat Apr 10 21:25:14 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 10 Apr 2021 23:25:14 +0200 Subject: [squeak-dev] Solving multiple termination bugs - summary & proposal In-Reply-To: References: <1617642027172-0.post@n4.nabble.com> <1618045093475-0.post@n4.nabble.com> Message-ID: I'll live with it, xcuz the bad anglishe. Le sam. 10 avr. 2021 à 23:21, Nicolas Cellier a écrit : > > Hi Jaromir, > many thanks for those efforts and for perseverating. > It must be a bit frustrating to not receive any answer to this good > work and deep investment, but there is a good reason for that: the > subject is tough, and not everyone is able to give you a quick answer > without reinvesting an equivalent slot of time as you personally did. > > This change-set looks good to my eyes, the level of comment is good > too and gives me some additional confidence. > I'm probably not at your level of expertise yet, but I vote for > integrating this in trunk. > In the meantime, I'll leave with it in my image(s) for a few days. > You can as well submit an inbox contribution as you did previously, > this is the preferred way, unless the changes span many packages. > > cheers > > Nicolas > > Le sam. 10 avr. 2021 à 10:58, Jaromir Matas a écrit : > > > > Hi, > > > > The enclosed changeset fixes all bugs/inconsistencies concerning process > > termination listed below. It's a simplified version of the previous > > proposal. Feedback very welcome indeed! > > > > The idea is to simply extend the existing mechanism for completing > > halfway-through unwind blocks and let it deal with *all* unwind blocks. > > > > best, > > > > Fix_terminate_v3.cs > > > > > > Jaromir Matas wrote > > > Hi All, > > > > > > here's a summary of bugs in the current termination procedure: > > > > > > 1. #isTerminated and #isSuspended fail to report correctly - in [1] > > > > > > 2. active process termination bug causing an image crash - in [2] > > > > > > 3. nested unwind bug: skipping some ensure blocks - in [3] > > > > > > 4. likely a bug: a failure to complete nested unwind blocks halfway thru > > > execution - also in [3] > > > > > > 5. Christoph's discovery: a failure to correctly close the debugger in > > > case > > > of error or non-local return in unwind - in [4] > > > > > > 6. inconsistent semantics of unwinding protected blocks during active vs. > > > suspended process termination > > > > > > > > > > > > ----- > > ^[^ Jaromir > > -- > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > From vanessa at codefrau.net Sat Apr 10 21:26:14 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sat, 10 Apr 2021 14:26:14 -0700 Subject: [squeak-dev] Need better default code font In-Reply-To: References: <91C1E5C0-6810-4F8F-B03E-CBE920FE2302@rowledge.org> <863A311D-1B53-4E5C-A8C6-D45DD587D0EF@rowledge.org> <20210405203657.312818C15D5@proxy.email-ssl.com.br> <6A4FEF27-13B6-4C5D-BFDB-9BD850524322@gmx.de> Message-ID: On Sat, Apr 10, 2021 at 00:02 Tobias Pape wrote: > Hi > > > On 10. Apr 2021, at 05:32, Vanessa Freudenberg > wrote: > > > > Thanks Tom, those look great! Kinda hard to pick a favorite really. > > > > Tobias: how hard is it to pick a glyph variant when importing the font? > > At the moment, impossible -.- > But if we pre-render, as with the bitmap-dejavu, we have all control… > > best regards > -tobias > That’s what I thought Tom was doing, so that’s what I meant, yes, just for importing a new bitmapped default code font. Would it have to be font-specific (e.g. for “Fira Sans” pick variant 2 for the zero glyph) or is there a generic way to say “if this font has multiple glyphs for zero, prefer the slashed variant”). That’s where my knowledge of font tech does not go far enough. –Vanessa– > > > > —Vanessa— > > > > On Fri, Apr 9, 2021 at 11:35 AM Tobias Pape wrote: > > > > > >> On 9. Apr 2021, at 20:27, Tom Beckmann wrote: > >> > >> Fira Sans, 11 > > > > note that Fira Sans also has a slashed-Zero variant, which could come in > handy… > > > > (still my favourite…) > > -t > > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Sat Apr 10 21:40:52 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 10 Apr 2021 23:40:52 +0200 Subject: [squeak-dev] Solving multiple termination bugs - summary & proposal In-Reply-To: References: <1617642027172-0.post@n4.nabble.com> <1618045093475-0.post@n4.nabble.com> Message-ID: BTW, I have moved your previous attempts to treated inbox, so please, do not fear to pollute the inbox again :) Le sam. 10 avr. 2021 à 23:25, Nicolas Cellier a écrit : > > I'll live with it, xcuz the bad anglishe. > > Le sam. 10 avr. 2021 à 23:21, Nicolas Cellier > a écrit : > > > > Hi Jaromir, > > many thanks for those efforts and for perseverating. > > It must be a bit frustrating to not receive any answer to this good > > work and deep investment, but there is a good reason for that: the > > subject is tough, and not everyone is able to give you a quick answer > > without reinvesting an equivalent slot of time as you personally did. > > > > This change-set looks good to my eyes, the level of comment is good > > too and gives me some additional confidence. > > I'm probably not at your level of expertise yet, but I vote for > > integrating this in trunk. > > In the meantime, I'll leave with it in my image(s) for a few days. > > You can as well submit an inbox contribution as you did previously, > > this is the preferred way, unless the changes span many packages. > > > > cheers > > > > Nicolas > > > > Le sam. 10 avr. 2021 à 10:58, Jaromir Matas a écrit : > > > > > > Hi, > > > > > > The enclosed changeset fixes all bugs/inconsistencies concerning process > > > termination listed below. It's a simplified version of the previous > > > proposal. Feedback very welcome indeed! > > > > > > The idea is to simply extend the existing mechanism for completing > > > halfway-through unwind blocks and let it deal with *all* unwind blocks. > > > > > > best, > > > > > > Fix_terminate_v3.cs > > > > > > > > > Jaromir Matas wrote > > > > Hi All, > > > > > > > > here's a summary of bugs in the current termination procedure: > > > > > > > > 1. #isTerminated and #isSuspended fail to report correctly - in [1] > > > > > > > > 2. active process termination bug causing an image crash - in [2] > > > > > > > > 3. nested unwind bug: skipping some ensure blocks - in [3] > > > > > > > > 4. likely a bug: a failure to complete nested unwind blocks halfway thru > > > > execution - also in [3] > > > > > > > > 5. Christoph's discovery: a failure to correctly close the debugger in > > > > case > > > > of error or non-local return in unwind - in [4] > > > > > > > > 6. inconsistent semantics of unwinding protected blocks during active vs. > > > > suspended process termination > > > > > > > > > > > > > > > > > > ----- > > > ^[^ Jaromir > > > -- > > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > > From commits at source.squeak.org Sun Apr 11 07:20:03 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 11 Apr 2021 07:20:03 0000 Subject: [squeak-dev] The Inbox: Kernel-jar.1385.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-jar.1385.mcz ==================== Summary ==================== Name: Kernel-jar.1385 Author: jar Time: 11 April 2021, 9:19:58.900241 am UUID: fc94f858-9307-e943-b23a-180be1ffad4a Ancestors: Kernel-mt.1383 Fix a list of termination bugs described in http://forum.world.st/Solving-multiple-termination-bugs-summary-amp-proposal-td5128285.html A set of tests will follow. =============== Diff against Kernel-mt.1383 =============== Item was changed: ----- Method: Process>>isSuspended (in category 'testing') ----- isSuspended + "A process is suspended if it is not active, not terminated and + not waiting in a scheduler or a semaphore queue." + + self isActiveProcess ifTrue: [^ false]. + ^myList isNil and: [self isTerminated not]! - "A process is suspended if it has been suspended with the suspend primitive. - It is distinguishable from the active process and a terminated process by - having a non-nil suspendedContext that is either not the bottom context - or has not reached its endPC." - ^nil == myList - and: [nil ~~ suspendedContext - and: [suspendedContext isBottomContext - ifTrue: [suspendedContext closure - ifNil: [suspendedContext methodClass ~~ Process - or: [suspendedContext selector ~~ #terminate]] - ifNotNil: [suspendedContext pc < suspendedContext closure endPC]] - ifFalse: [true]]]! Item was changed: ----- Method: Process>>isTerminated (in category 'testing') ----- isTerminated + "Answer if the receiver is terminated. A process is considered terminated + if the suspendedContext is the bottomContext and the pc is at the endPC" + - "Answer if the receiver is terminated, or at least terminating." self isActiveProcess ifTrue: [^ false]. + ^suspendedContext isNil or: [ + suspendedContext isBottomContext and: [ + suspendedContext isDead or: [suspendedContext atEnd]]]! - ^suspendedContext isNil - or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess. - If so, and the pc is at the endPC, the block has already sent and returned - from value and there is nothing more to do." - suspendedContext isBottomContext - and: [suspendedContext closure - ifNil: [suspendedContext methodClass == Process - and: [suspendedContext selector == #terminate]] - ifNotNil: [suspendedContext pc >= suspendedContext closure endPC]]]! Item was changed: ----- Method: Process>>terminate (in category 'changing process state') ----- terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating. If the process is in the middle of a critical: critical section, release it properly." + | ctxt unwindBlock oldList outerMost | + self isActiveProcess ifTrue: [ + "If terminating the active process, suspend it first and terminate it as a suspended process." + [self terminate] fork. + ^self suspend]. - | ctxt unwindBlock oldList | - self isActiveProcess ifTrue: - [ctxt := thisContext. - [ctxt := ctxt findNextUnwindContextUpTo: nil. - ctxt ~~ nil] whileTrue: - [(ctxt tempAt: 2) ifNil: - ["N.B. Unlike Context>>unwindTo: we do not set complete (tempAt: 2) to true." - unwindBlock := ctxt tempAt: 1. - thisContext terminateTo: ctxt. - unwindBlock value]]. - thisContext terminateTo: nil. - self suspend. - "If the process is resumed this will provoke a cannotReturn: error. - Would self debug: thisContext title: 'Resuming a terminated process' be better?" - ^self]. "Always suspend the process first so it doesn't accidentally get woken up. N.B. If oldList is a LinkedList then the process is runnable. If it is a Semaphore/Mutex et al then the process is blocked, and if it is nil then the process is already suspended." oldList := self suspend. suspendedContext ifNotNil: ["Release any method marked with the pragma. The argument is whether the process is runnable." self releaseCriticalSection: (oldList isNil or: [oldList class == LinkedList]). + "If terminating a process halfways through an unwind, try to complete that unwind block first; + if there are multiple such nested unwind blocks, try to complete the outer-most one; the inner + blocks will be completed in the process." + ctxt := suspendedContext. + [(ctxt := ctxt findNextUnwindContextUpTo: nil) isNil] whileFalse: + "Contexts under evaluation have already set their complete (tempAt: 2) to true." + [(ctxt tempAt:2) ifNotNil: [outerMost := ctxt]]. + outerMost ifNotNil: [ + "This is the outer-most unwind context currently under evaluation; + let's find an inner context executing outerMost's argument block (tempAt: 1)" + (suspendedContext findContextSuchThat: [:ctx | + ctx closure == (outerMost tempAt: 1)]) ifNotNil: [:inner | + "Let's finish the unfinished unwind context only (i.e. up to inner) and return here" + suspendedContext runUntilErrorOrReturnFrom: inner. + "Update the receiver's suspendedContext (the previous step reset its sender to nil)" + suspendedContext := outerMost]]. - "If terminating a process halfways through an unwind, try to complete that unwind block first." - (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: - [:outer| - (suspendedContext findContextSuchThat:[:c| c closure == (outer tempAt: 1)]) ifNotNil: - [:inner| "This is an unwind block currently under evaluation" - suspendedContext runUntilErrorOrReturnFrom: inner]]. + "Now all unwind blocks caught halfway through have been completed; + let's execute the ones still pending. Note: #findNextUnwindContextUpTo: starts + searching from the receiver's sender but the receiver itself may be an unwind context." + ctxt := suspendedContext. + ctxt isUnwindContext ifFalse: [ctxt := ctxt findNextUnwindContextUpTo: nil]. + [ctxt isNil] whileFalse: [ + (ctxt tempAt: 2) ifNil: [ + ctxt tempAt: 2 put: true. + unwindBlock := ctxt tempAt: 1. + "Create a context for the unwind block and execute it on the unwind block's stack. + Note: using #value instead of #runUntilErrorOrReturnFrom: would lead to executing + the unwind on the wrong stack preventing the correct execution of non-local returns." + suspendedContext := unwindBlock asContextWithSender: ctxt. + suspendedContext runUntilErrorOrReturnFrom: suspendedContext]. + ctxt := ctxt findNextUnwindContextUpTo: nil]. + + "Reset the context's pc and sender to nil for the benefit of isTerminated." + suspendedContext terminate]! - ctxt := self popTo: suspendedContext bottomContext. - ctxt == suspendedContext bottomContext ifFalse: - [self debugWithTitle: 'Unwind error during termination' translated full: false]. - "Set the context to its endPC for the benefit of isTerminated." - ctxt pc: ctxt endPC]! From m at jaromir.net Sun Apr 11 07:39:54 2021 From: m at jaromir.net (Jaromir Matas) Date: Sun, 11 Apr 2021 02:39:54 -0500 (CDT) Subject: [squeak-dev] Solving multiple termination bugs - summary & proposal In-Reply-To: References: <1617642027172-0.post@n4.nabble.com> <1618045093475-0.post@n4.nabble.com> Message-ID: <1618126794263-0.post@n4.nabble.com> Hi Nicolas, Thanks a lot for your encouragement! Sent to the Inbox. I'll add a set of tests a bit later. > > BTW, I have moved your previous attempts to treated inbox, so please, > do not fear to pollute the inbox again :) Yes, thanks again, that's exactly what I was fearing - creating more noise in the Inbox :) > > Le sam. 10 avr. 2021 à 23:21, Nicolas Cellier > <[hidden email]> a écrit : > > > > Hi Jaromir, > > many thanks for those efforts and for perseverating. > > It must be a bit frustrating to not receive any answer to this good > > work and deep investment, but there is a good reason for that: the > > subject is tough, and not everyone is able to give you a quick answer > > without reinvesting an equivalent slot of time as you personally did. > > > > This change-set looks good to my eyes, the level of comment is good > > too and gives me some additional confidence. > > I'm probably not at your level of expertise yet, but I vote for > > integrating this in trunk. > > In the meantime, I'll leave with it in my image(s) for a few days. > > You can as well submit an inbox contribution as you did previously, > > this is the preferred way, unless the changes span many packages. > > > > cheers > > > > Nicolas best, ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From commits at source.squeak.org Sun Apr 11 08:10:53 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 11 Apr 2021 08:10:53 0000 Subject: [squeak-dev] The Trunk: Tests-nice.446.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.446.mcz ==================== Summary ==================== Name: Tests-nice.446 Author: nice Time: 11 April 2021, 10:10:51.107508 am UUID: 4bf76380-a2ad-41d3-a16b-8684a2a9b938 Ancestors: Tests-tobe.445 The defaultAction of an Exception should be evaluated in the Context of the method that signalled the Exception. Thus, an enclosing exception handler (on:do:) upper in the stack shall still be active whenever the defaultAction raise another exception. This documents why simply deactivating the exception (see handlerActive, tempAt: 3, of #on:do:) is not the right way to fix handling of nested exception. See #testHandlerFromAction, see also https://source.squeak.org/treated/Kernel-ar.540.diff =============== Diff against Tests-tobe.445 =============== Item was added: + ----- Method: ExceptionTests>>testCatchingDefaultAction (in category 'tests - outer') ----- + testCatchingDefaultAction + "The #defaultAction method is executed in the context of the signaling environment. + The defaultAction will raise an UnhandledWarning that should be caught by this handler." + | result | + result := [ Warning signal: 'Warning signalled' ] on: UnhandledWarning do: [ :ex | 'UnhandledWarning caught' ]. + self assert: 'UnhandledWarning caught' equals: result! From bernhard at pieber.com Sun Apr 11 12:44:08 2021 From: bernhard at pieber.com (Bernhard Pieber) Date: Sun, 11 Apr 2021 12:44:08 +0000 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> Message-ID: Dear Squeakers, I have just been beaten by this when trying to run Seaside in a recent Squeak image. While it should be possible to add it to Grease for Squeak that is non-trivial for me given Grease is not developed using Monticello anymore, but using Metacello in a metadataless Cypress repository. While it might be easy for the Seaside maintainers I don’t want to put an extra burden on them given they asked us for help maintaining Seaside for Squeak. So I am strongly in favour of leaving it in Squeak, i.e. removing the deprecation. While I don’t disagree with the arguments for its deprecation, I value not breaking other people’s code more in this case. Thank you for your consideration, Bernhard > Am 05.01.2021 um 18:01 schrieb Eliot Miranda : > > >> On Jan 5, 2021, at 3:13 AM, Tobias Pape wrote: >>  >> >>>> On 5. Jan 2021, at 12:10, Marcel Taeumel wrote: >>>> >>>> Had I known the widespread understanding of #asMutator, I had objected more strongly against its removal -.- >>> Narf. >>> >>> Well, there is also the idea of "convenience methods" ... #asMutator could be one of those. >> >> Tim shows that it is essentially widespread, more than a convenience. >> lets just put it back… > > +1 > >> >>> Not sure how this affects GraphQL. Chris? >>> >>> Best, >>> Marcel >>>> Am 05.01.2021 12:09:38 schrieb Tobias Pape : >>>> >>>> >>>> Had I known the widespread understanding of #asMutator, I had objected more strongly against its removal -.- >>>> Narf. >>>> >>>> -t >>>> >>>>> On 2. Jan 2021, at 19:44, Tim Johnson wrote: >>>>> >>>>> Hi, >>>>> >>>>> First, before the rest of this complain-y message: >>>>> >>>>> **Happy 2021 to everybody!** >>>>> >>>>> Now to shamefully bring up a closed matter: in 2019 there was some discussion on the mailing list that led to the deprecation of #asMutator. Some portions of the discussion can be seen here: >>>>> >>>>> http://lists.squeakfoundation.org/pipermail/squeak-dev/2019-March/201810.html >>>>> http://lists.squeakfoundation.org/pipermail/squeak-dev/2019-March/201843.html >>>>> >>>>> Part of the argument was that "asMutator" and the notion of "mutators" was not seen elsewhere in the image, and that it conflicted with work someone was doing with GraphQL (?) which has its own notion of "mutators". Was there other rationale? >>>>> >>>>> In the meantime, various teams and projects will have to adapt their code. And, users have been coping with various packages not loading seamlessly in Squeak 5.3 due to this deprecation. >>>>> >>>>> Squot: https://github.com/hpi-swa/Squot/issues/266 >>>>> Seaside: https://github.com/SeasideSt/Seaside/issues/1195 >>>>> Also Seaside: https://github.com/SeasideSt/Seaside/search?q=asMutator >>>>> HPI "Home Desktop System": http://wiki.squeak.org/squeak/2860 >>>>> >>>>> I'm sorry for bringing up a settled matter, and for grandstanding a bit ("at what price progress?"), but: was #asMutator deprecated because of the argument that "mutators" are alien to Smalltalk and/or Squeak? If so, I (respectfully) have a hard time accepting part of that argument. A quick Google search turns up much literature. >>>>> >>>>> "To add an accessor method and a mutator method" (2015) >>>>> https://medium.com/smalltalk-talk/getting-the-message-667d77ff78d >>>>> >>>>> ^ the above quotes & cites Alan Lovejoy's "Smalltalk: Getting The Message" (2007) https://web.archive.org/web/20150908201317/http://www.smalltalk.org/articles/article_20100320_a3_Getting_The_Message.html >>>>> >>>>> See also: "simple accessor and mutator methods" (1998) >>>>> http://www.esug.org/data/Smalltalk/Historical/pocketst/whitepaper.html >>>>> >>>>> and: ST/X's asMutator (in protocol 'converting') >>>>> https://live.exept.de/ClassDoc/classDocOf,CharacterArray >>>>> >>>>> So: what is the long term strategy here? After methods are deprecated and removed from the image, when those methods served the purpose of compatibility with 3rd party packages and other Smalltalks, is it expected that each outside package will either (a) maintain its own compatibility layer, like Grease, or (b) implement the removed methods via class extensions, thus possibly introducing conflicts? >>>>> >>>>> Thanks, >>>>> Tim >>>>> >>>>> >>>>> >>>> >>>> >>>> >>> >> >> >> > From lewis at mail.msen.com Sun Apr 11 14:45:38 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Sun, 11 Apr 2021 10:45:38 -0400 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> Message-ID: <20210411144538.GA17226@shell.msen.com> On Sun, Apr 11, 2021 at 12:44:08PM +0000, Bernhard Pieber wrote: > Dear Squeakers, > > I have just been beaten by this when trying to run Seaside in a recent Squeak image. > > While it should be possible to add it to Grease for Squeak that is non-trivial for me given Grease is not developed using Monticello anymore, but using Metacello in a metadataless Cypress repository. While it might be easy for the Seaside maintainers I don???t want to put an extra burden on them given they asked us for help maintaining Seaside for Squeak. > > So I am strongly in favour of leaving it in Squeak, i.e. removing the deprecation. While I don???t disagree with the arguments for its deprecation, I value not breaking other people???s code more in this case. > > Thank you for your consideration, > Bernhard > I have no opinion regarding the various selectors, but I do think that is it important to support the people who do the work of maintaining external packages, especially important packages like Seaside. Letting asMutator be a synomym for asSimpleSetter along with a method comment explaining why it still exists seems to work fine, see attached. It passes the original SymbolTest>>tsetAsMutator (which is no longer in the image) so I expect that it should work for Seaside also. Dave > > Am 05.01.2021 um 18:01 schrieb Eliot Miranda : > > > > > >> On Jan 5, 2021, at 3:13 AM, Tobias Pape wrote: > >> ??? > >> > >>>> On 5. Jan 2021, at 12:10, Marcel Taeumel wrote: > >>>> > >>>> Had I known the widespread understanding of #asMutator, I had objected more strongly against its removal -.- > >>> Narf. > >>> > >>> Well, there is also the idea of "convenience methods" ... #asMutator could be one of those. > >> > >> Tim shows that it is essentially widespread, more than a convenience. > >> lets just put it back??? > > > > +1 > > > >> > >>> Not sure how this affects GraphQL. Chris? > >>> > >>> Best, > >>> Marcel > >>>> Am 05.01.2021 12:09:38 schrieb Tobias Pape : > >>>> > >>>> > >>>> Had I known the widespread understanding of #asMutator, I had objected more strongly against its removal -.- > >>>> Narf. > >>>> > >>>> -t > >>>> > >>>>> On 2. Jan 2021, at 19:44, Tim Johnson wrote: > >>>>> > >>>>> Hi, > >>>>> > >>>>> First, before the rest of this complain-y message: > >>>>> > >>>>> **Happy 2021 to everybody!** > >>>>> > >>>>> Now to shamefully bring up a closed matter: in 2019 there was some discussion on the mailing list that led to the deprecation of #asMutator. Some portions of the discussion can be seen here: > >>>>> > >>>>> http://lists.squeakfoundation.org/pipermail/squeak-dev/2019-March/201810.html > >>>>> http://lists.squeakfoundation.org/pipermail/squeak-dev/2019-March/201843.html > >>>>> > >>>>> Part of the argument was that "asMutator" and the notion of "mutators" was not seen elsewhere in the image, and that it conflicted with work someone was doing with GraphQL (?) which has its own notion of "mutators". Was there other rationale? > >>>>> > >>>>> In the meantime, various teams and projects will have to adapt their code. And, users have been coping with various packages not loading seamlessly in Squeak 5.3 due to this deprecation. > >>>>> > >>>>> Squot: https://github.com/hpi-swa/Squot/issues/266 > >>>>> Seaside: https://github.com/SeasideSt/Seaside/issues/1195 > >>>>> Also Seaside: https://github.com/SeasideSt/Seaside/search?q=asMutator > >>>>> HPI "Home Desktop System": http://wiki.squeak.org/squeak/2860 > >>>>> > >>>>> I'm sorry for bringing up a settled matter, and for grandstanding a bit ("at what price progress?"), but: was #asMutator deprecated because of the argument that "mutators" are alien to Smalltalk and/or Squeak? If so, I (respectfully) have a hard time accepting part of that argument. A quick Google search turns up much literature. > >>>>> > >>>>> "To add an accessor method and a mutator method" (2015) > >>>>> https://medium.com/smalltalk-talk/getting-the-message-667d77ff78d > >>>>> > >>>>> ^ the above quotes & cites Alan Lovejoy's "Smalltalk: Getting The Message" (2007) https://web.archive.org/web/20150908201317/http://www.smalltalk.org/articles/article_20100320_a3_Getting_The_Message.html > >>>>> > >>>>> See also: "simple accessor and mutator methods" (1998) > >>>>> http://www.esug.org/data/Smalltalk/Historical/pocketst/whitepaper.html > >>>>> > >>>>> and: ST/X's asMutator (in protocol 'converting') > >>>>> https://live.exept.de/ClassDoc/classDocOf,CharacterArray > >>>>> > >>>>> So: what is the long term strategy here? After methods are deprecated and removed from the image, when those methods served the purpose of compatibility with 3rd party packages and other Smalltalks, is it expected that each outside package will either (a) maintain its own compatibility layer, like Grease, or (b) implement the removed methods via class extensions, thus possibly introducing conflicts? > >>>>> > >>>>> Thanks, > >>>>> Tim > >>>>> > >>>>> > >>>>> > >>>> > >>>> > >>>> > >>> > >> > >> > >> > > > > > -------------- next part -------------- 'From Squeak6.0alpha of 3 April 2021 [latest update: #20329] on 11 April 2021 at 10:23:26 am'!!Symbol methodsFor: '*System-Support' stamp: 'dtl 4/11/2021 09:26'!asMutator "Synonym for asSimpleSetter, retained for support of external packages such as Seaside" ^ self asSimpleSetter! ! From nicolas.cellier.aka.nice at gmail.com Sun Apr 11 15:01:31 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sun, 11 Apr 2021 17:01:31 +0200 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <20210411144538.GA17226@shell.msen.com> References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> Message-ID: Hi all, it seems we have enough +1, let's just do it. Le dim. 11 avr. 2021 à 16:45, David T. Lewis a écrit : > > On Sun, Apr 11, 2021 at 12:44:08PM +0000, Bernhard Pieber wrote: > > Dear Squeakers, > > > > I have just been beaten by this when trying to run Seaside in a recent Squeak image. > > > > While it should be possible to add it to Grease for Squeak that is non-trivial for me given Grease is not developed using Monticello anymore, but using Metacello in a metadataless Cypress repository. While it might be easy for the Seaside maintainers I don???t want to put an extra burden on them given they asked us for help maintaining Seaside for Squeak. > > > > So I am strongly in favour of leaving it in Squeak, i.e. removing the deprecation. While I don???t disagree with the arguments for its deprecation, I value not breaking other people???s code more in this case. > > > > Thank you for your consideration, > > Bernhard > > > > I have no opinion regarding the various selectors, but I do think that > is it important to support the people who do the work of maintaining > external packages, especially important packages like Seaside. > > Letting asMutator be a synomym for asSimpleSetter along with a method > comment explaining why it still exists seems to work fine, see attached. > It passes the original SymbolTest>>tsetAsMutator (which is no longer in > the image) so I expect that it should work for Seaside also. > > Dave > > > > > Am 05.01.2021 um 18:01 schrieb Eliot Miranda : > > > > > > > > >> On Jan 5, 2021, at 3:13 AM, Tobias Pape wrote: > > >> ??? > > >> > > >>>> On 5. Jan 2021, at 12:10, Marcel Taeumel wrote: > > >>>> > > >>>> Had I known the widespread understanding of #asMutator, I had objected more strongly against its removal -.- > > >>> Narf. > > >>> > > >>> Well, there is also the idea of "convenience methods" ... #asMutator could be one of those. > > >> > > >> Tim shows that it is essentially widespread, more than a convenience. > > >> lets just put it back??? > > > > > > +1 > > > > > >> > > >>> Not sure how this affects GraphQL. Chris? > > >>> > > >>> Best, > > >>> Marcel > > >>>> Am 05.01.2021 12:09:38 schrieb Tobias Pape : > > >>>> > > >>>> > > >>>> Had I known the widespread understanding of #asMutator, I had objected more strongly against its removal -.- > > >>>> Narf. > > >>>> > > >>>> -t > > >>>> > > >>>>> On 2. Jan 2021, at 19:44, Tim Johnson wrote: > > >>>>> > > >>>>> Hi, > > >>>>> > > >>>>> First, before the rest of this complain-y message: > > >>>>> > > >>>>> **Happy 2021 to everybody!** > > >>>>> > > >>>>> Now to shamefully bring up a closed matter: in 2019 there was some discussion on the mailing list that led to the deprecation of #asMutator. Some portions of the discussion can be seen here: > > >>>>> > > >>>>> http://lists.squeakfoundation.org/pipermail/squeak-dev/2019-March/201810.html > > >>>>> http://lists.squeakfoundation.org/pipermail/squeak-dev/2019-March/201843.html > > >>>>> > > >>>>> Part of the argument was that "asMutator" and the notion of "mutators" was not seen elsewhere in the image, and that it conflicted with work someone was doing with GraphQL (?) which has its own notion of "mutators". Was there other rationale? > > >>>>> > > >>>>> In the meantime, various teams and projects will have to adapt their code. And, users have been coping with various packages not loading seamlessly in Squeak 5.3 due to this deprecation. > > >>>>> > > >>>>> Squot: https://github.com/hpi-swa/Squot/issues/266 > > >>>>> Seaside: https://github.com/SeasideSt/Seaside/issues/1195 > > >>>>> Also Seaside: https://github.com/SeasideSt/Seaside/search?q=asMutator > > >>>>> HPI "Home Desktop System": http://wiki.squeak.org/squeak/2860 > > >>>>> > > >>>>> I'm sorry for bringing up a settled matter, and for grandstanding a bit ("at what price progress?"), but: was #asMutator deprecated because of the argument that "mutators" are alien to Smalltalk and/or Squeak? If so, I (respectfully) have a hard time accepting part of that argument. A quick Google search turns up much literature. > > >>>>> > > >>>>> "To add an accessor method and a mutator method" (2015) > > >>>>> https://medium.com/smalltalk-talk/getting-the-message-667d77ff78d > > >>>>> > > >>>>> ^ the above quotes & cites Alan Lovejoy's "Smalltalk: Getting The Message" (2007) https://web.archive.org/web/20150908201317/http://www.smalltalk.org/articles/article_20100320_a3_Getting_The_Message.html > > >>>>> > > >>>>> See also: "simple accessor and mutator methods" (1998) > > >>>>> http://www.esug.org/data/Smalltalk/Historical/pocketst/whitepaper.html > > >>>>> > > >>>>> and: ST/X's asMutator (in protocol 'converting') > > >>>>> https://live.exept.de/ClassDoc/classDocOf,CharacterArray > > >>>>> > > >>>>> So: what is the long term strategy here? After methods are deprecated and removed from the image, when those methods served the purpose of compatibility with 3rd party packages and other Smalltalks, is it expected that each outside package will either (a) maintain its own compatibility layer, like Grease, or (b) implement the removed methods via class extensions, thus possibly introducing conflicts? > > >>>>> > > >>>>> Thanks, > > >>>>> Tim > > >>>>> > > >>>>> > > >>>>> > > >>>> > > >>>> > > >>>> > > >>> > > >> > > >> > > >> > > > > > > > > > > From commits at source.squeak.org Sun Apr 11 17:33:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 11 Apr 2021 17:33:26 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1384.mcz ==================== Summary ==================== Name: Kernel-nice.1384 Author: nice Time: 11 April 2021, 7:33:23.487481 pm UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 Ancestors: Kernel-mt.1383 Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. =============== Diff against Kernel-mt.1383 =============== Item was changed: ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- handleSignal: exception "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception and the handler is active then execute my handle block (second arg), otherwise forward this message to the next handler context. If none left, execute exception's defaultAction (see nil>>handleSignal:)." | handlerActive val | "If the context has been returned from the handlerActive temp var may not be accessible." handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. + ^self nextHandlerContext handleSignal: exception]. - [^self nextHandlerContext handleSignal: exception]. exception privHandlerContext: self contextTag. self tempAt: 3 put: false. "disable self while executing handle block" val := [(self tempAt: 2) cull: exception] + ifCurtailed: [self tempAt: 3 put: true]. - ensure: [self tempAt: 3 put: true]. self return: val "return from self if not otherwise directed in handle block" ! Item was added: + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- + reactivateHandlers + "Private - sent to exception handler context only (on:do:). + Reactivate all the handlers into the chain" + + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" + self nextHandlerContext reactivateHandlers! Item was added: + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- + reactivateHandlers + "reactivate all the exception handlers in the context chain" + self canSearchForSignalerContext + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! Item was changed: ----- Method: Exception>>resignalAs: (in category 'handling') ----- resignalAs: replacementException "Signal an alternative exception in place of the receiver." + self reactivateHandlers. self resumeUnchecked: replacementException signal! Item was changed: ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- handleSignal: exception + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! - ^ exception resumeUnchecked: exception defaultAction! Item was added: + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- + reactivateHandlers + "nothing to do for bottom context" + + ^ self! From nicolas.cellier.aka.nice at gmail.com Sun Apr 11 17:36:50 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sun, 11 Apr 2021 19:36:50 +0200 Subject: [squeak-dev] Revisiting the fix for nested exception handling Message-ID: Hi all, In order to purge the inbox, I've been in the process of reviewing brainfuck code (a very slow process). While at it, I decided to revisit the solution for nested exception handlers (see testHandlerFromAction). There are two similar and obsolete fixes in the inbox (due to ContextPart->Context transition), Kernel-nice.857 and Kernel-fbs.870 (backported from Cuis) that I moved to treated inbox for that reason. https://source.squeak.org/treated/Kernel-nice.857.diff https://source.squeak.org/treated/Kernel-fbs.870.diff Alas, those two solutions break the very peculiar expectations of testHandlerReentrancy. This is a pity, because to my knowledge, those expectations are essential for Tweak and Croquet. There was a previous attempt from Andreas which was more a simple hack in handleSignal:, that is to disable the handler by setting the temp variable handlerActive in on:do: to false (self tempAt: 3 put: false). I've generalized this solution. https://source.squeak.org/treated/Kernel-ar.540.diff However, there are several reasons why this does not work: the first one, objected by Julian Fitzell here http://lists.squeakfoundation.org/pipermail/squeak-dev/2011-January/156453.html is that the handler must be able to handle a secondary exception raised by the defaultAction. We can find similar expectations with other exception handling, like resignalAs (I will publish another test soon). However, there is some simple strategy: before resuming the exception, scan the context stack a second time so as to rearm the exception handlers that we disabled during handleSignal:. The major drawback, is that I have to spread a few self reactivateHandlers here and there, virtually before every send of #resumedUnchecked:. The second drawback is that scanning the stack a second time is not the most economical solution, but I don't care too much, we have to make it right first. If you find the courage to review, or more easily just to test it, find it in the inbox... Oups, I accidentally published in trunk... Well the review will be forced, if you don't like it, admin please remove or revert. Sorry. From commits at source.squeak.org Sun Apr 11 19:51:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 11 Apr 2021 19:51:37 0000 Subject: [squeak-dev] The Trunk: Tests-nice.447.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.447.mcz ==================== Summary ==================== Name: Tests-nice.447 Author: nice Time: 11 April 2021, 9:51:34.887822 pm UUID: 6c67ae13-0149-4816-ba0d-366139e50f4c Ancestors: Tests-nice.446 Add another Exception test: the outer signal handler will resignal an Exception handled by the inner signal handler: this should be caught and handled by the inner handler. =============== Diff against Tests-nice.446 =============== Item was changed: ----- Method: ExceptionTester>>basicTestSelectors (in category 'accessing') ----- basicTestSelectors + ^ #(#simpleEnsureTest #simpleEnsureTestWithNotification #simpleEnsureTestWithUparrow #simpleEnsureTestWithError #signalFromHandlerActionTest #resumableFallOffTheEndHandler #nonResumableFallOffTheEndHandler #doubleResumeTest #doubleResignalAsTest #simpleTimeoutWithZeroDurationTest #simpleTimeoutTest simpleNoTimeoutTest)! - ^ #(#simpleEnsureTest #simpleEnsureTestWithNotification #simpleEnsureTestWithUparrow #simpleEnsureTestWithError #signalFromHandlerActionTest #resumableFallOffTheEndHandler #nonResumableFallOffTheEndHandler #doubleResumeTest #simpleTimeoutWithZeroDurationTest #simpleTimeoutTest simpleNoTimeoutTest)! Item was added: + ----- Method: ExceptionTester>>doubleResignalAsTest (in category 'tests') ----- + doubleResignalAsTest + "ExceptionTester new doubleResignalAsTest" + + [[self doSomething. + MyTestError signal. + self doSomethingElse] + on: MyTestNotification + do: [:ex | ex resume: self doYetAnotherThing]] + on: MyTestError + do: [:ex | ex resignalAs: MyTestNotification new]! Item was added: + ----- Method: ExceptionTester>>doubleResignalAsTestResults (in category 'results') ----- + doubleResignalAsTestResults + + ^OrderedCollection new + add: self doSomethingString; + add: self doYetAnotherThingString; + add: self doSomethingElseString; + yourself! Item was added: + ----- Method: ExceptionTests>>testDoubleResignalAs (in category 'tests - ExceptionTester') ----- + testDoubleResignalAs + self assertSuccess: (ExceptionTester new runTest: #doubleResignalAsTest ) ! From commits at source.squeak.org Mon Apr 12 01:49:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 01:49:20 0000 Subject: [squeak-dev] The Trunk: 60Deprecated-dtl.93.mcz Message-ID: David T. Lewis uploaded a new version of 60Deprecated to project The Trunk: http://source.squeak.org/trunk/60Deprecated-dtl.93.mcz ==================== Summary ==================== Name: 60Deprecated-dtl.93 Author: dtl Time: 11 April 2021, 9:49:18.524698 pm UUID: 332f4c4f-97b4-463d-b226-b3dcad07e8f8 Ancestors: 60Deprecated-mt.92 Symbol>>asMutator is used by Seaside, do not deprecate it. Instead let it be a synonym for the preferred Symbol>>asSimpleSetter. =============== Diff against 60Deprecated-mt.92 =============== Item was removed: - ----- Method: Symbol>>asMutator (in category '*60Deprecated-converting') ----- - asMutator - "Return a setter message from a getter message. For example, #name asMutator returns #name:" - self deprecated: 'Use #asSimpleSetter instead'. - ^ self last = $: - ifTrue: [ self ] - ifFalse: [ (self copyWith: $:) asSymbol ]! From commits at source.squeak.org Mon Apr 12 01:50:57 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 01:50:57 0000 Subject: [squeak-dev] The Trunk: System-dtl.1225.mcz Message-ID: David T. Lewis uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-dtl.1225.mcz ==================== Summary ==================== Name: System-dtl.1225 Author: dtl Time: 11 April 2021, 9:50:52.898233 pm UUID: a96e7afc-11cc-48c8-8e72-d63f6295e092 Ancestors: System-tonyg.1224 Symbol>>asMutator is used by Seaside, do not deprecate it. Instead let it be a synonym for the preferred Symbol>>asSimpleSetter. =============== Diff against System-tonyg.1224 =============== Item was added: + ----- Method: Symbol>>asMutator (in category '*System-Support') ----- + asMutator + "Synonym for asSimpleSetter, retained for support of external packages such as Seaside" + + ^ self asSimpleSetter! From lewis at mail.msen.com Mon Apr 12 02:11:57 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Sun, 11 Apr 2021 22:11:57 -0400 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> Message-ID: <20210412021157.GA98993@shell.msen.com> On Sun, Apr 11, 2021 at 05:01:31PM +0200, Nicolas Cellier wrote: > Hi all, > it seems we have enough +1, let's just do it. > Done. From bernhard at pieber.com Mon Apr 12 06:11:05 2021 From: bernhard at pieber.com (Bernhard Pieber) Date: Mon, 12 Apr 2021 06:11:05 +0000 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <20210412021157.GA98993@shell.msen.com> References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> Message-ID: Thank you, David! Bernhard > Am 12.04.2021 um 04:11 schrieb David T. Lewis : > > > On Sun, Apr 11, 2021 at 05:01:31PM +0200, Nicolas Cellier wrote: >> Hi all, >> it seems we have enough +1, let's just do it. >> > > Done. From marcel.taeumel at hpi.de Mon Apr 12 06:43:45 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 12 Apr 2021 08:43:45 +0200 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> Message-ID: Hi Dave. Thanks. Maybe also add a pointer to the discussion on this list. Best, Marcel Am 12.04.2021 08:11:29 schrieb Bernhard Pieber : Thank you, David! Bernhard > Am 12.04.2021 um 04:11 schrieb David T. Lewis : > > > On Sun, Apr 11, 2021 at 05:01:31PM +0200, Nicolas Cellier wrote: >> Hi all, >> it seems we have enough +1, let's just do it. >> > > Done. -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 12 07:12:18 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 07:12:18 0000 Subject: [squeak-dev] The Trunk: Network-mt.245.mcz Message-ID: Marcel Taeumel uploaded a new version of Network to project The Trunk: http://source.squeak.org/trunk/Network-mt.245.mcz ==================== Summary ==================== Name: Network-mt.245 Author: mt Time: 12 April 2021, 9:12:16.314134 am UUID: b6adb21b-aa53-2341-9ef4-2220394f68d3 Ancestors: Network-ct.244, Network-pre.244 Merges ancestry. =============== Diff against Network-ct.244 =============== Item was removed: - ----- Method: SocketStream>>receiveDataIfAvailable (in category 'private-socket') ----- - receiveDataIfAvailable - "Deprecated. Use #receiveAvailableData instead" - - ^self receiveAvailableData! From commits at source.squeak.org Mon Apr 12 07:14:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 07:14:26 0000 Subject: [squeak-dev] The Trunk: SqueakSSL-Core-mt.34.mcz Message-ID: Marcel Taeumel uploaded a new version of SqueakSSL-Core to project The Trunk: http://source.squeak.org/trunk/SqueakSSL-Core-mt.34.mcz ==================== Summary ==================== Name: SqueakSSL-Core-mt.34 Author: mt Time: 12 April 2021, 9:14:25.544134 am UUID: 6814d7e9-d82d-5243-a25d-204a1d38dcd9 Ancestors: SqueakSSL-Core-topa.33 Complements Network-mt.245 (pre.244) =============== Diff against SqueakSSL-Core-topa.33 =============== Item was removed: - ----- Method: SecureSocketStream>>receiveDataIfAvailable (in category 'private-compat') ----- - receiveDataIfAvailable - "Pre Squeak 4.2 compatibility" - - ^self receiveAvailableData - ! From marcel.taeumel at hpi.de Mon Apr 12 07:22:20 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 12 Apr 2021 09:22:20 +0200 Subject: [squeak-dev] The Trunk: Tools-nice.1034.mcz In-Reply-To: References: Message-ID: Hi Nicolas, nice catch! Note that this fix applies to the "Message Trace" tool, which requires the "Trace Messages" preference to be enabled. The regular "Message Set" tool is not affected by this bug/fix. :-) Best, Marcel Am 10.04.2021 22:41:38 schrieb commits at source.squeak.org : Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-nice.1034.mcz ==================== Summary ==================== Name: Tools-nice.1034 Author: nice Time: 10 April 2021, 10:41:23.083509 pm UUID: fe72aa70-5707-479b-a576-e2950cfcf6a3 Ancestors: Tools-mt.1033 Quick fix for enabling search of references to a number or other literal from within a message list Example: 86400 cmd+n $a cmd+n #(0) cmd+n Note: it won't necessarily highlight numbers formatted differently like 16rFF for 255... This would probably require AST based search. =============== Diff against Tools-mt.1033 =============== Item was changed: ----- Method: MessageTrace>>addParentMethodsSending: (in category 'building') ----- addParentMethodsSending: selectorSymbol | methodsList | (methodsList := self systemNavigation allCallsOn: selectorSymbol) isEmpty ifTrue: [ ^(PopUpMenu labels: ' OK ') startUpWithCaption: 'There are no methods that send ', selectorSymbol ] ifFalse: [ self addParentMessages: methodsList + autoSelectString: selectorSymbol asString]! - autoSelectString: selectorSymbol ] - ! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 12 07:43:58 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 07:43:58 0000 Subject: [squeak-dev] The Inbox: KernelTests-jar.397.mcz Message-ID: A new version of KernelTests was added to project The Inbox: http://source.squeak.org/inbox/KernelTests-jar.397.mcz ==================== Summary ==================== Name: KernelTests-jar.397 Author: jar Time: 12 April 2021, 9:43:54.742464 am UUID: 6cf87c25-8484-a144-aa35-761de4aa60c1 Ancestors: KernelTests-codefrau.395 Clean up: release all processes still waiting at the semaphore or in the active priority queue. ProcessTest>>#testProcessStateTests doesn't terminate processes it opened. =============== Diff against KernelTests-codefrau.395 =============== Item was changed: ----- Method: ProcessTest>>testProcessStateTests (in category 'tests') ----- testProcessStateTests | semaphore | self assert: Processor activeProcess isActiveProcess. self deny: Processor activeProcess isBlocked. self assert: Processor activeProcess isRunnable. self deny: Processor activeProcess isSuspended. self deny: Processor activeProcess isTerminated. semaphore := Semaphore new. "These processes are runnable but haven't got to the wait yet because the active process is running." self deny: ([semaphore wait] forkAt: Processor activePriority) isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) isBlocked. self assert: ([semaphore wait] forkAt: Processor activePriority) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority) isTerminated. self deny: ([semaphore wait] forkAt: Processor activePriority) suspendingList == semaphore. + "These processes do get to run because, being higher priority they preempt the active process until they wait on the semaphore." - "These processes do get to run because, being higher priority they preempt the active process until yhey wait on the semaphore." self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isActiveProcess. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isTerminated. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) suspendingList == semaphore. "These processes should be suspended, not terminated." self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isRunnable. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isSuspended. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be terminated, not suspended." self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isRunnable. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isSuspended. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be suspended." self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isActiveProcess. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isBlocked. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isRunnable. self assert: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isSuspended. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isTerminated. "These processes should be terminated." self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isSuspended. + self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated. + + "Clean up: release all processes still waiting at the semaphore or in the active priority queue." + Processor yield. + [semaphore isEmpty] whileFalse: [semaphore signal] + ! - self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated! From marcel.taeumel at hpi.de Mon Apr 12 08:59:32 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 12 Apr 2021 10:59:32 +0200 Subject: [squeak-dev] Revisiting the fix for nested exception handling In-Reply-To: References: Message-ID: Hi Nicolas, thanks for looking into this. 4 senders and 3 implementors of #reactivateHandlers isn't too bad. However, I miss an implementation of #deactivateHandlers. I suppose it is that new line in #handleSignal:? Would you mind adding that for readability? :-) Best, Marcel Am 11.04.2021 19:37:11 schrieb Nicolas Cellier : Hi all, In order to purge the inbox, I've been in the process of reviewing brainfuck code (a very slow process). While at it, I decided to revisit the solution for nested exception handlers (see testHandlerFromAction). There are two similar and obsolete fixes in the inbox (due to ContextPart->Context transition), Kernel-nice.857 and Kernel-fbs.870 (backported from Cuis) that I moved to treated inbox for that reason. https://source.squeak.org/treated/Kernel-nice.857.diff https://source.squeak.org/treated/Kernel-fbs.870.diff Alas, those two solutions break the very peculiar expectations of testHandlerReentrancy. This is a pity, because to my knowledge, those expectations are essential for Tweak and Croquet. There was a previous attempt from Andreas which was more a simple hack in handleSignal:, that is to disable the handler by setting the temp variable handlerActive in on:do: to false (self tempAt: 3 put: false). I've generalized this solution. https://source.squeak.org/treated/Kernel-ar.540.diff However, there are several reasons why this does not work: the first one, objected by Julian Fitzell here http://lists.squeakfoundation.org/pipermail/squeak-dev/2011-January/156453.html is that the handler must be able to handle a secondary exception raised by the defaultAction. We can find similar expectations with other exception handling, like resignalAs (I will publish another test soon). However, there is some simple strategy: before resuming the exception, scan the context stack a second time so as to rearm the exception handlers that we disabled during handleSignal:. The major drawback, is that I have to spread a few self reactivateHandlers here and there, virtually before every send of #resumedUnchecked:. The second drawback is that scanning the stack a second time is not the most economical solution, but I don't care too much, we have to make it right first. If you find the courage to review, or more easily just to test it, find it in the inbox... Oups, I accidentally published in trunk... Well the review will be forced, if you don't like it, admin please remove or revert. Sorry. -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Mon Apr 12 11:00:20 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 12 Apr 2021 13:00:20 +0200 Subject: [squeak-dev] Revisiting the fix for nested exception handling In-Reply-To: References: Message-ID: Hi Marcel, yes, we can start naming the mysterious (tempAt:) and (tempAt:put:) operations with proper methods. That's what Andres Valloud did in Cuis. I did the bare minimum changes that could possibly work. That would be #deactivateHandler, because handleSignal: will only deactivate one at a time. The question about senders is whether there's one missing or not... We have to review each and every possible handling action, and ask again if ever we had a new action (not everyday's job, OK). Le lun. 12 avr. 2021 à 10:59, Marcel Taeumel a écrit : > > Hi Nicolas, > > thanks for looking into this. > > 4 senders and 3 implementors of #reactivateHandlers isn't too bad. However, I miss an implementation of #deactivateHandlers. I suppose it is that new line in #handleSignal:? Would you mind adding that for readability? :-) > > Best, > Marcel > > Am 11.04.2021 19:37:11 schrieb Nicolas Cellier : > > Hi all, > In order to purge the inbox, I've been in the process of reviewing > brainfuck code (a very slow process). While at it, I decided to > revisit the solution for nested exception handlers (see > testHandlerFromAction). > > There are two similar and obsolete fixes in the inbox (due to > ContextPart->Context transition), Kernel-nice.857 and Kernel-fbs.870 > (backported from Cuis) that I moved to treated inbox for that reason. > https://source.squeak.org/treated/Kernel-nice.857.diff > https://source.squeak.org/treated/Kernel-fbs.870.diff > > Alas, those two solutions break the very peculiar expectations of > testHandlerReentrancy. This is a pity, because to my knowledge, those > expectations are essential for Tweak and Croquet. > > There was a previous attempt from Andreas which was more a simple hack > in handleSignal:, that is to disable the handler by setting the temp > variable handlerActive in on:do: to false (self tempAt: 3 put: false). > I've generalized this solution. > https://source.squeak.org/treated/Kernel-ar.540.diff > > However, there are several reasons why this does not work: the first > one, objected by Julian Fitzell here > http://lists.squeakfoundation.org/pipermail/squeak-dev/2011-January/156453.html > is that the handler must be able to handle a secondary exception > raised by the defaultAction. We can find similar expectations with > other exception handling, like resignalAs (I will publish another test > soon). > > However, there is some simple strategy: before resuming the exception, > scan the context stack a second time so as to rearm the exception > handlers that we disabled during handleSignal:. > > The major drawback, is that I have to spread a few self > reactivateHandlers here and there, virtually before every send of > #resumedUnchecked:. > The second drawback is that scanning the stack a second time is not > the most economical solution, but I don't care too much, we have to > make it right first. > > If you find the courage to review, or more easily just to test it, > find it in the inbox... > Oups, I accidentally published in trunk... > Well the review will be forced, if you don't like it, admin please > remove or revert. > Sorry. > > From commits at source.squeak.org Mon Apr 12 15:35:11 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 15:35:11 0000 Subject: [squeak-dev] The Trunk: Network-nice.246.mcz Message-ID: Nicolas Cellier uploaded a new version of Network to project The Trunk: http://source.squeak.org/trunk/Network-nice.246.mcz ==================== Summary ==================== Name: Network-nice.246 Author: nice Time: 12 April 2021, 5:35:00.782058 pm UUID: 09001f79-2f03-bb46-be00-2b54f5b89d36 Ancestors: Network-mt.245 Redo the fix from Network-ct.242 with a slighlty different implementation: 1) use exception retry 2) avoid using in: aBlock where a temporary would do the job. Thanks to Christophe for original report and fix! (https://source.squeak.org/treated/Network-ct.242.diff) Original commit message below: Fixes two MNUs that can occur during connecting to an unavailable network resource. Bug #1 (stream>>>#timeout:) Steps to reproduce: 1. Start your image while an internet connection is available. Make any connection attempt (e.g. refresh a Monticello HTTP(s) repository) to ensure that the network is initialized (NetNameResolver initializeNetwork). 2. There are two alternative scenarios: 2.(i) Do it: WebClient httpGet: 'https://foo.bar'. 2.(ii) Turn off your internet connection (e.g. disable your WLAN adapter). Then make another connection attempt. In both scenarios, you will see the following error: MessageNotUnderstood: UndefinedObject>>timeout: (stream) WebClient>>connect WebClient>>sendRequest:contentBlock: ... This bug occurred because there was no check for the presence of any network socket for the request host/port. Bug #2 (#findNextHandlerContextStarting): Steps to reproduce: Do it: WebClient httpGet: 'https://'. Error: MessageNotUnderstood: UndefinedObject>>findNextHandlerContextStarting Context>>nextHandlerContext ConnectionRefused(Exception)>>pass ... =============== Diff against Network-mt.245 =============== Item was changed: ----- Method: SocketStream class>>openConnectionToHostNamed:port: (in category 'instance creation') ----- openConnectionToHostNamed: hostName port: portNumber + | addressInformations stream | NetNameResolver useOldNetwork ifTrue: [ | hostIP | hostIP := NetNameResolver addressForName: hostName timeout: 20. hostIP ifNil: [NetworkError signal: ('Cannot resolve {1}.' format: {hostName})]. + ^self openConnectionToHost: hostIP port: portNumber]. + addressInformations := SocketAddressInformation + forHost: hostName + service: portNumber asString + flags: 0 + addressFamily: 0 + socketType: SocketAddressInformation socketTypeStream + protocol: SocketAddressInformation protocolTCP. + addressInformations ifEmpty: [ + NoNetworkError signal: ('Could not find a network for {1} on port {2}' translated format: {hostName. portNumber})]. + stream := addressInformations readStream. + ^ [self on: stream next connect] on: NetworkError + do: [:exc | stream atEnd + ifTrue: + ["No more address to retry, pass the exception to upper level" + exc pass] + ifFalse: + ["retry with next address" + exc retry]].! - ^self openConnectionToHost: hostIP port: portNumber] - ifFalse: [| addressInformations lastError | - addressInformations := SocketAddressInformation - forHost: hostName - service: portNumber asString - flags: 0 - addressFamily: 0 - socketType: SocketAddressInformation socketTypeStream - protocol: SocketAddressInformation protocolTCP. - addressInformations do: [:addressInformation | - [^ self on: addressInformation connect] on: NetworkError do: [:e | lastError := e]]. - ^ lastError ifNotNil: [:e | e pass]]! From nicolas.cellier.aka.nice at gmail.com Mon Apr 12 17:28:35 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 12 Apr 2021 19:28:35 +0200 Subject: [squeak-dev] Error selector changed Message-ID: Hi all, >From time to time, (Compiler recompileAll) fails because some selector identity changed... Indeed, following snippet should always be true, but is sometimes false: selector == (Symbol findInterned: selector asString). In such case, I can attempt a doIt and continue: selector beWritableObject; becomeForward: (Symbol findInterned: selector asString). oldClass methodDictionary rehash Sometimes I'm tempted to integrate the workaround directly in code, but it would just mask a problem. Any clue on how this can happen? Nicolas From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 12 17:41:02 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 12 Apr 2021 17:41:02 +0000 Subject: [squeak-dev] Code reviews (was: Revisiting the fix for nested exception handling) In-Reply-To: References: Message-ID: Hi Nicolas, > In order to purge the inbox, I've been in the process of reviewing brainfuck code (a very slow process). While at it, I decided to revisit the solution for nested exception handlers (see testHandlerFromAction). I appreciate both of these very much, thank you for your efforts! (Regular) code review and integration is an important process, in particular for a bipartite community like us. I'm aware of the fact that personally, I am only piling up new proposals that need a review but almost never have helped to carry off/review existing ones. If there is anything I (or other interested people) could do to support you in cleaning up the inbox - that goes beyond the administrative power to press the merge button (a privilege which I consider myself not mature for at the moment) -, please let me know! Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Sonntag, 11. April 2021 19:36 Uhr An: The general-purpose Squeak developers list Betreff: [squeak-dev] Revisiting the fix for nested exception handling Hi all, In order to purge the inbox, I've been in the process of reviewing brainfuck code (a very slow process). While at it, I decided to revisit the solution for nested exception handlers (see testHandlerFromAction). There are two similar and obsolete fixes in the inbox (due to ContextPart->Context transition), Kernel-nice.857 and Kernel-fbs.870 (backported from Cuis) that I moved to treated inbox for that reason. https://source.squeak.org/treated/Kernel-nice.857.diff https://source.squeak.org/treated/Kernel-fbs.870.diff Alas, those two solutions break the very peculiar expectations of testHandlerReentrancy. This is a pity, because to my knowledge, those expectations are essential for Tweak and Croquet. There was a previous attempt from Andreas which was more a simple hack in handleSignal:, that is to disable the handler by setting the temp variable handlerActive in on:do: to false (self tempAt: 3 put: false). I've generalized this solution. https://source.squeak.org/treated/Kernel-ar.540.diff However, there are several reasons why this does not work: the first one, objected by Julian Fitzell here http://lists.squeakfoundation.org/pipermail/squeak-dev/2011-January/156453.html is that the handler must be able to handle a secondary exception raised by the defaultAction. We can find similar expectations with other exception handling, like resignalAs (I will publish another test soon). However, there is some simple strategy: before resuming the exception, scan the context stack a second time so as to rearm the exception handlers that we disabled during handleSignal:. The major drawback, is that I have to spread a few self reactivateHandlers here and there, virtually before every send of #resumedUnchecked:. The second drawback is that scanning the stack a second time is not the most economical solution, but I don't care too much, we have to make it right first. If you find the courage to review, or more easily just to test it, find it in the inbox... Oups, I accidentally published in trunk... Well the review will be forced, if you don't like it, admin please remove or revert. Sorry. -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 12 17:50:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 17:50:15 0000 Subject: [squeak-dev] The Trunk: Tools-eem.1035.mcz Message-ID: Eliot Miranda uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-eem.1035.mcz ==================== Summary ==================== Name: Tools-eem.1035 Author: eem Time: 12 April 2021, 10:50:12.075047 am UUID: 9f246bef-bed1-4852-8a0d-0ff3e243395f Ancestors: Tools-nice.1034 tempNames goes with namedTempAt: not tempAt: ; tempAt: merely being a more context-specific name (snuk snuk). =============== Diff against Tools-nice.1034 =============== Item was changed: ----- Method: Context>>tempsAndValuesLimitedTo:indent: (in category '*Tools-debugger access') ----- tempsAndValuesLimitedTo: sizeLimit indent: indent "Return a string of the temporary variabls and their current values" | aStream | aStream := WriteStream on: (String new: 100). self tempNames withIndexDo: [:title :index | indent timesRepeat: [aStream tab]. aStream nextPutAll: title; nextPut: $:; space; tab. aStream nextPutAll: + ((self namedTempAt: index) printStringLimitedTo: (sizeLimit - 3 - title size max: 1)). - ((self tempAt: index) printStringLimitedTo: (sizeLimit -3 -title size max: 1)). aStream cr]. ^aStream contents! From commits at source.squeak.org Mon Apr 12 18:02:24 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 18:02:24 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-eem.287.mcz Message-ID: Eliot Miranda uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-eem.287.mcz ==================== Summary ==================== Name: MorphicExtras-eem.287 Author: eem Time: 12 April 2021, 11:02:21.284327 am UUID: b74bcd77-a21f-4562-b441-5e2220720482 Ancestors: MorphicExtras-mt.286 Include the actual frame extent in the output of the CameraInterface test methods. =============== Diff against MorphicExtras-mt.286 =============== Item was changed: ----- Method: CameraInterface class>>interruptDrivenVideoTest: (in category 'test') ----- interruptDrivenVideoTest: camNum "A quick test of video input. Displays video on the screen until the mouse is pressed. Answer nil if the interrupt-driven interface is unavailable." "self interruptDrivenVideoTest: 1" "self interruptDrivenVideoTest: 2" "[self interruptDrivenVideoTest: 2] fork. self interruptDrivenVideoTest: 1" + | semaphore height frameExtent | - | semaphore height | height := 16. 1 to: camNum - 1 do: [:camIndex| "N.B. the of an unopened camera is 0 at 0" + height := height + (self frameExtent: camIndex) y + 16]. + (self cameraIsOpen: camNum) ifFalse: + [(self openCamera: camNum width: 352 height: 288) ifNil: - height := height + (CameraInterface frameExtent: camIndex) y + 16]. - (CameraInterface cameraIsOpen: camNum) ifFalse: - [(CameraInterface openCamera: camNum width: 352 height: 288) ifNil: [self inform: 'no camera'. ^nil]]. semaphore := Semaphore new. + [self camera: camNum setSemaphore: (Smalltalk registerExternalObject: semaphore)] - [CameraInterface camera: camNum setSemaphore: (Smalltalk registerExternalObject: semaphore)] on: Error do: [:err| Smalltalk unregisterExternalObject: semaphore. self inform: 'interrupt-driven camera interface unavailable: ', err messageText. ^nil]. [| f n startTime frameCount msecs fps | [semaphore wait. "N.B. the frame extent may not be known until the delivery of the first frame. So we have to delay initialization." startTime ifNil: + [(frameExtent := self frameExtent: camNum) x = 0 ifTrue: [self inform: 'no camera'. ^nil]. + f := Form extent: (self frameExtent: camNum) depth: 32. - [(self frameExtent: camNum) x = 0 ifTrue: [self inform: 'no camera'. ^nil]. - f := Form extent: (CameraInterface frameExtent: camNum) depth: 32. frameCount := 0. startTime := Time millisecondClockValue]. Sensor anyButtonPressed] whileFalse: + [n := self getFrameForCamera: camNum into: f bits. - [n := CameraInterface getFrameForCamera: camNum into: f bits. n > 0 ifTrue: [frameCount := frameCount + 1. f displayAt: 16 @ height]]. msecs := Time millisecondClockValue - startTime. fps := (frameCount * 1000) // msecs. + ^(self cameraName: camNum), ': ', frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'] - ^(CameraInterface cameraName: camNum), ': ', frameCount printString, ' frames at ', fps printString, ' frames/sec'] ensure: + [self closeCamera: camNum. - [CameraInterface closeCamera: camNum. Smalltalk unregisterExternalObject: semaphore. Sensor waitNoButton]! Item was changed: ----- Method: CameraInterface class>>videoTest: (in category 'test') ----- videoTest: camNum "A quick test of video input. Displays video on the screen until the mouse is pressed." "self videoTest: 1" "self videoTest: 2" + | frameExtent f n startTime frameCount msecs fps | + (self openCamera: camNum width: 320 height: 240) ifNil: [^ self inform: 'no camera']. - | f n startTime frameCount msecs fps | - (CameraInterface openCamera: camNum width: 320 height: 240) ifNil: [^ self inform: 'no camera']. self waitForCameraStart: camNum. + (frameExtent := self frameExtent: camNum) x = 0 ifTrue: [^ self inform: 'no camera']. + f := Form extent: (self frameExtent: camNum) depth: 32. - (self frameExtent: camNum) x = 0 ifTrue: [^ self inform: 'no camera']. - f := Form extent: (CameraInterface frameExtent: camNum) depth: 32. frameCount := 0. startTime := nil. + [Sensor anyButtonPressed] whileFalse: + [n := self getFrameForCamera: camNum into: f bits. + n > 0 ifTrue: + [startTime ifNil: [startTime := Time millisecondClockValue]. - [Sensor anyButtonPressed] whileFalse: [ - n := CameraInterface getFrameForCamera: camNum into: f bits. - n > 0 ifTrue: [ - startTime ifNil: [startTime := Time millisecondClockValue]. frameCount := frameCount + 1. f display]]. Sensor waitNoButton. msecs := Time millisecondClockValue - startTime. + self closeCamera: camNum. + fps := frameCount * 1000 // msecs. + ^frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'! - CameraInterface closeCamera: camNum. - fps := (frameCount * 1000) // msecs. - ^ frameCount printString, ' frames at ', fps printString, ' frames/sec'! From commits at source.squeak.org Mon Apr 12 18:30:55 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 18:30:55 0000 Subject: [squeak-dev] The Trunk: KernelTests-eem.396.mcz Message-ID: Eliot Miranda uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-eem.396.mcz ==================== Summary ==================== Name: KernelTests-eem.396 Author: eem Time: 12 April 2021, 11:30:53.654392 am UUID: 642cd275-3ce5-4cfb-a34f-1bb29d140e94 Ancestors: KernelTests-codefrau.395 Rename MethodContextTest to ContextTest =============== Diff against KernelTests-codefrau.395 =============== Item was added: + TestCase subclass: #ContextTest + instanceVariableNames: 'aCompiledMethod aReceiver aSender aContext' + classVariableNames: '' + poolDictionaries: '' + category: 'KernelTests-Methods'! + + !ContextTest commentStamp: 'ct 1/27/2020 13:03' prior: 0! + I am an SUnit Test of Context. See also BlockClosureTest. + See pages 430-437 of A. Goldberg and D. Robson's Smalltalk-80 The Language (aka the purple book), which deal with Contexts. My fixtures are from their example. To see how blocks are implemented in this version of Squeak see http://www.mirandabanda.org/cogblog/2008/06/07/closures-part-i/ and http://www.mirandabanda.org/cogblog/2008/07/22/closures-part-ii-the-bytecodes/. (The Squeak V3 byte codes are not quite the same as Smalltalk-80, and the SistaV1 byetcodes are quite different.) + My fixtures are: + aReceiver - just some arbitrary object, "Rectangle origin: 100 at 100 corner: 200 at 200" + aSender - just some arbitrary object, thisContext + aCompiledMethod - just some arbitrary method, "Rectangle rightCenter". + aContext - just some arbitray context ... + + ! Item was added: + ----- Method: ContextTest>>privRestartTest (in category 'private') ----- + privRestartTest + "This tests may loop endlessly if incorrect, so call it from another method testing it does not time out" + |a firstTimeThrough | + firstTimeThrough := true. + a := 10. + + self assert: 30 equals: [|b| + self assert: 10 = a . + self assert: nil == b. + b := a + 20. + firstTimeThrough ifTrue: [ + firstTimeThrough := false. + thisContext restart.]. + b] value + ! Item was added: + ----- Method: ContextTest>>setUp (in category 'running') ----- + setUp + super setUp. + aCompiledMethod := Rectangle methodDict at: #rightCenter. + aReceiver := 100 at 100 corner: 200 at 200. + aSender := thisContext. + aContext := Context sender: aSender receiver: aReceiver method: aCompiledMethod arguments: #(). ! Item was added: + ----- Method: ContextTest>>testActivateReturnValue (in category 'tests') ----- + testActivateReturnValue + self assert: (aSender activateReturn: aContext value: #()) isContext. + self assert: ((aSender activateReturn: aContext value: #()) receiver = aContext).! Item was added: + ----- Method: ContextTest>>testCopyStack (in category 'tests') ----- + testCopyStack + self assert: aContext copyStack printString = aContext printString.! Item was added: + ----- Method: ContextTest>>testCopyTo (in category 'tests') ----- + testCopyTo + + | context depth targetSender | + context := thisContext. + depth := 1. + targetSender := context. + [ (targetSender := targetSender sender) isNil ] whileFalse: [ + | original copy | + original := context. + copy := context copyTo: targetSender. + 1 to: depth do: [ :index | + index = 1 ifFalse: [ + "Since we're copying thisContext, the pc and stackPtr may be different for the current frame." + self + assert: original pc equals: copy pc; + assert: original stackPtr equals: copy stackPtr ]. + self + deny: original == copy; + assert: original method equals: copy method; + assert: original closure equals: copy closure; + assert: original receiver equals: copy receiver. + original := original sender. + copy := copy sender ]. + self + assert: copy isNil; + assert: original == targetSender. + depth := depth + 1 ]! Item was added: + ----- Method: ContextTest>>testFindContextSuchThat (in category 'tests') ----- + testFindContextSuchThat + self assert: (aContext findContextSuchThat: [:each| true]) printString = aContext printString. + self assert: (aContext hasContext: aContext). ! Item was added: + ----- Method: ContextTest>>testMethodContext (in category 'tests') ----- + testMethodContext + self assert: aContext home notNil. + self assert: aContext receiver notNil. + self assert: aContext method isCompiledMethod.! Item was added: + ----- Method: ContextTest>>testMethodIsBottomContext (in category 'tests') ----- + testMethodIsBottomContext + self assert: aContext bottomContext = aSender. + self assert: aContext secondFromBottom = aContext.! Item was added: + ----- Method: ContextTest>>testPrimitive100 (in category 'tests') ----- + testPrimitive100 + + { + {#isNil. {}. Object}. "valid 0-arg message" + {#=. {true}. UndefinedObject}. "valid unary message" + {#ifNil:ifNotNil:. {[2]. [:x | x]}. Object}. "valid binary message" + {}. "missing selector" + {#isNil}. "missing arguments" + {#isNil. 'not an array'}. "invalid arguments" + {#isNil. {}}. "missing lookupClass" + {#isNil. {'excess arg'}. Object}. "too many arguments" + {#=. {}. UndefinedObject}. "missing argument" + {#isNil. {}. Boolean}. "lookupClass not in inheritance chain" + } do: [:args | + self + assert: (Context runSimulated: [nil tryPrimitive: 100 withArgs: args]) + equals: (nil tryPrimitive: 100 withArgs: args)].! Item was added: + ----- Method: ContextTest>>testPrimitive83 (in category 'tests') ----- + testPrimitive83 + + { + {#isNil}. "valid 0-arg message" + {#=. true}. "valid unary message" + {#ifNil:ifNotNil:. [2]. [:x | x]}. "valid binary message" + {}. "missing selector" + {#isNil. 'excess arg'}. "too many arguments" + {#=}. "missing argument" + } do: [:args | + self + assert: (Context runSimulated: [nil tryPrimitive: 83 withArgs: args]) + equals: (nil tryPrimitive: 83 withArgs: args)].! Item was added: + ----- Method: ContextTest>>testPrimitive84 (in category 'tests') ----- + testPrimitive84 + + { + {#isNil. {}}. "valid 0-arg message" + {#=. {true}}. "valid unary message" + {#ifNil:ifNotNil:. {[2]. [:x | x]}}. "valid binary message" + {}. "missing selector" + {#isNil}. "missing arguments" + {#isNil. 'not an array'}. "invalid arguments" + {#isNil. {'excess arg'}}. "too many arguments" + {#=. {}}. "missing argument" + } do: [:args | + self + assert: (Context runSimulated: [nil tryPrimitive: 84 withArgs: args]) + equals: (nil tryPrimitive: 84 withArgs: args)].! Item was added: + ----- Method: ContextTest>>testRestart (in category 'tests') ----- + testRestart + self should: [self privRestartTest] notTakeMoreThan: 0.1 second! Item was added: + ----- Method: ContextTest>>testReturn (in category 'tests') ----- + testReturn + "Why am I overriding setUp? Because sender must be thisContext, i.e, testReturn, not setUp." + aContext := Context sender: thisContext receiver: aReceiver method: aCompiledMethod arguments: #(). + self assert: (aContext return: 5) = 5! Item was added: + ----- Method: ContextTest>>testSetUp (in category 'tests') ----- + testSetUp + "Note: In addition to verifying that the setUp worked the way it was expected to, testSetUp is used to illustrate the meaning of the simple access methods, methods that are not normally otherwise 'tested'" + self assert: aContext isContext. + self deny: aContext isExecutingBlock. + self deny: aContext isClosure. + self deny: aContext isDead. + "self assert: aMethodContext home = aReceiver." + "self assert: aMethodContext blockHome = aReceiver." + self assert: aContext receiver = aReceiver. + self assert: aContext method isCompiledMethod. + self assert: aContext method = aCompiledMethod. + self assert: aContext methodNode selector = #rightCenter. + self assert: (aContext methodNodeFormattedAndDecorated: true) selector = #rightCenter. + self assert: aContext client printString = 'ContextTest>>#testSetUp'. + ! Item was removed: - TestCase subclass: #MethodContextTest - instanceVariableNames: 'aCompiledMethod aReceiver aMethodContext aSender' - classVariableNames: '' - poolDictionaries: '' - category: 'KernelTests-Methods'! - - !MethodContextTest commentStamp: 'eem 3/30/2017 17:42' prior: 0! - I am an SUnit Test of Context. See also BlockClosureTest. - See pages 430-437 of A. Goldberg and D. Robson's Smalltalk-80 The Language (aka the purple book), which deal with Contexts. My fixtures are from their example. To see how blocks are implemented in this version of Squeak see http://www.mirandabanda.org/cogblog/2008/06/07/closures-part-i/ and http://www.mirandabanda.org/cogblog/2008/07/22/closures-part-ii-the-bytecodes/. (The Squeak V3 byte codes are not quite the same as Smalltalk-80, and the SistaV1 byetcodes are quite different.) - My fixtures are: - aReceiver - just some arbitrary object, "Rectangle origin: 100 at 100 corner: 200 at 200" - aSender - just some arbitrary object, thisContext - aCompiledMethod - just some arbitrary method, "Rectangle rightCenter". - aMethodContext - just some arbitray context ... - - ! Item was removed: - ----- Method: MethodContextTest>>privRestartTest (in category 'private') ----- - privRestartTest - "This tests may loop endlessly if incorrect, so call it from another method testing it does not time out" - |a firstTimeThrough | - firstTimeThrough := true. - a := 10. - - self assert: 30 equals: [|b| - self assert: 10 = a . - self assert: nil == b. - b := a + 20. - firstTimeThrough ifTrue: [ - firstTimeThrough := false. - thisContext restart.]. - b] value - ! Item was removed: - ----- Method: MethodContextTest>>setUp (in category 'running') ----- - setUp - super setUp. - aCompiledMethod := Rectangle methodDict at: #rightCenter. - aReceiver := 100 at 100 corner: 200 at 200. - aSender := thisContext. - aMethodContext := Context sender: aSender receiver: aReceiver method: aCompiledMethod arguments: #(). ! Item was removed: - ----- Method: MethodContextTest>>testActivateReturnValue (in category 'tests') ----- - testActivateReturnValue - self assert: (aSender activateReturn: aMethodContext value: #()) isContext. - self assert: ((aSender activateReturn: aMethodContext value: #()) receiver = aMethodContext).! Item was removed: - ----- Method: MethodContextTest>>testCopyStack (in category 'tests') ----- - testCopyStack - self assert: aMethodContext copyStack printString = aMethodContext printString.! Item was removed: - ----- Method: MethodContextTest>>testCopyTo (in category 'tests') ----- - testCopyTo - - | context depth targetSender | - context := thisContext. - depth := 1. - targetSender := context. - [ (targetSender := targetSender sender) isNil ] whileFalse: [ - | original copy | - original := context. - copy := context copyTo: targetSender. - 1 to: depth do: [ :index | - index = 1 ifFalse: [ - "Since we're copying thisContext, the pc and stackPtr may be different for the current frame." - self - assert: original pc equals: copy pc; - assert: original stackPtr equals: copy stackPtr ]. - self - deny: original == copy; - assert: original method equals: copy method; - assert: original closure equals: copy closure; - assert: original receiver equals: copy receiver. - original := original sender. - copy := copy sender ]. - self - assert: copy isNil; - assert: original == targetSender. - depth := depth + 1 ]! Item was removed: - ----- Method: MethodContextTest>>testFindContextSuchThat (in category 'tests') ----- - testFindContextSuchThat - self assert: (aMethodContext findContextSuchThat: [:each| true]) printString = aMethodContext printString. - self assert: (aMethodContext hasContext: aMethodContext). ! Item was removed: - ----- Method: MethodContextTest>>testMethodContext (in category 'tests') ----- - testMethodContext - self assert: aMethodContext home notNil. - self assert: aMethodContext receiver notNil. - self assert: aMethodContext method isCompiledMethod.! Item was removed: - ----- Method: MethodContextTest>>testMethodIsBottomContext (in category 'tests') ----- - testMethodIsBottomContext - self assert: aMethodContext bottomContext = aSender. - self assert: aMethodContext secondFromBottom = aMethodContext.! Item was removed: - ----- Method: MethodContextTest>>testRestart (in category 'tests') ----- - testRestart - self should: [self privRestartTest] notTakeMoreThan: 0.1 second! Item was removed: - ----- Method: MethodContextTest>>testReturn (in category 'tests') ----- - testReturn - "Why am I overriding setUp? Because sender must be thisContext, i.e, testReturn, not setUp." - aMethodContext := Context sender: thisContext receiver: aReceiver method: aCompiledMethod arguments: #(). - self assert: (aMethodContext return: 5) = 5! Item was removed: - ----- Method: MethodContextTest>>testSetUp (in category 'tests') ----- - testSetUp - "Note: In addition to verifying that the setUp worked the way it was expected to, testSetUp is used to illustrate the meaning of the simple access methods, methods that are not normally otherwise 'tested'" - self assert: aMethodContext isContext. - self deny: aMethodContext isExecutingBlock. - self deny: aMethodContext isClosure. - self deny: aMethodContext isDead. - "self assert: aMethodContext home = aReceiver." - "self assert: aMethodContext blockHome = aReceiver." - self assert: aMethodContext receiver = aReceiver. - self assert: aMethodContext method isCompiledMethod. - self assert: aMethodContext method = aCompiledMethod. - self assert: aMethodContext methodNode selector = #rightCenter. - self assert: (aMethodContext methodNodeFormattedAndDecorated: true) selector = #rightCenter. - self assert: aMethodContext client printString = 'MethodContextTest>>#testSetUp'. - ! From commits at source.squeak.org Mon Apr 12 18:31:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 18:31:40 0000 Subject: [squeak-dev] The Trunk: Monticello-eem.737.mcz Message-ID: Eliot Miranda uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-eem.737.mcz ==================== Summary ==================== Name: Monticello-eem.737 Author: eem Time: 12 April 2021, 11:31:38.465056 am UUID: 015970f1-92a9-4e6b-b0a2-9d6deba9d725 Ancestors: Monticello-mt.736 Eliminate shadowed variable warning(s). =============== Diff against Monticello-mt.736 =============== Item was changed: ----- Method: MCRepositoryInspector>>save (in category 'actions') ----- save self pickRepository ifNotNil: + [:repo | + (self repository = MCRepository inbox + and: [repo = MCRepository trunk or: [repo = MCRepository treated]]) ifTrue: + [self notify: 'Versions from the inbox should only be moved, not copied. Instead, use the web interface via source.squeak.org to manage inbox contributions.\\Do you want to proceed anyway?' translated withCRs]. + repo storeVersion: self version]! - [:repository | - (self repository = MCRepository inbox and: - [repository = MCRepository trunk or: [repository = MCRepository treated]]) ifTrue: - [self notify: 'Versions from the inbox should only be moved, not copied. Instead, use the web interface via source.squeak.org to manage inbox contributions.\\Do you want to proceed anyway?' translated withCRs]. - repository storeVersion: self version]! From commits at source.squeak.org Mon Apr 12 18:32:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 18:32:20 0000 Subject: [squeak-dev] The Trunk: Morphic-eem.1742.mcz Message-ID: Eliot Miranda uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-eem.1742.mcz ==================== Summary ==================== Name: Morphic-eem.1742 Author: eem Time: 12 April 2021, 11:32:16.715075 am UUID: c88153a2-36a5-447f-abd0-93a6b164fd6f Ancestors: Morphic-mt.1741 Eliminate shadowed variable warning(s). =============== Diff against Morphic-mt.1741 =============== Item was changed: ----- Method: BottomLeftGripMorph>>apply: (in category 'target resize') ----- apply: delta | oldBounds | oldBounds := self target bounds. self target bounds: (oldBounds origin + (delta x @ 0) corner: oldBounds corner + (0 @ delta y)). self flag: #workaround. "mt: Due to a layout-specific 'let us start in the top-left corner of a layout cell'-behavior, we have to go up the owner chain and propagate the delta. See Morph >> #layoutInBounds:positioning: and there section 1.2." + self target allOwnersDo: + [:anOwner | + (anOwner layoutPolicy notNil and: [anOwner ~~ Project current world]) + ifTrue: [anOwner left: owner left + delta x]].! - self target allOwnersDo: [:owner | - (owner layoutPolicy notNil and: [owner ~~ Project current world]) - ifTrue: [owner left: owner left + delta x]].! Item was changed: ----- Method: LeftGripMorph>>apply: (in category 'target resize') ----- apply: delta | oldBounds | oldBounds := self target bounds. self target bounds: (oldBounds origin + (delta x @ 0) corner: oldBounds corner). self flag: #workaround. "mt: Due to a layout-specific 'let us start in the top-left corner of a layout cell'-behavior, we have to go up the owner chain and propagate the delta. See Morph >> #layoutInBounds:positioning: and there section 1.2." + self target allOwnersDo: + [:anOwner | + (anOwner layoutPolicy notNil and: [anOwner ~~ Project current world]) + ifTrue: [anOwner left: anOwner left + delta x]].! - self target allOwnersDo: [:owner | - (owner layoutPolicy notNil and: [owner ~~ Project current world]) - ifTrue: [owner left: owner left + delta x]].! Item was changed: ----- Method: TopGripMorph>>apply: (in category 'target resize') ----- apply: delta | oldBounds | oldBounds := self target bounds. self target bounds: (oldBounds origin + (0 @ delta y) corner: oldBounds corner). self flag: #workaround. "mt: Due to a layout-specific 'let us start in the top-left corner of a layout cell'-behavior, we have to go up the owner chain and propagate the delta. See Morph >> #layoutInBounds:positioning: and there section 1.2." + self target allOwnersDo: + [:anOwner | + (anOwner layoutPolicy notNil and: [anOwner ~~ Project current world]) + ifTrue: [anOwner top: anOwner top + delta y]].! - self target allOwnersDo: [:owner | - (owner layoutPolicy notNil and: [owner ~~ Project current world]) - ifTrue: [owner top: owner top + delta y]].! Item was changed: ----- Method: TopLeftGripMorph>>apply: (in category 'target resize') ----- apply: delta | oldBounds | oldBounds := self target bounds. self target bounds: (oldBounds origin + delta corner: oldBounds corner). self flag: #workaround. "mt: Due to a layout-specific 'let us start in the top-left corner of a layout cell'-behavior, we have to go up the owner chain and propagate the delta. See Morph >> #layoutInBounds:positioning: and there section 1.2." + self target allOwnersDo: + [:anOwner | + (anOwner layoutPolicy notNil and: [anOwner ~~ Project current world]) + ifTrue: [anOwner topLeft: anOwner topLeft + delta]].! - self target allOwnersDo: [:owner | - (owner layoutPolicy notNil and: [owner ~~ Project current world]) - ifTrue: [owner topLeft: owner topLeft + delta]].! Item was changed: ----- Method: TopRightGripMorph>>apply: (in category 'target resize') ----- apply: delta | oldBounds | oldBounds := self target bounds. self target bounds: (oldBounds origin + (0 at delta y) corner: oldBounds corner + (delta x @ 0)). self flag: #workaround. "mt: Due to a layout-specific 'let us start in the top-left corner of a layout cell'-behavior, we have to go up the owner chain and propagate the delta. See Morph >> #layoutInBounds:positioning: and there section 1.2." + self target allOwnersDo: + [:anOwner | + (anOwner layoutPolicy notNil and: [anOwner ~~ Project current world]) + ifTrue: [anOwner top: anOwner top + delta y]].! - self target allOwnersDo: [:owner | - (owner layoutPolicy notNil and: [owner ~~ Project current world]) - ifTrue: [owner top: owner top + delta y]].! From commits at source.squeak.org Mon Apr 12 18:33:05 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 18:33:05 0000 Subject: [squeak-dev] The Trunk: MorphicTests-eem.74.mcz Message-ID: Eliot Miranda uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-eem.74.mcz ==================== Summary ==================== Name: MorphicTests-eem.74 Author: eem Time: 12 April 2021, 11:33:04.505845 am UUID: 90a13e5e-0e8c-4174-b9d3-15298b6c517c Ancestors: MorphicTests-mt.73 Fix some shadowed variable warning(s). =============== Diff against MorphicTests-mt.73 =============== Item was changed: ----- Method: MorphTest>>test10TransformKeepsLayer (in category 'tests - submorphs - layers') ----- test10TransformKeepsLayer + | aMorph transform | + aMorph := Morph new. - | morph transform | - morph := Morph new. transform := morph addFlexShell. + aMorph morphicLayerNumber: 50. - morph morphicLayerNumber: 50. self assert: 50 equals: transform morphicLayerNumber. transform morphicLayerNumber: 20. self assert: 20 equals: transform morphicLayerNumber. + transform removeMorph: aMorph. - transform removeMorph: morph. transform morphicLayerNumber: 50. self + assert: 20 equals: aMorph morphicLayerNumber; + assert: 50 equals: transform morphicLayerNumber! - assert: 20 equals: morph morphicLayerNumber; - assert: 50 equals: transform morphicLayerNumber.! Item was changed: ----- Method: MorphTest>>test12ResetLayerToDefault (in category 'tests - submorphs - layers') ----- test12ResetLayerToDefault + | aMorph default | + aMorph := Morph new. + default := aMorph morphicLayerNumber. - | morph default | - morph := Morph new. - default := morph morphicLayerNumber. + aMorph morphicLayerNumber: default * 2. + self deny: default equals: aMorph morphicLayerNumber. - morph morphicLayerNumber: default * 2. - self deny: default equals: morph morphicLayerNumber. morph morphicLayerNumber: nil. + self assert: default equals: aMorph morphicLayerNumber! - self assert: default equals: morph morphicLayerNumber.! From commits at source.squeak.org Mon Apr 12 18:35:55 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 18:35:55 0000 Subject: [squeak-dev] The Trunk: ToolBuilder-Kernel-eem.140.mcz Message-ID: Eliot Miranda uploaded a new version of ToolBuilder-Kernel to project The Trunk: http://source.squeak.org/trunk/ToolBuilder-Kernel-eem.140.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-eem.140 Author: eem Time: 12 April 2021, 11:35:54.040708 am UUID: 80cac10d-92fc-4ef0-b082-d146ec598543 Ancestors: ToolBuilder-Kernel-mt.139 Fix some shadowed variable warning(s). =============== Diff against ToolBuilder-Kernel-mt.139 =============== Item was changed: ----- Method: PluggableMultiColumnListSpec>>itemPaddings (in category 'accessing') ----- itemPaddings + ^ itemPaddings ifNil: [self itemPadding ifNil: [#()] ifNotNil: [:pad | {pad}]]! - ^ itemPaddings ifNil: [self itemPadding ifNil: [#()] ifNotNil: [:padding | {padding}]]! From commits at source.squeak.org Mon Apr 12 18:36:29 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 18:36:29 0000 Subject: [squeak-dev] The Trunk: Tools-eem.1036.mcz Message-ID: Eliot Miranda uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-eem.1036.mcz ==================== Summary ==================== Name: Tools-eem.1036 Author: eem Time: 12 April 2021, 11:36:27.582761 am UUID: 6f49f7a4-a29b-48eb-94d4-ad3be6cf607b Ancestors: Tools-eem.1035 Fix some shadowed variable warning(s). =============== Diff against Tools-eem.1035 =============== Item was changed: ----- Method: ContextVariablesInspector>>fieldStackTop (in category 'fields') ----- fieldStackTop ^ (self newFieldForType: #stackTop key: #stackTop) name: self stackTopTranslated; emphasizeName; + valueGetter: [:ctxt | ctxt top]; - valueGetter: [:context | context top]; valueGetterExpression: 'ThisContext top'; yourself! From commits at source.squeak.org Mon Apr 12 19:19:05 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 19:19:05 0000 Subject: [squeak-dev] The Inbox: Tests-ct.448.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-ct.448.mcz ==================== Summary ==================== Name: Tests-ct.448 Author: ct Time: 12 April 2021, 9:19:02.66824 pm UUID: 65aa0e1a-250a-724a-9f04-505db0722916 Ancestors: Tests-nice.447 Revises ExceptionTests >> #testCatchingDefaultAction to work when being debugged/simulated as well. This also decouples the test from the implementation details of UnhandledWarnings. For further reference, see also: https://github.com/LinqLover/SimulationStudio/runs/2319502648?check_suite_focus=true#step:4:441 =============== Diff against Tests-nice.447 =============== Item was changed: ----- Method: ExceptionTests>>testCatchingDefaultAction (in category 'tests - outer') ----- testCatchingDefaultAction + "The #defaultAction method is executed in the context of the signaling environment." + - "The #defaultAction method is executed in the context of the signaling environment. - The defaultAction will raise an UnhandledWarning that should be caught by this handler." | result | + result := [MyTestNotification signalForAction: [MyTestNotification signal: '2nd exception']] + on: MyTestNotification + do: [:ex | '2nd exception caught']. + self assert: '2nd exception caught' equals: result.! - result := [ Warning signal: 'Warning signalled' ] on: UnhandledWarning do: [ :ex | 'UnhandledWarning caught' ]. - self assert: 'UnhandledWarning caught' equals: result! Item was changed: Notification subclass: #MyTestNotification + instanceVariableNames: 'action' - instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tests-Exceptions'! Item was added: + ----- Method: MyTestNotification class>>signalForAction: (in category 'signaling') ----- + signalForAction: aBlock + + ^ self new + action: aBlock; + signal! Item was added: + ----- Method: MyTestNotification>>action (in category 'accessing') ----- + action + + ^ action! Item was added: + ----- Method: MyTestNotification>>action: (in category 'accessing') ----- + action: aBlock + + action := aBlock! Item was added: + ----- Method: MyTestNotification>>defaultAction (in category 'priv handling') ----- + defaultAction + + self action ifNotNil: [^ self action cull: self]. + + ^ super defaultAction! From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 12 19:22:32 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 12 Apr 2021 19:22:32 +0000 Subject: [squeak-dev] The Trunk: KernelTests-eem.396.mcz In-Reply-To: References: Message-ID: Thank you, finally! :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Montag, 12. April 2021 20:30:55 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: KernelTests-eem.396.mcz Eliot Miranda uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-eem.396.mcz ==================== Summary ==================== Name: KernelTests-eem.396 Author: eem Time: 12 April 2021, 11:30:53.654392 am UUID: 642cd275-3ce5-4cfb-a34f-1bb29d140e94 Ancestors: KernelTests-codefrau.395 Rename MethodContextTest to ContextTest =============== Diff against KernelTests-codefrau.395 =============== Item was added: + TestCase subclass: #ContextTest + instanceVariableNames: 'aCompiledMethod aReceiver aSender aContext' + classVariableNames: '' + poolDictionaries: '' + category: 'KernelTests-Methods'! + + !ContextTest commentStamp: 'ct 1/27/2020 13:03' prior: 0! + I am an SUnit Test of Context. See also BlockClosureTest. + See pages 430-437 of A. Goldberg and D. Robson's Smalltalk-80 The Language (aka the purple book), which deal with Contexts. My fixtures are from their example. To see how blocks are implemented in this version of Squeak see http://www.mirandabanda.org/cogblog/2008/06/07/closures-part-i/ and http://www.mirandabanda.org/cogblog/2008/07/22/closures-part-ii-the-bytecodes/. (The Squeak V3 byte codes are not quite the same as Smalltalk-80, and the SistaV1 byetcodes are quite different.) + My fixtures are: + aReceiver - just some arbitrary object, "Rectangle origin: 100 at 100 corner: 200 at 200" + aSender - just some arbitrary object, thisContext + aCompiledMethod - just some arbitrary method, "Rectangle rightCenter". + aContext - just some arbitray context ... + + ! Item was added: + ----- Method: ContextTest>>privRestartTest (in category 'private') ----- + privRestartTest + "This tests may loop endlessly if incorrect, so call it from another method testing it does not time out" + |a firstTimeThrough | + firstTimeThrough := true. + a := 10. + + self assert: 30 equals: [|b| + self assert: 10 = a . + self assert: nil == b. + b := a + 20. + firstTimeThrough ifTrue: [ + firstTimeThrough := false. + thisContext restart.]. + b] value + ! Item was added: + ----- Method: ContextTest>>setUp (in category 'running') ----- + setUp + super setUp. + aCompiledMethod := Rectangle methodDict at: #rightCenter. + aReceiver := 100 at 100 corner: 200 at 200. + aSender := thisContext. + aContext := Context sender: aSender receiver: aReceiver method: aCompiledMethod arguments: #(). ! Item was added: + ----- Method: ContextTest>>testActivateReturnValue (in category 'tests') ----- + testActivateReturnValue + self assert: (aSender activateReturn: aContext value: #()) isContext. + self assert: ((aSender activateReturn: aContext value: #()) receiver = aContext).! Item was added: + ----- Method: ContextTest>>testCopyStack (in category 'tests') ----- + testCopyStack + self assert: aContext copyStack printString = aContext printString.! Item was added: + ----- Method: ContextTest>>testCopyTo (in category 'tests') ----- + testCopyTo + + | context depth targetSender | + context := thisContext. + depth := 1. + targetSender := context. + [ (targetSender := targetSender sender) isNil ] whileFalse: [ + | original copy | + original := context. + copy := context copyTo: targetSender. + 1 to: depth do: [ :index | + index = 1 ifFalse: [ + "Since we're copying thisContext, the pc and stackPtr may be different for the current frame." + self + assert: original pc equals: copy pc; + assert: original stackPtr equals: copy stackPtr ]. + self + deny: original == copy; + assert: original method equals: copy method; + assert: original closure equals: copy closure; + assert: original receiver equals: copy receiver. + original := original sender. + copy := copy sender ]. + self + assert: copy isNil; + assert: original == targetSender. + depth := depth + 1 ]! Item was added: + ----- Method: ContextTest>>testFindContextSuchThat (in category 'tests') ----- + testFindContextSuchThat + self assert: (aContext findContextSuchThat: [:each| true]) printString = aContext printString. + self assert: (aContext hasContext: aContext). ! Item was added: + ----- Method: ContextTest>>testMethodContext (in category 'tests') ----- + testMethodContext + self assert: aContext home notNil. + self assert: aContext receiver notNil. + self assert: aContext method isCompiledMethod.! Item was added: + ----- Method: ContextTest>>testMethodIsBottomContext (in category 'tests') ----- + testMethodIsBottomContext + self assert: aContext bottomContext = aSender. + self assert: aContext secondFromBottom = aContext.! Item was added: + ----- Method: ContextTest>>testPrimitive100 (in category 'tests') ----- + testPrimitive100 + + { + {#isNil. {}. Object}. "valid 0-arg message" + {#=. {true}. UndefinedObject}. "valid unary message" + {#ifNil:ifNotNil:. {[2]. [:x | x]}. Object}. "valid binary message" + {}. "missing selector" + {#isNil}. "missing arguments" + {#isNil. 'not an array'}. "invalid arguments" + {#isNil. {}}. "missing lookupClass" + {#isNil. {'excess arg'}. Object}. "too many arguments" + {#=. {}. UndefinedObject}. "missing argument" + {#isNil. {}. Boolean}. "lookupClass not in inheritance chain" + } do: [:args | + self + assert: (Context runSimulated: [nil tryPrimitive: 100 withArgs: args]) + equals: (nil tryPrimitive: 100 withArgs: args)].! Item was added: + ----- Method: ContextTest>>testPrimitive83 (in category 'tests') ----- + testPrimitive83 + + { + {#isNil}. "valid 0-arg message" + {#=. true}. "valid unary message" + {#ifNil:ifNotNil:. [2]. [:x | x]}. "valid binary message" + {}. "missing selector" + {#isNil. 'excess arg'}. "too many arguments" + {#=}. "missing argument" + } do: [:args | + self + assert: (Context runSimulated: [nil tryPrimitive: 83 withArgs: args]) + equals: (nil tryPrimitive: 83 withArgs: args)].! Item was added: + ----- Method: ContextTest>>testPrimitive84 (in category 'tests') ----- + testPrimitive84 + + { + {#isNil. {}}. "valid 0-arg message" + {#=. {true}}. "valid unary message" + {#ifNil:ifNotNil:. {[2]. [:x | x]}}. "valid binary message" + {}. "missing selector" + {#isNil}. "missing arguments" + {#isNil. 'not an array'}. "invalid arguments" + {#isNil. {'excess arg'}}. "too many arguments" + {#=. {}}. "missing argument" + } do: [:args | + self + assert: (Context runSimulated: [nil tryPrimitive: 84 withArgs: args]) + equals: (nil tryPrimitive: 84 withArgs: args)].! Item was added: + ----- Method: ContextTest>>testRestart (in category 'tests') ----- + testRestart + self should: [self privRestartTest] notTakeMoreThan: 0.1 second! Item was added: + ----- Method: ContextTest>>testReturn (in category 'tests') ----- + testReturn + "Why am I overriding setUp? Because sender must be thisContext, i.e, testReturn, not setUp." + aContext := Context sender: thisContext receiver: aReceiver method: aCompiledMethod arguments: #(). + self assert: (aContext return: 5) = 5! Item was added: + ----- Method: ContextTest>>testSetUp (in category 'tests') ----- + testSetUp + "Note: In addition to verifying that the setUp worked the way it was expected to, testSetUp is used to illustrate the meaning of the simple access methods, methods that are not normally otherwise 'tested'" + self assert: aContext isContext. + self deny: aContext isExecutingBlock. + self deny: aContext isClosure. + self deny: aContext isDead. + "self assert: aMethodContext home = aReceiver." + "self assert: aMethodContext blockHome = aReceiver." + self assert: aContext receiver = aReceiver. + self assert: aContext method isCompiledMethod. + self assert: aContext method = aCompiledMethod. + self assert: aContext methodNode selector = #rightCenter. + self assert: (aContext methodNodeFormattedAndDecorated: true) selector = #rightCenter. + self assert: aContext client printString = 'ContextTest>>#testSetUp'. + ! Item was removed: - TestCase subclass: #MethodContextTest - instanceVariableNames: 'aCompiledMethod aReceiver aMethodContext aSender' - classVariableNames: '' - poolDictionaries: '' - category: 'KernelTests-Methods'! - - !MethodContextTest commentStamp: 'eem 3/30/2017 17:42' prior: 0! - I am an SUnit Test of Context. See also BlockClosureTest. - See pages 430-437 of A. Goldberg and D. Robson's Smalltalk-80 The Language (aka the purple book), which deal with Contexts. My fixtures are from their example. To see how blocks are implemented in this version of Squeak see http://www.mirandabanda.org/cogblog/2008/06/07/closures-part-i/ and http://www.mirandabanda.org/cogblog/2008/07/22/closures-part-ii-the-bytecodes/. (The Squeak V3 byte codes are not quite the same as Smalltalk-80, and the SistaV1 byetcodes are quite different.) - My fixtures are: - aReceiver - just some arbitrary object, "Rectangle origin: 100 at 100 corner: 200 at 200" - aSender - just some arbitrary object, thisContext - aCompiledMethod - just some arbitrary method, "Rectangle rightCenter". - aMethodContext - just some arbitray context ... - - ! Item was removed: - ----- Method: MethodContextTest>>privRestartTest (in category 'private') ----- - privRestartTest - "This tests may loop endlessly if incorrect, so call it from another method testing it does not time out" - |a firstTimeThrough | - firstTimeThrough := true. - a := 10. - - self assert: 30 equals: [|b| - self assert: 10 = a . - self assert: nil == b. - b := a + 20. - firstTimeThrough ifTrue: [ - firstTimeThrough := false. - thisContext restart.]. - b] value - ! Item was removed: - ----- Method: MethodContextTest>>setUp (in category 'running') ----- - setUp - super setUp. - aCompiledMethod := Rectangle methodDict at: #rightCenter. - aReceiver := 100 at 100 corner: 200 at 200. - aSender := thisContext. - aMethodContext := Context sender: aSender receiver: aReceiver method: aCompiledMethod arguments: #(). ! Item was removed: - ----- Method: MethodContextTest>>testActivateReturnValue (in category 'tests') ----- - testActivateReturnValue - self assert: (aSender activateReturn: aMethodContext value: #()) isContext. - self assert: ((aSender activateReturn: aMethodContext value: #()) receiver = aMethodContext).! Item was removed: - ----- Method: MethodContextTest>>testCopyStack (in category 'tests') ----- - testCopyStack - self assert: aMethodContext copyStack printString = aMethodContext printString.! Item was removed: - ----- Method: MethodContextTest>>testCopyTo (in category 'tests') ----- - testCopyTo - - | context depth targetSender | - context := thisContext. - depth := 1. - targetSender := context. - [ (targetSender := targetSender sender) isNil ] whileFalse: [ - | original copy | - original := context. - copy := context copyTo: targetSender. - 1 to: depth do: [ :index | - index = 1 ifFalse: [ - "Since we're copying thisContext, the pc and stackPtr may be different for the current frame." - self - assert: original pc equals: copy pc; - assert: original stackPtr equals: copy stackPtr ]. - self - deny: original == copy; - assert: original method equals: copy method; - assert: original closure equals: copy closure; - assert: original receiver equals: copy receiver. - original := original sender. - copy := copy sender ]. - self - assert: copy isNil; - assert: original == targetSender. - depth := depth + 1 ]! Item was removed: - ----- Method: MethodContextTest>>testFindContextSuchThat (in category 'tests') ----- - testFindContextSuchThat - self assert: (aMethodContext findContextSuchThat: [:each| true]) printString = aMethodContext printString. - self assert: (aMethodContext hasContext: aMethodContext). ! Item was removed: - ----- Method: MethodContextTest>>testMethodContext (in category 'tests') ----- - testMethodContext - self assert: aMethodContext home notNil. - self assert: aMethodContext receiver notNil. - self assert: aMethodContext method isCompiledMethod.! Item was removed: - ----- Method: MethodContextTest>>testMethodIsBottomContext (in category 'tests') ----- - testMethodIsBottomContext - self assert: aMethodContext bottomContext = aSender. - self assert: aMethodContext secondFromBottom = aMethodContext.! Item was removed: - ----- Method: MethodContextTest>>testRestart (in category 'tests') ----- - testRestart - self should: [self privRestartTest] notTakeMoreThan: 0.1 second! Item was removed: - ----- Method: MethodContextTest>>testReturn (in category 'tests') ----- - testReturn - "Why am I overriding setUp? Because sender must be thisContext, i.e, testReturn, not setUp." - aMethodContext := Context sender: thisContext receiver: aReceiver method: aCompiledMethod arguments: #(). - self assert: (aMethodContext return: 5) = 5! Item was removed: - ----- Method: MethodContextTest>>testSetUp (in category 'tests') ----- - testSetUp - "Note: In addition to verifying that the setUp worked the way it was expected to, testSetUp is used to illustrate the meaning of the simple access methods, methods that are not normally otherwise 'tested'" - self assert: aMethodContext isContext. - self deny: aMethodContext isExecutingBlock. - self deny: aMethodContext isClosure. - self deny: aMethodContext isDead. - "self assert: aMethodContext home = aReceiver." - "self assert: aMethodContext blockHome = aReceiver." - self assert: aMethodContext receiver = aReceiver. - self assert: aMethodContext method isCompiledMethod. - self assert: aMethodContext method = aCompiledMethod. - self assert: aMethodContext methodNode selector = #rightCenter. - self assert: (aMethodContext methodNodeFormattedAndDecorated: true) selector = #rightCenter. - self assert: aMethodContext client printString = 'MethodContextTest>>#testSetUp'. - ! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 12 19:29:36 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 19:29:36 0000 Subject: [squeak-dev] The Trunk: KernelTests-ct.377.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-ct.377.mcz ==================== Summary ==================== Name: KernelTests-ct.377 Author: ct Time: 19 February 2020, 12:18:45.853795 pm UUID: f0095798-52b3-bb4c-8b8b-5c6a1dbfe113 Ancestors: KernelTests-nice.373 Tests #readFrom: and #readCarefullyFrom: on Object. Regressions will be addressed in another commit. =============== Diff against KernelTests-nice.373 =============== Item was added: + ----- Method: ObjectTest>>testReadCarefullyFrom (in category 'tests') ----- + testReadCarefullyFrom + + self should: [Object readCarefullyFrom: nil] raise: Error. + self should: [Object readCarefullyFrom: Object new] raise: Error. + self assert: [(Object readCarefullyFrom: 'Object new') isKindOf: Object]. + self + should: [self + should: [Object newSubclass readCarefullyFrom: 'self assert: Object isNil'] + raise: AssertionFailure. "environment must be installed"] + raise: Error. "because we return nil" + self should: [(UndefinedObject readCarefullyFrom: 'Object new')] raise: Error. + self should: [Object readCarefullyFrom: 'Object new:'] raise: Error.! Item was added: + ----- Method: ObjectTest>>testReadFrom (in category 'tests') ----- + testReadFrom + + self should: [Object readFrom: nil] raise: Error. + self should: [Object readFrom: Object new] raise: Error. + self assert: [(Object readFrom: 'Object new') isKindOf: Object]. + self + should: [self + should: [Object newSubclass readFrom: 'self assert: Object isNil'] + raise: AssertionFailure. "environment must be installed"] + raise: Error. "because we return nil" + self should: [(UndefinedObject readFrom: 'Object new')] raise: Error. + self should: [Object readFrom: 'Object new:'] raise: SyntaxErrorNotification.! From christoph.thiede at student.hpi.uni-potsdam.de Mon Apr 12 19:32:23 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Mon, 12 Apr 2021 14:32:23 -0500 (CDT) Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: References: Message-ID: <1618255943259-0.post@n4.nabble.com> Hi Eliot, I fear that changes like this will not be very durable unless tested in any way. At the moment, you won't even notice a new shadow unless you have opened a Transcript by accident when accepting a method. Should we maybe show a message window for shadows instead when compiled interactively, analogously to the warnings about superfluous temps? (In a larger context, I would strongly opt for (finally) introducing a mechanism for linter/compiler annotations in CodeHolders. Most modern editors and IDEs have it, even Pharo; if Squeak does not want to get left behind, we should support something like this, too. It could or should be configurable, of course.) LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal name for a variable that holds Morph instances, right? :) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 12 19:35:47 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 12 Apr 2021 19:35:47 +0000 Subject: [squeak-dev] Mail daemon problems with Unicode? Message-ID: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> Hi all, do the mail daemons that are responsible for informing the list about new inbox/trunk versions (probably a part of SqueakSource) have a problem with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but as far as I can see, a notification email did not arrive. However, older and newer versions were announced as usual. Here is the header of the relevant version: --- Name: Tests-ct.449 Author: ct Time: 12 April 2021, 9:20:22.70324 pm UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 Ancestors: Tests-nice.447 Removes #testHandlerFromAction from expectedFailures because it now finally works 🎉 --- Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From m at jaromir.net Mon Apr 12 19:47:07 2021 From: m at jaromir.net (Jaromir Matas) Date: Mon, 12 Apr 2021 14:47:07 -0500 (CDT) Subject: [squeak-dev] #testProcessStateTests leaves unterminated processes behind Message-ID: <1618256827703-0.post@n4.nabble.com> ProcessTest>>#testProcessStateTests doesn't terminate processes it opened and leaves lots of runnable and blocked processes behind (almost gave me a heart attack when tested my #terminate fix). Are they supposed to get GC'd somehow? I sent a simple cleanup suggestion to the Inbox. http://forum.world.st/The-Inbox-KernelTests-jar-397-mcz-td5128422.html + "Clean up: release all processes still waiting at the semaphore or in the active priority queue." + Processor yield. + [semaphore isEmpty] whileFalse: [semaphore signal] ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 12 19:52:22 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 12 Apr 2021 19:52:22 +0000 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: Hi Nicolas, I could not reproduce the problem in a fresh trunk image after 12 attempts. How often do you need to recompile the image in order to experience the error, by average? Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Montag, 12. April 2021 19:28:35 An: The general-purpose Squeak developers list Betreff: [squeak-dev] Error selector changed Hi all, >From time to time, (Compiler recompileAll) fails because some selector identity changed... Indeed, following snippet should always be true, but is sometimes false: selector == (Symbol findInterned: selector asString). In such case, I can attempt a doIt and continue: selector beWritableObject; becomeForward: (Symbol findInterned: selector asString). oldClass methodDictionary rehash Sometimes I'm tempted to integrate the workaround directly in code, but it would just mask a problem. Any clue on how this can happen? Nicolas -------------- next part -------------- An HTML attachment was scrubbed... URL: From gkgoat6700 at gmail.com Mon Apr 12 19:54:55 2021 From: gkgoat6700 at gmail.com (Graham Kelly) Date: Mon, 12 Apr 2021 15:54:55 -0400 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: <4b3e5b32-6131-5739-2675-222d3143fccb@gmail.com> Hmm... something similar but worse happens in Cuis. Graham On 4/12/21 1:28 PM, Nicolas Cellier wrote: > Hi all, > From time to time, (Compiler recompileAll) fails because some selector > identity changed... > > Indeed, following snippet should always be true, but is sometimes false: > > selector == (Symbol findInterned: selector asString). > > In such case, I can attempt a doIt and continue: > > selector beWritableObject; becomeForward: (Symbol findInterned: > selector asString). > oldClass methodDictionary rehash > > Sometimes I'm tempted to integrate the workaround directly in code, > but it would just mask a problem. Any clue on how this can happen? > > Nicolas > From Das.Linux at gmx.de Mon Apr 12 20:08:10 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 12 Apr 2021 22:08:10 +0200 Subject: [squeak-dev] Mail daemon problems with Unicode? In-Reply-To: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> References: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> Message-ID: Not the mailer, but the squeaksource image for sure. Hope you did not disturb it ;) -t > On 12. Apr 2021, at 21:35, Thiede, Christoph wrote: > > Hi all, > > do the mail daemons that are responsible for informing the list about new inbox/trunk versions (probably a part of SqueakSource) have a problem with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but as far as I can see, a notification email did not arrive. However, older and newer versions were announced as usual. > > Here is the header of the relevant version: > > --- > Name: Tests-ct.449 > Author: ct > Time: 12 April 2021, 9:20:22.70324 pm > UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 > Ancestors: Tests-nice.447 > > Removes #testHandlerFromAction from expectedFailures because it now finally works 🎉 > --- > > Best, > Christoph From commits at source.squeak.org Mon Apr 12 20:11:43 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:11:43 0000 Subject: [squeak-dev] The Inbox: Collections-ct.934.mcz Message-ID: A new version of Collections was added to project The Inbox: http://source.squeak.org/inbox/Collections-ct.934.mcz ==================== Summary ==================== Name: Collections-ct.934 Author: ct Time: 12 April 2021, 10:11:41.51069 pm UUID: 84f5a3d9-3316-fd46-b89b-2fb0d2b625ef Ancestors: Collections-nice.933 Improves multilingual support for errors in collections. =============== Diff against Collections-nice.933 =============== Item was changed: ----- Method: Collection>>errorDifferentSize (in category 'private') ----- errorDifferentSize + ^ self error: 'Other collection must be the same size' translated! - self error: 'otherCollection must be the same size'! Item was changed: ----- Method: Collection>>errorEmptyCollection (in category 'private') ----- errorEmptyCollection + ^ self error: 'This collection is empty' translated! - self error: 'this collection is empty'! Item was changed: ----- Method: Collection>>errorNoMatch (in category 'private') ----- errorNoMatch + ^ self error: 'Collection sizes do not match' translated! - self error: 'collection sizes do not match'! Item was added: + ----- Method: Collection>>name (in category 'printing') ----- + name + + ^ String streamContents: [:stream | + self printNameOn: stream]! Item was changed: ----- Method: Dictionary>>errorValueNotFound (in category 'private') ----- errorValueNotFound + ^ self error: 'Value not found' translated! - self error: 'value not found'! Item was changed: ----- Method: HashedCollection>>errorNoFreeSpace (in category 'private') ----- errorNoFreeSpace + ^ self error: 'There is no free space in this collection!!' translated! - self error: 'There is no free space in this collection!!'! Item was changed: ----- Method: KeyNotFound>>messageText (in category 'accessing') ----- messageText + + ^ messageText ifNil: ['Key not found: {1}' translated format: {self key}]! - "Return a textual description of the exception." - ^messageText ifNil:['Key not found: ', key]! Item was changed: ----- Method: NotFound>>messageText (in category 'accessing') ----- messageText + + ^ messageText ifNil: ['Object is not in the collection.' translated]! - "Return a textual description of the exception." - ^messageText ifNil:['Object is not in the collection.']! Item was changed: ----- Method: OrderedCollection>>errorNoSuchElement (in category 'private') ----- errorNoSuchElement + ^ self error: ('Attempt to index a non-existent element in {1}' translated format: {self name})! - self error: (String streamContents: [ :stream | - stream nextPutAll: 'attempt to index a non-existent element in '. - self printNameOn: stream ])! Item was changed: ----- Method: OrderedCollection>>errorNotEnoughElements (in category 'private') ----- errorNotEnoughElements + ^ self error: ('Attempt to remove more elements than possible from {1}' translated format: {self name})! - self error: (String streamContents: [ :stream | - stream nextPutAll: 'attempt to remove more elements than possible from '. - self printNameOn: stream ])! Item was changed: ----- Method: SequenceableCollection>>errorFirstObject: (in category 'private') ----- errorFirstObject: anObject + + ^ self error: 'Specified object is first object' translated! - self error: 'specified object is first object'! Item was changed: ----- Method: SequenceableCollection>>errorLastObject: (in category 'private') ----- errorLastObject: anObject + + ^ self error: 'Specified object is last object' translated! - self error: 'specified object is last object'! Item was changed: ----- Method: SequenceableCollection>>errorOutOfBounds (in category 'private') ----- errorOutOfBounds + ^ self error: 'Indices are out of bounds' translated! - self error: 'indices are out of bounds'! From commits at source.squeak.org Mon Apr 12 20:12:34 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:12:34 0000 Subject: [squeak-dev] The Trunk: KernelTests-jar.397.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-jar.397.mcz ==================== Summary ==================== Name: KernelTests-jar.397 Author: jar Time: 12 April 2021, 9:43:54.742464 am UUID: 6cf87c25-8484-a144-aa35-761de4aa60c1 Ancestors: KernelTests-codefrau.395 Clean up: release all processes still waiting at the semaphore or in the active priority queue. ProcessTest>>#testProcessStateTests doesn't terminate processes it opened. =============== Diff against KernelTests-codefrau.395 =============== Item was changed: ----- Method: ProcessTest>>testProcessStateTests (in category 'tests') ----- testProcessStateTests | semaphore | self assert: Processor activeProcess isActiveProcess. self deny: Processor activeProcess isBlocked. self assert: Processor activeProcess isRunnable. self deny: Processor activeProcess isSuspended. self deny: Processor activeProcess isTerminated. semaphore := Semaphore new. "These processes are runnable but haven't got to the wait yet because the active process is running." self deny: ([semaphore wait] forkAt: Processor activePriority) isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) isBlocked. self assert: ([semaphore wait] forkAt: Processor activePriority) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority) isTerminated. self deny: ([semaphore wait] forkAt: Processor activePriority) suspendingList == semaphore. + "These processes do get to run because, being higher priority they preempt the active process until they wait on the semaphore." - "These processes do get to run because, being higher priority they preempt the active process until yhey wait on the semaphore." self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isActiveProcess. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isTerminated. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) suspendingList == semaphore. "These processes should be suspended, not terminated." self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isRunnable. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isSuspended. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be terminated, not suspended." self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isRunnable. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isSuspended. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be suspended." self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isActiveProcess. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isBlocked. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isRunnable. self assert: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isSuspended. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isTerminated. "These processes should be terminated." self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isSuspended. + self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated. + + "Clean up: release all processes still waiting at the semaphore or in the active priority queue." + Processor yield. + [semaphore isEmpty] whileFalse: [semaphore signal] + ! - self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated! From commits at source.squeak.org Mon Apr 12 20:12:45 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:12:45 0000 Subject: [squeak-dev] The Trunk: KernelTests-jar.395.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-jar.395.mcz ==================== Summary ==================== Name: KernelTests-jar.395 Author: jar Time: 31 March 2021, 11:14:30.909212 pm UUID: b63793d5-9635-c942-a9c5-132e788a8eda Ancestors: KernelTests-mt.394 complementing Kernel-jar.1384 (The Inbox) =============== Diff against KernelTests-mt.394 =============== Item was added: + ----- Method: ProcessTest>>testNestedUnwind (in category 'tests') ----- + testNestedUnwind + "Test all nested unwind blocks are correctly unwound; all unwind blocks halfway through their execution should be completed or at least attempted to complete, not only the innermost one" + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ "halfway through completion when suspended" + [ ] ensure: [ "halfway through completion when suspended" + Processor activeProcess suspend. + x1 := true]. + x2 := true] + ] ensure: [ "not started yet when suspended" + x3 := true] + ] fork. + Processor yield. + p terminate. + + self assert: x1 & x2 & x3! From commits at source.squeak.org Mon Apr 12 20:15:10 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:15:10 0000 Subject: [squeak-dev] The Inbox: Kernel-ct.1385.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-ct.1385.mcz ==================== Summary ==================== Name: Kernel-ct.1385 Author: ct Time: 12 April 2021, 10:15:07.18369 pm UUID: e2817a6e-1a1f-e246-aa66-2fa9289a7703 Ancestors: Kernel-nice.1384 Improves multilingual support for basic errors on Object. =============== Diff against Kernel-nice.1384 =============== Item was changed: ----- Method: Object>>error (in category 'error handling') ----- error "Throw a generic Error exception." + ^ self error: 'Error!!' translated! - ^self error: 'Error!!'.! Item was changed: ----- Method: Object>>errorImproperStore (in category 'private') ----- errorImproperStore "Create an error notification that an improper store was attempted." + ^ self error: 'Improper store into indexable object' translated! - self error: 'Improper store into indexable object'! Item was changed: ----- Method: Object>>errorNonIntegerIndex (in category 'private') ----- errorNonIntegerIndex "Create an error notification that an improper object was used as an index." + ^ self error: 'Only integers should be used as indices' translated! - self error: 'only integers should be used as indices'! Item was changed: ----- Method: Object>>errorSubscriptBounds: (in category 'private') ----- errorSubscriptBounds: index "Create an error notification that an improper integer was used as an index." + ^ self error: ('Subscript is out of bounds: {1}' translated format: {index})! - self error: 'subscript is out of bounds: ' , index printString! From commits at source.squeak.org Mon Apr 12 20:18:28 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:18:28 0000 Subject: [squeak-dev] The Inbox: Monticello-ct.740.mcz Message-ID: A new version of Monticello was added to project The Inbox: http://source.squeak.org/inbox/Monticello-ct.740.mcz ==================== Summary ==================== Name: Monticello-ct.740 Author: ct Time: 12 April 2021, 10:18:26.02269 pm UUID: c0c2562b-e801-ef4c-8628-3d352c513e0a Ancestors: Monticello-mt.736 Introduces MCPackageNotFound exception and usees it in MCRepository versions lookup. I would like to catch this error in [1, 2, 3]. [1] https://github.com/LinqLover/TelegramSmalltalkBot/blob/03be8437dfd9b9e98715d4fcc42fcea13cc90ae4/src/BaselineOfTelegramSmalltalkBot.package/BaselineOfTelegramSmalltalkBot.class/instance/depMergeVersion..st [2] https://github.com/LinqLover/TelegramBot/blob/e2d248eff9e24ca9a0423585b18d04c1191a725b/src/BaselineOfTelegramBot.package/BaselineOfTelegramBot.class/instance/depInbox..st [3] https://github.com/LinqLover/SimulationStudio/blob/743d48fdc10a70d572b1070b23c826f43c0dfb23/packages/BaselineOfSimulationStudio.package/BaselineOfSimulationStudio.class/instance/depInbox..st =============== Diff against Monticello-mt.736 =============== Item was added: + Error subclass: #MCPackageNotFound + instanceVariableNames: 'repository packageName' + classVariableNames: '' + poolDictionaries: '' + category: 'Monticello-Repositories'! Item was added: + ----- Method: MCPackageNotFound class>>signalForRepository:packageName: (in category 'signaling') ----- + signalForRepository: aRepository packageName: aString + + ^ self new + repository: aRepository packageName: aString; + signal! Item was added: + ----- Method: MCPackageNotFound>>messageText (in category 'printing') ----- + messageText + + ^ messageText ifNil: ['{1} not found in {2}' translated format: {self packageName. self repository}]! Item was added: + ----- Method: MCPackageNotFound>>packageName (in category 'accessing') ----- + packageName + + ^ packageName! Item was added: + ----- Method: MCPackageNotFound>>repository (in category 'accessing') ----- + repository + + ^ repository! Item was added: + ----- Method: MCPackageNotFound>>repository:packageName: (in category 'accessing') ----- + repository: aRepository packageName: aString + + repository := aRepository. + packageName := aString.! Item was changed: ----- Method: MCRepository>>highestNumberedVersionNameForPackageNamed: (in category 'versions') ----- highestNumberedVersionNameForPackageNamed: aString ^ (self versionNamesForPackageNamed: aString) + ifEmpty: [MCPackageNotFound signalForRepository: self packageName: aString] - ifEmpty: [ self error: aString , ' not found in ' , self asString ] ifNotEmptyDo: [ : versionNames | versionNames detectMax: [ : each | each versionNumber ] ]! From commits at source.squeak.org Mon Apr 12 20:18:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:18:40 0000 Subject: [squeak-dev] The Trunk: KernelTests-nice.398.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.398.mcz ==================== Summary ==================== Name: KernelTests-nice.398 Author: nice Time: 12 April 2021, 10:18:38.252683 pm UUID: ac7054ff-ef3d-4941-b690-66706b8a028c Ancestors: KernelTests-eem.396, KernelTests-ct.377, KernelTests-jar.397, KernelTests-jar.395 A merge commit: KernelTests-eem.396: Rename MethodContextTest to ContextTest KernelTests-ct.377: Tests #readFrom: and #readCarefullyFrom: on Object. KernelTests-jar.397: Clean up: release all processes still waiting at the semaphore or in the active priority queue. ProcessTest>>#testProcessStateTests doesn't terminate processes it opened. KernelTests-jar.395: Tests unwinding of nested ensure =============== Diff against KernelTests-eem.396 =============== Item was added: + ----- Method: ObjectTest>>testReadCarefullyFrom (in category 'tests') ----- + testReadCarefullyFrom + + self should: [Object readCarefullyFrom: nil] raise: Error. + self should: [Object readCarefullyFrom: Object new] raise: Error. + self assert: [(Object readCarefullyFrom: 'Object new') isKindOf: Object]. + self + should: [self + should: [Object newSubclass readCarefullyFrom: 'self assert: Object isNil'] + raise: AssertionFailure. "environment must be installed"] + raise: Error. "because we return nil" + self should: [(UndefinedObject readCarefullyFrom: 'Object new')] raise: Error. + self should: [Object readCarefullyFrom: 'Object new:'] raise: Error.! Item was added: + ----- Method: ObjectTest>>testReadFrom (in category 'tests') ----- + testReadFrom + + self should: [Object readFrom: nil] raise: Error. + self should: [Object readFrom: Object new] raise: Error. + self assert: [(Object readFrom: 'Object new') isKindOf: Object]. + self + should: [self + should: [Object newSubclass readFrom: 'self assert: Object isNil'] + raise: AssertionFailure. "environment must be installed"] + raise: Error. "because we return nil" + self should: [(UndefinedObject readFrom: 'Object new')] raise: Error. + self should: [Object readFrom: 'Object new:'] raise: SyntaxErrorNotification.! Item was added: + ----- Method: ProcessTest>>testNestedUnwind (in category 'tests') ----- + testNestedUnwind + "Test all nested unwind blocks are correctly unwound; all unwind blocks halfway through their execution should be completed or at least attempted to complete, not only the innermost one" + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ "halfway through completion when suspended" + [ ] ensure: [ "halfway through completion when suspended" + Processor activeProcess suspend. + x1 := true]. + x2 := true] + ] ensure: [ "not started yet when suspended" + x3 := true] + ] fork. + Processor yield. + p terminate. + + self assert: x1 & x2 & x3! Item was changed: ----- Method: ProcessTest>>testProcessStateTests (in category 'tests') ----- testProcessStateTests | semaphore | self assert: Processor activeProcess isActiveProcess. self deny: Processor activeProcess isBlocked. self assert: Processor activeProcess isRunnable. self deny: Processor activeProcess isSuspended. self deny: Processor activeProcess isTerminated. semaphore := Semaphore new. "These processes are runnable but haven't got to the wait yet because the active process is running." self deny: ([semaphore wait] forkAt: Processor activePriority) isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) isBlocked. self assert: ([semaphore wait] forkAt: Processor activePriority) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority) isTerminated. self deny: ([semaphore wait] forkAt: Processor activePriority) suspendingList == semaphore. + "These processes do get to run because, being higher priority they preempt the active process until they wait on the semaphore." - "These processes do get to run because, being higher priority they preempt the active process until yhey wait on the semaphore." self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isActiveProcess. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isTerminated. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) suspendingList == semaphore. "These processes should be suspended, not terminated." self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isRunnable. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isSuspended. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be terminated, not suspended." self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isRunnable. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isSuspended. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be suspended." self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isActiveProcess. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isBlocked. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isRunnable. self assert: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isSuspended. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isTerminated. "These processes should be terminated." self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isSuspended. + self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated. + + "Clean up: release all processes still waiting at the semaphore or in the active priority queue." + Processor yield. + [semaphore isEmpty] whileFalse: [semaphore signal] + ! - self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated! From commits at source.squeak.org Mon Apr 12 20:34:17 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:34:17 0000 Subject: [squeak-dev] The Trunk: KernelTests-nice.399.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.399.mcz ==================== Summary ==================== Name: KernelTests-nice.399 Author: nice Time: 12 April 2021, 10:34:15.635162 pm UUID: 9d4c795e-d8db-465d-b5f9-f07e88072ee3 Ancestors: KernelTests-nice.398 Generalize the clean-up made in KernelTests-jar.397, and move it to tearDown. This way, clean-up should also happen in case of failure. =============== Diff against KernelTests-nice.398 =============== Item was changed: ClassTestCase subclass: #ProcessTest + instanceVariableNames: 'semaphore' - instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'KernelTests-Processes'! !ProcessTest commentStamp: 'ul 8/16/2011 11:35' prior: 0! I hold test cases for generic Process-related behaviour.! Item was added: + ----- Method: ProcessTest>>setUp (in category 'running') ----- + setUp + semaphore := Semaphore new! Item was changed: ----- Method: ProcessTest>>tearDown (in category 'running') ----- tearDown + Processor activeProcess environmentRemoveKey: #processTests ifAbsent: []. + + "Release all processes still waiting at the semaphore or in the active priority queue." + Processor yield. + [semaphore isEmpty] whileFalse: [semaphore signal]! - Processor activeProcess environmentRemoveKey: #processTests ifAbsent: []! Item was changed: ----- Method: ProcessTest>>testAtomicSuspend (in category 'tests') ----- testAtomicSuspend "Test atomic suspend of foreign processes" + | list p | + p := [semaphore wait] fork. - | list p sema | - sema := Semaphore new. - p := [sema wait] fork. Processor yield. list := p suspendPrimitivelyOrFail. + self assert: list == semaphore. - self assert: list == sema. ! Item was changed: ----- Method: ProcessTest>>testProcessStateTests (in category 'tests') ----- testProcessStateTests - | semaphore | self assert: Processor activeProcess isActiveProcess. self deny: Processor activeProcess isBlocked. self assert: Processor activeProcess isRunnable. self deny: Processor activeProcess isSuspended. self deny: Processor activeProcess isTerminated. - semaphore := Semaphore new. - "These processes are runnable but haven't got to the wait yet because the active process is running." self deny: ([semaphore wait] forkAt: Processor activePriority) isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) isBlocked. self assert: ([semaphore wait] forkAt: Processor activePriority) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority) isTerminated. self deny: ([semaphore wait] forkAt: Processor activePriority) suspendingList == semaphore. "These processes do get to run because, being higher priority they preempt the active process until they wait on the semaphore." self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isActiveProcess. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isSuspended. self deny: ([semaphore wait] forkAt: Processor activePriority + 1) isTerminated. self assert: ([semaphore wait] forkAt: Processor activePriority + 1) suspendingList == semaphore. "These processes should be suspended, not terminated." self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isRunnable. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isSuspended. self deny: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess suspend] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be terminated, not suspended." self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isActiveProcess. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isBlocked. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isRunnable. self deny: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isSuspended. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) isTerminated. self assert: ([Processor activeProcess terminate] forkAt: Processor activePriority + 1) suspendingList isNil. "These processes should be suspended." self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isActiveProcess. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isBlocked. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isRunnable. self assert: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isSuspended. self deny: (([semaphore wait] forkAt: Processor activePriority) suspend; yourself) isTerminated. "These processes should be terminated." self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isActiveProcess. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isBlocked. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isRunnable. self deny: ([semaphore wait] forkAt: Processor activePriority) terminate isSuspended. + self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated.! - self assert: ([semaphore wait] forkAt: Processor activePriority) terminate isTerminated. - - "Clean up: release all processes still waiting at the semaphore or in the active priority queue." - Processor yield. - [semaphore isEmpty] whileFalse: [semaphore signal] - ! From nicolas.cellier.aka.nice at gmail.com Mon Apr 12 20:50:30 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 12 Apr 2021 22:50:30 +0200 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: Le lun. 12 avr. 2021 à 21:52, Thiede, Christoph a écrit : > > > Hi Nicolas, > > > I could not reproduce the problem in a fresh trunk image after 12 attempts. How often do you need to recompile the image in order to experience the error, by average? > I do not recompileAll often, and I don't think that recompiling is the action that is causing the Error, it rather reveals the Error. The root cause is mysterious, and very hard to track since the consequences get unnoticed... For those wondering, the problem is that some Symbol get duplicated violating the contract: any two Symbols are either identical (==) or different (~=). > > Best, > > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Nicolas Cellier > Gesendet: Montag, 12. April 2021 19:28:35 > An: The general-purpose Squeak developers list > Betreff: [squeak-dev] Error selector changed > > Hi all, > From time to time, (Compiler recompileAll) fails because some selector > identity changed... > > Indeed, following snippet should always be true, but is sometimes false: > > selector == (Symbol findInterned: selector asString). > > In such case, I can attempt a doIt and continue: > > selector beWritableObject; becomeForward: (Symbol findInterned: > selector asString). > oldClass methodDictionary rehash > > Sometimes I'm tempted to integrate the workaround directly in code, > but it would just mask a problem. Any clue on how this can happen? > > Nicolas > > From commits at source.squeak.org Mon Apr 12 20:53:53 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 20:53:53 0000 Subject: [squeak-dev] The Inbox: Kernel-jar.1386.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-jar.1386.mcz ==================== Summary ==================== Name: Kernel-jar.1386 Author: jar Time: 12 April 2021, 10:53:49.66946 pm UUID: 26cd98dc-59f6-0043-aa73-732e8144cf25 Ancestors: Kernel-nice.1384 Superseds Kernel-jar.1385 adding a little tweak and a comment; otherwise identical (Fix a list of termination bugs described in http://forum.world.st/Solving-multiple-termination-bugs-summary-amp-proposal-td5128285.html) =============== Diff against Kernel-nice.1384 =============== Item was changed: ----- Method: Process>>isSuspended (in category 'testing') ----- isSuspended + "A process is suspended if it is not active, not terminated and + not waiting in a scheduler or a semaphore queue." + + self isActiveProcess ifTrue: [^ false]. + ^myList isNil and: [self isTerminated not]! - "A process is suspended if it has been suspended with the suspend primitive. - It is distinguishable from the active process and a terminated process by - having a non-nil suspendedContext that is either not the bottom context - or has not reached its endPC." - ^nil == myList - and: [nil ~~ suspendedContext - and: [suspendedContext isBottomContext - ifTrue: [suspendedContext closure - ifNil: [suspendedContext methodClass ~~ Process - or: [suspendedContext selector ~~ #terminate]] - ifNotNil: [suspendedContext pc < suspendedContext closure endPC]] - ifFalse: [true]]]! Item was changed: ----- Method: Process>>isTerminated (in category 'testing') ----- isTerminated + "Answer if the receiver is terminated. A process is considered terminated + if the suspendedContext is the bottomContext and the pc is at the endPC" + - "Answer if the receiver is terminated, or at least terminating." self isActiveProcess ifTrue: [^ false]. + ^suspendedContext isNil or: [ + suspendedContext isBottomContext and: [ + suspendedContext isDead or: [suspendedContext atEnd]]]! - ^suspendedContext isNil - or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess. - If so, and the pc is at the endPC, the block has already sent and returned - from value and there is nothing more to do." - suspendedContext isBottomContext - and: [suspendedContext closure - ifNil: [suspendedContext methodClass == Process - and: [suspendedContext selector == #terminate]] - ifNotNil: [suspendedContext pc >= suspendedContext closure endPC]]]! Item was changed: ----- Method: Process>>terminate (in category 'changing process state') ----- terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating. If the process is in the middle of a critical: critical section, release it properly." + | ctxt unwindBlock oldList outerMost | + self isActiveProcess ifTrue: [ + "If terminating the active process, suspend it first and terminate it as a suspended process." + [self terminate] fork. + ^self suspend]. - | ctxt unwindBlock oldList | - self isActiveProcess ifTrue: - [ctxt := thisContext. - [ctxt := ctxt findNextUnwindContextUpTo: nil. - ctxt ~~ nil] whileTrue: - [(ctxt tempAt: 2) ifNil: - ["N.B. Unlike Context>>unwindTo: we do not set complete (tempAt: 2) to true." - unwindBlock := ctxt tempAt: 1. - thisContext terminateTo: ctxt. - unwindBlock value]]. - thisContext terminateTo: nil. - self suspend. - "If the process is resumed this will provoke a cannotReturn: error. - Would self debug: thisContext title: 'Resuming a terminated process' be better?" - ^self]. "Always suspend the process first so it doesn't accidentally get woken up. N.B. If oldList is a LinkedList then the process is runnable. If it is a Semaphore/Mutex et al then the process is blocked, and if it is nil then the process is already suspended." oldList := self suspend. suspendedContext ifNotNil: ["Release any method marked with the pragma. The argument is whether the process is runnable." self releaseCriticalSection: (oldList isNil or: [oldList class == LinkedList]). + "If terminating a process halfways through an unwind, try to complete that unwind block first; + if there are multiple such nested unwind blocks, try to complete the outer-most one; the inner + blocks will be completed in the process." + ctxt := suspendedContext. + [(ctxt := ctxt findNextUnwindContextUpTo: nil) isNil] whileFalse: + "Contexts under evaluation have already set their complete (tempAt: 2) to true." + [(ctxt tempAt:2) ifNotNil: [outerMost := ctxt]]. + outerMost ifNotNil: [ + "This is the outer-most unwind context currently under evaluation; + let's find an inner context executing outerMost's argument block (tempAt: 1)" + (suspendedContext findContextSuchThat: [:ctx | + ctx closure == (outerMost tempAt: 1)]) ifNotNil: [:inner | + "Let's finish the unfinished unwind context only (i.e. up to inner) and return here" + suspendedContext runUntilErrorOrReturnFrom: inner. + "Update the receiver's suspendedContext (the previous step reset its sender to nil); + return, if the execution stack reached its bottom (e.g. in case of non-local returns)." + (suspendedContext := outerMost sender) ifNil: [^self]]]. - "If terminating a process halfways through an unwind, try to complete that unwind block first." - (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: - [:outer| - (suspendedContext findContextSuchThat:[:c| c closure == (outer tempAt: 1)]) ifNotNil: - [:inner| "This is an unwind block currently under evaluation" - suspendedContext runUntilErrorOrReturnFrom: inner]]. + "Now all unwind blocks caught halfway through have been completed; + let's execute the ones still pending. Note: #findNextUnwindContextUpTo: starts + searching from the receiver's sender but the receiver itself may be an unwind context." + ctxt := suspendedContext. + ctxt isUnwindContext ifFalse: [ctxt := ctxt findNextUnwindContextUpTo: nil]. + [ctxt isNil] whileFalse: [ + (ctxt tempAt: 2) ifNil: [ + ctxt tempAt: 2 put: true. + unwindBlock := ctxt tempAt: 1. + "Create a context for the unwind block and execute it on the unwind block's stack. + Note: using #value instead of #runUntilErrorOrReturnFrom: would lead to executing + the unwind on the wrong stack preventing the correct execution of non-local returns." + suspendedContext := unwindBlock asContextWithSender: ctxt. + suspendedContext runUntilErrorOrReturnFrom: suspendedContext]. + ctxt := ctxt findNextUnwindContextUpTo: nil]. + + "Reset the context's pc and sender to nil for the benefit of isTerminated." + suspendedContext terminate]! - ctxt := self popTo: suspendedContext bottomContext. - ctxt == suspendedContext bottomContext ifFalse: - [self debugWithTitle: 'Unwind error during termination' translated full: false]. - "Set the context to its endPC for the benefit of isTerminated." - ctxt pc: ctxt endPC]! From lewis at mail.msen.com Mon Apr 12 20:56:10 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Mon, 12 Apr 2021 16:56:10 -0400 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> Message-ID: <20210412205610.GA33248@shell.msen.com> On Mon, Apr 12, 2021 at 08:43:45AM +0200, Marcel Taeumel wrote: > > > Am 12.04.2021 um 04:11 schrieb David T. Lewis : > > > > > > On Sun, Apr 11, 2021 at 05:01:31PM +0200, Nicolas Cellier wrote: > >> Hi all, > >> it seems we have enough +1, let's just do it. > >> > > > > Done. > > Hi Dave. > > Thanks. Maybe also add a pointer to the discussion on this list. > Hi Marcel, Yes, I should have added a link to the discussion. I could save a fixed System-dtl.1225 to trunk, although I am afraid it may cause problems for the update stream for people who have already loaded that version number with a different UUID in their trunk update. If someone can confirm that it is safe to replace the existing System-dtl.1225 with another one that differs only by commit comment and UUID, then I'll copy it up to trunk. Otherwise I think I'll play it safe and leave it alone. Thanks, Dave From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 12 21:11:54 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 12 Apr 2021 21:11:54 +0000 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <20210412205610.GA33248@shell.msen.com> References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> , <20210412205610.GA33248@shell.msen.com> Message-ID: <066c91fcefb8490da1676b6d275f055d@student.hpi.uni-potsdam.de> Maybe just create a new version and add the pointer directly into the comment of #asMutator? This will be even more helpful for people who wonder "Should I use #asMutator or #asSimpleSetter"? I also wonder whether #asMutator deserves a #deprecate flag at least. Otherwise, we will have the situation of two ambiguous selectors without any recommendation, again. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von David T. Lewis Gesendet: Montag, 12. April 2021 22:56:10 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) On Mon, Apr 12, 2021 at 08:43:45AM +0200, Marcel Taeumel wrote: > > > Am 12.04.2021 um 04:11 schrieb David T. Lewis : > > > > > > On Sun, Apr 11, 2021 at 05:01:31PM +0200, Nicolas Cellier wrote: > >> Hi all, > >> it seems we have enough +1, let's just do it. > >> > > > > Done. > > Hi Dave. > > Thanks. Maybe also add a pointer to the discussion on this list. > Hi Marcel, Yes, I should have added a link to the discussion. I could save a fixed System-dtl.1225 to trunk, although I am afraid it may cause problems for the update stream for people who have already loaded that version number with a different UUID in their trunk update. If someone can confirm that it is safe to replace the existing System-dtl.1225 with another one that differs only by commit comment and UUID, then I'll copy it up to trunk. Otherwise I think I'll play it safe and leave it alone. Thanks, Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 12 21:13:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 21:13:15 0000 Subject: [squeak-dev] The Inbox: Tests-jar.448.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-jar.448.mcz ==================== Summary ==================== Name: Tests-jar.448 Author: jar Time: 12 April 2021, 11:13:13.58946 pm UUID: 99c6f69a-288c-0648-80af-3b7aa014e9ba Ancestors: Tests-nice.447 Complement Kernel-jar.1386 (Fix a list of termination bugs described in http://forum.world.st/Solving-multiple-termination-bugs-summary-amp-proposal-td5128285.html) These basic tests illustrate the unwind semantics during termination implemented by the new #teminate.. Current implementation of #teminate will fail with these tests - they should accompany Kernel-jar.1386 (if accepted). Thanks =============== Diff against Tests-nice.447 =============== Item was changed: SystemOrganization addCategory: #'Tests-Bugs'! SystemOrganization addCategory: #'Tests-Compiler'! SystemOrganization addCategory: #'Tests-Dependencies'! SystemOrganization addCategory: #'Tests-Digital Signatures'! SystemOrganization addCategory: #'Tests-Environments'! SystemOrganization addCategory: #'Tests-Exceptions'! SystemOrganization addCategory: #'Tests-FilePackage'! SystemOrganization addCategory: #'Tests-Files'! SystemOrganization addCategory: #'Tests-Finalization'! SystemOrganization addCategory: #'Tests-Hex'! SystemOrganization addCategory: #'Tests-Installer-Core'! SystemOrganization addCategory: #'Tests-Localization'! SystemOrganization addCategory: #'Tests-Monticello'! SystemOrganization addCategory: #'Tests-Monticello-Mocks'! SystemOrganization addCategory: #'Tests-Monticello-Utils'! SystemOrganization addCategory: #'Tests-Object Events'! SystemOrganization addCategory: #'Tests-ObjectsAsMethods'! SystemOrganization addCategory: #'Tests-PrimCallController'! SystemOrganization addCategory: #'Tests-Release'! SystemOrganization addCategory: #'Tests-System-Applications'! SystemOrganization addCategory: #'Tests-System-Digital Signatures'! SystemOrganization addCategory: #'Tests-System-Object Storage'! SystemOrganization addCategory: #'Tests-System-Preferences'! SystemOrganization addCategory: #'Tests-System-Support'! SystemOrganization addCategory: #'Tests-Utilities'! SystemOrganization addCategory: #'Tests-VM'! - SystemOrganization addCategory: #'Tests-MonticelloMocks'! SystemOrganization addCategory: #'Tests-Sound'! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind1 (in category 'tests') ----- + testTerminationDuringNestedUnwind1 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ + [Processor activeProcess suspend] ensure: [ + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p is suspended and none of the unwind blocks has finished yet" + self assert: p isSuspended. + self deny: x1 | x2 | x3. + "now terminate the process and make sure all unwind blocks have finished" + p terminate. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind2 (in category 'tests') ----- + testTerminationDuringNestedUnwind2 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ + [ ] ensure: [ + Processor activeProcess suspend. + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p is suspended and none of the unwind blocks has finished yet" + self assert: p isSuspended. + self deny: x1 | x2 | x3. + "now terminate the process and make sure all unwind blocks have finished" + p terminate. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind3 (in category 'tests') ----- + testTerminationDuringNestedUnwind3 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ + [Processor yield] ensure: [ + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p is runnable and none of the unwind blocks has finished yet" + self assert: p isRunnable. + self deny: x1 | x2 | x3. + "now terminate the process and make sure all unwind blocks have finished" + p terminate. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind4 (in category 'tests') ----- + testTerminationDuringNestedUnwind4 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ + [ ] ensure: [ + Processor yield. + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p is suspended and none of the unwind blocks has finished yet" + self assert: p isRunnable. + self deny: x1 | x2 | x3. + "now terminate the process and make sure all unwind blocks have finished" + p terminate. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind5 (in category 'tests') ----- + testTerminationDuringNestedUnwind5 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ + [Processor activeProcess terminate] ensure: [ + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p suspended itself and none of the unwind blocks has finished yet" + self assert: p isSuspended. + self deny: x1 | x2 | x3. + "now let the termination continue and make sure all unwind blocks have finished" + Processor yield. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind6 (in category 'tests') ----- + testTerminationDuringNestedUnwind6 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 | + x1 := x2 := x3 := false. + p := + [ + [ + [ ] ensure: [ + [ ] ensure: [ + Processor activeProcess terminate. + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p suspended itself and none of the unwind blocks has finished yet" + self assert: p isSuspended. + self deny: x1 | x2 | x3. + "now let the termination continue and make sure all unwind blocks have finished" + Processor yield. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind7 (in category 'tests') ----- + testTerminationDuringNestedUnwind7 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 semaphore | + x1 := x2 := x3 := false. + semaphore := Semaphore new. + p := + [ + [ + [ ] ensure: [ + [semaphore wait] ensure: [ + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p is runnable and none of the unwind blocks has finished yet" + self assert: p isBlocked. + self deny: x1 | x2 | x3. + "now terminate the process and make sure all unwind blocks have finished" + p terminate. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! Item was added: + ----- Method: ProcessTerminateBug>>testTerminationDuringNestedUnwind8 (in category 'tests') ----- + testTerminationDuringNestedUnwind8 + "Test all nested unwind blocks are correctly unwound; + all unwind blocks halfway through their execution should be completed." + + | p x1 x2 x3 semaphore | + x1 := x2 := x3 := false. + semaphore := Semaphore new. + p := + [ + [ + [ ] ensure: [ + [ ] ensure: [ + semaphore wait. + x1 := true]. + x2 := true] + ] ensure: [ + x3 := true] + ] newProcess resume. + Processor yield. + "make sure p is runnable and none of the unwind blocks has finished yet" + self assert: p isBlocked. + self deny: x1 | x2 | x3. + "now terminate the process and make sure all unwind blocks have finished" + p terminate. + self assert: p isTerminated. + self assert: x1 & x2 & x3 + ! From commits at source.squeak.org Mon Apr 12 21:13:43 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 21:13:43 0000 Subject: [squeak-dev] The Trunk: Monticello-ct.740.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-ct.740.mcz ==================== Summary ==================== Name: Monticello-ct.740 Author: ct Time: 12 April 2021, 10:18:26.02269 pm UUID: c0c2562b-e801-ef4c-8628-3d352c513e0a Ancestors: Monticello-mt.736 Introduces MCPackageNotFound exception and usees it in MCRepository versions lookup. I would like to catch this error in [1, 2, 3]. [1] https://github.com/LinqLover/TelegramSmalltalkBot/blob/03be8437dfd9b9e98715d4fcc42fcea13cc90ae4/src/BaselineOfTelegramSmalltalkBot.package/BaselineOfTelegramSmalltalkBot.class/instance/depMergeVersion..st [2] https://github.com/LinqLover/TelegramBot/blob/e2d248eff9e24ca9a0423585b18d04c1191a725b/src/BaselineOfTelegramBot.package/BaselineOfTelegramBot.class/instance/depInbox..st [3] https://github.com/LinqLover/SimulationStudio/blob/743d48fdc10a70d572b1070b23c826f43c0dfb23/packages/BaselineOfSimulationStudio.package/BaselineOfSimulationStudio.class/instance/depInbox..st =============== Diff against Monticello-mt.736 =============== Item was added: + Error subclass: #MCPackageNotFound + instanceVariableNames: 'repository packageName' + classVariableNames: '' + poolDictionaries: '' + category: 'Monticello-Repositories'! Item was added: + ----- Method: MCPackageNotFound class>>signalForRepository:packageName: (in category 'signaling') ----- + signalForRepository: aRepository packageName: aString + + ^ self new + repository: aRepository packageName: aString; + signal! Item was added: + ----- Method: MCPackageNotFound>>messageText (in category 'printing') ----- + messageText + + ^ messageText ifNil: ['{1} not found in {2}' translated format: {self packageName. self repository}]! Item was added: + ----- Method: MCPackageNotFound>>packageName (in category 'accessing') ----- + packageName + + ^ packageName! Item was added: + ----- Method: MCPackageNotFound>>repository (in category 'accessing') ----- + repository + + ^ repository! Item was added: + ----- Method: MCPackageNotFound>>repository:packageName: (in category 'accessing') ----- + repository: aRepository packageName: aString + + repository := aRepository. + packageName := aString.! Item was changed: ----- Method: MCRepository>>highestNumberedVersionNameForPackageNamed: (in category 'versions') ----- highestNumberedVersionNameForPackageNamed: aString ^ (self versionNamesForPackageNamed: aString) + ifEmpty: [MCPackageNotFound signalForRepository: self packageName: aString] - ifEmpty: [ self error: aString , ' not found in ' , self asString ] ifNotEmptyDo: [ : versionNames | versionNames detectMax: [ : each | each versionNumber ] ]! From commits at source.squeak.org Mon Apr 12 21:33:41 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 21:33:41 0000 Subject: [squeak-dev] The Trunk: Monticello-jr.726.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-jr.726.mcz ==================== Summary ==================== Name: Monticello-jr.726 Author: jr Time: 28 June 2020, 10:07:19.980052 pm UUID: e8c6b590-8826-0144-a535-13cfa140b5dd Ancestors: Monticello-mt.725 Fix wrong traitCompositions in packages loaded from source.st As of Collections-ul.900, ReadStream>>match: does not alter the Stream position if the search sequence was not found. Failure to find the search sequence is indicated via the return value, but it was not checked in classDefinitionFrom:. The error could trigger load failures after loading Monticello-jr.720, in which the trait composition became relevant beyond just creating the class. The error did not surface for .mcz version files that contain a correct snapshot.bin file, which allows to forego the reading of the source.st file. There are versions out there without the snapshot.bin file. INIFile-jf.3.mcz as served by Squeaksource is such a version at the moment. =============== Diff against Monticello-mt.725 =============== Item was changed: ----- Method: MCStReader>>classDefinitionFrom: (in category 'converting') ----- classDefinitionFrom: aPseudoClass + | tokens definitionStream hasTraitComposition traitCompositionString lastIndex hasClassTraitComposition classTraitCompositionString typeOfSubclass className | - | tokens traitCompositionString lastIndex classTraitCompositionString typeOfSubclass className | tokens := Scanner new scanTokens: aPseudoClass definition. + definitionStream := ReadStream on: aPseudoClass definition. + hasTraitComposition := definitionStream match: 'uses:'. + traitCompositionString := hasTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. + definitionStream := ReadStream on: aPseudoClass metaClass definition asString. + hasClassTraitComposition := definitionStream match: 'uses:'. + classTraitCompositionString := hasClassTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. - traitCompositionString := ((ReadStream on: aPseudoClass definition) - match: 'uses:'; - upToAll: 'instanceVariableNames:') withBlanksTrimmed. - classTraitCompositionString := ((ReadStream on: aPseudoClass metaClass definition asString) - match: 'uses:'; - upToAll: 'instanceVariableNames:') withBlanksTrimmed. - traitCompositionString isEmpty ifTrue: [traitCompositionString := '{}']. - classTraitCompositionString isEmpty ifTrue: [classTraitCompositionString := '{}']. lastIndex := tokens size. className := tokens at: 3. typeOfSubclass := self typeOfSubclass: (tokens at: 2). "Compiled code classes are special cases of the #bytes class type" (#bytes == typeOfSubclass and: [self compiledCodeClassNames includes: className]) ifTrue: [typeOfSubclass := #compiledMethod]. ^ MCClassDefinition name: className superclassName: (tokens at: 1) traitComposition: traitCompositionString classTraitComposition: classTraitCompositionString category: (tokens at: lastIndex) instVarNames: ((tokens at: lastIndex - 6) findTokens: ' ') classVarNames: ((tokens at: lastIndex - 4) findTokens: ' ') poolDictionaryNames: ((tokens at: lastIndex - 2) findTokens: ' ') classInstVarNames: (self classInstVarNamesFor: aPseudoClass) type: typeOfSubclass comment: (self commentFor: aPseudoClass) commentStamp: (self commentStampFor: aPseudoClass)! From commits at source.squeak.org Mon Apr 12 21:33:57 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 21:33:57 0000 Subject: [squeak-dev] The Trunk: Monticello-ct.731.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-ct.731.mcz ==================== Summary ==================== Name: Monticello-ct.731 Author: ct Time: 12 October 2020, 1:22:55.228864 pm UUID: 29858029-e65e-ef4a-897b-3c420786d60e Ancestors: Monticello-mt.730 Make sure to reset the modified flag for working copies that have become empty after merging a version. =============== Diff against Monticello-mt.730 =============== Item was changed: ----- Method: MCWorkingCopy>>merged: (in category 'operations') ----- merged: aVersion ancestry addAncestor: aVersion info. + self changed. + self checkModified.! - self changed! From commits at source.squeak.org Mon Apr 12 21:44:27 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 21:44:27 0000 Subject: [squeak-dev] The Trunk: Monticello-ct.708.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-ct.708.mcz ==================== Summary ==================== Name: Monticello-ct.708 Author: ct Time: 14 December 2019, 5:34:25.115612 pm UUID: 4f24d611-8fbb-bd41-be15-3ca4c07aaa54 Ancestors: Monticello-ct.706 Fix MCSaveVersionDialog refreshing: Update text if the currently selected item changed =============== Diff against Monticello-ct.706 =============== Item was changed: ----- Method: MCSaveVersionDialog>>refresh (in category 'actions') ----- refresh + | latestSelection | + latestSelection := self selection. + self updateItems. self + selection: latestSelection; + changed: #list; + changed: #text.! - updateItems ; - changed: #list! From commits at source.squeak.org Mon Apr 12 21:44:36 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 21:44:36 0000 Subject: [squeak-dev] The Trunk: Monticello-ct.709.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-ct.709.mcz ==================== Summary ==================== Name: Monticello-ct.709 Author: ct Time: 21 December 2019, 12:56:07.492795 pm UUID: 70b14709-5b5a-bd45-a337-d354c56d8161 Ancestors: Monticello-ct.708 Implement #doItReceiver and #doItContext on MCCodeTool. Allows, for example, for inspecting a class variable from a save version dialog. =============== Diff against Monticello-ct.708 =============== Item was added: + ----- Method: MCCodeTool>>doItContext (in category 'accessing') ----- + doItContext + ^ nil! Item was added: + ----- Method: MCCodeTool>>doItReceiver (in category 'accessing') ----- + doItReceiver + ^ self selectedClass! From leves at caesar.elte.hu Mon Apr 12 21:47:28 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Mon, 12 Apr 2021 23:47:28 +0200 (CEST) Subject: [squeak-dev] Mail daemon problems with Unicode? In-Reply-To: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> References: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, It's more likely that squeaksource doesn't handle WideStrings in commit messages properly. Also, I discourage the use of emojis in commit messages. Yours appears as a question mark in my image, which changes the meaning of the message quite a bit: Removes #testHandlerFromAction from expectedFailures because it now finally works ? Levente On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > Hi all, > > > do the mail daemons that are responsible for informing the list about new inbox/trunk versions (probably a part of SqueakSource) have a problem with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but as far > as I can see, a notification email did not arrive. However, older and newer versions were announced as usual. > > > Here is the header of the relevant version: > > > --- > > Name: Tests-ct.449 > Author: ct > Time: 12 April 2021, 9:20:22.70324 pm > UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 > Ancestors: Tests-nice.447 > > Removes #testHandlerFromAction from expectedFailures because it now finally works 🎉 > > --- > > > Best, > > Christoph > > > From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 12 21:53:33 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 12 Apr 2021 21:53:33 +0000 Subject: [squeak-dev] Mail daemon problems with Unicode? In-Reply-To: References: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de>, Message-ID: Hi Levente, I see your point, but maybe it would be a better idea to choose another fallback character for unknown characters instead of sticking with these old character limitations. :-) That question mark has confused me already too often. Maybe something like � or □? But we would need to patch all fonts in the image to make this possible ... Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Levente Uzonyi Gesendet: Montag, 12. April 2021 23:47:28 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Mail daemon problems with Unicode? Hi Christoph, It's more likely that squeaksource doesn't handle WideStrings in commit messages properly. Also, I discourage the use of emojis in commit messages. Yours appears as a question mark in my image, which changes the meaning of the message quite a bit: Removes #testHandlerFromAction from expectedFailures because it now finally works ? Levente On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > Hi all, > > > do the mail daemons that are responsible for informing the list about new inbox/trunk versions (probably a part of SqueakSource) have a problem with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but as far > as I can see, a notification email did not arrive. However, older and newer versions were announced as usual. > > > Here is the header of the relevant version: > > > --- > > Name: Tests-ct.449 > Author: ct > Time: 12 April 2021, 9:20:22.70324 pm > UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 > Ancestors: Tests-nice.447 > > Removes #testHandlerFromAction from expectedFailures because it now finally works 🎉 > > --- > > > Best, > > Christoph > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 12 21:55:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 21:55:46 0000 Subject: [squeak-dev] The Trunk: Monticello-nice.741.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-nice.741.mcz ==================== Summary ==================== Name: Monticello-nice.741 Author: nice Time: 12 April 2021, 11:55:44.241641 pm UUID: ed3f3912-0b93-4673-acfe-b79c9e69886a Ancestors: Monticello-eem.737, Monticello-ct.740, Monticello-jr.726, Monticello-ct.731, Monticello-ct.709 Merge commit: Monticello-eem.737: Eliminate shadowed variable warning(s). Monticello-ct.740: Introduces MCPackageNotFound exception and usees it in MCRepository versions lookup. I would like to catch this error in [1, 2, 3]. Monticello-jr.726: Fix wrong traitCompositions in packages loaded from source.st Monticello-ct.731: Make sure to reset the modified flag for working copies that have become empty after merging a version. Monticello-ct.709: Implement #doItReceiver and #doItContext on MCCodeTool. Allows, for example, for inspecting a class variable from a save version dialog. - and its ancestor: - Monticello-ct.708: Fix MCSaveVersionDialog refreshing: Update text if the currently selected item changed =============== Diff against Monticello-eem.737 =============== Item was added: + ----- Method: MCCodeTool>>doItContext (in category 'accessing') ----- + doItContext + ^ nil! Item was added: + ----- Method: MCCodeTool>>doItReceiver (in category 'accessing') ----- + doItReceiver + ^ self selectedClass! Item was added: + Error subclass: #MCPackageNotFound + instanceVariableNames: 'repository packageName' + classVariableNames: '' + poolDictionaries: '' + category: 'Monticello-Repositories'! Item was added: + ----- Method: MCPackageNotFound class>>signalForRepository:packageName: (in category 'signaling') ----- + signalForRepository: aRepository packageName: aString + + ^ self new + repository: aRepository packageName: aString; + signal! Item was added: + ----- Method: MCPackageNotFound>>messageText (in category 'printing') ----- + messageText + + ^ messageText ifNil: ['{1} not found in {2}' translated format: {self packageName. self repository}]! Item was added: + ----- Method: MCPackageNotFound>>packageName (in category 'accessing') ----- + packageName + + ^ packageName! Item was added: + ----- Method: MCPackageNotFound>>repository (in category 'accessing') ----- + repository + + ^ repository! Item was added: + ----- Method: MCPackageNotFound>>repository:packageName: (in category 'accessing') ----- + repository: aRepository packageName: aString + + repository := aRepository. + packageName := aString.! Item was changed: ----- Method: MCRepository>>highestNumberedVersionNameForPackageNamed: (in category 'versions') ----- highestNumberedVersionNameForPackageNamed: aString ^ (self versionNamesForPackageNamed: aString) + ifEmpty: [MCPackageNotFound signalForRepository: self packageName: aString] - ifEmpty: [ self error: aString , ' not found in ' , self asString ] ifNotEmptyDo: [ : versionNames | versionNames detectMax: [ : each | each versionNumber ] ]! Item was changed: ----- Method: MCSaveVersionDialog>>refresh (in category 'actions') ----- refresh + | latestSelection | + latestSelection := self selection. + self updateItems. self + selection: latestSelection; + changed: #list; + changed: #text.! - updateItems ; - changed: #list! Item was changed: ----- Method: MCStReader>>classDefinitionFrom: (in category 'converting') ----- classDefinitionFrom: aPseudoClass + | tokens definitionStream hasTraitComposition traitCompositionString lastIndex hasClassTraitComposition classTraitCompositionString typeOfSubclass className | - | tokens traitCompositionString lastIndex classTraitCompositionString typeOfSubclass className | tokens := Scanner new scanTokens: aPseudoClass definition. + definitionStream := ReadStream on: aPseudoClass definition. + hasTraitComposition := definitionStream match: 'uses:'. + traitCompositionString := hasTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. + definitionStream := ReadStream on: aPseudoClass metaClass definition asString. + hasClassTraitComposition := definitionStream match: 'uses:'. + classTraitCompositionString := hasClassTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. - traitCompositionString := ((ReadStream on: aPseudoClass definition) - match: 'uses:'; - upToAll: 'instanceVariableNames:') withBlanksTrimmed. - classTraitCompositionString := ((ReadStream on: aPseudoClass metaClass definition asString) - match: 'uses:'; - upToAll: 'instanceVariableNames:') withBlanksTrimmed. - traitCompositionString isEmpty ifTrue: [traitCompositionString := '{}']. - classTraitCompositionString isEmpty ifTrue: [classTraitCompositionString := '{}']. lastIndex := tokens size. className := tokens at: 3. typeOfSubclass := self typeOfSubclass: (tokens at: 2). "Compiled code classes are special cases of the #bytes class type" (#bytes == typeOfSubclass and: [self compiledCodeClassNames includes: className]) ifTrue: [typeOfSubclass := #compiledMethod]. ^ MCClassDefinition name: className superclassName: (tokens at: 1) traitComposition: traitCompositionString classTraitComposition: classTraitCompositionString category: (tokens at: lastIndex) instVarNames: ((tokens at: lastIndex - 6) findTokens: ' ') classVarNames: ((tokens at: lastIndex - 4) findTokens: ' ') poolDictionaryNames: ((tokens at: lastIndex - 2) findTokens: ' ') classInstVarNames: (self classInstVarNamesFor: aPseudoClass) type: typeOfSubclass comment: (self commentFor: aPseudoClass) commentStamp: (self commentStampFor: aPseudoClass)! Item was changed: ----- Method: MCWorkingCopy>>merged: (in category 'operations') ----- merged: aVersion ancestry addAncestor: aVersion info. + self changed. + self checkModified.! - self changed! From leves at caesar.elte.hu Mon Apr 12 21:56:23 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Mon, 12 Apr 2021 23:56:23 +0200 (CEST) Subject: [squeak-dev] Mail daemon problems with Unicode? In-Reply-To: References: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de>, Message-ID: Hi Christoph, either that or the image could support unicode characters. :) Btw, my text-based email client doesn't support that character either. It shows an inverted question mark instead. Levente On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > Hi Levente, > > > I see your point, but maybe it would be a better idea to choose another fallback character for unknown characters instead of sticking with these old character limitations. :-) That question mark has confused me already too > often. Maybe something like ??? or □? But we would need to patch all fonts in the image to make this possible ... > > > Best, > > Christoph > > _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ > Von: Squeak-dev im Auftrag von Levente Uzonyi > Gesendet: Montag, 12. April 2021 23:47:28 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] Mail daemon problems with Unicode?   > Hi Christoph, > > It's more likely that squeaksource doesn't handle WideStrings in commit > messages properly. > Also, I discourage the use of emojis in commit messages. Yours appears as > a question mark in my image, which changes the meaning of the message > quite a bit: > > Removes #testHandlerFromAction from expectedFailures because it now finally works ? > > > Levente > > On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > > > > Hi all, > > > > > > do the mail daemons that are responsible for informing the list about new inbox/trunk versions (probably a part of SqueakSource) have a problem with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but as > far > > as I can see, a notification email did not arrive. However, older and newer versions were announced as usual. > > > > > > Here is the header of the relevant version: > > > > > > --- > > > > Name: Tests-ct.449 > > Author: ct > > Time: 12 April 2021, 9:20:22.70324 pm > > UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 > > Ancestors: Tests-nice.447 > > > > Removes #testHandlerFromAction from expectedFailures because it now finally works 🎉 > > > > --- > > > > > > Best, > > > > Christoph > > > > > > > > From nicolas.cellier.aka.nice at gmail.com Mon Apr 12 22:19:07 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 00:19:07 +0200 Subject: [squeak-dev] The Inbox: Tests-ct.448.mcz In-Reply-To: References: Message-ID: Hi Christoph, I agree that using Warning and UnhandledWarning is fragile. Especially since we can disable the warnings altogether! But see below... Le lun. 12 avr. 2021 à 21:19, a écrit : > > A new version of Tests was added to project The Inbox: > http://source.squeak.org/inbox/Tests-ct.448.mcz > > ==================== Summary ==================== > > Name: Tests-ct.448 > Author: ct > Time: 12 April 2021, 9:19:02.66824 pm > UUID: 65aa0e1a-250a-724a-9f04-505db0722916 > Ancestors: Tests-nice.447 > > Revises ExceptionTests >> #testCatchingDefaultAction to work when being debugged/simulated as well. This also decouples the test from the implementation details of UnhandledWarnings. > > For further reference, see also: https://github.com/LinqLover/SimulationStudio/runs/2319502648?check_suite_focus=true#step:4:441 > > =============== Diff against Tests-nice.447 =============== > > Item was changed: > ----- Method: ExceptionTests>>testCatchingDefaultAction (in category 'tests - outer') ----- > testCatchingDefaultAction > + "The #defaultAction method is executed in the context of the signaling environment." > + > - "The #defaultAction method is executed in the context of the signaling environment. > - The defaultAction will raise an UnhandledWarning that should be caught by this handler." > | result | > + result := [MyTestNotification signalForAction: [MyTestNotification signal: '2nd exception']] > + on: MyTestNotification > + do: [:ex | '2nd exception caught']. I do not understand here: MyTestNotification will be caught, and thus won't have a chance to trigger the defaultAction and 2nd notification right? Maybe you meant something like this: [MyTestNotification signalForAction: [MyTestError signal: '2nd exception']] on: MyTestError do: ... > + on: MyTestNotification > + self assert: '2nd exception caught' equals: result.! > - result := [ Warning signal: 'Warning signalled' ] on: UnhandledWarning do: [ :ex | 'UnhandledWarning caught' ]. > - self assert: 'UnhandledWarning caught' equals: result! > > Item was changed: > Notification subclass: #MyTestNotification > + instanceVariableNames: 'action' > - instanceVariableNames: '' > classVariableNames: '' > poolDictionaries: '' > category: 'Tests-Exceptions'! > > Item was added: > + ----- Method: MyTestNotification class>>signalForAction: (in category 'signaling') ----- > + signalForAction: aBlock > + > + ^ self new > + action: aBlock; > + signal! > > Item was added: > + ----- Method: MyTestNotification>>action (in category 'accessing') ----- > + action > + > + ^ action! > > Item was added: > + ----- Method: MyTestNotification>>action: (in category 'accessing') ----- > + action: aBlock > + > + action := aBlock! > > Item was added: > + ----- Method: MyTestNotification>>defaultAction (in category 'priv handling') ----- > + defaultAction > + > + self action ifNotNil: [^ self action cull: self]. > + > + ^ super defaultAction! > > From leves at caesar.elte.hu Mon Apr 12 22:29:35 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Tue, 13 Apr 2021 00:29:35 +0200 (CEST) Subject: [squeak-dev] The Trunk: Monticello-jr.726.mcz In-Reply-To: References: Message-ID: Hi Nicolas, I haven't reviewed this change, but the original bug related to ReadStream >> #match: has been fixed a while ago. Levente On Mon, 12 Apr 2021, commits at source.squeak.org wrote: > Nicolas Cellier uploaded a new version of Monticello to project The Trunk: > http://source.squeak.org/trunk/Monticello-jr.726.mcz > > ==================== Summary ==================== > > Name: Monticello-jr.726 > Author: jr > Time: 28 June 2020, 10:07:19.980052 pm > UUID: e8c6b590-8826-0144-a535-13cfa140b5dd > Ancestors: Monticello-mt.725 > > Fix wrong traitCompositions in packages loaded from source.st > > As of Collections-ul.900, ReadStream>>match: does not alter the Stream position if the search sequence was not found. Failure to find the search sequence is indicated via the return value, but it was not checked in classDefinitionFrom:. > > The error could trigger load failures after loading Monticello-jr.720, in which the trait composition became relevant beyond just creating the class. > > The error did not surface for .mcz version files that contain a correct snapshot.bin file, which allows to forego the reading of the source.st file. > > There are versions out there without the snapshot.bin file. INIFile-jf.3.mcz as served by Squeaksource is such a version at the moment. > > =============== Diff against Monticello-mt.725 =============== > > Item was changed: > ----- Method: MCStReader>>classDefinitionFrom: (in category 'converting') ----- > classDefinitionFrom: aPseudoClass > + | tokens definitionStream hasTraitComposition traitCompositionString lastIndex hasClassTraitComposition classTraitCompositionString typeOfSubclass className | > - | tokens traitCompositionString lastIndex classTraitCompositionString typeOfSubclass className | > tokens := Scanner new scanTokens: aPseudoClass definition. > + definitionStream := ReadStream on: aPseudoClass definition. > + hasTraitComposition := definitionStream match: 'uses:'. > + traitCompositionString := hasTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. > + definitionStream := ReadStream on: aPseudoClass metaClass definition asString. > + hasClassTraitComposition := definitionStream match: 'uses:'. > + classTraitCompositionString := hasClassTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. > - traitCompositionString := ((ReadStream on: aPseudoClass definition) > - match: 'uses:'; > - upToAll: 'instanceVariableNames:') withBlanksTrimmed. > - classTraitCompositionString := ((ReadStream on: aPseudoClass metaClass definition asString) > - match: 'uses:'; > - upToAll: 'instanceVariableNames:') withBlanksTrimmed. > - traitCompositionString isEmpty ifTrue: [traitCompositionString := '{}']. > - classTraitCompositionString isEmpty ifTrue: [classTraitCompositionString := '{}']. > lastIndex := tokens size. > > className := tokens at: 3. > typeOfSubclass := self typeOfSubclass: (tokens at: 2). > "Compiled code classes are special cases of the #bytes class type" > (#bytes == typeOfSubclass and: [self compiledCodeClassNames includes: className]) > ifTrue: [typeOfSubclass := #compiledMethod]. > > ^ MCClassDefinition > name: className > superclassName: (tokens at: 1) > traitComposition: traitCompositionString > classTraitComposition: classTraitCompositionString > category: (tokens at: lastIndex) > instVarNames: ((tokens at: lastIndex - 6) findTokens: ' ') > classVarNames: ((tokens at: lastIndex - 4) findTokens: ' ') > poolDictionaryNames: ((tokens at: lastIndex - 2) findTokens: ' ') > classInstVarNames: (self classInstVarNamesFor: aPseudoClass) > type: typeOfSubclass > comment: (self commentFor: aPseudoClass) > commentStamp: (self commentStampFor: aPseudoClass)! From nicolas.cellier.aka.nice at gmail.com Mon Apr 12 22:35:17 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 00:35:17 +0200 Subject: [squeak-dev] The Trunk: Monticello-jr.726.mcz In-Reply-To: References: Message-ID: Hi Levente, thanks, I think that we can revert this specific change. There are too many contributions rotting in the inbox, this one was relatively new, less than a year old ;) Le mar. 13 avr. 2021 à 00:29, Levente Uzonyi a écrit : > > Hi Nicolas, > > I haven't reviewed this change, but the original bug related to > ReadStream >> #match: has been fixed a while ago. > > > Levente > > On Mon, 12 Apr 2021, commits at source.squeak.org wrote: > > > Nicolas Cellier uploaded a new version of Monticello to project The Trunk: > > http://source.squeak.org/trunk/Monticello-jr.726.mcz > > > > ==================== Summary ==================== > > > > Name: Monticello-jr.726 > > Author: jr > > Time: 28 June 2020, 10:07:19.980052 pm > > UUID: e8c6b590-8826-0144-a535-13cfa140b5dd > > Ancestors: Monticello-mt.725 > > > > Fix wrong traitCompositions in packages loaded from source.st > > > > As of Collections-ul.900, ReadStream>>match: does not alter the Stream position if the search sequence was not found. Failure to find the search sequence is indicated via the return value, but it was not checked in classDefinitionFrom:. > > > > The error could trigger load failures after loading Monticello-jr.720, in which the trait composition became relevant beyond just creating the class. > > > > The error did not surface for .mcz version files that contain a correct snapshot.bin file, which allows to forego the reading of the source.st file. > > > > There are versions out there without the snapshot.bin file. INIFile-jf.3.mcz as served by Squeaksource is such a version at the moment. > > > > =============== Diff against Monticello-mt.725 =============== > > > > Item was changed: > > ----- Method: MCStReader>>classDefinitionFrom: (in category 'converting') ----- > > classDefinitionFrom: aPseudoClass > > + | tokens definitionStream hasTraitComposition traitCompositionString lastIndex hasClassTraitComposition classTraitCompositionString typeOfSubclass className | > > - | tokens traitCompositionString lastIndex classTraitCompositionString typeOfSubclass className | > > tokens := Scanner new scanTokens: aPseudoClass definition. > > + definitionStream := ReadStream on: aPseudoClass definition. > > + hasTraitComposition := definitionStream match: 'uses:'. > > + traitCompositionString := hasTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. > > + definitionStream := ReadStream on: aPseudoClass metaClass definition asString. > > + hasClassTraitComposition := definitionStream match: 'uses:'. > > + classTraitCompositionString := hasClassTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. > > - traitCompositionString := ((ReadStream on: aPseudoClass definition) > > - match: 'uses:'; > > - upToAll: 'instanceVariableNames:') withBlanksTrimmed. > > - classTraitCompositionString := ((ReadStream on: aPseudoClass metaClass definition asString) > > - match: 'uses:'; > > - upToAll: 'instanceVariableNames:') withBlanksTrimmed. > > - traitCompositionString isEmpty ifTrue: [traitCompositionString := '{}']. > > - classTraitCompositionString isEmpty ifTrue: [classTraitCompositionString := '{}']. > > lastIndex := tokens size. > > > > className := tokens at: 3. > > typeOfSubclass := self typeOfSubclass: (tokens at: 2). > > "Compiled code classes are special cases of the #bytes class type" > > (#bytes == typeOfSubclass and: [self compiledCodeClassNames includes: className]) > > ifTrue: [typeOfSubclass := #compiledMethod]. > > > > ^ MCClassDefinition > > name: className > > superclassName: (tokens at: 1) > > traitComposition: traitCompositionString > > classTraitComposition: classTraitCompositionString > > category: (tokens at: lastIndex) > > instVarNames: ((tokens at: lastIndex - 6) findTokens: ' ') > > classVarNames: ((tokens at: lastIndex - 4) findTokens: ' ') > > poolDictionaryNames: ((tokens at: lastIndex - 2) findTokens: ' ') > > classInstVarNames: (self classInstVarNamesFor: aPseudoClass) > > type: typeOfSubclass > > comment: (self commentFor: aPseudoClass) > > commentStamp: (self commentStampFor: aPseudoClass)! > From commits at source.squeak.org Mon Apr 12 23:57:22 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 12 Apr 2021 23:57:22 0000 Subject: [squeak-dev] The Trunk: ST80-ct.255.mcz Message-ID: Nicolas Cellier uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-ct.255.mcz ==================== Summary ==================== Name: ST80-ct.255 Author: ct Time: 6 June 2020, 3:48:16.215278 pm UUID: 5469be3e-28ef-c54e-952c-674500374c05 Ancestors: ST80-nice.254 Fix Transcript in MVC projects if preference 'Force transcript updates to screen' is disabled. Thanks to Marcel (mt) for the hint! =============== Diff against ST80-nice.254 =============== Item was changed: ----- Method: PluggableTextView>>update: (in category 'updating') ----- update: aSymbol "Refer to the comment in View|update:. Do nothing if the given symbol does not match any action. " aSymbol == #wantToChange ifTrue: [self canDiscardEdits ifFalse: [self promptForCancel]. ^ self]. aSymbol == #flash ifTrue: [^ controller flash]. aSymbol == getTextSelector ifTrue: [^ self updateDisplayContents]. aSymbol == getSelectionSelector ifTrue: [^ self setSelection: self getSelection]. aSymbol == #clearUserEdits ifTrue: [^ self hasUnacceptedEdits: false]. (aSymbol == #autoSelect and: [getSelectionSelector ~~ nil]) ifTrue: [ParagraphEditor abandonChangeText. "no replacement!!" ^ controller setSearch: model autoSelectString; againOrSame: true]. + (#(#appendEntry appendEntryLater) includes: aSymbol) ifTrue: - aSymbol == #appendEntry ifTrue: [^ controller doOccluded: [controller appendEntry]]. aSymbol == #clearText ifTrue: [^ controller doOccluded: [controller changeText: Text new]]. aSymbol == #bs ifTrue: [^ controller doOccluded: [controller bsText]]. aSymbol == #codeChangedElsewhere ifTrue: [^ self hasEditingConflicts: true]. aSymbol == #saveContents ifTrue: [^self controller saveContentsInFile]. aSymbol == #close ifTrue: [^self topView controller closeAndUnscheduleNoTerminate]. aSymbol == #acceptChanges ifTrue: [^ self controller accept]. aSymbol == #revertChanges ifTrue: [^ self controller cancel].! From commits at source.squeak.org Tue Apr 13 00:03:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 00:03:26 0000 Subject: [squeak-dev] The Trunk: ST80-ct.258.mcz Message-ID: Nicolas Cellier uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-ct.258.mcz ==================== Summary ==================== Name: ST80-ct.258 Author: ct Time: 5 September 2020, 1:20:54.682421 am UUID: db2a2f67-e818-ea46-b2f6-f4a9950577db Ancestors: ST80-mt.257 Fixes home and end keys in MVC editors if the text is empty =============== Diff against ST80-mt.257 =============== Item was changed: ----- Method: ParagraphEditor>>cursorEnd: (in category 'nonediting/nontyping keys') ----- cursorEnd: characterStream "Private - Move cursor end of current line." | string | self closeTypeIn: characterStream. string := paragraph text string. self moveCursor: [:position | Preferences wordStyleCursorMovement + ifTrue: [ + paragraph lines + at: (paragraph lineIndexOfCharacterIndex: position) + ifPresent: [:targetLine | targetLine last + (targetLine last = string size) asBit] + ifAbsent: [position]] + ifFalse: [ - ifTrue:[| targetLine | - targetLine := paragraph lines at:(paragraph lineIndexOfCharacterIndex: position). - targetLine = paragraph lines last - ifTrue:[targetLine last + 1] - ifFalse:[targetLine last]] - ifFalse:[ string indexOfAnyOf: CharacterSet crlf startingAt: position ifAbsent:[string size + 1]]] forward: true specialBlock:[:dummy | string size + 1]. ^true! Item was changed: ----- Method: ParagraphEditor>>cursorHome: (in category 'nonediting/nontyping keys') ----- cursorHome: characterStream "Private - Move cursor from position in current line to beginning of current line. If control key is pressed put cursor at beginning of text" | string | string := paragraph text string. self + moveCursor: [:position | Preferences wordStyleCursorMovement + ifTrue: [ + paragraph lines + at: (paragraph lineIndexOfCharacterIndex: position) + ifPresent: [:targetLine | targetLine first] ifAbsent: [position]] - moveCursor: [ :position | Preferences wordStyleCursorMovement - ifTrue:[ - (paragraph lines at:(paragraph lineIndexOfCharacterIndex: position)) first] ifFalse:[ (string lastIndexOfAnyOf: CharacterSet crlf startingAt: position - 1) + 1]] forward: false specialBlock: [:dummy | 1]. ^true! From commits at source.squeak.org Tue Apr 13 00:05:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 00:05:20 0000 Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz Message-ID: Nicolas Cellier uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-nice.265.mcz ==================== Summary ==================== Name: ST80-nice.265 Author: nice Time: 13 April 2021, 2:05:18.555491 am UUID: 1e580d8e-d2fc-4037-bf38-ec2f21c4db05 Ancestors: ST80-mt.264, ST80-ct.258, ST80-ct.255 Merge commit ST80-mt.264: Work around the changes in Collections-nice.925 to make MVC work again. :-) ST80-ct.258: Fixes home and end keys in MVC editors if the text is empty ST80-ct.255: Fix Transcript in MVC projects if preference 'Force transcript updates to screen' is disabled. =============== Diff against ST80-mt.264 =============== Item was changed: ----- Method: ParagraphEditor>>cursorEnd: (in category 'nonediting/nontyping keys') ----- cursorEnd: characterStream "Private - Move cursor end of current line." | string | self closeTypeIn: characterStream. string := paragraph text string. self moveCursor: [:position | Preferences wordStyleCursorMovement + ifTrue: [ + paragraph lines + at: (paragraph lineIndexOfCharacterIndex: position) + ifPresent: [:targetLine | targetLine last + (targetLine last = string size) asBit] + ifAbsent: [position]] + ifFalse: [ - ifTrue:[| targetLine | - targetLine := paragraph lines at:(paragraph lineIndexOfCharacterIndex: position). - targetLine = paragraph lines last - ifTrue:[targetLine last + 1] - ifFalse:[targetLine last]] - ifFalse:[ string indexOfAnyOf: CharacterSet crlf startingAt: position ifAbsent:[string size + 1]]] forward: true specialBlock:[:dummy | string size + 1]. ^true! Item was changed: ----- Method: ParagraphEditor>>cursorHome: (in category 'nonediting/nontyping keys') ----- cursorHome: characterStream "Private - Move cursor from position in current line to beginning of current line. If control key is pressed put cursor at beginning of text" | string | string := paragraph text string. self + moveCursor: [:position | Preferences wordStyleCursorMovement + ifTrue: [ + paragraph lines + at: (paragraph lineIndexOfCharacterIndex: position) + ifPresent: [:targetLine | targetLine first] ifAbsent: [position]] - moveCursor: [ :position | Preferences wordStyleCursorMovement - ifTrue:[ - (paragraph lines at:(paragraph lineIndexOfCharacterIndex: position)) first] ifFalse:[ (string lastIndexOfAnyOf: CharacterSet crlf startingAt: position - 1) + 1]] forward: false specialBlock: [:dummy | 1]. ^true! Item was changed: ----- Method: PluggableTextView>>update: (in category 'updating') ----- update: aSymbol "Refer to the comment in View|update:. Do nothing if the given symbol does not match any action. " aSymbol == #wantToChange ifTrue: [self canDiscardEdits ifFalse: [self promptForCancel]. ^ self]. aSymbol == #flash ifTrue: [^ controller flash]. aSymbol == getTextSelector ifTrue: [^ self updateDisplayContents]. aSymbol == getSelectionSelector ifTrue: [^ self setSelection: self getSelection]. aSymbol == #clearUserEdits ifTrue: [^ self hasUnacceptedEdits: false]. (aSymbol == #autoSelect and: [getSelectionSelector ~~ nil]) ifTrue: [ParagraphEditor abandonChangeText. "no replacement!!" ^ controller setSearch: model autoSelectString; againOrSame: true]. + (#(#appendEntry appendEntryLater) includes: aSymbol) ifTrue: - aSymbol == #appendEntry ifTrue: [^ controller doOccluded: [controller appendEntry]]. aSymbol == #clearText ifTrue: [^ controller doOccluded: [controller changeText: Text new]]. aSymbol == #bs ifTrue: [^ controller doOccluded: [controller bsText]]. aSymbol == #codeChangedElsewhere ifTrue: [^ self hasEditingConflicts: true]. aSymbol == #saveContents ifTrue: [^self controller saveContentsInFile]. aSymbol == #close ifTrue: [^self topView controller closeAndUnscheduleNoTerminate]. aSymbol == #acceptChanges ifTrue: [^ self controller accept]. aSymbol == #revertChanges ifTrue: [^ self controller cancel].! From commits at source.squeak.org Tue Apr 13 00:54:22 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 00:54:22 0000 Subject: [squeak-dev] The Trunk: Tests-jr.436.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-jr.436.mcz ==================== Summary ==================== Name: Tests-jr.436 Author: jr Time: 28 June 2020, 10:18:05.236052 pm UUID: 049894aa-5f79-a44d-a2c0-ee65887af7ac Ancestors: Tests-mt.435 Test class definition reading testClassDefinitionFromPseudoClass exposes the traitComposition bug triggered by Collections-ul.900. Monticello-jr.726 is supposed to fix this bug. =============== Diff against Tests-mt.435 =============== Item was added: + ----- Method: MCStReaderTest>>testClassDefinition (in category 'tests') ----- + testClassDefinition + | reader definition | + reader := MCStReader on: 'Object subclass: #NewClass + instanceVariableNames: ''instVar1 instVar2'' + classVariableNames: ''ClassVar1 ClassVar2'' + poolDictionaries: ''Pool1 Pool2'' + category: ''NewCategory''!!' readStream. + definition := reader definitions first. + self assert: definition isClassDefinition; + assert: #NewClass equals: definition className; + assert: #(instVar1 instVar2) equals: definition instVarNames asArray; + assert: #(ClassVar1 ClassVar2) equals: definition classVarNames asArray; + assert: #(Pool1 Pool2) equals: definition poolDictionaries asArray; + assert: 'NewCategory' equals: definition category; + assert: '{}' equals: definition traitCompositionString; + assert: '{}' equals: definition classTraitCompositionString.! Item was added: + ----- Method: MCStReaderTest>>testClassDefinitionFromPseudoClass (in category 'tests') ----- + testClassDefinitionFromPseudoClass + | reader pseudoClass definition | + reader := MCStReader new. + pseudoClass := PseudoClass new + name: #NewClass; + definition: 'Object subclass: #NewClass + instanceVariableNames: ''instVar1 instVar2'' + classVariableNames: ''ClassVar1 ClassVar2'' + poolDictionaries: ''Pool1 Pool2'' + category: ''NewCategory'''; + yourself. + definition := reader classDefinitionFrom: pseudoClass. + self assert: definition isClassDefinition; + assert: #NewClass equals: definition className; + assert: #(instVar1 instVar2) equals: definition instVarNames asArray; + assert: #(ClassVar1 ClassVar2) equals: definition classVarNames asArray; + assert: #(Pool1 Pool2) equals: definition poolDictionaries asArray; + assert: 'NewCategory' equals: definition category; + assert: '{}' equals: definition traitCompositionString; + assert: '{}' equals: definition classTraitCompositionString.! From commits at source.squeak.org Tue Apr 13 00:56:55 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 00:56:55 0000 Subject: [squeak-dev] The Trunk: Tests-nice.448.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.448.mcz ==================== Summary ==================== Name: Tests-nice.448 Author: nice Time: 13 April 2021, 2:56:53.406097 am UUID: 2e7d1b04-14b7-410c-9ef8-20688a8fd857 Ancestors: Tests-nice.447, Tests-jr.436 Merge Tests-jr.436: Test class definition reading =============== Diff against Tests-nice.447 =============== Item was changed: SystemOrganization addCategory: #'Tests-Bugs'! SystemOrganization addCategory: #'Tests-Compiler'! SystemOrganization addCategory: #'Tests-Dependencies'! SystemOrganization addCategory: #'Tests-Digital Signatures'! SystemOrganization addCategory: #'Tests-Environments'! SystemOrganization addCategory: #'Tests-Exceptions'! SystemOrganization addCategory: #'Tests-FilePackage'! SystemOrganization addCategory: #'Tests-Files'! SystemOrganization addCategory: #'Tests-Finalization'! SystemOrganization addCategory: #'Tests-Hex'! SystemOrganization addCategory: #'Tests-Installer-Core'! SystemOrganization addCategory: #'Tests-Localization'! SystemOrganization addCategory: #'Tests-Monticello'! SystemOrganization addCategory: #'Tests-Monticello-Mocks'! SystemOrganization addCategory: #'Tests-Monticello-Utils'! SystemOrganization addCategory: #'Tests-Object Events'! SystemOrganization addCategory: #'Tests-ObjectsAsMethods'! SystemOrganization addCategory: #'Tests-PrimCallController'! SystemOrganization addCategory: #'Tests-Release'! SystemOrganization addCategory: #'Tests-System-Applications'! SystemOrganization addCategory: #'Tests-System-Digital Signatures'! SystemOrganization addCategory: #'Tests-System-Object Storage'! SystemOrganization addCategory: #'Tests-System-Preferences'! SystemOrganization addCategory: #'Tests-System-Support'! SystemOrganization addCategory: #'Tests-Utilities'! SystemOrganization addCategory: #'Tests-VM'! - SystemOrganization addCategory: #'Tests-MonticelloMocks'! SystemOrganization addCategory: #'Tests-Sound'! Item was added: + ----- Method: MCStReaderTest>>testClassDefinition (in category 'tests') ----- + testClassDefinition + | reader definition | + reader := MCStReader on: 'Object subclass: #NewClass + instanceVariableNames: ''instVar1 instVar2'' + classVariableNames: ''ClassVar1 ClassVar2'' + poolDictionaries: ''Pool1 Pool2'' + category: ''NewCategory''!!' readStream. + definition := reader definitions first. + self assert: definition isClassDefinition; + assert: #NewClass equals: definition className; + assert: #(instVar1 instVar2) equals: definition instVarNames asArray; + assert: #(ClassVar1 ClassVar2) equals: definition classVarNames asArray; + assert: #(Pool1 Pool2) equals: definition poolDictionaries asArray; + assert: 'NewCategory' equals: definition category; + assert: '{}' equals: definition traitCompositionString; + assert: '{}' equals: definition classTraitCompositionString.! Item was added: + ----- Method: MCStReaderTest>>testClassDefinitionFromPseudoClass (in category 'tests') ----- + testClassDefinitionFromPseudoClass + | reader pseudoClass definition | + reader := MCStReader new. + pseudoClass := PseudoClass new + name: #NewClass; + definition: 'Object subclass: #NewClass + instanceVariableNames: ''instVar1 instVar2'' + classVariableNames: ''ClassVar1 ClassVar2'' + poolDictionaries: ''Pool1 Pool2'' + category: ''NewCategory'''; + yourself. + definition := reader classDefinitionFrom: pseudoClass. + self assert: definition isClassDefinition; + assert: #NewClass equals: definition className; + assert: #(instVar1 instVar2) equals: definition instVarNames asArray; + assert: #(ClassVar1 ClassVar2) equals: definition classVarNames asArray; + assert: #(Pool1 Pool2) equals: definition poolDictionaries asArray; + assert: 'NewCategory' equals: definition category; + assert: '{}' equals: definition traitCompositionString; + assert: '{}' equals: definition classTraitCompositionString.! From commits at source.squeak.org Tue Apr 13 00:59:22 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 00:59:22 0000 Subject: [squeak-dev] The Trunk: Monticello-nice.742.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-nice.742.mcz ==================== Summary ==================== Name: Monticello-nice.742 Author: nice Time: 13 April 2021, 2:59:20.188121 am UUID: b83bdaba-8e8c-4c01-984a-f5ea46f50529 Ancestors: Monticello-nice.741 Revert Monticello-jr.726 because the proper patch of match: have been integrated already. =============== Diff against Monticello-nice.741 =============== Item was changed: ----- Method: MCStReader>>classDefinitionFrom: (in category 'converting') ----- classDefinitionFrom: aPseudoClass + | tokens traitCompositionString lastIndex classTraitCompositionString typeOfSubclass className | - | tokens definitionStream hasTraitComposition traitCompositionString lastIndex hasClassTraitComposition classTraitCompositionString typeOfSubclass className | tokens := Scanner new scanTokens: aPseudoClass definition. + traitCompositionString := ((ReadStream on: aPseudoClass definition) + match: 'uses:'; + upToAll: 'instanceVariableNames:') withBlanksTrimmed. + classTraitCompositionString := ((ReadStream on: aPseudoClass metaClass definition asString) + match: 'uses:'; + upToAll: 'instanceVariableNames:') withBlanksTrimmed. + traitCompositionString isEmpty ifTrue: [traitCompositionString := '{}']. + classTraitCompositionString isEmpty ifTrue: [classTraitCompositionString := '{}']. - definitionStream := ReadStream on: aPseudoClass definition. - hasTraitComposition := definitionStream match: 'uses:'. - traitCompositionString := hasTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. - definitionStream := ReadStream on: aPseudoClass metaClass definition asString. - hasClassTraitComposition := definitionStream match: 'uses:'. - classTraitCompositionString := hasClassTraitComposition ifTrue: [(definitionStream upToAll: 'instanceVariableNames:') withBlanksTrimmed] ifFalse: ['{}']. lastIndex := tokens size. className := tokens at: 3. typeOfSubclass := self typeOfSubclass: (tokens at: 2). "Compiled code classes are special cases of the #bytes class type" (#bytes == typeOfSubclass and: [self compiledCodeClassNames includes: className]) ifTrue: [typeOfSubclass := #compiledMethod]. ^ MCClassDefinition name: className superclassName: (tokens at: 1) traitComposition: traitCompositionString classTraitComposition: classTraitCompositionString category: (tokens at: lastIndex) instVarNames: ((tokens at: lastIndex - 6) findTokens: ' ') classVarNames: ((tokens at: lastIndex - 4) findTokens: ' ') poolDictionaryNames: ((tokens at: lastIndex - 2) findTokens: ' ') classInstVarNames: (self classInstVarNamesFor: aPseudoClass) type: typeOfSubclass comment: (self commentFor: aPseudoClass) commentStamp: (self commentStampFor: aPseudoClass)! From lewis at mail.msen.com Tue Apr 13 02:10:41 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Mon, 12 Apr 2021 22:10:41 -0400 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <066c91fcefb8490da1676b6d275f055d@student.hpi.uni-potsdam.de> References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> <20210412205610.GA33248@shell.msen.com> <066c91fcefb8490da1676b6d275f055d@student.hpi.uni-potsdam.de> Message-ID: <20210413021041.GA63987@shell.msen.com> On Mon, Apr 12, 2021 at 09:11:54PM +0000, Thiede, Christoph wrote: > Maybe just create a new version and add the pointer directly into the > comment of #asMutator? This will be even more helpful for people who > wonder "Should I use #asMutator or #asSimpleSetter"? > > I also wonder whether #asMutator deserves a #deprecate flag at least. > Otherwise, we will have the situation of two ambiguous selectors without > any recommendation, again. > Let's not over-engineer it. Just look at the method comment. Is anyone ever going to use a method with a name like "asMutator" without first looking at the method to see what it does? I certainly hope not :-) Symbol>>asMutator "Synonym for asSimpleSetter, retained for support of external packages such as Seaside" ^ self asSimpleSetter Dave From asqueaker at gmail.com Tue Apr 13 04:17:28 2021 From: asqueaker at gmail.com (Chris Muller) Date: Mon, 12 Apr 2021 23:17:28 -0500 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: Hi all, Just FYI, I'm allocating 100% of my Squeak-energy this year to Magma 2 as well as various image explorations to attempt to expose the class library in various ways via GraphQL schemas. Some of this work would likely be mutually distracting if I were immersed in core Squeak development. For example, exploring whether Method Pragmas can be loadable from their own "extension" package, *on top* of existing methods.. Anyway, I do hope someone will consider running for 2021 in my stead. Anyone who does will get my vote. :) - Chris On Fri, Apr 2, 2021 at 3:10 AM Rein, Patrick wrote: > Hi All, > > It's that time again (although with a new person telling you this). > Time to raise your voices and elect your leaders! Can you believe > it's been over a year already? > > It's a time for you to stand up, help your community and volunteer to > serve! > > Squeak wants you! > > Every year we elect the SOB (Squeak Oversight Board) consisting of > seven members from our community. The current board members are: > 1. Vanessa Freudenberg > 2. Tim Rowledge > 3. Marcel Taeumel > 4. Craig Latta > 5. David T. Lewis > 6. Chris Muller > 7. John-Reed Maffeo > > For more info on the board please see: > https://squeakboard.wordpress.com/our-mission/ > > Everything about the election, including schedule and more, can be tracked > here: > http://wiki.squeak.org/squeak/6656 > > Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members > and campaigning! > > Candidates should nominate themselves and start their campaign on the > squeak-dev mailing list. Or if you nominate someone else, make sure > that person really wants to run. :) I will not put anyone on the > candidate list until that person makes it known on squeak-dev that > he/she intends to run. > > During this period, the candidates should ideally present themselves > on squeak-dev, unless they have already done so, and the community can > ask questions. > > I encourage you to reach out to potential candidates, people that are > active in the community and represent your views, and ask them to run. > Some people will not run without encouragement. Also, I know that > some people wait to the last minute to run for the board to see if > others will run but please consider getting this year off to a faster > start and just jump right in! > > The schedule and process are as follows: > > Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members > and campaigning! > Friday 16th of April 2021, 18.00 UTC: Candidate list is finalized. > Friday 16th of April 2021, 19.00 UTC: Online election starts. > Friday 30th of April 2021, 19.00 UTC: Online election ends. > Results will be announced immediately after the election ends. > > The voting period is two week long and ballots are sent out via email. > > And how do you end up on the voter list? See below. :) > > IMPORTANT: New voters will NOT be added once the election is started. > You MUST try to get on the voter list before the 16th of April 2021 > or you will NOT be able to vote. If your Email has changed please try > to make sure it is changed on the list of voters before the election > starts. > > -------------------------- > > If you were invited to vote last year you are already on the voter > list, no worries! If you are a new Squeaker and wish to vote you > should do ONE of the following: > > * Get a "known" Squeaker to vouch for you. If a known Squeaker > sends an email to voters (at) squeak.org giving me a name and email > for you, then I will add you. > > * Send an email to voters (at) squeak.org yourself (and CC to > squeak-dev if you like) with information/arguments showing me that you > are indeed serious about voting and that you are indeed a Squeaker. > > When the voting period starts all voters will receive an email with > instructions and a link to the voting website. > > If there are any further questions, just reply *in this thread* and I > will closely track it - or send email to voters (at) squeak.org which > is updated and points to me. > > ...so let's get on with it! > > All the best, > Patrick Rein > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From asqueaker at gmail.com Tue Apr 13 05:16:01 2021 From: asqueaker at gmail.com (Chris Muller) Date: Tue, 13 Apr 2021 00:16:01 -0500 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: > > For those wondering, the problem is that some Symbol get duplicated > violating the contract: > any two Symbols are either identical (==) or different (~=). Possible become without copyHash? -------------- next part -------------- An HTML attachment was scrubbed... URL: From asqueaker at gmail.com Tue Apr 13 05:21:58 2021 From: asqueaker at gmail.com (Chris Muller) Date: Tue, 13 Apr 2021 00:21:58 -0500 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <20210413021041.GA63987@shell.msen.com> References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> <20210412205610.GA33248@shell.msen.com> <066c91fcefb8490da1676b6d275f055d@student.hpi.uni-potsdam.de> <20210413021041.GA63987@shell.msen.com> Message-ID: Another option is to use "browse revisions", then select the revision which un-deprecates it and select, "browse origin". Then you will have the version name which can be searched on the list. :) On Mon, Apr 12, 2021 at 9:10 PM David T. Lewis wrote: > On Mon, Apr 12, 2021 at 09:11:54PM +0000, Thiede, Christoph wrote: > > Maybe just create a new version and add the pointer directly into the > > comment of #asMutator? This will be even more helpful for people who > > wonder "Should I use #asMutator or #asSimpleSetter"? > > > > I also wonder whether #asMutator deserves a #deprecate flag at least. > > Otherwise, we will have the situation of two ambiguous selectors without > > any recommendation, again. > > > > Let's not over-engineer it. Just look at the method comment. Is anyone > ever going to use a method with a name like "asMutator" without first > looking at the method to see what it does? I certainly hope not :-) > > Symbol>>asMutator > "Synonym for asSimpleSetter, retained for support of external packages > such as Seaside" > ^ self asSimpleSetter > > Dave > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bstjean at yahoo.com Tue Apr 13 05:29:04 2021 From: bstjean at yahoo.com (Benoit St-Jean) Date: Tue, 13 Apr 2021 05:29:04 +0000 (UTC) Subject: [squeak-dev] Squeak Oversight Board meeting References: <1578280042.800870.1618291744720.ref@mail.yahoo.com> Message-ID: <1578280042.800870.1618291744720@mail.yahoo.com> What's the frequency of the SOB meetings and around what time do you guys meet?  I'm in the Montreal area if that helps. And via which tool? Zoom? Teams? On the same subject (SOB), what is the role and functions of SOB members?  I could only find old pages related to that on the swiki! tia  -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 13 07:19:25 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 09:19:25 +0200 Subject: [squeak-dev] Squeak Oversight Board meeting In-Reply-To: <1578280042.800870.1618291744720@mail.yahoo.com> References: <1578280042.800870.1618291744720.ref@mail.yahoo.com> <1578280042.800870.1618291744720@mail.yahoo.com> Message-ID: Hi there. We currently meet on 1st and 3rd Wednesdays each month at 19:00 (CEST, UTC +2), which is 13:00 (EDT, UTC -4). Depending on the location of a board's members, we can move this slot around. We currently use Jitsi for the meetings. We document meeting minutes via GoogleDocs. During the meetings, we usually discuss important topics around the community, which surface mostly on the squeak-dev mailing list. We also discuss organizational stuff around Squeak's infrastructure (e.g. Website, SqueakSource, ...). I think some important matters for the next board period include: - Bintray will shut down on May 1, which affects the OpenSmalltalkVM daily builds - TravisCI limits build resources for open source, which might entail a switch to GitHub Actions, which affects the continuous build of Squeak bundles - "Oversighting" the next Squeak Release, which is usually delegated to a (maybe non-board) release manager + helpers Best, Marcel Am 13.04.2021 07:29:19 schrieb Benoit St-Jean via Squeak-dev : What's the frequency of the SOB meetings and around what time do you guys meet?  I'm in the Montreal area if that helps. And via which tool? Zoom? Teams? On the same subject (SOB), what is the role and functions of SOB members?  I could only find old pages related to that on the swiki! tia  -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 13 07:36:05 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 09:36:05 +0200 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> <20210412205610.GA33248@shell.msen.com> <066c91fcefb8490da1676b6d275f055d@student.hpi.uni-potsdam.de> <20210413021041.GA63987@shell.msen.com> Message-ID: Hi Chris! > Another option is to use "browse revisions", then select the revision  > which un-deprecates it and select, "browse origin".  Then you will > have the version name which can be searched on the list.   :) Works like a charm. :-) Would be nice if you somehow show the repository description in the revisions browser. Then, users could inspect the list of repositories if some issue occurs. Best, Marcel Am 13.04.2021 07:22:45 schrieb Chris Muller : Another option is to use "browse revisions", then select the revision which un-deprecates it and select, "browse origin".  Then you will have the version name which can be searched on the list.   :) On Mon, Apr 12, 2021 at 9:10 PM David T. Lewis wrote: On Mon, Apr 12, 2021 at 09:11:54PM +0000, Thiede, Christoph wrote: > Maybe just create a new version and add the pointer directly into the > comment of #asMutator? This will be even more helpful for people who > wonder "Should I use #asMutator or #asSimpleSetter"? > > I also wonder whether #asMutator deserves a #deprecate flag at least. > Otherwise, we will have the situation of two ambiguous selectors without > any recommendation, again. > Let's not over-engineer it. Just look at the method comment. Is anyone ever going to use a method with a name like "asMutator" without first looking at the method to see what it does?  I certainly hope not :-)   Symbol>>asMutator     "Synonym for asSimpleSetter, retained for support of external packages such as Seaside"     ^ self asSimpleSetter Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 13 08:10:15 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 10:10:15 +0200 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: Maybe unrelated, but I will remove that extension "Symbol >> #extern:", which manipulates the symbol tables for a single test in CompilerExceptionTest, present since March 2020. I think that 1) garbage collection should take care of unused symbols and 2) test can find a better way to produce "unknown symbols" :-) Best, Marcel Am 13.04.2021 07:16:48 schrieb Chris Muller : For those wondering, the problem is that some Symbol get duplicated violating the contract: any two Symbols are either identical (==) or different (~=). Possible become without copyHash?  -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Apr 13 08:51:16 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 08:51:16 0000 Subject: [squeak-dev] The Trunk: Tests-mt.449.mcz Message-ID: Marcel Taeumel uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-mt.449.mcz ==================== Summary ==================== Name: Tests-mt.449 Author: mt Time: 13 April 2021, 10:51:15.223811 am UUID: 23984a3a-fc1c-2a44-a023-9862b3d2ba8d Ancestors: Tests-nice.448 Simplify #testUnknownSelector. Avoid interfering with garbage collection and symbol tables. (Note that #lookup: is the preferred interface, not #findInterned: or #hasInterned:ifTrue:. The concept of internalization should not leak into client code.) =============== Diff against Tests-nice.448 =============== Item was changed: TestCase subclass: #CompilerExceptionsTest + instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection' - instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection tearDowns' classVariableNames: '' poolDictionaries: '' category: 'Tests-Compiler'! Item was added: + ----- Method: CompilerExceptionsTest>>generateUnknownSelector (in category 'private') ----- + generateUnknownSelector + + | selector num | + selector := 'yourself'. + num := 0. + [(Symbol lookup: selector, num) notNil] whileTrue: [num := num + 1]. + ^ selector, num! Item was removed: - ----- Method: CompilerExceptionsTest>>setUp (in category 'running') ----- - setUp - - super setUp. - tearDowns := OrderedCollection new. - Symbol hasInterned: self unknownSelector ifTrue: [:symbol | - tearDowns add: [Symbol intern: symbol]]. - Symbol extern: self unknownSelector.! Item was changed: ----- Method: CompilerExceptionsTest>>tearDown (in category 'running') ----- tearDown self removeGeneratedMethods. - Symbol extern: self unknownSelector. - tearDowns do: #value. super tearDown.! Item was changed: ----- Method: CompilerExceptionsTest>>testUnknownSelector (in category 'tests') ----- testUnknownSelector + | unknownSelector | + self flag: #flaky. "mt: This test depends on a list of suggestions that is derived from the system's known selectors. Any desired replacement might not be present in the actual list. Maybe we could use an index-based choice instead." + unknownSelector := self generateUnknownSelector. self + compiling: 'griffle self ' , unknownSelector - compiling: 'griffle self ' , self unknownSelector shouldRaise: UnknownSelector + andSelect: unknownSelector - andSelect: self unknownSelector testing: { + false -> [ + self assertCanceled. + self assert: (Symbol lookup: unknownSelector) isNil]. + 'yourself' -> [ + self assertSucceeded: 'griffle self yourself'. + self assert: (Symbol lookup: unknownSelector) isNil]. + unknownSelector -> [ - false -> [self assertCanceled]. - 'yourself' -> [self assertSucceeded: 'griffle self yourself']. - self unknownSelector -> [ self assertSucceeded. + self assert: (Symbol lookup: unknownSelector) notNil] }. + unknownSelector := self generateUnknownSelector. - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |]). - Symbol extern: self unknownSelector] }. self + compiling: 'griffle [ self ' , unknownSelector , ' ] value' - compiling: 'griffle [ self ' , self unknownSelector , ' ] value' shouldRaise: UnknownSelector + andSelect: unknownSelector - andSelect: self unknownSelector testing: { + false -> [ + self assertCanceled. + self assert: (Symbol lookup: unknownSelector) isNil]. + 'yourself' -> [ + self assertSucceeded: 'griffle [ self yourself ] value'. + self assert: (Symbol lookup: unknownSelector) isNil]. + unknownSelector -> [ - false -> [self assertCanceled]. - 'yourself' -> [self assertSucceeded: 'griffle [ self yourself ] value']. - self unknownSelector -> [ self assertSucceeded. + self assert: (Symbol lookup: unknownSelector) notNil] }.! - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |])] }.! Item was removed: - ----- Method: CompilerExceptionsTest>>unknownSelector (in category 'private') ----- - unknownSelector - - ^ 'yourrsellff'! Item was removed: - ----- Method: Symbol class>>extern: (in category '*Tests-release') ----- - extern: aStringOrSymbol - - {NewSymbols. SymbolTable} do: [:table | - table remove: aStringOrSymbol ifAbsent: []].! From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 09:22:21 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 11:22:21 +0200 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: I have a clue: Symbol allSubInstances reject: [:s | (Symbol findInterned: s asString) == s]. returns two problematic Symbols: OrderedCollection(#openPluggableFileListLabel:in: #dialogStringFromQuery:withTitle:). This means that some duplicated symbols still exist in my image... And they can end up in the SymbolTable thru (Symbol rehash). Who did create those duplicates remains an open question, but how the duplicates might sneak into the SymbolTable is no more a mystery (though it remains to analyze who does Symbol rehash...) Le mar. 13 avr. 2021 à 10:10, Marcel Taeumel a écrit : > > Maybe unrelated, but I will remove that extension "Symbol >> #extern:", which manipulates the symbol tables for a single test in CompilerExceptionTest, present since March 2020. I think that 1) garbage collection should take care of unused symbols and 2) test can find a better way to produce "unknown symbols" :-) > > Best, > Marcel > > Am 13.04.2021 07:16:48 schrieb Chris Muller : >> >> For those wondering, the problem is that some Symbol get duplicated >> violating the contract: >> any two Symbols are either identical (==) or different (~=). > > > Possible become without copyHash? > > From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 09:25:00 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 11:25:00 +0200 Subject: [squeak-dev] The Trunk: Tests-mt.449.mcz In-Reply-To: References: Message-ID: Le mar. 13 avr. 2021 à 10:51, a écrit : > > Marcel Taeumel uploaded a new version of Tests to project The Trunk: > http://source.squeak.org/trunk/Tests-mt.449.mcz > > ==================== Summary ==================== > > Name: Tests-mt.449 > Author: mt > Time: 13 April 2021, 10:51:15.223811 am > UUID: 23984a3a-fc1c-2a44-a023-9862b3d2ba8d > Ancestors: Tests-nice.448 > > Simplify #testUnknownSelector. Avoid interfering with garbage collection and symbol tables. > > (Note that #lookup: is the preferred interface, not #findInterned: or #hasInterned:ifTrue:. The concept of internalization should not leak into client code.) May I suggest to classify them as private then? > > =============== Diff against Tests-nice.448 =============== > > Item was changed: > TestCase subclass: #CompilerExceptionsTest > + instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection' > - instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection tearDowns' > classVariableNames: '' > poolDictionaries: '' > category: 'Tests-Compiler'! > > Item was added: > + ----- Method: CompilerExceptionsTest>>generateUnknownSelector (in category 'private') ----- > + generateUnknownSelector > + > + | selector num | > + selector := 'yourself'. > + num := 0. > + [(Symbol lookup: selector, num) notNil] whileTrue: [num := num + 1]. > + ^ selector, num! > > Item was removed: > - ----- Method: CompilerExceptionsTest>>setUp (in category 'running') ----- > - setUp > - > - super setUp. > - tearDowns := OrderedCollection new. > - Symbol hasInterned: self unknownSelector ifTrue: [:symbol | > - tearDowns add: [Symbol intern: symbol]]. > - Symbol extern: self unknownSelector.! > > Item was changed: > ----- Method: CompilerExceptionsTest>>tearDown (in category 'running') ----- > tearDown > > self removeGeneratedMethods. > - Symbol extern: self unknownSelector. > - tearDowns do: #value. > super tearDown.! > > Item was changed: > ----- Method: CompilerExceptionsTest>>testUnknownSelector (in category 'tests') ----- > testUnknownSelector > > + | unknownSelector | > + self flag: #flaky. "mt: This test depends on a list of suggestions that is derived from the system's known selectors. Any desired replacement might not be present in the actual list. Maybe we could use an index-based choice instead." > + unknownSelector := self generateUnknownSelector. > self > + compiling: 'griffle self ' , unknownSelector > - compiling: 'griffle self ' , self unknownSelector > shouldRaise: UnknownSelector > + andSelect: unknownSelector > - andSelect: self unknownSelector > testing: { > + false -> [ > + self assertCanceled. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + 'yourself' -> [ > + self assertSucceeded: 'griffle self yourself'. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + unknownSelector -> [ > - false -> [self assertCanceled]. > - 'yourself' -> [self assertSucceeded: 'griffle self yourself']. > - self unknownSelector -> [ > self assertSucceeded. > + self assert: (Symbol lookup: unknownSelector) notNil] }. > + unknownSelector := self generateUnknownSelector. > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |]). > - Symbol extern: self unknownSelector] }. > self > + compiling: 'griffle [ self ' , unknownSelector , ' ] value' > - compiling: 'griffle [ self ' , self unknownSelector , ' ] value' > shouldRaise: UnknownSelector > + andSelect: unknownSelector > - andSelect: self unknownSelector > testing: { > + false -> [ > + self assertCanceled. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + 'yourself' -> [ > + self assertSucceeded: 'griffle [ self yourself ] value'. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + unknownSelector -> [ > - false -> [self assertCanceled]. > - 'yourself' -> [self assertSucceeded: 'griffle [ self yourself ] value']. > - self unknownSelector -> [ > self assertSucceeded. > + self assert: (Symbol lookup: unknownSelector) notNil] }.! > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |])] }.! > > Item was removed: > - ----- Method: CompilerExceptionsTest>>unknownSelector (in category 'private') ----- > - unknownSelector > - > - ^ 'yourrsellff'! > > Item was removed: > - ----- Method: Symbol class>>extern: (in category '*Tests-release') ----- > - extern: aStringOrSymbol > - > - {NewSymbols. SymbolTable} do: [:table | > - table remove: aStringOrSymbol ifAbsent: []].! > > From marcel.taeumel at hpi.de Tue Apr 13 09:44:24 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 11:44:24 +0200 Subject: [squeak-dev] The Trunk: Tests-mt.449.mcz In-Reply-To: References: Message-ID: > May I suggest to classify them as private then? Hmm... #hasInterned:ifTrue: is "private" already. ;-) Maybe #findInterned: should be, too. Yet, soft-deprecation via "self flag: #deprecated" might be even better since both are actually implemented through #lookup:.  Best, Marcel Am 13.04.2021 11:25:27 schrieb Nicolas Cellier : Le mar. 13 avr. 2021 à 10:51, a écrit : > > Marcel Taeumel uploaded a new version of Tests to project The Trunk: > http://source.squeak.org/trunk/Tests-mt.449.mcz > > ==================== Summary ==================== > > Name: Tests-mt.449 > Author: mt > Time: 13 April 2021, 10:51:15.223811 am > UUID: 23984a3a-fc1c-2a44-a023-9862b3d2ba8d > Ancestors: Tests-nice.448 > > Simplify #testUnknownSelector. Avoid interfering with garbage collection and symbol tables. > > (Note that #lookup: is the preferred interface, not #findInterned: or #hasInterned:ifTrue:. The concept of internalization should not leak into client code.) May I suggest to classify them as private then? > > =============== Diff against Tests-nice.448 =============== > > Item was changed: > TestCase subclass: #CompilerExceptionsTest > + instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection' > - instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection tearDowns' > classVariableNames: '' > poolDictionaries: '' > category: 'Tests-Compiler'! > > Item was added: > + ----- Method: CompilerExceptionsTest>>generateUnknownSelector (in category 'private') ----- > + generateUnknownSelector > + > + | selector num | > + selector := 'yourself'. > + num := 0. > + [(Symbol lookup: selector, num) notNil] whileTrue: [num := num + 1]. > + ^ selector, num! > > Item was removed: > - ----- Method: CompilerExceptionsTest>>setUp (in category 'running') ----- > - setUp > - > - super setUp. > - tearDowns := OrderedCollection new. > - Symbol hasInterned: self unknownSelector ifTrue: [:symbol | > - tearDowns add: [Symbol intern: symbol]]. > - Symbol extern: self unknownSelector.! > > Item was changed: > ----- Method: CompilerExceptionsTest>>tearDown (in category 'running') ----- > tearDown > > self removeGeneratedMethods. > - Symbol extern: self unknownSelector. > - tearDowns do: #value. > super tearDown.! > > Item was changed: > ----- Method: CompilerExceptionsTest>>testUnknownSelector (in category 'tests') ----- > testUnknownSelector > > + | unknownSelector | > + self flag: #flaky. "mt: This test depends on a list of suggestions that is derived from the system's known selectors. Any desired replacement might not be present in the actual list. Maybe we could use an index-based choice instead." > + unknownSelector := self generateUnknownSelector. > self > + compiling: 'griffle self ' , unknownSelector > - compiling: 'griffle self ' , self unknownSelector > shouldRaise: UnknownSelector > + andSelect: unknownSelector > - andSelect: self unknownSelector > testing: { > + false -> [ > + self assertCanceled. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + 'yourself' -> [ > + self assertSucceeded: 'griffle self yourself'. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + unknownSelector -> [ > - false -> [self assertCanceled]. > - 'yourself' -> [self assertSucceeded: 'griffle self yourself']. > - self unknownSelector -> [ > self assertSucceeded. > + self assert: (Symbol lookup: unknownSelector) notNil] }. > + unknownSelector := self generateUnknownSelector. > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |]). > - Symbol extern: self unknownSelector] }. > self > + compiling: 'griffle [ self ' , unknownSelector , ' ] value' > - compiling: 'griffle [ self ' , self unknownSelector , ' ] value' > shouldRaise: UnknownSelector > + andSelect: unknownSelector > - andSelect: self unknownSelector > testing: { > + false -> [ > + self assertCanceled. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + 'yourself' -> [ > + self assertSucceeded: 'griffle [ self yourself ] value'. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + unknownSelector -> [ > - false -> [self assertCanceled]. > - 'yourself' -> [self assertSucceeded: 'griffle [ self yourself ] value']. > - self unknownSelector -> [ > self assertSucceeded. > + self assert: (Symbol lookup: unknownSelector) notNil] }.! > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |])] }.! > > Item was removed: > - ----- Method: CompilerExceptionsTest>>unknownSelector (in category 'private') ----- > - unknownSelector > - > - ^ 'yourrsellff'! > > Item was removed: > - ----- Method: Symbol class>>extern: (in category '*Tests-release') ----- > - extern: aStringOrSymbol > - > - {NewSymbols. SymbolTable} do: [:table | > - table remove: aStringOrSymbol ifAbsent: []].! > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Apr 13 09:46:52 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 09:46:52 0000 Subject: [squeak-dev] The Trunk: Morphic-nice.1743.mcz Message-ID: Nicolas Cellier uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-nice.1743.mcz ==================== Summary ==================== Name: Morphic-nice.1743 Author: nice Time: 13 April 2021, 11:46:40.70289 am UUID: d369fef2-23fa-2c47-867b-e21b9615d22b Ancestors: Morphic-eem.1742 Prefer Symbol lookup: to #findInterned: =============== Diff against Morphic-eem.1742 =============== Item was changed: ----- Method: SearchBar>>smartSearch:in: (in category 'searching') ----- smartSearch: text in: morph "Take the user input and perform an appropriate search" | input newContents | self removeResultsWidget. input := text asString ifEmpty:[^self]. self class useSmartSearch ifFalse: [^ ToolSet default browseMessageNames: input]. + (Symbol lookup: input) ifNotNil: - (Symbol findInterned: input) ifNotNil: [:symbol| input := symbol]. "If it is a global or a full class name, browse that class." (Smalltalk bindingOf: input) ifNotNil: [:assoc| | class | class := (assoc value isBehavior ifTrue:[assoc value] ifFalse:[assoc value class]) theNonMetaClass. Project current world submorphs do: [:windowMorph| (windowMorph isSystemWindow and: [(windowMorph model isKindOf: Browser) and: [windowMorph model isDisplayingClass: class]]) ifTrue: [windowMorph beKeyWindow. ^windowMorph model displayClass: class]]. ^ToolSet browse: class selector: nil]. "If it is a symbol and there are implementors of it, browse those implementors." input isSymbol ifTrue: [(SystemNavigation new allImplementorsOf: input) ifNotEmpty: [:list| ^SystemNavigation new browseMessageList: list name: 'Implementors of ' , input]]. "If it starts uppercase, browse classes if any. Otherwise, just search for messages." input first isUppercase ifTrue: [(UIManager default classFromPattern: input withCaption: '') ifNotNil: [:aClass| ^ToolSet browse: aClass selector: nil]. newContents := input, ' -- not found.'. self searchTerm: newContents. self selection: (input size+1 to: newContents size). self currentHand newKeyboardFocus: morph textMorph. ^ self]. "Default to browse message names..." ToolSet default browseMessageNames: input! From commits at source.squeak.org Tue Apr 13 09:48:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 09:48:15 0000 Subject: [squeak-dev] The Trunk: Tools-nice.1037.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-nice.1037.mcz ==================== Summary ==================== Name: Tools-nice.1037 Author: nice Time: 13 April 2021, 11:48:06.48889 am UUID: 8144ec43-bc2a-4145-8d24-e68052041c0c Ancestors: Tools-eem.1036 Prefer Symbol lookup: to #findInterned: =============== Diff against Tools-eem.1036 =============== Item was changed: ----- Method: StringHolder>>browseLocalSenders (in category '*Tools') ----- browseLocalSenders self selectedClassOrMetaClass ifNotNil: [:cls| | token | token := UIManager default request: 'browse for selector or literal'. token isEmpty ifTrue: [^self]. Scanner new typedScan: token do: [:scannedToken :tokenType| token := tokenType = #word ifTrue: + [(Symbol lookup: token) - [(Symbol findInterned: token) ifNil: [^UIManager default inform: 'no such selector: ', token] ifNotNil: [:symbol| symbol]] ifFalse: [scannedToken]. self systemNavigation browseAllCallsOn: token localTo: cls]]! From marcel.taeumel at hpi.de Tue Apr 13 09:53:41 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 11:53:41 +0200 Subject: [squeak-dev] The Trunk: Tests-mt.449.mcz In-Reply-To: References: Message-ID: Hey Eliot, recently, you chose #findInterned: over #lookup:. Can you recall how this happened? What is your opinion on this matter? :-) Here is a remark from Levente about this from July 2019: http://forum.world.st/The-Trunk-Morphic-mt-1491-mcz-tp5101075p5101089.html [http://forum.world.st/The-Trunk-Morphic-mt-1491-mcz-tp5101075p5101089.html] Best, Marcel Am 13.04.2021 11:44:24 schrieb Marcel Taeumel : > May I suggest to classify them as private then? Hmm... #hasInterned:ifTrue: is "private" already. ;-) Maybe #findInterned: should be, too. Yet, soft-deprecation via "self flag: #deprecated" might be even better since both are actually implemented through #lookup:.  Best, Marcel Am 13.04.2021 11:25:27 schrieb Nicolas Cellier : Le mar. 13 avr. 2021 à 10:51, a écrit : > > Marcel Taeumel uploaded a new version of Tests to project The Trunk: > http://source.squeak.org/trunk/Tests-mt.449.mcz > > ==================== Summary ==================== > > Name: Tests-mt.449 > Author: mt > Time: 13 April 2021, 10:51:15.223811 am > UUID: 23984a3a-fc1c-2a44-a023-9862b3d2ba8d > Ancestors: Tests-nice.448 > > Simplify #testUnknownSelector. Avoid interfering with garbage collection and symbol tables. > > (Note that #lookup: is the preferred interface, not #findInterned: or #hasInterned:ifTrue:. The concept of internalization should not leak into client code.) May I suggest to classify them as private then? > > =============== Diff against Tests-nice.448 =============== > > Item was changed: > TestCase subclass: #CompilerExceptionsTest > + instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection' > - instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection tearDowns' > classVariableNames: '' > poolDictionaries: '' > category: 'Tests-Compiler'! > > Item was added: > + ----- Method: CompilerExceptionsTest>>generateUnknownSelector (in category 'private') ----- > + generateUnknownSelector > + > + | selector num | > + selector := 'yourself'. > + num := 0. > + [(Symbol lookup: selector, num) notNil] whileTrue: [num := num + 1]. > + ^ selector, num! > > Item was removed: > - ----- Method: CompilerExceptionsTest>>setUp (in category 'running') ----- > - setUp > - > - super setUp. > - tearDowns := OrderedCollection new. > - Symbol hasInterned: self unknownSelector ifTrue: [:symbol | > - tearDowns add: [Symbol intern: symbol]]. > - Symbol extern: self unknownSelector.! > > Item was changed: > ----- Method: CompilerExceptionsTest>>tearDown (in category 'running') ----- > tearDown > > self removeGeneratedMethods. > - Symbol extern: self unknownSelector. > - tearDowns do: #value. > super tearDown.! > > Item was changed: > ----- Method: CompilerExceptionsTest>>testUnknownSelector (in category 'tests') ----- > testUnknownSelector > > + | unknownSelector | > + self flag: #flaky. "mt: This test depends on a list of suggestions that is derived from the system's known selectors. Any desired replacement might not be present in the actual list. Maybe we could use an index-based choice instead." > + unknownSelector := self generateUnknownSelector. > self > + compiling: 'griffle self ' , unknownSelector > - compiling: 'griffle self ' , self unknownSelector > shouldRaise: UnknownSelector > + andSelect: unknownSelector > - andSelect: self unknownSelector > testing: { > + false -> [ > + self assertCanceled. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + 'yourself' -> [ > + self assertSucceeded: 'griffle self yourself'. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + unknownSelector -> [ > - false -> [self assertCanceled]. > - 'yourself' -> [self assertSucceeded: 'griffle self yourself']. > - self unknownSelector -> [ > self assertSucceeded. > + self assert: (Symbol lookup: unknownSelector) notNil] }. > + unknownSelector := self generateUnknownSelector. > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |]). > - Symbol extern: self unknownSelector] }. > self > + compiling: 'griffle [ self ' , unknownSelector , ' ] value' > - compiling: 'griffle [ self ' , self unknownSelector , ' ] value' > shouldRaise: UnknownSelector > + andSelect: unknownSelector > - andSelect: self unknownSelector > testing: { > + false -> [ > + self assertCanceled. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + 'yourself' -> [ > + self assertSucceeded: 'griffle [ self yourself ] value'. > + self assert: (Symbol lookup: unknownSelector) isNil]. > + unknownSelector -> [ > - false -> [self assertCanceled]. > - 'yourself' -> [self assertSucceeded: 'griffle [ self yourself ] value']. > - self unknownSelector -> [ > self assertSucceeded. > + self assert: (Symbol lookup: unknownSelector) notNil] }.! > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |])] }.! > > Item was removed: > - ----- Method: CompilerExceptionsTest>>unknownSelector (in category 'private') ----- > - unknownSelector > - > - ^ 'yourrsellff'! > > Item was removed: > - ----- Method: Symbol class>>extern: (in category '*Tests-release') ----- > - extern: aStringOrSymbol > - > - {NewSymbols. SymbolTable} do: [:table | > - table remove: aStringOrSymbol ifAbsent: []].! > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 09:54:04 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 11:54:04 +0200 Subject: [squeak-dev] The Trunk: Tests-mt.449.mcz In-Reply-To: References: Message-ID: findInterned: could be deprecated because completely equivalent to lookup:. I removed its usage in core image, but there are other in external packages (refactoring browser for example). Le mar. 13 avr. 2021 à 11:44, Marcel Taeumel a écrit : > > > May I suggest to classify them as private then? > > Hmm... #hasInterned:ifTrue: is "private" already. ;-) Maybe #findInterned: should be, too. Yet, soft-deprecation via "self flag: #deprecated" might be even better since both are actually implemented through #lookup:. > > Best, > Marcel > > Am 13.04.2021 11:25:27 schrieb Nicolas Cellier : > > Le mar. 13 avr. 2021 à 10:51, a écrit : > > > > Marcel Taeumel uploaded a new version of Tests to project The Trunk: > > http://source.squeak.org/trunk/Tests-mt.449.mcz > > > > ==================== Summary ==================== > > > > Name: Tests-mt.449 > > Author: mt > > Time: 13 April 2021, 10:51:15.223811 am > > UUID: 23984a3a-fc1c-2a44-a023-9862b3d2ba8d > > Ancestors: Tests-nice.448 > > > > Simplify #testUnknownSelector. Avoid interfering with garbage collection and symbol tables. > > > > (Note that #lookup: is the preferred interface, not #findInterned: or #hasInterned:ifTrue:. The concept of internalization should not leak into client code.) > > May I suggest to classify them as private then? > > > > > =============== Diff against Tests-nice.448 =============== > > > > Item was changed: > > TestCase subclass: #CompilerExceptionsTest > > + instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection' > > - instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection tearDowns' > > classVariableNames: '' > > poolDictionaries: '' > > category: 'Tests-Compiler'! > > > > Item was added: > > + ----- Method: CompilerExceptionsTest>>generateUnknownSelector (in category 'private') ----- > > + generateUnknownSelector > > + > > + | selector num | > > + selector := 'yourself'. > > + num := 0. > > + [(Symbol lookup: selector, num) notNil] whileTrue: [num := num + 1]. > > + ^ selector, num! > > > > Item was removed: > > - ----- Method: CompilerExceptionsTest>>setUp (in category 'running') ----- > > - setUp > > - > > - super setUp. > > - tearDowns := OrderedCollection new. > > - Symbol hasInterned: self unknownSelector ifTrue: [:symbol | > > - tearDowns add: [Symbol intern: symbol]]. > > - Symbol extern: self unknownSelector.! > > > > Item was changed: > > ----- Method: CompilerExceptionsTest>>tearDown (in category 'running') ----- > > tearDown > > > > self removeGeneratedMethods. > > - Symbol extern: self unknownSelector. > > - tearDowns do: #value. > > super tearDown.! > > > > Item was changed: > > ----- Method: CompilerExceptionsTest>>testUnknownSelector (in category 'tests') ----- > > testUnknownSelector > > > > + | unknownSelector | > > + self flag: #flaky. "mt: This test depends on a list of suggestions that is derived from the system's known selectors. Any desired replacement might not be present in the actual list. Maybe we could use an index-based choice instead." > > + unknownSelector := self generateUnknownSelector. > > self > > + compiling: 'griffle self ' , unknownSelector > > - compiling: 'griffle self ' , self unknownSelector > > shouldRaise: UnknownSelector > > + andSelect: unknownSelector > > - andSelect: self unknownSelector > > testing: { > > + false -> [ > > + self assertCanceled. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + 'yourself' -> [ > > + self assertSucceeded: 'griffle self yourself'. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + unknownSelector -> [ > > - false -> [self assertCanceled]. > > - 'yourself' -> [self assertSucceeded: 'griffle self yourself']. > > - self unknownSelector -> [ > > self assertSucceeded. > > + self assert: (Symbol lookup: unknownSelector) notNil] }. > > + unknownSelector := self generateUnknownSelector. > > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |]). > > - Symbol extern: self unknownSelector] }. > > self > > + compiling: 'griffle [ self ' , unknownSelector , ' ] value' > > - compiling: 'griffle [ self ' , self unknownSelector , ' ] value' > > shouldRaise: UnknownSelector > > + andSelect: unknownSelector > > - andSelect: self unknownSelector > > testing: { > > + false -> [ > > + self assertCanceled. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + 'yourself' -> [ > > + self assertSucceeded: 'griffle [ self yourself ] value'. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + unknownSelector -> [ > > - false -> [self assertCanceled]. > > - 'yourself' -> [self assertSucceeded: 'griffle [ self yourself ] value']. > > - self unknownSelector -> [ > > self assertSucceeded. > > + self assert: (Symbol lookup: unknownSelector) notNil] }.! > > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |])] }.! > > > > Item was removed: > > - ----- Method: CompilerExceptionsTest>>unknownSelector (in category 'private') ----- > > - unknownSelector > > - > > - ^ 'yourrsellff'! > > > > Item was removed: > > - ----- Method: Symbol class>>extern: (in category '*Tests-release') ----- > > - extern: aStringOrSymbol > > - > > - {NewSymbols. SymbolTable} do: [:table | > > - table remove: aStringOrSymbol ifAbsent: []].! > > > > > > From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 10:00:39 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 12:00:39 +0200 Subject: [squeak-dev] The Trunk: Tests-mt.449.mcz In-Reply-To: References: Message-ID: I think that findInterned: is old, probably from st80 epoch... hasInterned:ifTrue: also, it may be cross-dialect. Strange that we did put it in private... a massive rewrite of (Symbol hasInterned: aString ifTrue: [:aSymbol | ...]) into ((Symbol lookup: aString) ifNotNil: [:aSymbol | ...]) is possible, except in the rare cases when we use the returned value of the send, which is a Boolean. But it is questionable... Le mar. 13 avr. 2021 à 11:53, Marcel Taeumel a écrit : > > Hey Eliot, > > recently, you chose #findInterned: over #lookup:. Can you recall how this happened? What is your opinion on this matter? :-) > > Here is a remark from Levente about this from July 2019: > http://forum.world.st/The-Trunk-Morphic-mt-1491-mcz-tp5101075p5101089.html > > Best, > Marcel > > Am 13.04.2021 11:44:24 schrieb Marcel Taeumel : > > > May I suggest to classify them as private then? > > Hmm... #hasInterned:ifTrue: is "private" already. ;-) Maybe #findInterned: should be, too. Yet, soft-deprecation via "self flag: #deprecated" might be even better since both are actually implemented through #lookup:. > > Best, > Marcel > > Am 13.04.2021 11:25:27 schrieb Nicolas Cellier : > > Le mar. 13 avr. 2021 à 10:51, a écrit : > > > > Marcel Taeumel uploaded a new version of Tests to project The Trunk: > > http://source.squeak.org/trunk/Tests-mt.449.mcz > > > > ==================== Summary ==================== > > > > Name: Tests-mt.449 > > Author: mt > > Time: 13 April 2021, 10:51:15.223811 am > > UUID: 23984a3a-fc1c-2a44-a023-9862b3d2ba8d > > Ancestors: Tests-nice.448 > > > > Simplify #testUnknownSelector. Avoid interfering with garbage collection and symbol tables. > > > > (Note that #lookup: is the preferred interface, not #findInterned: or #hasInterned:ifTrue:. The concept of internalization should not leak into client code.) > > May I suggest to classify them as private then? > > > > > =============== Diff against Tests-nice.448 =============== > > > > Item was changed: > > TestCase subclass: #CompilerExceptionsTest > > + instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection' > > - instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection tearDowns' > > classVariableNames: '' > > poolDictionaries: '' > > category: 'Tests-Compiler'! > > > > Item was added: > > + ----- Method: CompilerExceptionsTest>>generateUnknownSelector (in category 'private') ----- > > + generateUnknownSelector > > + > > + | selector num | > > + selector := 'yourself'. > > + num := 0. > > + [(Symbol lookup: selector, num) notNil] whileTrue: [num := num + 1]. > > + ^ selector, num! > > > > Item was removed: > > - ----- Method: CompilerExceptionsTest>>setUp (in category 'running') ----- > > - setUp > > - > > - super setUp. > > - tearDowns := OrderedCollection new. > > - Symbol hasInterned: self unknownSelector ifTrue: [:symbol | > > - tearDowns add: [Symbol intern: symbol]]. > > - Symbol extern: self unknownSelector.! > > > > Item was changed: > > ----- Method: CompilerExceptionsTest>>tearDown (in category 'running') ----- > > tearDown > > > > self removeGeneratedMethods. > > - Symbol extern: self unknownSelector. > > - tearDowns do: #value. > > super tearDown.! > > > > Item was changed: > > ----- Method: CompilerExceptionsTest>>testUnknownSelector (in category 'tests') ----- > > testUnknownSelector > > > > + | unknownSelector | > > + self flag: #flaky. "mt: This test depends on a list of suggestions that is derived from the system's known selectors. Any desired replacement might not be present in the actual list. Maybe we could use an index-based choice instead." > > + unknownSelector := self generateUnknownSelector. > > self > > + compiling: 'griffle self ' , unknownSelector > > - compiling: 'griffle self ' , self unknownSelector > > shouldRaise: UnknownSelector > > + andSelect: unknownSelector > > - andSelect: self unknownSelector > > testing: { > > + false -> [ > > + self assertCanceled. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + 'yourself' -> [ > > + self assertSucceeded: 'griffle self yourself'. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + unknownSelector -> [ > > - false -> [self assertCanceled]. > > - 'yourself' -> [self assertSucceeded: 'griffle self yourself']. > > - self unknownSelector -> [ > > self assertSucceeded. > > + self assert: (Symbol lookup: unknownSelector) notNil] }. > > + unknownSelector := self generateUnknownSelector. > > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |]). > > - Symbol extern: self unknownSelector] }. > > self > > + compiling: 'griffle [ self ' , unknownSelector , ' ] value' > > - compiling: 'griffle [ self ' , self unknownSelector , ' ] value' > > shouldRaise: UnknownSelector > > + andSelect: unknownSelector > > - andSelect: self unknownSelector > > testing: { > > + false -> [ > > + self assertCanceled. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + 'yourself' -> [ > > + self assertSucceeded: 'griffle [ self yourself ] value'. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + unknownSelector -> [ > > - false -> [self assertCanceled]. > > - 'yourself' -> [self assertSucceeded: 'griffle [ self yourself ] value']. > > - self unknownSelector -> [ > > self assertSucceeded. > > + self assert: (Symbol lookup: unknownSelector) notNil] }.! > > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |])] }.! > > > > Item was removed: > > - ----- Method: CompilerExceptionsTest>>unknownSelector (in category 'private') ----- > > - unknownSelector > > - > > - ^ 'yourrsellff'! > > > > Item was removed: > > - ----- Method: Symbol class>>extern: (in category '*Tests-release') ----- > > - extern: aStringOrSymbol > > - > > - {NewSymbols. SymbolTable} do: [:table | > > - table remove: aStringOrSymbol ifAbsent: []].! > > > > > > From marcel.taeumel at hpi.de Tue Apr 13 10:03:46 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 12:03:46 +0200 Subject: [squeak-dev] The Trunk: Tests-mt.449.mcz In-Reply-To: References: Message-ID: > a massive rewrite of (Symbol hasInterned: aString ifTrue: [:aSymbol | ...]) into ((Symbol lookup: aString) ifNotNil: [:aSymbol | ...]) is possible Hmm... only 34 senders. Would me take about 2 hours max, I suppose. I volunteer. Should I do it? Best, Marcel Am 13.04.2021 12:01:05 schrieb Nicolas Cellier : I think that findInterned: is old, probably from st80 epoch... hasInterned:ifTrue: also, it may be cross-dialect. Strange that we did put it in private... a massive rewrite of (Symbol hasInterned: aString ifTrue: [:aSymbol | ...]) into ((Symbol lookup: aString) ifNotNil: [:aSymbol | ...]) is possible, except in the rare cases when we use the returned value of the send, which is a Boolean. But it is questionable... Le mar. 13 avr. 2021 à 11:53, Marcel Taeumel a écrit : > > Hey Eliot, > > recently, you chose #findInterned: over #lookup:. Can you recall how this happened? What is your opinion on this matter? :-) > > Here is a remark from Levente about this from July 2019: > http://forum.world.st/The-Trunk-Morphic-mt-1491-mcz-tp5101075p5101089.html > > Best, > Marcel > > Am 13.04.2021 11:44:24 schrieb Marcel Taeumel : > > > May I suggest to classify them as private then? > > Hmm... #hasInterned:ifTrue: is "private" already. ;-) Maybe #findInterned: should be, too. Yet, soft-deprecation via "self flag: #deprecated" might be even better since both are actually implemented through #lookup:. > > Best, > Marcel > > Am 13.04.2021 11:25:27 schrieb Nicolas Cellier : > > Le mar. 13 avr. 2021 à 10:51, a écrit : > > > > Marcel Taeumel uploaded a new version of Tests to project The Trunk: > > http://source.squeak.org/trunk/Tests-mt.449.mcz > > > > ==================== Summary ==================== > > > > Name: Tests-mt.449 > > Author: mt > > Time: 13 April 2021, 10:51:15.223811 am > > UUID: 23984a3a-fc1c-2a44-a023-9862b3d2ba8d > > Ancestors: Tests-nice.448 > > > > Simplify #testUnknownSelector. Avoid interfering with garbage collection and symbol tables. > > > > (Note that #lookup: is the preferred interface, not #findInterned: or #hasInterned:ifTrue:. The concept of internalization should not leak into client code.) > > May I suggest to classify them as private then? > > > > > =============== Diff against Tests-nice.448 =============== > > > > Item was changed: > > TestCase subclass: #CompilerExceptionsTest > > + instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection' > > - instanceVariableNames: 'text selectionInterval originalText previousSelection originalSelection tearDowns' > > classVariableNames: '' > > poolDictionaries: '' > > category: 'Tests-Compiler'! > > > > Item was added: > > + ----- Method: CompilerExceptionsTest>>generateUnknownSelector (in category 'private') ----- > > + generateUnknownSelector > > + > > + | selector num | > > + selector := 'yourself'. > > + num := 0. > > + [(Symbol lookup: selector, num) notNil] whileTrue: [num := num + 1]. > > + ^ selector, num! > > > > Item was removed: > > - ----- Method: CompilerExceptionsTest>>setUp (in category 'running') ----- > > - setUp > > - > > - super setUp. > > - tearDowns := OrderedCollection new. > > - Symbol hasInterned: self unknownSelector ifTrue: [:symbol | > > - tearDowns add: [Symbol intern: symbol]]. > > - Symbol extern: self unknownSelector.! > > > > Item was changed: > > ----- Method: CompilerExceptionsTest>>tearDown (in category 'running') ----- > > tearDown > > > > self removeGeneratedMethods. > > - Symbol extern: self unknownSelector. > > - tearDowns do: #value. > > super tearDown.! > > > > Item was changed: > > ----- Method: CompilerExceptionsTest>>testUnknownSelector (in category 'tests') ----- > > testUnknownSelector > > > > + | unknownSelector | > > + self flag: #flaky. "mt: This test depends on a list of suggestions that is derived from the system's known selectors. Any desired replacement might not be present in the actual list. Maybe we could use an index-based choice instead." > > + unknownSelector := self generateUnknownSelector. > > self > > + compiling: 'griffle self ' , unknownSelector > > - compiling: 'griffle self ' , self unknownSelector > > shouldRaise: UnknownSelector > > + andSelect: unknownSelector > > - andSelect: self unknownSelector > > testing: { > > + false -> [ > > + self assertCanceled. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + 'yourself' -> [ > > + self assertSucceeded: 'griffle self yourself'. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + unknownSelector -> [ > > - false -> [self assertCanceled]. > > - 'yourself' -> [self assertSucceeded: 'griffle self yourself']. > > - self unknownSelector -> [ > > self assertSucceeded. > > + self assert: (Symbol lookup: unknownSelector) notNil] }. > > + unknownSelector := self generateUnknownSelector. > > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |]). > > - Symbol extern: self unknownSelector] }. > > self > > + compiling: 'griffle [ self ' , unknownSelector , ' ] value' > > - compiling: 'griffle [ self ' , self unknownSelector , ' ] value' > > shouldRaise: UnknownSelector > > + andSelect: unknownSelector > > - andSelect: self unknownSelector > > testing: { > > + false -> [ > > + self assertCanceled. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + 'yourself' -> [ > > + self assertSucceeded: 'griffle [ self yourself ] value'. > > + self assert: (Symbol lookup: unknownSelector) isNil]. > > + unknownSelector -> [ > > - false -> [self assertCanceled]. > > - 'yourself' -> [self assertSucceeded: 'griffle [ self yourself ] value']. > > - self unknownSelector -> [ > > self assertSucceeded. > > + self assert: (Symbol lookup: unknownSelector) notNil] }.! > > - self assert: (Symbol hasInterned: self unknownSelector ifTrue: [:symbol |])] }.! > > > > Item was removed: > > - ----- Method: CompilerExceptionsTest>>unknownSelector (in category 'private') ----- > > - unknownSelector > > - > > - ^ 'yourrsellff'! > > > > Item was removed: > > - ----- Method: Symbol class>>extern: (in category '*Tests-release') ----- > > - extern: aStringOrSymbol > > - > > - {NewSymbols. SymbolTable} do: [:table | > > - table remove: aStringOrSymbol ifAbsent: []].! > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Apr 13 10:10:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 10:10:15 0000 Subject: [squeak-dev] The Inbox: 60Deprecated-nice.94.mcz Message-ID: Nicolas Cellier uploaded a new version of 60Deprecated to project The Inbox: http://source.squeak.org/inbox/60Deprecated-nice.94.mcz ==================== Summary ==================== Name: 60Deprecated-nice.94 Author: nice Time: 13 April 2021, 12:10:09.32989 pm UUID: 2efd14b2-b4f1-3247-848e-c5f8f0ef9ced Ancestors: 60Deprecated-dtl.93 Deprecate Symbol findInterned: aString in favour of lookup: BEWARE: #findInterned: is an old dialect that might still be used by a Number of external packages, including refactoring browser. This must be discussed. =============== Diff against 60Deprecated-dtl.93 =============== Item was added: + ----- Method: Symbol class>>findInterned: (in category '*60Deprecated-instance creation') ----- + findInterned: aString + + self deprecated: 'Use #lookup: instead.'. + ^ self lookup: aString! From marcel.taeumel at hpi.de Tue Apr 13 10:13:08 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 12:13:08 +0200 Subject: [squeak-dev] The Inbox: 60Deprecated-nice.94.mcz In-Reply-To: References: Message-ID: Hi Nicolas, actually deprecating Symbol API is often dangerous. Especially since Monticello installs moved methods before other changes. I vote for "self flag: #deprecated" or an extra checkpoint in Squeak's update map. Best, Marcel Am 13.04.2021 12:10:22 schrieb commits at source.squeak.org : Nicolas Cellier uploaded a new version of 60Deprecated to project The Inbox: http://source.squeak.org/inbox/60Deprecated-nice.94.mcz ==================== Summary ==================== Name: 60Deprecated-nice.94 Author: nice Time: 13 April 2021, 12:10:09.32989 pm UUID: 2efd14b2-b4f1-3247-848e-c5f8f0ef9ced Ancestors: 60Deprecated-dtl.93 Deprecate Symbol findInterned: aString in favour of lookup: BEWARE: #findInterned: is an old dialect that might still be used by a Number of external packages, including refactoring browser. This must be discussed. =============== Diff against 60Deprecated-dtl.93 =============== Item was added: + ----- Method: Symbol class>>findInterned: (in category '*60Deprecated-instance creation') ----- + findInterned: aString + + self deprecated: 'Use #lookup: instead.'. + ^ self lookup: aString! -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 10:20:20 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 12:20:20 +0200 Subject: [squeak-dev] The Inbox: 60Deprecated-nice.94.mcz In-Reply-To: References: Message-ID: It's in the inbox precisely for discussion :) Le mar. 13 avr. 2021 à 12:13, Marcel Taeumel a écrit : > > Hi Nicolas, > > actually deprecating Symbol API is often dangerous. Especially since Monticello installs moved methods before other changes. I vote for "self flag: #deprecated" or an extra checkpoint in Squeak's update map. > > Best, > Marcel > > Am 13.04.2021 12:10:22 schrieb commits at source.squeak.org : > > Nicolas Cellier uploaded a new version of 60Deprecated to project The Inbox: > http://source.squeak.org/inbox/60Deprecated-nice.94.mcz > > ==================== Summary ==================== > > Name: 60Deprecated-nice.94 > Author: nice > Time: 13 April 2021, 12:10:09.32989 pm > UUID: 2efd14b2-b4f1-3247-848e-c5f8f0ef9ced > Ancestors: 60Deprecated-dtl.93 > > Deprecate Symbol findInterned: aString in favour of lookup: > > BEWARE: #findInterned: is an old dialect that might still be used by a Number of external packages, including refactoring browser. > > This must be discussed. > > =============== Diff against 60Deprecated-dtl.93 =============== > > Item was added: > + ----- Method: Symbol class>>findInterned: (in category '*60Deprecated-instance creation') ----- > + findInterned: aString > + > + self deprecated: 'Use #lookup: instead.'. > + ^ self lookup: aString! > > > From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 10:28:38 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 12:28:38 +0200 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: And one of the two duplicated Symbol #openPluggableFileListLabel:in: appear as both added and removed method in 60Deprecated package! (see png attached) Le mar. 13 avr. 2021 à 11:22, Nicolas Cellier a écrit : > > I have a clue: > > Symbol allSubInstances reject: [:s | (Symbol findInterned: s > asString) == s]. > > returns two problematic Symbols: > > OrderedCollection(#openPluggableFileListLabel:in: > #dialogStringFromQuery:withTitle:). > > This means that some duplicated symbols still exist in my image... > And they can end up in the SymbolTable thru (Symbol rehash). > > Who did create those duplicates remains an open question, but how the > duplicates might sneak into the SymbolTable is no more a mystery > (though it remains to analyze who does Symbol rehash...) > > Le mar. 13 avr. 2021 à 10:10, Marcel Taeumel a écrit : > > > > Maybe unrelated, but I will remove that extension "Symbol >> #extern:", which manipulates the symbol tables for a single test in CompilerExceptionTest, present since March 2020. I think that 1) garbage collection should take care of unused symbols and 2) test can find a better way to produce "unknown symbols" :-) > > > > Best, > > Marcel > > > > Am 13.04.2021 07:16:48 schrieb Chris Muller : > >> > >> For those wondering, the problem is that some Symbol get duplicated > >> violating the contract: > >> any two Symbols are either identical (==) or different (~=). > > > > > > Possible become without copyHash? > > > > -------------- next part -------------- A non-text attachment was scrubbed... Name: deprecated.png Type: image/png Size: 9154 bytes Desc: not available URL: From commits at source.squeak.org Tue Apr 13 11:35:35 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 11:35:35 0000 Subject: [squeak-dev] The Trunk: Morphic-nice.1625.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-nice.1625.mcz ==================== Summary ==================== Name: Morphic-nice.1625 Author: nice Time: 17 February 2020, 5:06:10.606532 pm UUID: 094e2566-ddfe-2340-8fab-2338d255e164 Ancestors: Morphic-mt.1624 Free our mind from un-initialized LayoutFrame. There should not be any such thing. Require Graphics-nice.425 =============== Diff against Morphic-mt.1624 =============== Item was changed: ----- Method: BorderedMorph>>addMorph:fullFrame: (in category 'resize handling') ----- addMorph: aMorph fullFrame: aLayoutFrame "Add aMorph according to aLayoutFrame." self cellGap > 0 ifTrue: [ | left right bottom top spacing | spacing := self cellGap. + left := aLayoutFrame leftOffset. + right := aLayoutFrame rightOffset. - left := aLayoutFrame leftOffset ifNil: [0]. - right := aLayoutFrame rightOffset ifNil: [0]. + bottom := aLayoutFrame bottomOffset. + top := aLayoutFrame topOffset. - bottom := aLayoutFrame bottomOffset ifNil: [0]. - top := aLayoutFrame topOffset ifNil: [0]. "Add a spacing to the frame if it is not top or leftmost." aLayoutFrame leftFraction = 0 ifFalse: [left := left + spacing] ifTrue: [ "Expect another, resizable widget besides me if I have a fixed width." aLayoutFrame hasFixedWidth ifTrue: [right := right - spacing]]. aLayoutFrame topFraction = 0 ifFalse: [top := top + spacing] ifTrue: [ "Expect another, resizable widget besides me if I have a fixed height." aLayoutFrame hasFixedHeight ifTrue: [bottom := bottom - spacing]]. aLayoutFrame topOffset: top; bottomOffset: bottom; leftOffset: left; rightOffset: right]. super addMorph: aMorph fullFrame: aLayoutFrame. self wantsPaneSplitters ifTrue: [self addPaneSplitters].! Item was changed: ----- Method: BorderedMorph>>addPaneHSplitterAtBottomOfRow: (in category 'resize handling') ----- addPaneHSplitterAtBottomOfRow: someMorphs | targetY minX maxX splitter | targetY := someMorphs first layoutFrame bottomFraction. minX := (someMorphs detectMin: [:each | each layoutFrame leftFraction]) layoutFrame leftFraction. maxX := (someMorphs detectMax: [:each | each layoutFrame rightFraction]) layoutFrame rightFraction. splitter := ProportionalSplitterMorph new beSplitsTopAndBottom; yourself. splitter layoutFrame: (LayoutFrame fractions: (minX @ targetY corner: maxX @ targetY) + offsets: (someMorphs first layoutFrame leftOffset @ 0 + corner: someMorphs first layoutFrame rightOffset @ AbstractResizerMorph gripThickness)). - offsets: ((someMorphs first layoutFrame leftOffset ifNil: [0]) @ 0 - corner: (someMorphs first layoutFrame rightOffset ifNil: [0]) @ AbstractResizerMorph gripThickness)). self addMorphBack: (splitter position: self position).! Item was changed: ----- Method: BorderedMorph>>addPaneVSplitterAtRightOfColumn: (in category 'resize handling') ----- addPaneVSplitterAtRightOfColumn: someMorphs | targetX minY maxY splitter | targetX := someMorphs first layoutFrame rightFraction. minY := (someMorphs detectMin: [:each | each layoutFrame topFraction]) layoutFrame topFraction. maxY := (someMorphs detectMax: [:each | each layoutFrame bottomFraction]) layoutFrame bottomFraction. splitter := ProportionalSplitterMorph new beSplitsLeftAndRight; yourself. splitter layoutFrame: (LayoutFrame fractions: (targetX @ minY corner: targetX @ maxY) + offsets: (0 @ (someMorphs first layoutFrame topOffset) + corner: (AbstractResizerMorph gripThickness@ (someMorphs first layoutFrame bottomOffset)))). - offsets: (0 @ (someMorphs first layoutFrame topOffset ifNil: [0]) - corner: (AbstractResizerMorph gripThickness@ (someMorphs first layoutFrame bottomOffset ifNil: [0])))). self addMorphBack: (splitter position: self position).! Item was changed: ----- Method: BorderedMorph>>linkSubmorphsToSplitters (in category 'resize handling') ----- linkSubmorphsToSplitters self splitters do: [:splitter | splitter splitsTopAndBottom ifTrue: [ self submorphsDo: [:morph | ((morph ~= splitter and: [morph layoutFrame bottomFraction = splitter layoutFrame topFraction]) and: [morph layoutFrame hasFixedHeight not + or: [(morph layoutFrame topOffset) < 0]]) - or: [(morph layoutFrame topOffset ifNil: [0]) < 0]]) ifTrue: [splitter addLeftOrTop: morph]. ((morph ~= splitter and: [morph layoutFrame topFraction = splitter layoutFrame bottomFraction]) and: [morph layoutFrame hasFixedHeight not + or: [(morph layoutFrame bottomOffset) > 0]]) - or: [(morph layoutFrame bottomOffset ifNil: [0]) > 0]]) ifTrue: [splitter addRightOrBottom: morph]]]. splitter splitsLeftAndRight ifTrue: [ self submorphsDo: [:morph | ((morph ~= splitter and: [morph layoutFrame rightFraction = splitter layoutFrame leftFraction]) and: [morph layoutFrame hasFixedWidth not + or: [(morph layoutFrame leftOffset) < 0]]) - or: [(morph layoutFrame leftOffset ifNil: [0]) < 0]]) ifTrue: [splitter addLeftOrTop: morph]. ((morph ~= splitter and: [morph layoutFrame leftFraction = splitter layoutFrame rightFraction]) and: [morph layoutFrame hasFixedWidth not + or: [(morph layoutFrame rightOffset) > 0]]) - or: [(morph layoutFrame rightOffset ifNil: [0]) > 0]]) ifTrue: [splitter addRightOrBottom: morph]]]]! Item was changed: ----- Method: ProportionalSplitterMorph>>balanceOffsets (in category 'events') ----- balanceOffsets | fdx fdy | (self hasProperty: #fullDelta) ifFalse: [^ self]. fdx := (self valueOfProperty: #fullDelta) x. fdy := (self valueOfProperty: #fullDelta) y. self layoutFrame hasFixedHeight ifTrue: [ | otop obot ctop cbot topf | otop := (owner submorphs detect: [:m | m layoutFrame topFraction isZero] ifNone: [^ self]) in: [:tm | + tm top - (tm layoutFrame topOffset)]. - tm top - (tm layoutFrame topOffset ifNil: [0])]. obot := (owner submorphs detect: [:m | m layoutFrame bottomFraction = 1] ifNone: [^ self]) in: [:tm | + tm bottom - (tm layoutFrame bottomOffset)]. - tm bottom - (tm layoutFrame bottomOffset ifNil: [0])]. ctop := (self layoutFrame topFraction * (obot - otop)) rounded + + otop + (self layoutFrame topOffset). - + otop + (self layoutFrame topOffset ifNil: [0]). cbot := (self layoutFrame bottomFraction * (obot - otop)) rounded + + otop + (self layoutFrame bottomOffset). - + otop + (self layoutFrame bottomOffset ifNil: [0]). topf := self layoutFrame topFraction. self layoutFrame topFraction: ((ctop + cbot) * 0.5 - otop) / (obot - otop) asFloat. self layoutFrame bottomFraction: self layoutFrame topFraction. self layoutFrame topOffset: self layoutFrame topOffset - fdy. self layoutFrame bottomOffset: self layoutFrame bottomOffset - fdy. (leftOrTop copy union: rightOrBottom) do: [:m | (m layoutFrame topFraction closeTo: topf) ifTrue: [ m layoutFrame topFraction: self layoutFrame topFraction. m layoutFrame topOffset: m layoutFrame topOffset - fdy]. (m layoutFrame bottomFraction closeTo: topf) ifTrue: [ m layoutFrame bottomFraction: self layoutFrame topFraction. m layoutFrame bottomOffset: m layoutFrame bottomOffset - fdy]]] . self layoutFrame hasFixedWidth ifTrue: [ | oleft oright cleft cright leftf | oleft := (owner submorphs detect: [:m | m layoutFrame leftFraction isZero] ifNone: [^ self]) in: [:tm | + tm left - (tm layoutFrame leftOffset)]. - tm left - (tm layoutFrame leftOffset ifNil: [0])]. oright := (owner submorphs detect: [:m | m layoutFrame rightFraction = 1] ifNone: [^ self]) in: [:tm | + tm right - (tm layoutFrame rightOffset)]. - tm right - (tm layoutFrame rightOffset ifNil: [0])]. cleft := (self layoutFrame leftFraction * (oright - oleft)) rounded + + oleft + (self layoutFrame leftOffset). - + oleft + (self layoutFrame leftOffset ifNil: [0]). cright := (self layoutFrame rightFraction * (oright - oleft)) rounded + + oleft + (self layoutFrame rightOffset). - + oleft + (self layoutFrame rightOffset ifNil: [0]). leftf := self layoutFrame leftFraction. self layoutFrame leftFraction: ((cleft + cright) * 0.5 - oleft) / (oright - oleft) asFloat. self layoutFrame rightFraction: self layoutFrame leftFraction. self layoutFrame leftOffset: self layoutFrame leftOffset - fdx. self layoutFrame rightOffset: self layoutFrame rightOffset - fdx. (leftOrTop copy union: rightOrBottom) do: [:m | (m layoutFrame leftFraction closeTo: leftf) ifTrue: [ m layoutFrame leftFraction: self layoutFrame leftFraction. m layoutFrame leftOffset: m layoutFrame leftOffset - fdx]. (m layoutFrame rightFraction closeTo: leftf) ifTrue: [ m layoutFrame rightFraction: self layoutFrame leftFraction. m layoutFrame rightOffset: m layoutFrame rightOffset - fdx.]]] . self removeProperty: #fullDelta. owner layoutChanged ! Item was changed: ----- Method: ProportionalSplitterMorph>>repositionBy: (in category 'events') ----- repositionBy: delta | selfTop selfBottom selfLeft selfRight | self setProperty: #fullDelta toValue: ((self valueOfProperty: #fullDelta) ifNil: [0 at 0]) + delta. leftOrTop do: [ : each | | firstRight firstBottom firstLeft firstTop | + firstRight := each layoutFrame rightOffset. + firstBottom := each layoutFrame bottomOffset. - firstRight := each layoutFrame rightOffset ifNil: [ 0 ]. - firstBottom := each layoutFrame bottomOffset ifNil: [ 0 ]. each layoutFrame rightOffset: firstRight + delta x. each layoutFrame bottomOffset: firstBottom + delta y. each layoutFrame hasFixedHeight ifTrue: [ + firstTop := each layoutFrame topOffset. - firstTop := each layoutFrame topOffset ifNil: [ 0 ]. each layoutFrame topOffset: firstTop + delta y ]. each layoutFrame hasFixedWidth ifTrue: [ + firstLeft := each layoutFrame leftOffset. - firstLeft := each layoutFrame leftOffset ifNil: [ 0 ]. each layoutFrame leftOffset: firstLeft + delta x. ] ]. rightOrBottom do: [ : each | | secondLeft secondTop secondRight secondBottom | + secondLeft := each layoutFrame leftOffset. + secondTop := each layoutFrame topOffset. - secondLeft := each layoutFrame leftOffset ifNil: [ 0 ]. - secondTop := each layoutFrame topOffset ifNil: [ 0 ]. each layoutFrame leftOffset: secondLeft + delta x. each layoutFrame topOffset: secondTop + delta y. each layoutFrame hasFixedHeight ifTrue: [ + secondBottom := each layoutFrame bottomOffset. - secondBottom := each layoutFrame bottomOffset ifNil: [ 0 ]. each layoutFrame bottomOffset: secondBottom + delta y. ]. each layoutFrame hasFixedWidth ifTrue: [ + secondRight := each layoutFrame rightOffset. - secondRight := each layoutFrame rightOffset ifNil: [ 0 ]. each layoutFrame rightOffset: secondRight + delta x. ] ]. + selfTop := self layoutFrame topOffset. + selfBottom := self layoutFrame bottomOffset. + selfLeft := self layoutFrame leftOffset. + selfRight := self layoutFrame rightOffset. - selfTop := self layoutFrame topOffset ifNil: [ 0 ]. - selfBottom := self layoutFrame bottomOffset ifNil: [ 0 ]. - selfLeft := self layoutFrame leftOffset ifNil: [ 0 ]. - selfRight := self layoutFrame rightOffset ifNil: [ 0 ]. self layoutFrame topOffset: selfTop + delta y ; bottomOffset: selfBottom + delta y ; leftOffset: selfLeft + delta x ; rightOffset: selfRight + delta x. self owner layoutChanged. self movements removeFirst; add: (splitsTopAndBottom ifTrue: [ delta y sign ] ifFalse: [ delta x sign ])! Item was changed: ----- Method: SystemWindow>>convertAlignment (in category 'layout') ----- convertAlignment "Primarily Jesse Welton's code to convert old system windows to ones with modern layout scheme" self layoutPolicy: ProportionalLayout new. (paneMorphs isNil or: [paneRects isNil or: [paneMorphs size ~= paneRects size]]) ifFalse: [self addLabelArea. self putLabelItemsInLabelArea. self setFramesForLabelArea. paneMorphs with: paneRects do: [:m :r | | frame | frame := LayoutFrame new. frame leftFraction: r left; rightFraction: r right; topFraction: r top; bottomFraction: r bottom. m layoutFrame: frame. m hResizing: #spaceFill; vResizing: #spaceFill]]. labelArea isNil ifTrue: [self addLabelArea. self putLabelItemsInLabelArea. self setFramesForLabelArea. paneMorphs ifNotNil: [paneMorphs do: [:m | | frame | frame := m layoutFrame ifNil: [LayoutFrame new]. + frame topOffset: (frame topOffset) - self labelHeight. - frame topOffset: (frame topOffset ifNil: [0]) - self labelHeight. frame bottomFraction ~= 1.0 ifTrue: + [frame bottomOffset: (frame bottomOffset) - self labelHeight]]]]. - [frame bottomOffset: (frame bottomOffset ifNil: [0]) - self labelHeight]]]]. label ifNotNil: [| frame | frame := LayoutFrame new. frame leftFraction: 0.5; topFraction: 0; leftOffset: label width negated // 2. label layoutFrame: frame]. collapseBox ifNotNil: [| frame | frame := LayoutFrame new. frame rightFraction: 1; topFraction: 0; rightOffset: -1; topOffset: 1. collapseBox layoutFrame: frame]. stripes ifNotNil: [| frame | frame := LayoutFrame new. frame leftFraction: 0; topFraction: 0; rightFraction: 1; leftOffset: 1; topOffset: 1; rightOffset: -1. stripes first layoutFrame: frame. stripes first height: self labelHeight - 2. stripes first hResizing: #spaceFill. frame := LayoutFrame new. frame leftFraction: 0; topFraction: 0; rightFraction: 1; leftOffset: 3; topOffset: 3; rightOffset: -3. stripes last layoutFrame: frame. stripes last height: self labelHeight - 6. stripes last hResizing: #spaceFill]. menuBox ifNotNil: [| frame | frame := LayoutFrame new. frame leftFraction: 0; leftOffset: 19; topFraction: 0; topOffset: 1. menuBox layoutFrame: frame]. closeBox ifNotNil: [| frame | frame := LayoutFrame new. frame leftFraction: 0; leftOffset: 4; topFraction: 0; topOffset: 1. closeBox layoutFrame: frame]! Item was changed: ----- Method: SystemWindow>>setPaneRectsFromBounds (in category 'geometry') ----- setPaneRectsFromBounds "Reset proportional specs from actual bounds, eg, after reframing panes" | layoutBounds | layoutBounds := self layoutBounds. paneMorphs do:[:m| | box left bottom top frame right | frame := m layoutFrame. box := m bounds. frame ifNotNil:[ + left := box left - layoutBounds left - frame leftOffset. + right := box right - layoutBounds left - frame rightOffset. + top := box top - layoutBounds top - frame topOffset. + bottom := box bottom - layoutBounds top - frame bottomOffset. - left := box left - layoutBounds left - (frame leftOffset ifNil:[0]). - right := box right - layoutBounds left - (frame rightOffset ifNil:[0]). - top := box top - layoutBounds top - (frame topOffset ifNil:[0]). - bottom := box bottom - layoutBounds top - (frame bottomOffset ifNil:[0]). frame leftFraction: (left / layoutBounds width asFloat). frame rightFraction: (right / layoutBounds width asFloat). frame topFraction: (top / layoutBounds height asFloat). frame bottomFraction: (bottom / layoutBounds height asFloat). ]. ].! From commits at source.squeak.org Tue Apr 13 11:41:21 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 11:41:21 0000 Subject: [squeak-dev] The Trunk: Graphics-ct.418.mcz Message-ID: Marcel Taeumel uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-ct.418.mcz ==================== Summary ==================== Name: Graphics-ct.418 Author: ct Time: 20 September 2019, 7:41:50.741726 pm UUID: eabbce5b-ef86-6e42-8fb2-8b789a51d798 Ancestors: Graphics-nice.417 Add Color>>#veryMuchDarker We also have #veryMuchLighter, so balance this out :) =============== Diff against Graphics-nice.417 =============== Item was added: + ----- Method: Color>>veryMuchDarker (in category 'transformations') ----- + veryMuchDarker + + ^ self alphaMixed: 0.25 with: Color black + ! From commits at source.squeak.org Tue Apr 13 12:17:45 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 12:17:45 0000 Subject: [squeak-dev] The Trunk: Graphics-mt.447.mcz Message-ID: Marcel Taeumel uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-mt.447.mcz ==================== Summary ==================== Name: Graphics-mt.447 Author: mt Time: 13 April 2021, 2:17:38.592381 pm UUID: 297ae9ef-ec22-b340-b60d-2639c8765aa4 Ancestors: Graphics-mt.446, Graphics-ct.437, Graphics-ct.419 Merges Graphics-ct.437, Graphics-ct.419 -- which complements Graphics-cbc.372 (Note that I think it makes sense to either let #isIntegerRectangle always decide on rounding or introduce an IntegerRectangle as proposed by Eliot some time ago. Rectangles are usually immutable anyway. http://forum.world.st/The-Inbox-Graphics-cbc-372-mcz-tp4940274p4940451.html) =============== Diff against Graphics-mt.446 =============== Item was added: + ----- Method: Point>>exactCenter: (in category 'converting to rectangle') ----- + exactCenter: aPoint + "Answer a Rectangle whose extent is the receiver and whose center is exactly aPoint. This is one of the infix ways of expressing the creation of a rectangle." + + ^ Rectangle exactCenter: aPoint extent: self! Item was added: + ----- Method: Rectangle>>pointAtFraction: (in category 'rectangle functions') ----- + pointAtFraction: relativePoint + + | result | + result := self origin + (self extent * relativePoint). + ^ self isIntegerRectangle + ifTrue: [result rounded] + ifFalse: [result]! From commits at source.squeak.org Tue Apr 13 12:18:41 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 12:18:41 0000 Subject: [squeak-dev] The Trunk: Graphics-ct.437.mcz Message-ID: Marcel Taeumel uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-ct.437.mcz ==================== Summary ==================== Name: Graphics-ct.437 Author: ct Time: 24 August 2020, 1:26:40.516818 pm UUID: 66c6c2fd-6978-6d43-8eda-c22f0a5defca Ancestors: Graphics-kfr.436 Proposal: Add Point >> #exactCenter:, complementing Graphics-cbc.372. Refine relevant method comments in Point and Rectangle. Usage example: m := Morph new. m changeProportionalLayout. n := Morph new. n color: Color red. m addMorph: n fullFrame: (LayoutFrame fractions: ( 0.5 @ 0.25 exactCenter: 0.5 @ 0.5)). m openInHand. =============== Diff against Graphics-kfr.436 =============== Item was changed: ----- Method: Point>>center: (in category 'converting to rectangle') ----- center: aPoint + "Answer a Rectangle whose extent is the receiver and whose center is approximately aPoint (after rounding to integers). This is one of the infix ways of expressing the creation of a rectangle." - "Answer a Rectangle whose extent is the receiver and whose center is - aPoint. This is one of the infix ways of expressing the creation of a - rectangle." + ^ Rectangle center: aPoint extent: self! - ^Rectangle center: aPoint extent: self! Item was added: + ----- Method: Point>>exactCenter: (in category 'converting to rectangle') ----- + exactCenter: aPoint + "Answer a Rectangle whose extent is the receiver and whose center is exactly aPoint. This is one of the infix ways of expressing the creation of a rectangle." + + ^ Rectangle exactCenter: aPoint extent: self! Item was changed: ----- Method: Rectangle class>>center:extent: (in category 'instance creation') ----- center: centerPoint extent: extentPoint + "Answer an instance of me whose center is approximately centerPoint (after rounding to integers) and whose extent is extentPoint." - "Answer an instance of me whose center is centerPoint and width - by height is extentPoint. " + ^ self origin: centerPoint - (extentPoint // 2) extent: extentPoint! - ^self origin: centerPoint - (extentPoint//2) extent: extentPoint! Item was changed: ----- Method: Rectangle class>>exactCenter:extent: (in category 'instance creation') ----- exactCenter: centerPoint extent: extentPoint + "Answer an instance of me whose center is exactly centerPoint and whose extent is extentPoint." + - "Answer an instance of me whose center is centerPoint and width - by height is extentPoint. " ^ self origin: centerPoint - (extentPoint / 2) extent: extentPoint ! From commits at source.squeak.org Tue Apr 13 12:18:57 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 12:18:57 0000 Subject: [squeak-dev] The Trunk: Graphics-ct.419.mcz Message-ID: Marcel Taeumel uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-ct.419.mcz ==================== Summary ==================== Name: Graphics-ct.419 Author: ct Time: 20 September 2019, 7:45:53.388726 pm UUID: 5deebfce-0321-9645-aebd-0b4bfb428259 Ancestors: Graphics-nice.417 Add Rectangle>>#pointAtFraction: Example: [(5 at 5 rect: 10 at 20) pointAtFraction: 0.5 at 1] will give you 7.5 @ 20. dep:feat-ol =============== Diff against Graphics-nice.417 =============== Item was added: + ----- Method: Rectangle>>pointAtFraction: (in category 'rectangle functions') ----- + pointAtFraction: relativePoint + + ^ self origin + (self extent * relativePoint)! From commits at source.squeak.org Tue Apr 13 12:36:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 12:36:15 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1744.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1744.mcz ==================== Summary ==================== Name: Morphic-mt.1744 Author: mt Time: 13 April 2021, 2:36:03.188381 pm UUID: 4f11bc72-a3e8-f641-bccd-13f087ce6464 Ancestors: Morphic-nice.1743, Morphic-ct.1528 Merges Morphic-ct.1528 with extended commentary. =============== Diff against Morphic-nice.1743 =============== Item was added: + ----- Method: Morph>>pointAtFraction: (in category 'geometry') ----- + pointAtFraction: relativePoint + "For values between 0.0 and 1.0, answers a point that lies within the receiver's bounds. This method is a more general form of #center (meaning 0.5 at 0.5), #topLeft (meaning 0.0 at 0.0), #bottomCenter (meaning 0.5 at 1.0), etc. If can be useful for layout policies that want to position or resize their submorphs by fraction." + + ^ self bounds pointAtFraction: relativePoint! From commits at source.squeak.org Tue Apr 13 12:36:50 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 12:36:50 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1528.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1528.mcz ==================== Summary ==================== Name: Morphic-ct.1528 Author: ct Time: 20 September 2019, 8:29:00.755726 pm UUID: 343a1917-50b8-6c4e-8faf-2252dd3dcf63 Ancestors: Morphic-mt.1526 Implement #pointAtFraction: in Morph Complements Graphics-ct.419 =============== Diff against Morphic-mt.1526 =============== Item was added: + ----- Method: Morph>>pointAtFraction: (in category 'geometry') ----- + pointAtFraction: relativePoint + + ^ self bounds pointAtFraction: relativePoint! From commits at source.squeak.org Tue Apr 13 13:38:24 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 13:38:24 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1745.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1745.mcz ==================== Summary ==================== Name: Morphic-mt.1745 Author: mt Time: 13 April 2021, 3:38:18.936381 pm UUID: 7e11094a-3fe8-a049-8282-2a50dde1647f Ancestors: Morphic-mt.1744, Morphic-ct.1529 Merges Morphic-ct.1529 yet favor "assure" over "ensure", following the existing interface in Morph. Also, there already is #addFlexShellIfNecessary, so let's just use that. =============== Diff against Morphic-mt.1744 =============== Item was added: + ----- Method: Morph>>assureFlexShell (in category 'rotate scale and flex') ----- + assureFlexShell + "Canonical assure message when working with flex shells." + + ^ self addFlexShellIfNecessary! Item was added: + ----- Method: TransformationMorph>>addFlexShellIfNecessary (in category 'rotate scale and flex') ----- + addFlexShellIfNecessary + "I already am a flex shell."! From commits at source.squeak.org Tue Apr 13 13:38:54 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 13:38:54 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1529.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1529.mcz ==================== Summary ==================== Name: Morphic-ct.1529 Author: ct Time: 20 September 2019, 8:31:06.547726 pm UUID: 872c2c23-b57a-e44d-b8bb-b9a43f58151e Ancestors: Morphic-mt.1526 Utility: Morph >> #ensureFlexShell Avoid nesting a Morph into multiple flex shells in some scenarios. =============== Diff against Morphic-mt.1526 =============== Item was added: + ----- Method: Morph>>ensureFlexShell (in category 'rotate scale and flex') ----- + ensureFlexShell + + ^ self addFlexShell! Item was added: + ----- Method: TransformationMorph>>ensureFlexShell (in category 'rotate scale and flex') ----- + ensureFlexShell + + ^ self! From commits at source.squeak.org Tue Apr 13 13:54:30 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 13:54:30 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1746.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1746.mcz ==================== Summary ==================== Name: Morphic-mt.1746 Author: mt Time: 13 April 2021, 3:54:24.673381 pm UUID: 5d6b1c65-025e-d44a-98f0-d73358bb9a0e Ancestors: Morphic-mt.1745, Morphic-ct.1531, Morphic-ct.1539, Morphic-ct.1556 Merges bugfixes and QoL enhancements from Morphic-ct.1531, Morphic-ct.1539, Morphic-ct.1556 =============== Diff against Morphic-mt.1745 =============== Item was changed: ----- Method: MorphicProject>>canApplyUserInterfaceTheme (in category 'updating') ----- canApplyUserInterfaceTheme + ^ world notNil! - ^ true! Item was changed: ----- Method: MorphicProject>>previewImageForm (in category 'display') ----- previewImageForm + ^ self world imageForm scaledToSize: self viewSize! - ^ self world imageForm! Item was added: + ----- Method: NewColorPickerMorph class>>on:colorSelector: (in category 'create') ----- + on: objectToHaveItsColorSet colorSelector: colorSymbol + ^ self + on: objectToHaveItsColorSet + getColorSelector: colorSymbol + setColorSelector: colorSymbol asMutator! Item was added: + ----- Method: NewColorPickerMorph class>>on:getColorSelector:setColorSelector: (in category 'create') ----- + on: objectToHaveItsColorSet getColorSelector: colorGetterSymbol setColorSelector: colorSetterSymbol + ^ self + on: objectToHaveItsColorSet + originalColor: (colorGetterSymbol value: objectToHaveItsColorSet) + setColorSelector: colorSetterSymbol! Item was changed: ----- Method: ProjectViewMorph class>>newProjectViewInAWindowFor: (in category 'project window creation') ----- newProjectViewInAWindowFor: aProject "Return an instance of me on a new Morphic project (in a SystemWindow)." | window proj | proj := self on: aProject. window := (SystemWindow labelled: aProject name) model: aProject. + window extent: proj extent. window addMorph: proj frame: (0 at 0 corner: 1.0 at 1.0). proj borderWidth: 0. ^ window ! Item was changed: ----- Method: ProjectViewMorph class>>openOn: (in category 'instance creation') ----- openOn: aProject "Open a ProjectViewMorph for the project in question" + ProjectViewOpenNotification signal ifFalse: [^ self]. + + (Preferences projectViewsInWindows + ifTrue: [ (self newProjectViewInAWindowFor: aProject) ] + ifFalse: [ (self on: aProject) ]) + openAsTool.! - ProjectViewOpenNotification signal ifTrue: [ - Preferences projectViewsInWindows ifTrue: [ - (self newProjectViewInAWindowFor: aProject) openInWorld - ] ifFalse: [ - (self on: aProject) openInWorld "but where??" - ]. - ]. - ! Item was added: + ----- Method: ProjectViewMorph>>initialExtent (in category 'geometry') ----- + initialExtent + + ^ 300 @ 200! Item was changed: ----- Method: ProjectViewMorph>>initialize (in category 'initialization') ----- initialize "Initialize the receiver." super initialize. + self extent: self initialExtent * RealEstateAgent scaleFactor. "currentBorderColor := Color gray." self addProjectNameMorphFiller. self enableDragNDrop: true. self isOpaque: true. ! Item was changed: ----- Method: ProjectViewMorph>>on: (in category 'events') ----- on: aProject project := aProject. self addProjectNameMorphFiller. lastProjectThumbnail := nil. + project viewSize ifNil: [project viewSize: self extent]. project thumbnail: project previewImageForm. + self extent: project thumbnail extent.! - project thumbnail - ifNil: [self extent: 100 at 80] "more like screen dimensions?" - ifNotNil: [self extent: project thumbnail extent].! From commits at source.squeak.org Tue Apr 13 13:54:51 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 13:54:51 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1531.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1531.mcz ==================== Summary ==================== Name: Morphic-ct.1531 Author: ct Time: 20 September 2019, 8:46:54.327726 pm UUID: 9ba3d907-10d4-524a-9e97-cd66a530f0ef Ancestors: Morphic-mt.1526 Fix a bug in MorphicProject>>#applyUserInterfaceTheme While working with many Projects during the latest weeks, I often noticed DNUs when changing the UI theme. Apparently UserInterfaceTheme>>#apply asks ALL objects in memory to apply the theme, so if a project was recently closed and not yet gc'ed, I got an error. =============== Diff against Morphic-mt.1526 =============== Item was changed: ----- Method: MorphicProject>>canApplyUserInterfaceTheme (in category 'updating') ----- canApplyUserInterfaceTheme + ^ world notNil! - ^ true! From commits at source.squeak.org Tue Apr 13 13:55:03 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 13:55:03 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1534.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1534.mcz ==================== Summary ==================== Name: Morphic-ct.1534 Author: ct Time: 20 September 2019, 8:57:09.233726 pm UUID: 9adeb330-a9c3-9b4c-a8e8-ee1ff7566968 Ancestors: Morphic-mt.1526 Add convenience constructor for NewColorPickerMorph. We don't need a color if we have the getter. =============== Diff against Morphic-mt.1526 =============== Item was added: + ----- Method: NewColorPickerMorph class>>on:getColorSelector:setColorSelector: (in category 'create') ----- + on: objectToHaveItsColorSet getColorSelector: colorGetterSymbol setColorSelector: colorSetterSymbol + ^ self + on: objectToHaveItsColorSet + originalColor: (colorGetterSymbol value: objectToHaveItsColorSet) + setColorSelector: colorSetterSymbol! From commits at source.squeak.org Tue Apr 13 13:55:19 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 13:55:19 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1539.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1539.mcz ==================== Summary ==================== Name: Morphic-ct.1539 Author: ct Time: 1 October 2019, 2:30:30.532339 pm UUID: 18bcdacc-91ad-9f40-87b4-1a1b0996373b Ancestors: Morphic-ct.1534 Add even more convenient constructor for NewColorPickerMorph (NewColorPickerMorph on: Morph new openInWorld colorSelector: #color) openInHand =============== Diff against Morphic-ct.1534 =============== Item was added: + ----- Method: NewColorPickerMorph class>>on:colorSelector: (in category 'create') ----- + on: objectToHaveItsColorSet colorSelector: colorSymbol + ^ self + on: objectToHaveItsColorSet + getColorSelector: colorSymbol + setColorSelector: colorSymbol asMutator! From commits at source.squeak.org Tue Apr 13 13:55:42 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 13:55:42 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1556.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1556.mcz ==================== Summary ==================== Name: Morphic-ct.1556 Author: ct Time: 1 October 2019, 4:14:07.036339 pm UUID: b353603d-f85b-6f45-b660-2f137d99eb5d Ancestors: Morphic-ul.1552 Complements System-ct.1106 and reworks ProjectViewMorph preview sizes. Fixes a bug since a few commits, where ProjectViewMorphs without windows have the full size of their model's world. Extract #initialExtent, use a modern value, and set it respecting scaleFactor. Simplify #on: paths. Simplify #openOn: and use RealEstateAgent for convenience. =============== Diff against Morphic-ul.1552 =============== Item was changed: ----- Method: MorphicProject>>previewImageForm (in category 'display') ----- previewImageForm + ^ self world imageForm scaledToSize: self viewSize! - ^ self world imageForm! Item was changed: ----- Method: ProjectViewMorph class>>newProjectViewInAWindowFor: (in category 'project window creation') ----- newProjectViewInAWindowFor: aProject "Return an instance of me on a new Morphic project (in a SystemWindow)." | window proj | proj := self on: aProject. window := (SystemWindow labelled: aProject name) model: aProject. + window extent: proj extent. window addMorph: proj frame: (0 at 0 corner: 1.0 at 1.0). proj borderWidth: 0. ^ window ! Item was changed: ----- Method: ProjectViewMorph class>>openOn: (in category 'instance creation') ----- openOn: aProject "Open a ProjectViewMorph for the project in question" + ProjectViewOpenNotification signal ifFalse: [^ self]. + + (Preferences projectViewsInWindows + ifTrue: [ (self newProjectViewInAWindowFor: aProject) ] + ifFalse: [ (self on: aProject) ]) + openAsTool.! - ProjectViewOpenNotification signal ifTrue: [ - Preferences projectViewsInWindows ifTrue: [ - (self newProjectViewInAWindowFor: aProject) openInWorld - ] ifFalse: [ - (self on: aProject) openInWorld "but where??" - ]. - ]. - ! Item was added: + ----- Method: ProjectViewMorph>>initialExtent (in category 'geometry') ----- + initialExtent + + ^ 300 @ 200! Item was changed: ----- Method: ProjectViewMorph>>initialize (in category 'initialization') ----- initialize "Initialize the receiver." super initialize. + self extent: self initialExtent * RealEstateAgent scaleFactor. "currentBorderColor := Color gray." self addProjectNameMorphFiller. self enableDragNDrop: true. self isOpaque: true. ! Item was changed: ----- Method: ProjectViewMorph>>on: (in category 'events') ----- on: aProject project := aProject. self addProjectNameMorphFiller. lastProjectThumbnail := nil. + project viewSize ifNil: [project viewSize: self extent]. project thumbnail: project previewImageForm. + self extent: project thumbnail extent.! - project thumbnail - ifNil: [self extent: 100 at 80] "more like screen dimensions?" - ifNotNil: [self extent: project thumbnail extent].! From commits at source.squeak.org Tue Apr 13 14:39:42 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:39:42 0000 Subject: [squeak-dev] The Trunk: Morphic-nice.1747.mcz Message-ID: Nicolas Cellier uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-nice.1747.mcz ==================== Summary ==================== Name: Morphic-nice.1747 Author: nice Time: 13 April 2021, 4:39:30.44342 pm UUID: 84977ec2-5a36-cd45-9eae-15db41b3963f Ancestors: Morphic-mt.1746 Use isSymbol rather than isKindOf: Symbol =============== Diff against Morphic-mt.1746 =============== Item was changed: ----- Method: TheWorldMenu>>fillIn:from: (in category 'construction') ----- fillIn: aMenu from: dataForMenu "A menu constructor utility by RAA. dataForMenu is a list of items which mean: nil Indicates to add a line first element is symbol Add updating item with the symbol as the wording selector second element is a list second element has the receiver and selector first element is a string Add menu item with the string as its wording second element is a list second element has the receiver and selector a third element exists Use it as the balloon text a fourth element exists Use it as the enablement selector (updating case only)" dataForMenu do: [ :itemData | | item | itemData ifNil: [aMenu addLine] ifNotNil: + [item := itemData first isSymbol - [item := (itemData first isKindOf: Symbol) ifTrue: [aMenu addUpdating: itemData first target: self selector: #doMenuItem:with: argumentList: {itemData second}] ifFalse: [aMenu add: itemData first translated target: self selector: #doMenuItem:with: argumentList: {itemData second}]. itemData size >= 3 ifTrue: [aMenu balloonTextForLastItem: itemData third translated. itemData size >= 4 ifTrue: [item enablementSelector: itemData fourth]]]]. ^ aMenu! From leves at caesar.elte.hu Tue Apr 13 14:40:59 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Tue, 13 Apr 2021 16:40:59 +0200 (CEST) Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: Hi Marcel, To ensure consistency and thread safety without using a mutex, the two WeakSets which make up the symbol table are treated as if they were immutable. Removing from them without creating a copy just breaks that contract. Levente On Tue, 13 Apr 2021, Marcel Taeumel wrote: > Maybe unrelated, but I will remove that extension "Symbol >> #extern:", which manipulates the symbol tables for a single test in CompilerExceptionTest, present since March 2020. I think that 1) garbage collection should take > care of unused symbols and 2) test can find a better way to produce "unknown symbols" :-) > Best, > Marcel > > Am 13.04.2021 07:16:48 schrieb Chris Muller : > > For those wondering, the problem is that some Symbol get duplicated > violating the contract: > any two Symbols are either identical (==) or different (~=). > > > Possible become without copyHash?  > > > From commits at source.squeak.org Tue Apr 13 14:42:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:42:26 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-nice.288.mcz Message-ID: Nicolas Cellier uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-nice.288.mcz ==================== Summary ==================== Name: MorphicExtras-nice.288 Author: nice Time: 13 April 2021, 4:42:17.42642 pm UUID: 433930ea-23a3-bf42-839b-0f6b1251fc9e Ancestors: MorphicExtras-eem.287 Fixup URLMorph: there is no instance of Symbol, Symbol is an abstract class for a few years now (15 years ?). We must test someObject isSymbol rather than someObject class == Symbol (or ~~ Symbol like here). While at it, prefer isSymbol to isKindOf: Symbol. =============== Diff against MorphicExtras-eem.287 =============== Item was changed: ----- Method: PostscriptCanvas>>drawPolygon:color:borderWidth:borderColor: (in category 'drawing-polygons') ----- drawPolygon: vertices color: aColor borderWidth: bw borderColor: bc | fillC | fillC := self shadowColor ifNil:[aColor]. self preserveStateDuring: [:pc | pc outlinePolygon: vertices; setLinewidth: bw; fill: fillC + andStroke: (bc isSymbol - andStroke: ((bc isKindOf: Symbol) ifTrue: [Color gray] ifFalse: [bc])]! Item was changed: ----- Method: PostscriptCanvas>>stroke: (in category 'private') ----- stroke: strokeColor strokeColor ifNil: [^self]. + strokeColor isSymbol - (strokeColor isKindOf: Symbol) ifTrue: [^self paint: Color gray operation: #stroke "punt"]. strokeColor isSolidFill ifTrue: [^self paint: strokeColor asColor operation: #stroke]. self preserveStateDuring: [:inner | inner strokepath; fill: strokeColor]! Item was changed: ----- Method: URLMorph>>mouseUp: (in category 'event handling') ----- mouseUp: evt | pg ow newPage mm bookUrl bk | "If url of a book, open it to that page, or bring it in and open to that page." book ifNotNil: [book == false ifFalse: [ (bookUrl := book) isString ifFalse: [ bookUrl := (SqueakPage stemUrl: url), '.bo']. + (bk := BookMorph isInWorld: self world withUrl: bookUrl) isSymbol + ifFalse: [^ bk goToPageUrl: url]. - (bk := BookMorph isInWorld: self world withUrl: bookUrl) class ~~ Symbol - ifTrue: [^ bk goToPageUrl: url]. bk == #conflict ifTrue: [ ^ self inform: 'This book is already open in some other project']. (bk := BookMorph new fromURL: bookUrl) ifNil: [^ self]. bk goToPageUrl: url. "turn to the page" ^ HandMorph attach: bk]]. "If inside a SqueakPage, replace it!!" pg := self enclosingPage. pg ifNotNil: [ (ow := pg contentsMorph owner) ifNotNil: [ pg contentsMorph delete. "from its owner" newPage := SqueakPageCache atURL: url. mm := newPage fetchContents. mm ifNotNil: [ow addMorph: mm. page := newPage]. ^ self]]. "If I am a project, jump -- not done yet" "For now, just put new page on the hand" newPage := SqueakPageCache atURL: url. mm := newPage fetchInformIfError. mm ifNotNil: [self primaryHand attachMorph: mm. page := newPage]. ! From commits at source.squeak.org Tue Apr 13 14:43:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:43:20 0000 Subject: [squeak-dev] The Trunk: ST80-nice.266.mcz Message-ID: Nicolas Cellier uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-nice.266.mcz ==================== Summary ==================== Name: ST80-nice.266 Author: nice Time: 13 April 2021, 4:43:13.39042 pm UUID: 0986578e-d295-ce49-9499-d1d9a36429e7 Ancestors: ST80-nice.265 Prefer isSymbol to isKindOf: Symbol =============== Diff against ST80-nice.265 =============== Item was changed: ----- Method: PluggableListView>>verifyContents (in category 'updating') ----- verifyContents | newItems existingSelection anIndex | "Called on window reactivation to react to possible structural changes. Update contents if necessary." newItems := self getList. ((items == newItems) "fastest" or: [items = newItems]) ifTrue: [^ self]. self flash. "list has changed beneath us; could get annoying, but hell" existingSelection := list stringAtLineNumber: (selection + (topDelimiter ifNil: [0] ifNotNil: [1])). "account for cursed ------ row" self list: newItems. + (newItems size > 0 and: [newItems first isSymbol]) ifTrue: - (newItems size > 0 and: [newItems first isKindOf: Symbol]) ifTrue: [existingSelection := existingSelection asSymbol]. (anIndex := newItems indexOf: existingSelection ifAbsent: [nil]) ifNotNil: [model noteSelectionIndex: anIndex for: getListSelector.] ifNil: [self changeModelSelection: 0]. selection := 0. " to display the list without selection " self displayView. self update: getSelectionSelector. ! From commits at source.squeak.org Tue Apr 13 14:44:24 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:44:24 0000 Subject: [squeak-dev] The Trunk: Protocols-nice.81.mcz Message-ID: Nicolas Cellier uploaded a new version of Protocols to project The Trunk: http://source.squeak.org/trunk/Protocols-nice.81.mcz ==================== Summary ==================== Name: Protocols-nice.81 Author: nice Time: 13 April 2021, 4:44:18.02742 pm UUID: 1437ca2c-3deb-cc4d-ba31-982555254f5a Ancestors: Protocols-mt.80 Simplify Symbol lookup. =============== Diff against Protocols-mt.80 =============== Item was changed: ----- Method: Lexicon>>setSendersSearch (in category 'senders') ----- setSendersSearch "Put up a list of messages sent in the current message, find all methods of the browsee which send the one the user chooses, and show that list in the message-list pane, with the 'query results' item selected in the category-list pane" | selectorSet aSelector aString | self selectedMessageName ifNil: [aString := UIManager default request: 'Type selector to search for' initialAnswer: 'flag:'. aString isEmptyOrNil ifTrue: [^ self]. + aSelector := Symbol lookup: aString] - Symbol - hasInterned: aString - ifTrue: [:sel | aSelector := sel]] ifNotNil: [self selectMessageAndEvaluate: [:sel | aSelector := sel]]. aSelector ifNil: [^ self]. selectorSet := Set new. (self systemNavigation allCallsOn: aSelector) do: [:anItem | selectorSet add: anItem methodSymbol]. selectorSet := selectorSet select: [:sel | currentVocabulary includesSelector: sel forInstance: self targetObject ofClass: targetClass limitClass: limitClass]. selectorSet size > 0 ifTrue: [currentQuery := #senders. currentQueryParameter := aSelector. self categoryListIndex: (categoryList indexOf: self class queryCategoryName). self messageListIndex: 0]! From commits at source.squeak.org Tue Apr 13 14:47:32 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:47:32 0000 Subject: [squeak-dev] The Trunk: EToys-nice.439.mcz Message-ID: Nicolas Cellier uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-nice.439.mcz ==================== Summary ==================== Name: EToys-nice.439 Author: nice Time: 13 April 2021, 4:47:19.66742 pm UUID: 220b1439-8ff4-3f49-91da-b48b71b43946 Ancestors: EToys-nice.438 Fix SyntaxMorph : Symbol is an abstract class for a few years now (15 years ?), we can simply test someObject isSymbol, but should not use someObject class == Symbol, that should never happen. While at it, prefer isSymbol to isKindOf: Symbol. =============== Diff against EToys-nice.438 =============== Item was changed: SystemOrganization addCategory: #'Etoys-Buttons'! SystemOrganization addCategory: #'Etoys-CustomEvents'! SystemOrganization addCategory: #'Etoys-Experimental'! SystemOrganization addCategory: #'Etoys-OLPC-Display'! SystemOrganization addCategory: #'Etoys-Outliner'! SystemOrganization addCategory: #'Etoys-Protocols'! SystemOrganization addCategory: #'Etoys-Protocols-Type Vocabularies'! SystemOrganization addCategory: #'Etoys-ReleaseBuilder'! SystemOrganization addCategory: #'Etoys-Scripting'! SystemOrganization addCategory: #'Etoys-Scripting Support'! SystemOrganization addCategory: #'Etoys-Scripting Tiles'! SystemOrganization addCategory: #'Etoys-Squeakland-BroomMorphs-Base'! SystemOrganization addCategory: #'Etoys-Squeakland-BroomMorphs-Connectors'! SystemOrganization addCategory: #'Etoys-Squeakland-EToys-Kedama'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Buttons'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Calendar'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Debugger'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Help'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Input'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Scripting'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Scripting Support'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Scripting Tiles'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-SpeechBubbles'! SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Tile Scriptors'! SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Text'! SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Tools-Intersection'! SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Tools-Simplification'! SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Tools-Triangulation'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Basic'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Books'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Components'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Demo'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Experimental'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Games'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Games-Chess'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Games-Chess960'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-GeeMail'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Kernel'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Mentoring'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Navigators'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-PDA'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-PartsBin'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Support'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Widgets'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Windows'! SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Worlds'! SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-AdditionalMorphs'! SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-Charts'! SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-Postscript Filters'! SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-Widgets'! SystemOrganization addCategory: #'Etoys-Squeakland-Multilingual-Languages'! SystemOrganization addCategory: #'Etoys-Squeakland-Multilingual-TextConversion'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Formatter'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Forms'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Parser'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Parser Entities'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Tokenizer'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-MIME'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-TelNet WordNet'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-UI'! SystemOrganization addCategory: #'Etoys-Squeakland-Network-Url'! - SystemOrganization addCategory: #'Etoys-Squeakland-Protocols-Type Vocabularies'! SystemOrganization addCategory: #'Etoys-Squeakland-SISS-Serialization'! SystemOrganization addCategory: #'Etoys-Squeakland-ST80-Morphic'! SystemOrganization addCategory: #'Etoys-Squeakland-SUnit'! SystemOrganization addCategory: #'Etoys-Squeakland-Sound-Interface'! SystemOrganization addCategory: #'Etoys-Squeakland-Sound-Ogg'! SystemOrganization addCategory: #'Etoys-Squeakland-Sound-Scores'! SystemOrganization addCategory: #'Etoys-Squeakland-Sugar'! SystemOrganization addCategory: #'Etoys-Squeakland-Support'! SystemOrganization addCategory: #'Etoys-Squeakland-System-Clipboard-Extended'! SystemOrganization addCategory: #'Etoys-Squeakland-System-Compiler'! SystemOrganization addCategory: #'Etoys-Squeakland-System-Exceptions Kernel'! SystemOrganization addCategory: #'Etoys-Squeakland-System-Support'! SystemOrganization addCategory: #'Etoys-Squeakland-Tools-Changes'! SystemOrganization addCategory: #'Etoys-Squeakland-Tools-Explorer'! SystemOrganization addCategory: #'Etoys-Squeakland-Tools-Process Browser'! SystemOrganization addCategory: #'Etoys-Squeakland-Tweak-Kedama-ObjectVectors'! SystemOrganization addCategory: #'Etoys-Squeakland-Tweak-Kedama-ParseTree-AttributeDefinition'! SystemOrganization addCategory: #'Etoys-Squeakland-Tweak-Kedama-ParseTreeTransformer'! SystemOrganization addCategory: #'Etoys-Stacks'! SystemOrganization addCategory: #'Etoys-StarSqueak'! SystemOrganization addCategory: #'Etoys-Support'! SystemOrganization addCategory: #'Etoys-Tests'! SystemOrganization addCategory: #'Etoys-Tile Scriptors'! SystemOrganization addCategory: #'Etoys-UserInterfaceTheme'! SystemOrganization addCategory: #'Etoys-Widgets'! Item was changed: ----- Method: PhraseTileMorph>>vocabulary: (in category 'initialization') ----- vocabulary: aVocab "Set the vocabulary" + vocabularySymbol := aVocab isSymbol - vocabularySymbol := (aVocab isKindOf: Symbol) ifTrue: [aVocab] ifFalse: [aVocab vocabularyName]! Item was changed: ----- Method: SyntaxMorph>>getCurrentValue (in category 'accessing') ----- getCurrentValue parseNode ifNil: [^nil]. + parseNode isSymbol ifTrue: [^nil]. "special" - parseNode class == Symbol ifTrue: [^nil]. "special" ^parseNode currentValueIn: self hostContext! Item was changed: ----- Method: TileMorph>>rawVocabulary: (in category 'initialization') ----- rawVocabulary: aVocabulary "Set the receiver's vocabulary, without side effects." + vocabularySymbol := aVocabulary isSymbol - vocabularySymbol := (aVocabulary isKindOf: Symbol) ifTrue: [aVocabulary] ifFalse: [aVocabulary vocabularyName]! From commits at source.squeak.org Tue Apr 13 14:49:04 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:49:04 0000 Subject: [squeak-dev] The Trunk: Collections-nice.934.mcz Message-ID: Nicolas Cellier uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-nice.934.mcz ==================== Summary ==================== Name: Collections-nice.934 Author: nice Time: 13 April 2021, 4:48:56.45442 pm UUID: ef1096e7-ebfe-e843-9853-f106df649cf4 Ancestors: Collections-nice.933 Make a Symbol lookup more straightforward. =============== Diff against Collections-nice.933 =============== Item was changed: ----- Method: TextLink>>validate: (in category 'initialize-release') ----- validate: specString "Can this string be decoded to be Class space Method (or Comment, Definition, Hierarchy)? If so, return it in valid format, else nil" | list first mid last | list := specString findTokens: ' .|'. list isEmpty ifTrue: [ ^nil ]. last := list last. last first isUppercase ifTrue: [ (#('Comment' 'Definition' 'Hierarchy') includes: last) ifFalse: [^ nil]. "Check for 'Rectangle Comment Comment' and remove last one" (list at: list size - 1 ifAbsent: [^nil]) = last ifTrue: [list := list allButLast]]. list size > 3 ifTrue: [^ nil]. list size < 2 ifTrue: [^ nil]. + first := Symbol lookup: list first. - Symbol hasInterned: list first ifTrue: [:sym | first := sym]. first ifNil: [^ nil]. Smalltalk at: first ifAbsent: [^ nil]. mid := list size = 3 ifTrue: [(list at: 2) = 'class' ifTrue: ['class '] ifFalse: [^ nil]] ifFalse: ['']. "OK if method name is not interned -- may not be defined yet" ^ first, ' ', mid, last! From commits at source.squeak.org Tue Apr 13 14:54:08 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:54:08 0000 Subject: [squeak-dev] The Trunk: System-mt.1226.mcz Message-ID: Marcel Taeumel uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-mt.1226.mcz ==================== Summary ==================== Name: System-mt.1226 Author: mt Time: 13 April 2021, 4:54:04.935381 pm UUID: ab7c50e5-0316-1844-98b9-73e2a1a27e2b Ancestors: System-dtl.1225 Discard all graphics imports during release building. =============== Diff against System-dtl.1225 =============== Item was added: + ----- Method: Imports class>>cleanUp: (in category 'class initialization') ----- + cleanUp: aggressive + + aggressive ifTrue: [default := nil].! From commits at source.squeak.org Tue Apr 13 14:57:36 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:57:36 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.289.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.289.mcz ==================== Summary ==================== Name: MorphicExtras-mt.289 Author: mt Time: 13 April 2021, 4:57:33.587381 pm UUID: f869cf93-ce30-b14d-bc80-f48c40ce95f4 Ancestors: MorphicExtras-nice.288 Treats Graphics-ct.422 (inbox). This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-nice.288 =============== Item was added: + ----- Method: Form class>>exampleColorSees (in category '*MorphicExtras-examples') ----- + exampleColorSees + "Form exampleColorSees" + "First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon. + Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this + Third shows the hit area - where red touches blue - superimposed on the original scene. + Fourth column is the tally of hits via the old algorithm + Last column shows the tally of hits via the new prim" + + | formA formB maskA offset tally map intersection left top dCanvas sensitiveColor soughtColor index | + formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing" + Project current world restoreMorphicDisplay; doOneCycle. + + sensitiveColor := Color red. + soughtColor := Color blue. + + top := 50. + dCanvas := FormCanvas on: Display. + -50 to: 80 by: 10 do:[:p| + offset:= p at 0. "vary this to check different states" + left := 10. + + formA := (Form extent: 100 at 50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths". + formB := Form extent: 100 at 50 depth: 32. + + "make a red square in the middle of the form" + (FormCanvas on: formA) fillRectangle: (25 at 25 extent: 50 at 5) fillStyle: sensitiveColor. + (FormCanvas on: formA) fillRectangle: (25 at 30 extent: 50 at 5) fillStyle: Color transparent. + (FormCanvas on: formA) fillRectangle: (25 at 35 extent: 50 at 50) fillStyle: Color yellow. + "formA displayOn: Display at: left at top rule: Form paint. + dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. + left := left + 150." + + "make a blue block on the right half of the form" + (FormCanvas on: formB) fillRectangle: (50 at 0 extent: 50 at 100) fillStyle: soughtColor. + (FormCanvas on: formB) fillRectangle: (60 at 0 extent: 10 at 100) fillStyle: Color palePeach. + "formB displayOn: Display at: left at top rule: Form paint. + dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. + left := left + 150." + + intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox). + + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 150. + + maskA := Form extent: intersection extent depth: 1. + + map := Bitmap new: (1 bitShift: (formA depth min: 15)). + map at: (index := sensitiveColor indexInMap: map) put: 1. + + maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0 at 0 colorMap: map. + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. left := left + 150. + + "intersect world pixels of the color we're looking for with sensitive pixels mask" + map at: index put: 0. "clear map and reuse it" + map at: (soughtColor indexInMap: map) put: 1. + + maskA + copyBits: intersection + from: formB at: 0 at 0 clippingBox: formB boundingBox + rule: Form and + fillColor: nil + map: map. + + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 170. + + (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20). + left := left + 70. + + "now try using the new primitive" + tally := (BitBlt + destForm: formB + sourceForm: formA + fillColor: nil + combinationRule: 3 "really ought to work with nil but prim code checks" + destOrigin: intersection origin + sourceOrigin: (offset negated max: 0 at 0) + extent: intersection extent + clipRect: intersection) + primCompareColor: ((sensitiveColor pixelValueForDepth: formA depth) ) to: ((soughtColor pixelValueForDepth: formB depth) ) test: (Form compareMatchColor bitOr: Form compareTallyFlag). + tally asString asDisplayText displayOn: Display at: left@(top +20). + top:= top + 60]! Item was added: + ----- Method: Form class>>exampleTouchTest (in category '*MorphicExtras-examples') ----- + exampleTouchTest + "Form exampleTouchTest" + "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a + non-transparent pixel of the background upon which it is displayed. + First column shows a form with a red block in the midst of transparent area sneaking up on a form with a transparent LHS and blue RHS. The green frame shows the intersection area. + Second column shows in grey the part of the red that is within the intersection. + Third column shows in black the blue that is within the intersection. + Fourth column shows just the A touching B area. + Fifth column is the tally of hits via the old algorithm + Last column shows the tally of hits via the new prim" + |formA formB maskA maskB offset tally map intersection left top dCanvas| + formA := formB := maskA := maskB := offset := tally := map := intersection := nil. "just to shut up the compiler when testing" + + Project current world restoreMorphicDisplay; doOneCycle. + + top := 50. + dCanvas := FormCanvas on: Display. + -50 to: 80 by: 10 do:[:p| + offset:= p at 0. "vary this to check different states" + left := 10. + + formA := Form extent: 100 at 50 depth: 32. + formB := Form extent: 100 at 50 depth: 16. + + "make a red square in the middle of the form" + (FormCanvas on: formA) fillRectangle: (25 at 25 extent: 50 at 5) fillStyle: Color yellow. + (FormCanvas on: formA) fillRectangle: (25 at 30 extent: 50 at 5) fillStyle: Color transparent. + (FormCanvas on: formA) fillRectangle: (25 at 35 extent: 50 at 50) fillStyle: Color red. + "formA displayOn: Display at: left at top rule: Form paint. + dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. + left := left + 150." + + "make a blue block on the right half of the form" + (FormCanvas on: formB) fillRectangle: (50 at 0 extent: 50 at 100) fillStyle: Color blue. + (FormCanvas on: formB) fillRectangle: (60 at 0 extent: 10 at 100) fillStyle: Color palePeach. + "formB displayOn: Display at: left at top rule: Form paint. + dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. + left := left + 150." + + intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox). + + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 150. + + maskA := Form extent: intersection extent depth: 2. + formA displayOn: maskA at: offset - intersection origin rule: Form paint. + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 150. + + maskB := Form extent: intersection extent depth: 2. + formB displayOn: maskB at: intersection origin negated rule: Form paint. + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + maskB displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 150. + + map := Bitmap new: 4 withAll: 1. + map at: 1 put: 0. "transparent" + + maskA copyBits: maskA boundingBox from: maskA at: 0 at 0 colorMap: map. + "maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 150." + + maskB copyBits: maskB boundingBox from: maskB at: 0 at 0 colorMap: map. + "maskB displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 150." + + maskB displayOn: maskA at: 0 at 0 rule: Form and. + maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 170. + + (maskA boundingBox area -( maskA tallyPixelValues at: 1)) asString asDisplayText displayOn: Display at: left@(top +20). + left := left + 70. + + "now try using the new primitive" + tally := (BitBlt + destForm: formB + sourceForm: formA + fillColor: nil + combinationRule: 3 "really ought to work with nil but prim code checks" + destOrigin: intersection origin + sourceOrigin: (offset negated max: 0 at 0) + extent: intersection extent + clipRect: intersection) + primCompareColor: ((Color transparent pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((Color transparent pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorANotColorB bitOr: Form compareTallyFlag). + tally asString asDisplayText displayOn: Display at: left@(top +20). + top:= top + 60]! Item was added: + ----- Method: Form class>>exampleTouchingColor (in category '*MorphicExtras-examples') ----- + exampleTouchingColor + "Form exampleTouchingColor" + "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a + particular color pixel of the background upon which it is displayed. + First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon. + Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this + Third shows the hit area (black) superimposed on the original scene + Fourth column is the tally of hits via the old algorithm + Last column shows the tally of hits via the new prim" + |formA formB maskA offset tally map intersection left top dCanvas ignoreColor soughtColor| + formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing" + Project current world restoreMorphicDisplay; doOneCycle. + + ignoreColor := Color transparent. + soughtColor := Color blue. + + top := 50. + dCanvas := FormCanvas on: Display. + -50 to: 80 by: 10 do:[:p| + offset:= p at 0. "vary this to check different states" + left := 10. + + formA := (Form extent: 100 at 50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths". + formB := Form extent: 100 at 50 depth: 32. + + "make a red square in the middle of the form" + (FormCanvas on: formA) fillRectangle: (25 at 25 extent: 50 at 5) fillStyle: Color red. + (FormCanvas on: formA) fillRectangle: (25 at 30 extent: 50 at 5) fillStyle: Color transparent. + (FormCanvas on: formA) fillRectangle: (25 at 35 extent: 50 at 50) fillStyle: Color yellow. + "formA displayOn: Display at: left at top rule: Form paint. + dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. + left := left + 150." + + "make a blue block on the right half of the form" + (FormCanvas on: formB) fillRectangle: (50 at 0 extent: 50 at 100) fillStyle: soughtColor. + (FormCanvas on: formB) fillRectangle: (60 at 0 extent: 10 at 100) fillStyle: Color palePeach. + "formB displayOn: Display at: left at top rule: Form paint. + dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. + left := left + 150." + + intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox). + + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 150. + + maskA := Form extent: intersection extent depth: 1. + + map := Bitmap new: (1 bitShift: (formA depth min: 15)). + map atAllPut: 1. + map at: ( ignoreColor indexInMap: map) put: 0. + + maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0 at 0 colorMap: map. + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. left := left + 150. + + "intersect world pixels of the color we're looking for with sensitive pixels mask" + map atAllPut: 0. "clear map and reuse it" + map at: (soughtColor indexInMap: map) put: 1. + + maskA + copyBits: intersection + from: formB at: 0 at 0 clippingBox: formB boundingBox + rule: Form and + fillColor: nil + map: map. + + formB displayOn: Display at: left at top rule: Form paint. + formA displayOn: Display at: (left at top) + offset rule: Form paint. + maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. + dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. + left := left + 170. + + (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20). + left := left + 70. + + "now try using the new primitive" + tally := (BitBlt + destForm: formB + sourceForm: formA + fillColor: nil + combinationRule: 3 "really ought to work with nil but prim code checks" + destOrigin: intersection origin + sourceOrigin: (offset negated max: 0 at 0) + extent: intersection extent + clipRect: intersection) + primCompareColor: ((ignoreColor pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((soughtColor pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorAMatchColorB bitOr: Form compareTallyFlag). + tally asString asDisplayText displayOn: Display at: left@(top +20). + top:= top + 60]! Item was added: + ----- Method: Form class>>squeakLogo (in category '*MorphicExtras-sprites') ----- + squeakLogo + + ^ Imports default imports + at: #squeakLogo + ifAbsentPut: [ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self squeakLogoContents readStream) ]! Item was added: + ----- Method: Form class>>squeakLogoContents (in category '*MorphicExtras-sprites') ----- (excessive size, no diff calculated) Item was added: + ----- Method: MenuIcons class>>backIconContents (in category '*MorphicExtras-private - icons') ----- + backIconContents + "Private - Method generated with the content of the file /home/dgd/back.png" + ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 + RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAADRElEQVRIie3WW4hVVRgH8N/e+5y56aCizpnR + jJzUCNFqLhqEWGlQDz0mGEJBCSL1Ur1YZA9BSIZGZg9dVBoo0B5D6qGwOzVaairZiJiKZ0hs + 1NE5c2bm7N3DmXF2zQyO5lv+YbFZa/2/77+/y9prcxNpNFnoHi3/xUU4LtYiszX5WGC/ULsW + m69XMLgqo8UzEhtRlVpNJJb62Tc3TnCxnH7bBR65sra0nt8vkC9Ah9Ay7U5d2Z+jUrUaoRqx + Hr/qGp9gk0cFPsB0UFfFugUsybH1N7YfS7O7UTE4/u2vgDze02ijXUrRCLFmzwtswwRhwGO3 + Wb55tcWNzQ75g7+KfNmZtqhEZoyXz2IKlutSIe+LNCnQ7A08NxRVuKHVywvXWG+lDXZ5SRs9 + A7Qd53g3pSQlG1GboTY7PKojNh/hXBFK+s0oC85XocoOrASzJ6p9+wE7c69I8K7PfKrdgBK4 + XYNWc+VMFgwGlkgU9Svo06OooOiksw7u3MPrhwySVmVAlTasAAummPzWg16oXWGdD+13fESe + ulxSZ5I7zTJHg1tNVxIr6FNQ1KlLuw7fOkJ9dTqHDwWarBJoA7lqPlqiflJO58gGuz78cJZn + fxya/ZQRutdQKZY1MKlifGJJzEA/A32UUs+4NDhispVcjtMRdmeU7BBag8iJM5yOmDmPYIwj + 2pXn5MGy2LhQl3pJF0O/2CuwBXzfS0cnR7+j9/IoUSWcPnINYuhNcRN/DnXpRFUOoFFNwKYa + wgJ1s2mYS1TuLedOceLAsIMwIsoSZEhC4oCBgD70xpzB9ktcGExr4PHhvLVqFPsaM02NeC2L + XjKVTJtVdp7vKNfufB1bznO2RLE03lhj5P5ZqBZ3SHyFnFsyrM+SFEaabqrm6CjrY6Mf79tn + 7cjOaDVfbA+mmRzyajUVqXpGE3g6NQ88IXZYKFISCUVioUAfetDjolOOKZbpo6HV3WK70SCL + F2uZ0V3eOzCFd64cm8/t8/C1hDr29dSqXuwT3AfuyjIvy66etPVT9tp2YwShWRZvYu0ouydd + MG8oVePFyOspjbxY3m4znMD9hm/90xJPOuzYmLZj4Oq/GENYZKqS1QKxPlsdNMqX4Sb+D/gb + LOgMCUjhiw4AAAAASUVORK5CYII='! Item was added: + ----- Method: MenuIcons class>>forwardIconContents (in category '*MorphicExtras-private - icons') ----- + forwardIconContents + "Private - Method generated with the content of the file /home/dgd/forward.png" + ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 + RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAADXUlEQVRIie3WX2iVZRwH8M97znv2f1o2Fy4r + hxMvhhCeTewmJcuEbiLLP0GECoJWEIlYUBoR3QTVhRRIXffvJupiBF4oRCZukq5Na4LhlKnT + 6XE7c/P8ebs4O8fNlh3nVdEPHnif5/d8f9/3+33e53le/usRvyv0UknzzDXgQrmQ2IzJkt4V + 6BT4xVJfWKa5HFgwI7J27fIOmerQmMBOnfbeGWGrChXmoVZeSlZKjzQisEyznA4s1lhFWwMd + Z4tZIh0SNjk8vc03CZO2Yzcap32R6WLLIrYt5sgl3jvOudFiZlBki6O+vxVSsKTNK9iLurLJ + 4PkFLKy38YE1Wp5b7uT1P+hJEakV2KDJiAGHpipMSmAIdeoT7GwlGzGaJT2pjeUK49l8Aflw + HZtaqI57xwv22OhD33qj+2OZXYe5OFaYF/nIUTtMmB5ot0LeAbB5kSXbn9LqIRXCUksIBZOE + Dxl2RJ8T+ktjKy2x1RpN5lh7aY/Lr+6n71qR9EvjXtLjRijnyVKt+TVOOqtNiyc84kENQnGJ + Cef7XXLKgGtG9Ruc4u4B3Q7o1mKelxue9ennCYOv76fzMoENqmXxYiDpK6wD7y9ldVPZS3i7 + mKPe0PAQ6w/etDfwTIjh0qx0mounuXEdAUFAECMekqgkrCCsJFFReA7+/twYMkx9guVz+W7C + +rwVIVKlWUGK/vPlSQgC5rfSuGD6fD7H6V76SvXGBPbFBJM2aCpTHhlEEQO/E+X/mhu+TO9B + jl3lxETNyG5dTsbdb1xgK+gaY3YdFdXkagiqCWuIVxFWEYbEYhMkUUFFWEntPYWimXHOdHO2 + l5Fa3koVyQ5aaJteUYCYpAtoKFtdTYwd9zF/sGBtY3OBfOgcuSz5Wbw2zHgEXVilq7B0cUSa + jKEdNWURZiL6MqyMCkrTVxhNFZTnZ7MrzWgeesSt0ulKETr1GFviXjUqkJAVE8rLysnIqZKT + 0SzmR1SCfXVEIzfxV+t5e4QbEZzCY7oMTKa48+sp6TNsAetn8fi1wvY4Vssnw8Vb41c8rcuZ + W+EzIVyNH0r99gT9Oc6XvtavZWx2XHo6+Mwu4DY/iTx6y2hO5E1HfXA76Ex/MTbh50n930RW + /xMZM1VYxLZZK2/MQh2+kbuLWv/Hvyj+BJaPHpqZ0oo8AAAAAElFTkSuQmCC'! Item was added: + ----- Method: MenuIcons class>>helpIconContents (in category '*MorphicExtras-private - icons') ----- + helpIconContents + "Private - Method generated with the content of the file /home/dgd/help.png" + ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 + RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAAGoklEQVRIicWWeWxU1xWHv/fmzZvF4wF3AION + XXuKgSAT0yZhNaRKIMIToARSkbQJIVEw2CW0FRQEIoUUNWpLSCsFlECxUKpilsqCsFjESzFl + bGpsEG4DqUjBLRiN8W6P7Vk8753+ETCbIbSq2t8/V/e+q/vdc879HT34H0t5xH2PAbOByTfn + UeA68CngB/r+28COzXxt0GNYARDgLBEO08tFot3ANuAdIPxIQNmEejZAriK8BDhNCCkKn13r + 4srmSrLqrvJqE2nEo953QD19rKCFUkLXgTnA+YcBVYBzDXwT4SeGsB6T1yIma1eWEFtyXN88 + bNwzCzLRB4QBHKOXckJYNCXJEW/5aPpo68QTm9AeBNQAFJOAWGifuJMqwDrI49xvt+m+fXv3 + 2CyqlZ0VL6MMSwKLBSJRJNAEIvyUNt7Xe/ng19vx+XKUtetWZx49dqiyutbx98o8a9ctiICu + wF+jii2/n1y7jO01S8nxJLpLn587q7epuUlERM6cOSPzJk2TnvIqCZVXSaS8SowDx6T82RfF + 6XRKZWWl3Klfbnk35ozXwpqDKXcAFX/eoC2V+YPe6weeWcqERU/FfTZufEYkEomIiEhnZ1CK + i0+I3e6Ro08vktIn5knFs6/I56+ukinDU6SwsFAG0sof5cfcHkeAIcTfOr9yuSvTn+eu/TK6 + XJw75rHX7lLFX3lKRETa2jrkyJFyKSo6LpmZk2Q6HnkOj8zCI9PxSGKiV5qb2wYEBoNBSU0f + HhvscWzrB+a5X/HnufeoZ9/kceAvBZcGT16y+A2ZNjWbUCjMqVM1RKN9tLQ009p6PVqtB3tO + 2robTurBi+fjo1esVvOfM2Y8E6upqb3vYbhcLpblrrAYhrkUcJ3Kd+eLQr6uGKuoyaXoD4t4 + yxanSH39lZt1q5OiouPy4Ye/Mz2eYdfgdj3uVHZ2dlZqqjdYV1d3X5Tlf/SL7kTiB9tf8+e5 + L/tXOJMAVAUyV1fQk5aWHktLS6ejo4tr1wIAbN26paG1tWkucHogoN/vr+vrCy3ZuHFj8N5v + 4VAfSUkpjBo1ai7wZ0xLDoDWZ1A20mXd1Gpq2vz58zlXc562zhAOh4OOjmaVrzByIBA4Vlpa + epdJw+EI4XCE5KRkWtuax6jSN9vAeuJkvqtKnVLAb62XtZStjQoHVq6hOGMq7/U4yG4JEYtF + Enl4+1OAHaqq9t65eONGCwDd3d3YbHZt6keh68ARDUu2CiTOJ47nvGOwohDs6cWDhZt9UwOy + HgJ8B1jc29vrKSsr61/84ot/ICIEAg3YdL27arkjWRFllihGlQo0dWCACABxaSMB8GJFBWw2 + 2/cHAKlAHvD2ehJYb7hVn8/H7t27CQSa6Orqpr7+Ch2dHUxMsSWYivWoqLIme3v3BQDXHJxm + 1DZWzOMnpenAMdmZ8Lh4cciECRNkxIgRoZkzZ751R2rnAFcAeYN4ieCVKF75ZEqOaCji8y2U + PXsOSY7vO6I7kVULx+fe11ttKCVX+brE3lwnV3ftk9R4j6xbt04Mw5Bdu3bJkCFDRNM0w+12 + 96iqagBSwgiJ3oTFXv6hGOVV8umLy2QobklISBbNZpXMrNEdD6rFwnnESbN9jEwdniKrV6+X + 9vbOfk+1t7fLjh07ZMOGDeLz+QSQ0yRLVMuQ2HdXiFFeJe3FFXIkeYrsJl2ySBBQJGPMqIIH + AVWgJBlNdJsuP3/3fTl4sEQuXaqXWCx2l6EbGxsFkKJpPjH2HZVQeZU0Hi6Tkqzn5QBe+T3p + kkqc6DY9CiTcC7LcHAUo9gw2X4pqqsN/usLidLqx6S7q6xsIBnuIxQzC4QhWq87evfvxjh3H + 2Kee5GpFNRd+9gHdl68CsI8uziidaBYtxzCMC/cC7/JYbS4Na/5EXk2jXhiJRl3Dhqay4IXv + MSP7aRTl9taCggL8pWVsiyVgl9s3LqSLw0ordrv9x6FQ6DcDpfJeYLtuwTv5YxzOePfHXcGu + maCQOCyVMRmZjExJxaJaaGtt4+DBT8jDzSTsXCBCMZ18rob6TNNcABx9UO3uUm0uLdU/wHNr + bnfx7SGJg0ptcYqhOxHdoYrVoYnVroui6mJHFwVNQDGBQ8Dor2Lc++9xwxojEWitXspoVcGn + 0ll95BJLf1FLuhjm+NezePvkdcv+S4FIT1gYjVANHAYuPkpQd6X0bC7rTXgB6FXAA6xFwYuw + XCwswOQbirDliZ1kKl+W7d/WfY353OsMBfjWbpr7L7KM2WKyWBTCCvzqyZ387T+B/V/0L+bC + W2tds0/6AAAAAElFTkSuQmCC'! Item was added: + ----- Method: MenuIcons class>>openIconContents (in category '*MorphicExtras-private - icons') ----- + openIconContents + "Private - Method generated with the content of the file /home/dgd/open.png" + ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 + RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAAGO0lEQVRIieWWW0wc5xXHf9/MzuwNFnNbYLFJ + ggFjgs1l1yYhqTExdlKlbpVA7FiK08qt3SqqJSt5cCu/9MVSq0qtKiupZNLkIU2bKoG0TsCY + RtTGhYLDGjvBxlAcQ1i8G67mzt5m+jDLxU6jKm3y1CMdndGMvu93/uc78+nA/4UdzcEM8DOQ + Dm9j2xE3+YD4OljiSCmnEPwYWATmEtPSUmVZZmzk9hzwV0nibVWm4VQnM18FUHZncNSW4Mjd + 5PEo0xMTdmtcHAeOH2fnMzWqSVE2j/tGqhcXgy+6XTzkycD80AaGPxxh8b9WeNjNzwvKyo4f + e/lldF2nu6WF906fxpGcTM2xY7iys+lpb6ezsZGPWlsJh0IRBBfQqTNJvPvKhwS+lEKPC6ce + DVXv2rmAQCcjv4yKmn0oqsrvTpzA/0kfj3znacr37qVy/36cWVnS0vx89mQg8KSm6S+Wutjj + ySShOA1/d4Dp/6jwRx4KNZ2PT9W9gMooyDZIehxsm7h98ya/+uER8rcm84MTz4N1o+FCZWp0 + lEtNTXQ2NjIyMGBsBl4N6pCpq71E/79V+K08JmdD/GTbrnLZ4ZAAHRb7IDxJfGYZkXCEno7L + PLbHCQt9MNMBwUGsFsgpLadi30FKKiux2O1M+P2u4Pz8LqFz1O3iGU8GE14/1+4Cnh9Ec7uo + ydq8OT0rOwEkFYQK0Rmw5ZGceT/v177Ojic9mG12EApE5iA4BDNdsHADR4JCwcM7qXruMLml + pUiyzJjP54yEwzUeF0VuF/VePxqADODOoNwSt66o9JEcAyYpxsamdVgTs7h64QIfdfyTnC3Z + 2BMcse8qyCpoYQjdhrkriIUeUtITKK56mh3VzzLc38+Yz7cZnSWvn4srwFIXGxdnF/ZU7Xvc + OIlloK6BZQMFZWXc7LnBO789Q2BkBmucg+SMVISkGhVZdqIQDMBcN6oSpuypF+g8e5aFmRmH + 10/tCnB7JmJxfv5Q1YFqFAUDJimgB0EyY0vMxLN7D+6qKob7B2n64wd8UN/JZ7dnQTaTlJaC + rFiMNZIaK/sdhKOUqdEx+q9cDXUHqAXChsIMAsBLuSVFijMzBSQTCJMRI1MQnQWixCWmsmXH + LnY/9zybPG6mJ6dpfa+Nd2qbCYUk8orzYqoVY73lPob7b9HTeSl4JWC+DNGADOD1o7ldVKhm + 68aiRz0g5FWokEEPQ2TaOKvwOESXSEhNJW9bBTtqnmXrNx7l3Jv1jPnv8OD2wliJFTC7+LR/ + kI/b2pe6A+YGUGVpuV11ON/V8neiugUk66rLNpBsqxEgMgkLAzDbBUtDrM/bxLFXTtPd1sut + vnGQ40COB0BRVQSYjIWaZRWo87el+XkG+3wgWe52eTnem4jFgIfGiE9KYvfB79LacAkkO8h2 + QKBYLAhh9AogrQBfvUwnMNjRdH71X5TMhosYUHxBApEp0DXK936bXu91giHJgCKhqCoIlBhG + WwEaVeW1tjPvc2d8brXVhXlN639BApLRlWarle1PfBPvhStGIkIgm0xIKyWVgmuBaCZej0Yi + wT/88jdomrz6e4hlxWsTMN+dgLYIukbl/v10NLUa71cqufwQDt0FfLUTn65z4Grrxeipl36K + b+BTAypMsbg2AeXzFdDmSXQ6cSSnMDoyDmJle6HKyCCCMvfYZT833C56x3y+na3179oHr90g + dcN9JKZnGLeQEIBkbLbsyLGog1BJTE+nz9tN9pYtBIaG6Wpu5vqYqT4UFUPSvUCA017eBnLR + +XVPe3vkF4e+z8mD36PhtTcY+cQXK+Ma5ctXoTCBHuKBwkJ0YonFzCJjAvnzCpfN6yfo9XOu + bD21IY1r45+N09/V5bxYV2f9R0Mj47cDKGYr65wZSLJpVTWAkNB1QVJ6OoHBIbqamxmYMP15 + Lqz2funJrLqAMllIT5lNeqVF1otUs2p+oLCQnOJicktLyN66FYvNhhbVAGg7c4bfnzzJ2ZuW + Q8N3lv70P42CrnhSHkyRn7CpekWcqhdZFD1fkaX49Xl55JaUkJWfT8tbb3Hreu/Cm1etBxej + i3/5KmdPO5jTi9J0jzNOe3idJVpgNbEhojE1OCWfa/eZLsJSy9cy7AIy2FMAJ2gOkOZBvQVT + 0/8ClPo3sCGCJrEAAAAASUVORK5CYII='! From commits at source.squeak.org Tue Apr 13 14:58:48 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 14:58:48 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1748.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1748.mcz ==================== Summary ==================== Name: Morphic-mt.1748 Author: mt Time: 13 April 2021, 4:58:42.939381 pm UUID: c321b488-2e30-7d4d-b0be-79d866ac5ce0 Ancestors: Morphic-nice.1747 Complements MorphicExtras-mt.289 =============== Diff against Morphic-nice.1747 =============== Item was removed: - ----- Method: Form class>>exampleColorSees (in category '*Morphic-examples') ----- - exampleColorSees - "Form exampleColorSees" - "First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon. - Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this - Third shows the hit area - where red touches blue - superimposed on the original scene. - Fourth column is the tally of hits via the old algorithm - Last column shows the tally of hits via the new prim" - - | formA formB maskA offset tally map intersection left top dCanvas sensitiveColor soughtColor index | - formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing" - Project current world restoreMorphicDisplay; doOneCycle. - - sensitiveColor := Color red. - soughtColor := Color blue. - - top := 50. - dCanvas := FormCanvas on: Display. - -50 to: 80 by: 10 do:[:p| - offset:= p at 0. "vary this to check different states" - left := 10. - - formA := (Form extent: 100 at 50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths". - formB := Form extent: 100 at 50 depth: 32. - - "make a red square in the middle of the form" - (FormCanvas on: formA) fillRectangle: (25 at 25 extent: 50 at 5) fillStyle: sensitiveColor. - (FormCanvas on: formA) fillRectangle: (25 at 30 extent: 50 at 5) fillStyle: Color transparent. - (FormCanvas on: formA) fillRectangle: (25 at 35 extent: 50 at 50) fillStyle: Color yellow. - "formA displayOn: Display at: left at top rule: Form paint. - dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. - left := left + 150." - - "make a blue block on the right half of the form" - (FormCanvas on: formB) fillRectangle: (50 at 0 extent: 50 at 100) fillStyle: soughtColor. - (FormCanvas on: formB) fillRectangle: (60 at 0 extent: 10 at 100) fillStyle: Color palePeach. - "formB displayOn: Display at: left at top rule: Form paint. - dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. - left := left + 150." - - intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox). - - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 150. - - maskA := Form extent: intersection extent depth: 1. - - map := Bitmap new: (1 bitShift: (formA depth min: 15)). - map at: (index := sensitiveColor indexInMap: map) put: 1. - - maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0 at 0 colorMap: map. - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. left := left + 150. - - "intersect world pixels of the color we're looking for with sensitive pixels mask" - map at: index put: 0. "clear map and reuse it" - map at: (soughtColor indexInMap: map) put: 1. - - maskA - copyBits: intersection - from: formB at: 0 at 0 clippingBox: formB boundingBox - rule: Form and - fillColor: nil - map: map. - - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 170. - - (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20). - left := left + 70. - - "now try using the new primitive" - tally := (BitBlt - destForm: formB - sourceForm: formA - fillColor: nil - combinationRule: 3 "really ought to work with nil but prim code checks" - destOrigin: intersection origin - sourceOrigin: (offset negated max: 0 at 0) - extent: intersection extent - clipRect: intersection) - primCompareColor: ((sensitiveColor pixelValueForDepth: formA depth) ) to: ((soughtColor pixelValueForDepth: formB depth) ) test: (Form compareMatchColor bitOr: Form compareTallyFlag). - tally asString asDisplayText displayOn: Display at: left@(top +20). - top:= top + 60]! Item was removed: - ----- Method: Form class>>exampleTouchTest (in category '*Morphic-examples') ----- - exampleTouchTest - "Form exampleTouchTest" - "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a - non-transparent pixel of the background upon which it is displayed. - First column shows a form with a red block in the midst of transparent area sneaking up on a form with a transparent LHS and blue RHS. The green frame shows the intersection area. - Second column shows in grey the part of the red that is within the intersection. - Third column shows in black the blue that is within the intersection. - Fourth column shows just the A touching B area. - Fifth column is the tally of hits via the old algorithm - Last column shows the tally of hits via the new prim" - |formA formB maskA maskB offset tally map intersection left top dCanvas| - formA := formB := maskA := maskB := offset := tally := map := intersection := nil. "just to shut up the compiler when testing" - - Project current world restoreMorphicDisplay; doOneCycle. - - top := 50. - dCanvas := FormCanvas on: Display. - -50 to: 80 by: 10 do:[:p| - offset:= p at 0. "vary this to check different states" - left := 10. - - formA := Form extent: 100 at 50 depth: 32. - formB := Form extent: 100 at 50 depth: 16. - - "make a red square in the middle of the form" - (FormCanvas on: formA) fillRectangle: (25 at 25 extent: 50 at 5) fillStyle: Color yellow. - (FormCanvas on: formA) fillRectangle: (25 at 30 extent: 50 at 5) fillStyle: Color transparent. - (FormCanvas on: formA) fillRectangle: (25 at 35 extent: 50 at 50) fillStyle: Color red. - "formA displayOn: Display at: left at top rule: Form paint. - dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. - left := left + 150." - - "make a blue block on the right half of the form" - (FormCanvas on: formB) fillRectangle: (50 at 0 extent: 50 at 100) fillStyle: Color blue. - (FormCanvas on: formB) fillRectangle: (60 at 0 extent: 10 at 100) fillStyle: Color palePeach. - "formB displayOn: Display at: left at top rule: Form paint. - dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. - left := left + 150." - - intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox). - - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 150. - - maskA := Form extent: intersection extent depth: 2. - formA displayOn: maskA at: offset - intersection origin rule: Form paint. - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 150. - - maskB := Form extent: intersection extent depth: 2. - formB displayOn: maskB at: intersection origin negated rule: Form paint. - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - maskB displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 150. - - map := Bitmap new: 4 withAll: 1. - map at: 1 put: 0. "transparent" - - maskA copyBits: maskA boundingBox from: maskA at: 0 at 0 colorMap: map. - "maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 150." - - maskB copyBits: maskB boundingBox from: maskB at: 0 at 0 colorMap: map. - "maskB displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 150." - - maskB displayOn: maskA at: 0 at 0 rule: Form and. - maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 170. - - (maskA boundingBox area -( maskA tallyPixelValues at: 1)) asString asDisplayText displayOn: Display at: left@(top +20). - left := left + 70. - - "now try using the new primitive" - tally := (BitBlt - destForm: formB - sourceForm: formA - fillColor: nil - combinationRule: 3 "really ought to work with nil but prim code checks" - destOrigin: intersection origin - sourceOrigin: (offset negated max: 0 at 0) - extent: intersection extent - clipRect: intersection) - primCompareColor: ((Color transparent pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((Color transparent pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorANotColorB bitOr: Form compareTallyFlag). - tally asString asDisplayText displayOn: Display at: left@(top +20). - top:= top + 60]! Item was removed: - ----- Method: Form class>>exampleTouchingColor (in category '*Morphic-examples') ----- - exampleTouchingColor - "Form exampleTouchingColor" - "Demonstrate the algorithm used in Scratch code to determine if a sprite's non-transparent pixels touch a - particular color pixel of the background upon which it is displayed. - First column as above shows the sneaky red/yellow pirate sneaking up on the blue/peach galleon. - Second column shows the 1bpp made from the red/yellow/transparent - white -> ignore this, black -> test this - Third shows the hit area (black) superimposed on the original scene - Fourth column is the tally of hits via the old algorithm - Last column shows the tally of hits via the new prim" - |formA formB maskA offset tally map intersection left top dCanvas ignoreColor soughtColor| - formA := formB := maskA := offset := tally := map := intersection := nil. "just to shut up the compiler when testing" - Project current world restoreMorphicDisplay; doOneCycle. - - ignoreColor := Color transparent. - soughtColor := Color blue. - - top := 50. - dCanvas := FormCanvas on: Display. - -50 to: 80 by: 10 do:[:p| - offset:= p at 0. "vary this to check different states" - left := 10. - - formA := (Form extent: 100 at 50 depth: 32) asFormOfDepth: 16 "so we can try original forms of other depths". - formB := Form extent: 100 at 50 depth: 32. - - "make a red square in the middle of the form" - (FormCanvas on: formA) fillRectangle: (25 at 25 extent: 50 at 5) fillStyle: Color red. - (FormCanvas on: formA) fillRectangle: (25 at 30 extent: 50 at 5) fillStyle: Color transparent. - (FormCanvas on: formA) fillRectangle: (25 at 35 extent: 50 at 50) fillStyle: Color yellow. - "formA displayOn: Display at: left at top rule: Form paint. - dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. - left := left + 150." - - "make a blue block on the right half of the form" - (FormCanvas on: formB) fillRectangle: (50 at 0 extent: 50 at 100) fillStyle: soughtColor. - (FormCanvas on: formB) fillRectangle: (60 at 0 extent: 10 at 100) fillStyle: Color palePeach. - "formB displayOn: Display at: left at top rule: Form paint. - dCanvas frameRectangle: (left at top extent: formA extent) width:2 color: Color green. - left := left + 150." - - intersection := (formA boundingBox translateBy: offset) intersect: (formB boundingBox). - - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 150. - - maskA := Form extent: intersection extent depth: 1. - - map := Bitmap new: (1 bitShift: (formA depth min: 15)). - map atAllPut: 1. - map at: ( ignoreColor indexInMap: map) put: 0. - - maskA copyBits: (intersection translateBy: offset negated) from: formA at: 0 at 0 colorMap: map. - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. left := left + 150. - - "intersect world pixels of the color we're looking for with sensitive pixels mask" - map atAllPut: 0. "clear map and reuse it" - map at: (soughtColor indexInMap: map) put: 1. - - maskA - copyBits: intersection - from: formB at: 0 at 0 clippingBox: formB boundingBox - rule: Form and - fillColor: nil - map: map. - - formB displayOn: Display at: left at top rule: Form paint. - formA displayOn: Display at: (left at top) + offset rule: Form paint. - maskA displayOn: Display at: (left at top) + intersection origin rule: Form paint. - dCanvas frameRectangle: (intersection translateBy: left at top) width:2 color: Color green. - left := left + 170. - - (maskA tallyPixelValues at: 2) asString asDisplayText displayOn: Display at: left@(top +20). - left := left + 70. - - "now try using the new primitive" - tally := (BitBlt - destForm: formB - sourceForm: formA - fillColor: nil - combinationRule: 3 "really ought to work with nil but prim code checks" - destOrigin: intersection origin - sourceOrigin: (offset negated max: 0 at 0) - extent: intersection extent - clipRect: intersection) - primCompareColor: ((ignoreColor pixelValueForDepth: formA depth) bitAnd: 16rFFFFFF) to: ((soughtColor pixelValueForDepth: formB depth) bitAnd: 16rFFFFFF) test: (Form compareNotColorAMatchColorB bitOr: Form compareTallyFlag). - tally asString asDisplayText displayOn: Display at: left@(top +20). - top:= top + 60]! Item was removed: - ----- Method: MenuIcons class>>backIconContents (in category 'private - icons') ----- - backIconContents - "Private - Method generated with the content of the file /home/dgd/back.png" - ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 - RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAADRElEQVRIie3WW4hVVRgH8N/e+5y56aCizpnR - jJzUCNFqLhqEWGlQDz0mGEJBCSL1Ur1YZA9BSIZGZg9dVBoo0B5D6qGwOzVaairZiJiKZ0hs - 1NE5c2bm7N3DmXF2zQyO5lv+YbFZa/2/77+/y9prcxNpNFnoHi3/xUU4LtYiszX5WGC/ULsW - m69XMLgqo8UzEhtRlVpNJJb62Tc3TnCxnH7bBR65sra0nt8vkC9Ah9Ay7U5d2Z+jUrUaoRqx - Hr/qGp9gk0cFPsB0UFfFugUsybH1N7YfS7O7UTE4/u2vgDze02ijXUrRCLFmzwtswwRhwGO3 - Wb55tcWNzQ75g7+KfNmZtqhEZoyXz2IKlutSIe+LNCnQ7A08NxRVuKHVywvXWG+lDXZ5SRs9 - A7Qd53g3pSQlG1GboTY7PKojNh/hXBFK+s0oC85XocoOrASzJ6p9+wE7c69I8K7PfKrdgBK4 - XYNWc+VMFgwGlkgU9Svo06OooOiksw7u3MPrhwySVmVAlTasAAummPzWg16oXWGdD+13fESe - ulxSZ5I7zTJHg1tNVxIr6FNQ1KlLuw7fOkJ9dTqHDwWarBJoA7lqPlqiflJO58gGuz78cJZn - fxya/ZQRutdQKZY1MKlifGJJzEA/A32UUs+4NDhispVcjtMRdmeU7BBag8iJM5yOmDmPYIwj - 2pXn5MGy2LhQl3pJF0O/2CuwBXzfS0cnR7+j9/IoUSWcPnINYuhNcRN/DnXpRFUOoFFNwKYa - wgJ1s2mYS1TuLedOceLAsIMwIsoSZEhC4oCBgD70xpzB9ktcGExr4PHhvLVqFPsaM02NeC2L - XjKVTJtVdp7vKNfufB1bznO2RLE03lhj5P5ZqBZ3SHyFnFsyrM+SFEaabqrm6CjrY6Mf79tn - 7cjOaDVfbA+mmRzyajUVqXpGE3g6NQ88IXZYKFISCUVioUAfetDjolOOKZbpo6HV3WK70SCL - F2uZ0V3eOzCFd64cm8/t8/C1hDr29dSqXuwT3AfuyjIvy66etPVT9tp2YwShWRZvYu0ouydd - MG8oVePFyOspjbxY3m4znMD9hm/90xJPOuzYmLZj4Oq/GENYZKqS1QKxPlsdNMqX4Sb+D/gb - LOgMCUjhiw4AAAAASUVORK5CYII='! Item was changed: + ----- Method: MenuIcons class>>blankIconOfWidth: (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>blankIconOfWidth: (in category 'private - icons') ----- blankIconOfWidth: aNumber ^ Icons at: ('blankIcon-' , aNumber asString) asSymbol ifAbsentPut: [Form extent: aNumber @ 1 depth:8]! Item was changed: + ----- Method: MenuIcons class>>configurationIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>configurationIcon (in category 'private - icons') ----- configurationIcon "Private - Generated method" ^ Icons at: #'configuration' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self configurationIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>confirmIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>confirmIcon (in category 'private - icons') ----- confirmIcon "Private - Generated method" ^ Icons at: #'confirm' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self confirmIconContents readStream) ].! Item was removed: - ----- Method: MenuIcons class>>forwardIconContents (in category 'private - icons') ----- - forwardIconContents - "Private - Method generated with the content of the file /home/dgd/forward.png" - ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 - RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAADXUlEQVRIie3WX2iVZRwH8M97znv2f1o2Fy4r - hxMvhhCeTewmJcuEbiLLP0GECoJWEIlYUBoR3QTVhRRIXffvJupiBF4oRCZukq5Na4LhlKnT - 6XE7c/P8ebs4O8fNlh3nVdEPHnif5/d8f9/3+33e53le/usRvyv0UknzzDXgQrmQ2IzJkt4V - 6BT4xVJfWKa5HFgwI7J27fIOmerQmMBOnfbeGWGrChXmoVZeSlZKjzQisEyznA4s1lhFWwMd - Z4tZIh0SNjk8vc03CZO2Yzcap32R6WLLIrYt5sgl3jvOudFiZlBki6O+vxVSsKTNK9iLurLJ - 4PkFLKy38YE1Wp5b7uT1P+hJEakV2KDJiAGHpipMSmAIdeoT7GwlGzGaJT2pjeUK49l8Aflw - HZtaqI57xwv22OhD33qj+2OZXYe5OFaYF/nIUTtMmB5ot0LeAbB5kSXbn9LqIRXCUksIBZOE - Dxl2RJ8T+ktjKy2x1RpN5lh7aY/Lr+6n71qR9EvjXtLjRijnyVKt+TVOOqtNiyc84kENQnGJ - Cef7XXLKgGtG9Ruc4u4B3Q7o1mKelxue9ennCYOv76fzMoENqmXxYiDpK6wD7y9ldVPZS3i7 - mKPe0PAQ6w/etDfwTIjh0qx0mounuXEdAUFAECMekqgkrCCsJFFReA7+/twYMkx9guVz+W7C - +rwVIVKlWUGK/vPlSQgC5rfSuGD6fD7H6V76SvXGBPbFBJM2aCpTHhlEEQO/E+X/mhu+TO9B - jl3lxETNyG5dTsbdb1xgK+gaY3YdFdXkagiqCWuIVxFWEYbEYhMkUUFFWEntPYWimXHOdHO2 - l5Fa3koVyQ5aaJteUYCYpAtoKFtdTYwd9zF/sGBtY3OBfOgcuSz5Wbw2zHgEXVilq7B0cUSa - jKEdNWURZiL6MqyMCkrTVxhNFZTnZ7MrzWgeesSt0ulKETr1GFviXjUqkJAVE8rLysnIqZKT - 0SzmR1SCfXVEIzfxV+t5e4QbEZzCY7oMTKa48+sp6TNsAetn8fi1wvY4Vssnw8Vb41c8rcuZ - W+EzIVyNH0r99gT9Oc6XvtavZWx2XHo6+Mwu4DY/iTx6y2hO5E1HfXA76Ex/MTbh50n930RW - /xMZM1VYxLZZK2/MQh2+kbuLWv/Hvyj+BJaPHpqZ0oo8AAAAAElFTkSuQmCC'! Item was changed: + ----- Method: MenuIcons class>>fugueBroomIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>fugueBroomIcon (in category 'private - icons') ----- fugueBroomIcon ^ Icons at: #broom ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self fugueBroomIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>fugueDocumentClockIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>fugueDocumentClockIcon (in category 'private - icons') ----- fugueDocumentClockIcon ^ Icons at: #documentClock ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self fugueDocumentClockIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>fugueUserSilhouetteQuestionIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>fugueUserSilhouetteQuestionIcon (in category 'private - icons') ----- fugueUserSilhouetteQuestionIcon ^ Icons at: #userSilhouetteQuestion ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self fugueUserSilhouetteQuestionIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>fullScreenIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>fullScreenIcon (in category 'private - icons') ----- fullScreenIcon "Private - Generated method" ^ Icons at: #'fullScreen' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self fullScreenIconContents readStream) ].! Item was removed: - ----- Method: MenuIcons class>>helpIconContents (in category 'private - icons') ----- - helpIconContents - "Private - Method generated with the content of the file /home/dgd/help.png" - ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 - RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAAGoklEQVRIicWWeWxU1xWHv/fmzZvF4wF3AION - XXuKgSAT0yZhNaRKIMIToARSkbQJIVEw2CW0FRQEIoUUNWpLSCsFlECxUKpilsqCsFjESzFl - bGpsEG4DqUjBLRiN8W6P7Vk8753+ETCbIbSq2t8/V/e+q/vdc879HT34H0t5xH2PAbOByTfn - UeA68CngB/r+28COzXxt0GNYARDgLBEO08tFot3ANuAdIPxIQNmEejZAriK8BDhNCCkKn13r - 4srmSrLqrvJqE2nEo953QD19rKCFUkLXgTnA+YcBVYBzDXwT4SeGsB6T1yIma1eWEFtyXN88 - bNwzCzLRB4QBHKOXckJYNCXJEW/5aPpo68QTm9AeBNQAFJOAWGifuJMqwDrI49xvt+m+fXv3 - 2CyqlZ0VL6MMSwKLBSJRJNAEIvyUNt7Xe/ng19vx+XKUtetWZx49dqiyutbx98o8a9ctiICu - wF+jii2/n1y7jO01S8nxJLpLn587q7epuUlERM6cOSPzJk2TnvIqCZVXSaS8SowDx6T82RfF - 6XRKZWWl3Klfbnk35ozXwpqDKXcAFX/eoC2V+YPe6weeWcqERU/FfTZufEYkEomIiEhnZ1CK - i0+I3e6Ro08vktIn5knFs6/I56+ukinDU6SwsFAG0sof5cfcHkeAIcTfOr9yuSvTn+eu/TK6 - XJw75rHX7lLFX3lKRETa2jrkyJFyKSo6LpmZk2Q6HnkOj8zCI9PxSGKiV5qb2wYEBoNBSU0f - HhvscWzrB+a5X/HnufeoZ9/kceAvBZcGT16y+A2ZNjWbUCjMqVM1RKN9tLQ009p6PVqtB3tO - 2robTurBi+fjo1esVvOfM2Y8E6upqb3vYbhcLpblrrAYhrkUcJ3Kd+eLQr6uGKuoyaXoD4t4 - yxanSH39lZt1q5OiouPy4Ye/Mz2eYdfgdj3uVHZ2dlZqqjdYV1d3X5Tlf/SL7kTiB9tf8+e5 - L/tXOJMAVAUyV1fQk5aWHktLS6ejo4tr1wIAbN26paG1tWkucHogoN/vr+vrCy3ZuHFj8N5v - 4VAfSUkpjBo1ai7wZ0xLDoDWZ1A20mXd1Gpq2vz58zlXc562zhAOh4OOjmaVrzByIBA4Vlpa - epdJw+EI4XCE5KRkWtuax6jSN9vAeuJkvqtKnVLAb62XtZStjQoHVq6hOGMq7/U4yG4JEYtF - Enl4+1OAHaqq9t65eONGCwDd3d3YbHZt6keh68ARDUu2CiTOJ47nvGOwohDs6cWDhZt9UwOy - HgJ8B1jc29vrKSsr61/84ot/ICIEAg3YdL27arkjWRFllihGlQo0dWCACABxaSMB8GJFBWw2 - 2/cHAKlAHvD2ehJYb7hVn8/H7t27CQSa6Orqpr7+Ch2dHUxMsSWYivWoqLIme3v3BQDXHJxm - 1DZWzOMnpenAMdmZ8Lh4cciECRNkxIgRoZkzZ751R2rnAFcAeYN4ieCVKF75ZEqOaCji8y2U - PXsOSY7vO6I7kVULx+fe11ttKCVX+brE3lwnV3ftk9R4j6xbt04Mw5Bdu3bJkCFDRNM0w+12 - 96iqagBSwgiJ3oTFXv6hGOVV8umLy2QobklISBbNZpXMrNEdD6rFwnnESbN9jEwdniKrV6+X - 9vbOfk+1t7fLjh07ZMOGDeLz+QSQ0yRLVMuQ2HdXiFFeJe3FFXIkeYrsJl2ySBBQJGPMqIIH - AVWgJBlNdJsuP3/3fTl4sEQuXaqXWCx2l6EbGxsFkKJpPjH2HZVQeZU0Hi6Tkqzn5QBe+T3p - kkqc6DY9CiTcC7LcHAUo9gw2X4pqqsN/usLidLqx6S7q6xsIBnuIxQzC4QhWq87evfvxjh3H - 2Kee5GpFNRd+9gHdl68CsI8uziidaBYtxzCMC/cC7/JYbS4Na/5EXk2jXhiJRl3Dhqay4IXv - MSP7aRTl9taCggL8pWVsiyVgl9s3LqSLw0ordrv9x6FQ6DcDpfJeYLtuwTv5YxzOePfHXcGu - maCQOCyVMRmZjExJxaJaaGtt4+DBT8jDzSTsXCBCMZ18rob6TNNcABx9UO3uUm0uLdU/wHNr - bnfx7SGJg0ptcYqhOxHdoYrVoYnVroui6mJHFwVNQDGBQ8Dor2Lc++9xwxojEWitXspoVcGn - 0ll95BJLf1FLuhjm+NezePvkdcv+S4FIT1gYjVANHAYuPkpQd6X0bC7rTXgB6FXAA6xFwYuw - XCwswOQbirDliZ1kKl+W7d/WfY353OsMBfjWbpr7L7KM2WKyWBTCCvzqyZ387T+B/V/0L+bC - W2tds0/6AAAAAElFTkSuQmCC'! Item was changed: + ----- Method: MenuIcons class>>homeIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>homeIcon (in category 'private - icons') ----- homeIcon "Private - Generated method" ^ Icons at: #'home' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self homeIconContents readStream) ].! Item was changed: ----- Method: MenuIcons class>>initializeIcons (in category 'class initialization') ----- initializeIcons "self initialize" + - | methods | Icons := IdentityDictionary new. - methods := self class selectors - select: [:each | '*Icon' match: each asString]. - methods - do: [:each | Icons - at: each - put: (MenuIcons perform: each)]. self initializeTranslations. ! Item was changed: + ----- Method: MenuIcons class>>jumpIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>jumpIcon (in category 'private - icons') ----- jumpIcon "Private - Generated method" ^ Icons at: #'jump' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self jumpIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>objectsIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>objectsIcon (in category 'private - icons') ----- objectsIcon "Private - Generated method" ^ Icons at: #'objects' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self objectsIconContents readStream) ].! Item was removed: - ----- Method: MenuIcons class>>openIconContents (in category 'private - icons') ----- - openIconContents - "Private - Method generated with the content of the file /home/dgd/open.png" - ^ 'iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAABHNCSVQICAgIfAhkiAAAABF0 - RVh0U29mdHdhcmUAU29kaXBvZGmU4xfQAAAGO0lEQVRIieWWW0wc5xXHf9/MzuwNFnNbYLFJ - ggFjgs1l1yYhqTExdlKlbpVA7FiK08qt3SqqJSt5cCu/9MVSq0qtKiupZNLkIU2bKoG0TsCY - RtTGhYLDGjvBxlAcQ1i8G67mzt5m+jDLxU6jKm3y1CMdndGMvu93/uc78+nA/4UdzcEM8DOQ - Dm9j2xE3+YD4OljiSCmnEPwYWATmEtPSUmVZZmzk9hzwV0nibVWm4VQnM18FUHZncNSW4Mjd - 5PEo0xMTdmtcHAeOH2fnMzWqSVE2j/tGqhcXgy+6XTzkycD80AaGPxxh8b9WeNjNzwvKyo4f - e/lldF2nu6WF906fxpGcTM2xY7iys+lpb6ezsZGPWlsJh0IRBBfQqTNJvPvKhwS+lEKPC6ce - DVXv2rmAQCcjv4yKmn0oqsrvTpzA/0kfj3znacr37qVy/36cWVnS0vx89mQg8KSm6S+Wutjj - ySShOA1/d4Dp/6jwRx4KNZ2PT9W9gMooyDZIehxsm7h98ya/+uER8rcm84MTz4N1o+FCZWp0 - lEtNTXQ2NjIyMGBsBl4N6pCpq71E/79V+K08JmdD/GTbrnLZ4ZAAHRb7IDxJfGYZkXCEno7L - PLbHCQt9MNMBwUGsFsgpLadi30FKKiux2O1M+P2u4Pz8LqFz1O3iGU8GE14/1+4Cnh9Ec7uo - ydq8OT0rOwEkFYQK0Rmw5ZGceT/v177Ojic9mG12EApE5iA4BDNdsHADR4JCwcM7qXruMLml - pUiyzJjP54yEwzUeF0VuF/VePxqADODOoNwSt66o9JEcAyYpxsamdVgTs7h64QIfdfyTnC3Z - 2BMcse8qyCpoYQjdhrkriIUeUtITKK56mh3VzzLc38+Yz7cZnSWvn4srwFIXGxdnF/ZU7Xvc - OIlloK6BZQMFZWXc7LnBO789Q2BkBmucg+SMVISkGhVZdqIQDMBcN6oSpuypF+g8e5aFmRmH - 10/tCnB7JmJxfv5Q1YFqFAUDJimgB0EyY0vMxLN7D+6qKob7B2n64wd8UN/JZ7dnQTaTlJaC - rFiMNZIaK/sdhKOUqdEx+q9cDXUHqAXChsIMAsBLuSVFijMzBSQTCJMRI1MQnQWixCWmsmXH - LnY/9zybPG6mJ6dpfa+Nd2qbCYUk8orzYqoVY73lPob7b9HTeSl4JWC+DNGADOD1o7ldVKhm - 68aiRz0g5FWokEEPQ2TaOKvwOESXSEhNJW9bBTtqnmXrNx7l3Jv1jPnv8OD2wliJFTC7+LR/ - kI/b2pe6A+YGUGVpuV11ON/V8neiugUk66rLNpBsqxEgMgkLAzDbBUtDrM/bxLFXTtPd1sut - vnGQ40COB0BRVQSYjIWaZRWo87el+XkG+3wgWe52eTnem4jFgIfGiE9KYvfB79LacAkkO8h2 - QKBYLAhh9AogrQBfvUwnMNjRdH71X5TMhosYUHxBApEp0DXK936bXu91giHJgCKhqCoIlBhG - WwEaVeW1tjPvc2d8brXVhXlN639BApLRlWarle1PfBPvhStGIkIgm0xIKyWVgmuBaCZej0Yi - wT/88jdomrz6e4hlxWsTMN+dgLYIukbl/v10NLUa71cqufwQDt0FfLUTn65z4Grrxeipl36K - b+BTAypMsbg2AeXzFdDmSXQ6cSSnMDoyDmJle6HKyCCCMvfYZT833C56x3y+na3179oHr90g - dcN9JKZnGLeQEIBkbLbsyLGog1BJTE+nz9tN9pYtBIaG6Wpu5vqYqT4UFUPSvUCA017eBnLR - +XVPe3vkF4e+z8mD36PhtTcY+cQXK+Ma5ctXoTCBHuKBwkJ0YonFzCJjAvnzCpfN6yfo9XOu - bD21IY1r45+N09/V5bxYV2f9R0Mj47cDKGYr65wZSLJpVTWAkNB1QVJ6OoHBIbqamxmYMP15 - Lqz2funJrLqAMllIT5lNeqVF1otUs2p+oLCQnOJicktLyN66FYvNhhbVAGg7c4bfnzzJ2ZuW - Q8N3lv70P42CrnhSHkyRn7CpekWcqhdZFD1fkaX49Xl55JaUkJWfT8tbb3Hreu/Cm1etBxej - i3/5KmdPO5jTi9J0jzNOe3idJVpgNbEhojE1OCWfa/eZLsJSy9cy7AIy2FMAJ2gOkOZBvQVT - 0/8ClPo3sCGCJrEAAAAASUVORK5CYII='! Item was changed: + ----- Method: MenuIcons class>>paintIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>paintIcon (in category 'private - icons') ----- paintIcon "Private - Generated method" ^ Icons at: #'paint' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self paintIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>projectIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>projectIcon (in category 'private - icons') ----- projectIcon "Private - Generated method" ^ Icons at: #'project' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self projectIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>publishIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>publishIcon (in category 'private - icons') ----- publishIcon "Private - Generated method" ^ Icons at: #'publish' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self publishIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallBackIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallBackIcon (in category 'private - icons') ----- smallBackIcon "Private - Generated method" ^ Icons at: #'smallBack' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallBackIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallDoItIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallDoItIcon (in category 'private - icons') ----- smallDoItIcon "Private - Generated method" ^ Icons at: #'smallDoIt' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallDoItIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallExpertIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallExpertIcon (in category 'private - icons') ----- smallExpertIcon "Private - Generated method" ^ Icons at: #'smallExpert' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallExpertIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallExportIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallExportIcon (in category 'private - icons') ----- smallExportIcon "Private - Generated method" ^ Icons at: #'smallExport' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallExportIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallForwardIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallForwardIcon (in category 'private - icons') ----- smallForwardIcon "Private - Generated method" ^ Icons at: #'smallForward' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallForwardIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallFullScreenIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallFullScreenIcon (in category 'private - icons') ----- smallFullScreenIcon "Private - Generated method" ^ Icons at: #'smallFullScreen' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallFullScreenIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallInspectItIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallInspectItIcon (in category 'private - icons') ----- smallInspectItIcon "Private - Generated method" ^ Icons at: #'smallInspectIt' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallInspectItIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallJumpIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallJumpIcon (in category 'private - icons') ----- smallJumpIcon "Private - Generated method" ^ Icons at: #'smallJump' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallJumpIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallLanguageIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallLanguageIcon (in category 'private - icons') ----- smallLanguageIcon "Private - Generated method" ^ Icons at: #'smallLanguage' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallLanguageIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallLoadProjectIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallLoadProjectIcon (in category 'private - icons') ----- smallLoadProjectIcon "Private - Generated method" ^ Icons at: #'smallLoadProject' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallLoadProjectIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallNewIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallNewIcon (in category 'private - icons') ----- smallNewIcon "Private - Generated method" ^ Icons at: #'smallNew' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallNewIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallObjectCatalogIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallObjectCatalogIcon (in category 'private - icons') ----- smallObjectCatalogIcon "Private - Generated method" ^ Icons at: #'smallObjectCatalog' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallObjectCatalogIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallObjectsIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallObjectsIcon (in category 'private - icons') ----- smallObjectsIcon "Private - Generated method" ^ Icons at: #'smallObjects' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallObjectsIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallPaintIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallPaintIcon (in category 'private - icons') ----- smallPaintIcon "Private - Generated method" ^ Icons at: #'smallPaint' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallPaintIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallPublishIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallPublishIcon (in category 'private - icons') ----- smallPublishIcon "Private - Generated method" ^ Icons at: #'smallPublish' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallPublishIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallSelectIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallSelectIcon (in category 'private - icons') ----- smallSelectIcon "Private - Generated method" ^ Icons at: #'smallSelect' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallSelectIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallSqueakIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallSqueakIcon (in category 'private - icons') ----- smallSqueakIcon "Private - Generated method" ^ Icons at: #'smallSqueak' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallSqueakIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallUpdateIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallUpdateIcon (in category 'private - icons') ----- smallUpdateIcon "Private - Generated method" ^ Icons at: #'smallUpdate' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallUpdateIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>smallVolumeIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>smallVolumeIcon (in category 'private - icons') ----- smallVolumeIcon "Private - Generated method" ^ Icons at: #'smallVolume' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self smallVolumeIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>squeakIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>squeakIcon (in category 'private - icons') ----- squeakIcon "Private - Generated method" ^ Icons at: #'squeak' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self squeakIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>volumeIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>volumeIcon (in category 'private - icons') ----- volumeIcon "Private - Generated method" ^ Icons at: #'volume' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self volumeIconContents readStream) ].! Item was changed: + ----- Method: MenuIcons class>>windowIcon (in category 'accessing - icons') ----- - ----- Method: MenuIcons class>>windowIcon (in category 'private - icons') ----- windowIcon "Private - Generated method" ^ Icons at: #'window' ifAbsentPut:[ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self windowIconContents readStream) ].! From marcel.taeumel at hpi.de Tue Apr 13 15:00:56 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 17:00:56 +0200 Subject: [squeak-dev] Error selector changed In-Reply-To: References: Message-ID: Hi Levente, good to know! Well, I know this pattern, just did not notice it got applied here. Even better that I got rid of #extern:. Best, Marcel Am 13.04.2021 16:41:06 schrieb Levente Uzonyi : Hi Marcel, To ensure consistency and thread safety without using a mutex, the two WeakSets which make up the symbol table are treated as if they were immutable. Removing from them without creating a copy just breaks that contract. Levente On Tue, 13 Apr 2021, Marcel Taeumel wrote: > Maybe unrelated, but I will remove that extension "Symbol >> #extern:", which manipulates the symbol tables for a single test in CompilerExceptionTest, present since March 2020. I think that 1) garbage collection should take > care of unused symbols and 2) test can find a better way to produce "unknown symbols" :-) > Best, > Marcel > > Am 13.04.2021 07:16:48 schrieb Chris Muller : > > For those wondering, the problem is that some Symbol get duplicated > violating the contract: > any two Symbols are either identical (==) or different (~=). > > > Possible become without copyHash? > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Apr 13 15:05:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:05:40 0000 Subject: [squeak-dev] The Trunk: Collections-mt.935.mcz Message-ID: Marcel Taeumel uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-mt.935.mcz ==================== Summary ==================== Name: Collections-mt.935 Author: mt Time: 13 April 2021, 5:05:38.802381 pm UUID: 17800d3d-5975-7144-9608-deb8f5fccc2c Ancestors: Collections-nice.934 Document thread-safety in symbol table(s) as class comment. Thanks to Levente (ul)! =============== Diff against Collections-nice.934 =============== Item was changed: String subclass: #Symbol instanceVariableNames: '' classVariableNames: 'NewSymbols SymbolTable' poolDictionaries: '' category: 'Collections-Strings'! + !Symbol commentStamp: 'mt 4/13/2021 17:04' prior: 0! + I represent Strings that are created uniquely. Thus, someString asSymbol == someString asSymbol. + + ATTENTION!! To ensure consistency and thread safety without using a mutex, the two WeakSets which make up the symbol table are treated as if they were immutable. Removing from them without creating a copy just breaks that contract.! - !Symbol commentStamp: '' prior: 0! - I represent Strings that are created uniquely. Thus, someString asSymbol == someString asSymbol.! From marcel.taeumel at hpi.de Tue Apr 13 15:08:27 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 13 Apr 2021 17:08:27 +0200 Subject: [squeak-dev] The Inbox: 60Deprecated-nice.94.mcz In-Reply-To: References: Message-ID: :-) +1 for deprecating it somehow -1 for using #deprecated: (also for the sake of backwards compatibility in other projects) Best, Marcel Am 13.04.2021 12:20:45 schrieb Nicolas Cellier : It's in the inbox precisely for discussion :) Le mar. 13 avr. 2021 à 12:13, Marcel Taeumel a écrit : > > Hi Nicolas, > > actually deprecating Symbol API is often dangerous. Especially since Monticello installs moved methods before other changes. I vote for "self flag: #deprecated" or an extra checkpoint in Squeak's update map. > > Best, > Marcel > > Am 13.04.2021 12:10:22 schrieb commits at source.squeak.org : > > Nicolas Cellier uploaded a new version of 60Deprecated to project The Inbox: > http://source.squeak.org/inbox/60Deprecated-nice.94.mcz > > ==================== Summary ==================== > > Name: 60Deprecated-nice.94 > Author: nice > Time: 13 April 2021, 12:10:09.32989 pm > UUID: 2efd14b2-b4f1-3247-848e-c5f8f0ef9ced > Ancestors: 60Deprecated-dtl.93 > > Deprecate Symbol findInterned: aString in favour of lookup: > > BEWARE: #findInterned: is an old dialect that might still be used by a Number of external packages, including refactoring browser. > > This must be discussed. > > =============== Diff against 60Deprecated-dtl.93 =============== > > Item was added: > + ----- Method: Symbol class>>findInterned: (in category '*60Deprecated-instance creation') ----- > + findInterned: aString > + > + self deprecated: 'Use #lookup: instead.'. > + ^ self lookup: aString! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Apr 13 15:29:19 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:29:19 0000 Subject: [squeak-dev] The Trunk: Graphics-mt.448.mcz Message-ID: Marcel Taeumel uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-mt.448.mcz ==================== Summary ==================== Name: Graphics-mt.448 Author: mt Time: 13 April 2021, 5:29:12.533381 pm UUID: c614cbd7-dfc4-e94f-a47a-145e43d22a16 Ancestors: Graphics-mt.447, Graphics-ct.421 Merges Graphics-ct.421 Note that this message aligns with #atRandom, #atRandom:, and #random in other object kinds. =============== Diff against Graphics-mt.447 =============== Item was added: + ----- Method: Rectangle>>randomPoint (in category 'random') ----- + randomPoint + + ^ self randomPoint: ThreadSafeRandom value! Item was added: + ----- Method: Rectangle>>randomPoint: (in category 'random') ----- + randomPoint: aGenerator + "Answers a random point that lies within the receiver." + + ^ self pointAtFraction: aGenerator next @ aGenerator next! From commits at source.squeak.org Tue Apr 13 15:30:11 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:30:11 0000 Subject: [squeak-dev] The Trunk: GraphicsTests-mt.57.mcz Message-ID: Marcel Taeumel uploaded a new version of GraphicsTests to project The Trunk: http://source.squeak.org/trunk/GraphicsTests-mt.57.mcz ==================== Summary ==================== Name: GraphicsTests-mt.57 Author: mt Time: 13 April 2021, 5:30:10.904381 pm UUID: c9be18bf-f4b0-4345-bb55-e3f3a0133d56 Ancestors: GraphicsTests-ct.56 Adds tests for #pointAtFraction: and #randomPoint. =============== Diff against GraphicsTests-ct.56 =============== Item was added: + ----- Method: RectangleTest>>testPointAtFraction (in category 'tests') ----- + testPointAtFraction + + | r | + r := Rectangle origin: 0 at 0 extent: 50 at 50. + + { + r topLeft . 0.0 @ 0.0 . + r center . 0.5 @ 0.5 . + r bottomRight . 1.0 @ 1.0 . + + 5 at 5 . 0.1 @ 0.1 . + 40 at 50 . 0.8 @ 1.0 + + } groupsDo: [ :expected :fraction | + self assert: expected equals: (r pointAtFraction: fraction)].! Item was added: + ----- Method: RectangleTest>>testPointAtFractionExact (in category 'tests') ----- + testPointAtFractionExact + + | r | + r := Rectangle origin: 0.2 at 0.2 corner: 1.0 at 1.0. + + { + r topLeft . 0.0 @ 0.0 . + "r center . 0.5 @ 0.5 . --- Not yet working." + r bottomRight . 1.0 @ 1.0 . + + 0.6 @ 0.6 . 0.5 @ 0.5 . + + } groupsDo: [ :expected :fraction | + self assert: (expected closeTo: (r pointAtFraction: fraction))].! Item was added: + ----- Method: RectangleTest>>testRandomPoint (in category 'tests') ----- + testRandomPoint + + | r | + r := Rectangle origin: 0 at 0 extent: 50 at 50. + self assert: (r containsPoint: r randomPoint). + self assert: r randomPoint isIntegerPoint.! Item was added: + ----- Method: RectangleTest>>testRandomPointExact (in category 'tests') ----- + testRandomPointExact + + | r | + r := Rectangle origin: 0.2 at 0.2 corner: 1.0 at 1.0. + self assert: (r containsPoint: r randomPoint). + self deny: r randomPoint isIntegerPoint.! From commits at source.squeak.org Tue Apr 13 15:30:45 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:30:45 0000 Subject: [squeak-dev] The Trunk: Graphics-ct.421.mcz Message-ID: Marcel Taeumel uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-ct.421.mcz ==================== Summary ==================== Name: Graphics-ct.421 Author: ct Time: 20 September 2019, 8:02:53.666726 pm UUID: 2f6f7585-e896-1741-95e7-5b86b5db6062 Ancestors: Graphics-ct.420 Use a better Random generator for default Thanks Marcel! :) =============== Diff against Graphics-ct.419 =============== Item was added: + ----- Method: Rectangle>>randomPoint (in category 'random') ----- + randomPoint + + ^ self randomPoint: ThreadSafeRandom value! Item was added: + ----- Method: Rectangle>>randomPoint: (in category 'random') ----- + randomPoint: aGenerator + + ^ self pointAtFraction: aGenerator next @ aGenerator next! From commits at source.squeak.org Tue Apr 13 15:31:00 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:31:00 0000 Subject: [squeak-dev] The Trunk: Graphics-ct.420.mcz Message-ID: Marcel Taeumel uploaded a new version of Graphics to project The Trunk: http://source.squeak.org/trunk/Graphics-ct.420.mcz ==================== Summary ==================== Name: Graphics-ct.420 Author: ct Time: 20 September 2019, 7:51:45.343726 pm UUID: 639154ec-e7c5-1346-8da0-e2180c88613e Ancestors: Graphics-ct.419 Add random functions for Rectangle Try out: [Morph new openInWorld; center: World bounds randomPoint] =============== Diff against Graphics-ct.419 =============== Item was added: + ----- Method: Rectangle>>randomPoint (in category 'random') ----- + randomPoint + + ^ self randomPoint: Random new! Item was added: + ----- Method: Rectangle>>randomPoint: (in category 'random') ----- + randomPoint: aGenerator + + ^ self pointAtFraction: aGenerator next @ aGenerator next! From commits at source.squeak.org Tue Apr 13 15:52:35 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:52:35 0000 Subject: [squeak-dev] The Trunk: Compiler-nice.456.mcz Message-ID: Nicolas Cellier uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-nice.456.mcz ==================== Summary ==================== Name: Compiler-nice.456 Author: nice Time: 13 April 2021, 5:52:23.50842 pm UUID: 3acf97cf-d6b4-5545-9976-f16c287011ba Ancestors: Compiler-tobe.455 Simplify Symbol lookup a little bit. Similar to rewrite rule same assignment in both ifTrue:ifFalse: branches. =============== Diff against Compiler-tobe.455 =============== Item was changed: ----- Method: Parser>>messagePart:repeat: (in category 'expression types') ----- messagePart: level repeat: repeat | start receiver selector args precedence words keywordStart | [receiver := parseNode. (hereType == #keyword and: [level >= 3]) ifTrue: [start := self startOfNextToken. selector := WriteStream on: (String new: 32). args := OrderedCollection new. words := OrderedCollection new. [hereType == #keyword] whileTrue: [keywordStart := self startOfNextToken + requestorOffset. selector nextPutAll: self advance. words addLast: (keywordStart to: self endOfLastToken + requestorOffset). self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 2 repeat: true. args addLast: parseNode]. + selector := (Symbol lookup: selector contents) + ifNil: [ self correctSelector: selector contents + wordIntervals: words + exprInterval: (start to: self endOfLastToken) + ifAbort: [ ^ self fail ] ]. - (Symbol hasInterned: selector contents ifTrue: [ :sym | selector := sym]) - ifFalse: [ selector := self correctSelector: selector contents - wordIntervals: words - exprInterval: (start to: self endOfLastToken) - ifAbort: [ ^ self fail ] ]. precedence := 3] ifFalse: [ (level >= 2 and: [hereType == #verticalBar]) ifTrue: [self transformAVerticalBarIntoABinarySelector]. (hereType == #binary and: [level >= 2]) ifTrue: [start := self startOfNextToken. selector := self advance asOctetString asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args := Array with: parseNode. precedence := 2] ifFalse: [hereType == #word ifTrue: [start := self startOfNextToken. selector := self advance. args := #(). words := OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). + selector := (Symbol lookup: selector) + ifNil: [ self correctSelector: selector + wordIntervals: words + exprInterval: (start to: self endOfLastToken) + ifAbort: [ ^ self fail ] ]. - (Symbol hasInterned: selector ifTrue: [ :sym | selector := sym]) - ifFalse: [ selector := self correctSelector: selector - wordIntervals: words - exprInterval: (start to: self endOfLastToken) - ifAbort: [ ^ self fail ] ]. precedence := 1] ifFalse: [^args notNil]]]. parseNode := MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! Item was changed: ----- Method: Parser>>pragmaStatementKeywords (in category 'pragmas') ----- pragmaStatementKeywords "Read a single pragma statement. Parse all generic pragmas in the form of: and remember them, including primitives." | selector arguments words index keyword | selector := String new. arguments := OrderedCollection new. words := OrderedCollection new. [ hereType = #keyword or: [ (hereType = #word or: [ hereType = #binary ]) and: [ selector isEmpty ] ] ] whileTrue: [ index := self startOfNextToken + requestorOffset. selector := selector , self advance. words add: (index to: self endOfLastToken + requestorOffset). (selector last = $: or: [ selector first isLetter not ]) ifTrue: [ arguments add: (self pragmaLiteral: selector) ] ]. selector numArgs ~= arguments size ifTrue: [ ^ self expected: 'pragma argument' ]. + keyword := (Symbol lookup: selector) + ifNil: [ self - (Symbol hasInterned: selector - ifTrue: [ :value | keyword := value]) - ifFalse: [ - keyword := self correctSelector: selector wordIntervals: words exprInterval: (words first first to: words last last) ifAbort: [ ^ self fail ] ]. self addPragma: (Pragma keyword: keyword arguments: arguments asArray). ^ true! From commits at source.squeak.org Tue Apr 13 15:58:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:58:15 0000 Subject: [squeak-dev] The Trunk: EToys-nice.440.mcz Message-ID: Nicolas Cellier uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-nice.440.mcz ==================== Summary ==================== Name: EToys-nice.440 Author: nice Time: 13 April 2021, 5:54:56.04842 pm UUID: ff17f473-468b-dd40-b397-46da19a4bee7 Ancestors: EToys-nice.439 Simplify Symbol lookup a little bit. Similar to rewrite rule same assignment in both ifTrue:ifFalse: branches. Essentially same change as super. =============== Diff against EToys-nice.439 =============== Item was changed: ----- Method: DialectParser>>messagePart:repeat:initialKeyword: (in category 'as yet unclassified') ----- messagePart: level repeat: repeat initialKeyword: kwdIfAny | start receiver selector args precedence words keywordStart | [receiver := parseNode. (self matchKeyword and: [level >= 3]) ifTrue: [start := self startOfNextToken. selector := WriteStream on: (String new: 32). selector nextPutAll: kwdIfAny. args := OrderedCollection new. words := OrderedCollection new. [self matchKeyword] whileTrue: [keywordStart := self startOfNextToken + requestorOffset. selector nextPutAll: self advance , ':'. words addLast: (keywordStart to: hereEnd + requestorOffset). self primaryExpression ifFalse: [^ self expected: 'Argument']. args addLast: parseNode]. + selector := (Symbol lookup: selector contents) + ifNil: [ self correctSelector: selector contents + wordIntervals: words + exprInterval: (start to: self endOfLastToken) + ifAbort: [ ^ self fail ] ]. - (Symbol hasInterned: selector contents ifTrue: [ :sym | selector := sym]) - ifFalse: [ selector := self correctSelector: selector contents - wordIntervals: words - exprInterval: (start to: self endOfLastToken) - ifAbort: [ ^ self fail ] ]. precedence := 3] ifFalse: [((hereType == #binary or: [hereType == #verticalBar]) and: [level >= 2]) ifTrue: [start := self startOfNextToken. selector := self advance asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args := Array with: parseNode. precedence := 2] ifFalse: [(hereType == #word and: [(#(leftParenthesis leftBracket leftBrace) includes: tokenType) not]) ifTrue: [start := self startOfNextToken. selector := self advance. args := #(). words := OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). + selector := (Symbol lookup: selector) + ifNil: [ self correctSelector: selector + wordIntervals: words + exprInterval: (start to: self endOfLastToken) + ifAbort: [ ^ self fail ] ]. - (Symbol hasInterned: selector ifTrue: [ :sym | selector := sym]) - ifFalse: [ selector := self correctSelector: selector - wordIntervals: words - exprInterval: (start to: self endOfLastToken) - ifAbort: [ ^ self fail ] ]. precedence := 1] ifFalse: [^args notNil]]]. parseNode := MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! From commits at source.squeak.org Tue Apr 13 15:59:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 15:59:37 0000 Subject: [squeak-dev] The Trunk: PackageInfo-Base-nice.74.mcz Message-ID: Nicolas Cellier uploaded a new version of PackageInfo-Base to project The Trunk: http://source.squeak.org/trunk/PackageInfo-Base-nice.74.mcz ==================== Summary ==================== Name: PackageInfo-Base-nice.74 Author: nice Time: 13 April 2021, 5:59:31.56042 pm UUID: 39619bb2-bd27-2b49-a287-3448bd554bd4 Ancestors: PackageInfo-Base-mt.73 Prefer isSymbol to isKindOf: Symbol =============== Diff against PackageInfo-Base-mt.73 =============== Item was changed: ----- Method: PackageInfo>>externalCallers (in category 'dependencies') ----- externalCallers ^ self + externalRefsSelect: [:literal | literal isSymbol] - externalRefsSelect: [:literal | literal isKindOf: Symbol] thenCollect: [:l | l].! From commits at source.squeak.org Tue Apr 13 16:00:51 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 16:00:51 0000 Subject: [squeak-dev] The Trunk: Tools-nice.1038.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-nice.1038.mcz ==================== Summary ==================== Name: Tools-nice.1038 Author: nice Time: 13 April 2021, 6:00:43.25042 pm UUID: 72d3e1ab-053b-5543-9dea-b96259cb2911 Ancestors: Tools-nice.1037 Simplify Symbol lookup =============== Diff against Tools-nice.1037 =============== Item was changed: ----- Method: SelectorBrowser>>selectedMessageName (in category 'accessing') ----- selectedMessageName + "Answer the name of the currently selected message or nil if not a known Symbol." - "Answer the name of the currently selected message." | example tokens | selectorIndex = 0 ifTrue: [^nil]. example := selectorList at: selectorIndex. tokens := Scanner new scanTokens: example. tokens size = 1 ifTrue: [^ tokens first]. tokens first == #'^' ifTrue: [^ nil]. (tokens second includes: $:) ifTrue: [^ example findSelector]. + ^Symbol lookup: tokens second! - Symbol hasInterned: tokens second ifTrue: [:aSymbol | ^ aSymbol]. - ^ nil! From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 16:25:45 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 18:25:45 +0200 Subject: [squeak-dev] ParserRemovedUnusedTemps Message-ID: The class is in category Tests-Exceptions, only ever used (caught) by ScriptParser and never raised (signalled). Err? From Christoph.Thiede at student.hpi.uni-potsdam.de Tue Apr 13 16:32:04 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Tue, 13 Apr 2021 16:32:04 +0000 Subject: [squeak-dev] ParserRemovedUnusedTemps In-Reply-To: References: Message-ID: <73cafd7c1b8d4d6eabd66ddd0853169e@student.hpi.uni-potsdam.de> Hm, if it's never signaled, we should delete it, shouldn't we? :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Dienstag, 13. April 2021 18:25:45 An: The general-purpose Squeak developers list Betreff: [squeak-dev] ParserRemovedUnusedTemps The class is in category Tests-Exceptions, only ever used (caught) by ScriptParser and never raised (signalled). Err? -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Apr 13 16:32:45 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 16:32:45 0000 Subject: [squeak-dev] The Trunk: Tests-nice.450.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.450.mcz ==================== Summary ==================== Name: Tests-nice.450 Author: nice Time: 13 April 2021, 6:32:38.49942 pm UUID: 88d71628-1262-524d-bbc0-7489c23848f3 Ancestors: Tests-mt.449 Revises ExceptionTests >> #testCatchingDefaultAction to work when being debugged/simulated as well. This also decouples the test from the implementation details of UnhandledWarnings. Also, Warning may be entirely disabled by a Preference, making the test fail. Removes #testHandlerFromAction from expectedFailures because it now finally works. This is same as Tests-ct.448 and Tests-ct.449, with a slightly different test, such that the defaultAction is triggered. Thanks Christoph! =============== Diff against Tests-mt.449 =============== Item was removed: - ----- Method: ExceptionTests>>expectedFailures (in category 'failures') ----- - expectedFailures - "This test is a feature request. For more information on this issue visit: - http://forum.world.st/The-Inbox-Tests-TestRunner-156-mcz-tc4643910.html#a4643987 - http://forum.world.st/ExceptionTests-Wrong-error-handler-tc4848699.html - http://forum.world.st/ExceptionTests-gt-testHandlerFromAction-fails-tc4872828.html#a4872958" - - ^ #(testHandlerFromAction).! Item was changed: ----- Method: ExceptionTests>>testCatchingDefaultAction (in category 'tests - outer') ----- testCatchingDefaultAction "The #defaultAction method is executed in the context of the signaling environment. + It must thus be caught by the handler." + - The defaultAction will raise an UnhandledWarning that should be caught by this handler." | result | + result := [MyTestNotification signalForAction: [MyTestError signal: '2nd exception']] + on: MyTestError + do: [:ex | '2nd exception caught']. + self assert: '2nd exception caught' equals: result.! - result := [ Warning signal: 'Warning signalled' ] on: UnhandledWarning do: [ :ex | 'UnhandledWarning caught' ]. - self assert: 'UnhandledWarning caught' equals: result! Item was changed: Notification subclass: #MyTestNotification + instanceVariableNames: 'action' - instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tests-Exceptions'! Item was added: + ----- Method: MyTestNotification class>>signalForAction: (in category 'signaling') ----- + signalForAction: aBlock + + ^ self new + action: aBlock; + signal! Item was added: + ----- Method: MyTestNotification>>action (in category 'accessing') ----- + action + + ^ action! Item was added: + ----- Method: MyTestNotification>>action: (in category 'accessing') ----- + action: aBlock + + action := aBlock! Item was added: + ----- Method: MyTestNotification>>defaultAction (in category 'priv handling') ----- + defaultAction + + self action ifNotNil: [^ self action cull: self]. + + ^ super defaultAction! From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 16:38:01 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 18:38:01 +0200 Subject: [squeak-dev] ParserRemovedUnusedTemps In-Reply-To: <73cafd7c1b8d4d6eabd66ddd0853169e@student.hpi.uni-potsdam.de> References: <73cafd7c1b8d4d6eabd66ddd0853169e@student.hpi.uni-potsdam.de> Message-ID: IOW, understand where it comes from, if it was replaced by something else in between, if catching it serves a useful feature at all, and fix its usage... Le mar. 13 avr. 2021 à 18:32, Thiede, Christoph a écrit : > > Hm, if it's never signaled, we should delete it, shouldn't we? :-) > > > Best, > > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Nicolas Cellier > Gesendet: Dienstag, 13. April 2021 18:25:45 > An: The general-purpose Squeak developers list > Betreff: [squeak-dev] ParserRemovedUnusedTemps > > The class is in category Tests-Exceptions, only ever used (caught) by > ScriptParser and never raised (signalled). Err? > > From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 16:40:31 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 18:40:31 +0200 Subject: [squeak-dev] ParserRemovedUnusedTemps In-Reply-To: References: <73cafd7c1b8d4d6eabd66ddd0853169e@student.hpi.uni-potsdam.de> Message-ID: In Exceptions-ar.18.mcz... Item was removed: - Notification subclass: #ParserRemovedUnusedTemps - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Exceptions-Tests'! Le mar. 13 avr. 2021 à 18:38, Nicolas Cellier a écrit : > > IOW, understand where it comes from, if it was replaced by something > else in between, if catching it serves a useful feature at all, and > fix its usage... > > Le mar. 13 avr. 2021 à 18:32, Thiede, Christoph > a écrit : > > > > Hm, if it's never signaled, we should delete it, shouldn't we? :-) > > > > > > Best, > > > > Christoph > > > > ________________________________ > > Von: Squeak-dev im Auftrag von Nicolas Cellier > > Gesendet: Dienstag, 13. April 2021 18:25:45 > > An: The general-purpose Squeak developers list > > Betreff: [squeak-dev] ParserRemovedUnusedTemps > > > > The class is in category Tests-Exceptions, only ever used (caught) by > > ScriptParser and never raised (signalled). Err? > > > > From Christoph.Thiede at student.hpi.uni-potsdam.de Tue Apr 13 16:42:29 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Tue, 13 Apr 2021 16:42:29 +0000 Subject: [squeak-dev] The Trunk: Tests-nice.450.mcz In-Reply-To: References: Message-ID: Yes, you're right with the MyTestError, of course. Thanks for merging this and all the other recent stuff!! :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Dienstag, 13. April 2021 18:32:45 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Tests-nice.450.mcz Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.450.mcz ==================== Summary ==================== Name: Tests-nice.450 Author: nice Time: 13 April 2021, 6:32:38.49942 pm UUID: 88d71628-1262-524d-bbc0-7489c23848f3 Ancestors: Tests-mt.449 Revises ExceptionTests >> #testCatchingDefaultAction to work when being debugged/simulated as well. This also decouples the test from the implementation details of UnhandledWarnings. Also, Warning may be entirely disabled by a Preference, making the test fail. Removes #testHandlerFromAction from expectedFailures because it now finally works. This is same as Tests-ct.448 and Tests-ct.449, with a slightly different test, such that the defaultAction is triggered. Thanks Christoph! =============== Diff against Tests-mt.449 =============== Item was removed: - ----- Method: ExceptionTests>>expectedFailures (in category 'failures') ----- - expectedFailures - "This test is a feature request. For more information on this issue visit: - http://forum.world.st/The-Inbox-Tests-TestRunner-156-mcz-tc4643910.html#a4643987 - http://forum.world.st/ExceptionTests-Wrong-error-handler-tc4848699.html - http://forum.world.st/ExceptionTests-gt-testHandlerFromAction-fails-tc4872828.html#a4872958" - - ^ #(testHandlerFromAction).! Item was changed: ----- Method: ExceptionTests>>testCatchingDefaultAction (in category 'tests - outer') ----- testCatchingDefaultAction "The #defaultAction method is executed in the context of the signaling environment. + It must thus be caught by the handler." + - The defaultAction will raise an UnhandledWarning that should be caught by this handler." | result | + result := [MyTestNotification signalForAction: [MyTestError signal: '2nd exception']] + on: MyTestError + do: [:ex | '2nd exception caught']. + self assert: '2nd exception caught' equals: result.! - result := [ Warning signal: 'Warning signalled' ] on: UnhandledWarning do: [ :ex | 'UnhandledWarning caught' ]. - self assert: 'UnhandledWarning caught' equals: result! Item was changed: Notification subclass: #MyTestNotification + instanceVariableNames: 'action' - instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Tests-Exceptions'! Item was added: + ----- Method: MyTestNotification class>>signalForAction: (in category 'signaling') ----- + signalForAction: aBlock + + ^ self new + action: aBlock; + signal! Item was added: + ----- Method: MyTestNotification>>action (in category 'accessing') ----- + action + + ^ action! Item was added: + ----- Method: MyTestNotification>>action: (in category 'accessing') ----- + action: aBlock + + action := aBlock! Item was added: + ----- Method: MyTestNotification>>defaultAction (in category 'priv handling') ----- + defaultAction + + self action ifNotNil: [^ self action cull: self]. + + ^ super defaultAction! -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 16:51:02 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 18:51:02 +0200 Subject: [squeak-dev] Mail daemon problems with Unicode? In-Reply-To: References: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> Message-ID: The fun of it is that the package cannot be browsed nor moved to treated via web interface... https://source.squeak.org/inbox/Tests-ct.449.diff Or try https://source.squeak.org/inbox.html and click on News... It will have to be removed manually (unless we fix more unicode at server side...) Le lun. 12 avr. 2021 à 23:56, Levente Uzonyi a écrit : > Hi Christoph, > > either that or the image could support unicode characters. :) > Btw, my text-based email client doesn't support that character either. > It shows an inverted question mark instead. > > > Levente > > On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > > > > Hi Levente, > > > > > > I see your point, but maybe it would be a better idea to choose another > fallback character for unknown characters instead of sticking with these > old character limitations. :-) That question mark has confused me already > too > > often. Maybe something like ??? or □? But we would need to patch all > fonts in the image to make this possible ... > > > > > > Best, > > > > Christoph > > > > > _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ > > Von: Squeak-dev im > Auftrag von Levente Uzonyi > > Gesendet: Montag, 12. April 2021 23:47:28 > > An: The general-purpose Squeak developers list > > Betreff: Re: [squeak-dev] Mail daemon problems with Unicode? > > Hi Christoph, > > > > It's more likely that squeaksource doesn't handle WideStrings in commit > > messages properly. > > Also, I discourage the use of emojis in commit messages. Yours appears as > > a question mark in my image, which changes the meaning of the message > > quite a bit: > > > > Removes #testHandlerFromAction from expectedFailures because it now > finally works ? > > > > > > Levente > > > > On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > > > > > > > Hi all, > > > > > > > > > do the mail daemons that are responsible for informing the list about > new inbox/trunk versions (probably a part of SqueakSource) have a problem > with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but > as > > far > > > as I can see, a notification email did not arrive. However, older and > newer versions were announced as usual. > > > > > > > > > Here is the header of the relevant version: > > > > > > > > > --- > > > > > > Name: Tests-ct.449 > > > Author: ct > > > Time: 12 April 2021, 9:20:22.70324 pm > > > UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 > > > Ancestors: Tests-nice.447 > > > > > > Removes #testHandlerFromAction from expectedFailures because it now > finally works 🎉 > > > > > > --- > > > > > > > > > Best, > > > > > > Christoph > > > > > > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Tue Apr 13 17:00:52 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Tue, 13 Apr 2021 17:00:52 +0000 Subject: [squeak-dev] Mail daemon problems with Unicode? In-Reply-To: References: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> , Message-ID: <4888392bd0b34b8397c38c3c7f1b9dfc@student.hpi.uni-potsdam.de> > Or try https://source.squeak.org/inbox.html and click on News... Ouch. Sorry for that ... Can't you remove it via Monticello? Or will the problem be solved just by merging it and uploading another version on top of it? Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Dienstag, 13. April 2021 18:51:02 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Mail daemon problems with Unicode? The fun of it is that the package cannot be browsed nor moved to treated via web interface... https://source.squeak.org/inbox/Tests-ct.449.diff Or try https://source.squeak.org/inbox.html and click on News... It will have to be removed manually (unless we fix more unicode at server side...) Le lun. 12 avr. 2021 à 23:56, Levente Uzonyi > a écrit : Hi Christoph, either that or the image could support unicode characters. :) Btw, my text-based email client doesn't support that character either. It shows an inverted question mark instead. Levente On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > Hi Levente, > > > I see your point, but maybe it would be a better idea to choose another fallback character for unknown characters instead of sticking with these old character limitations. :-) That question mark has confused me already too > often. Maybe something like ??? or □? But we would need to patch all fonts in the image to make this possible ... > > > Best, > > Christoph > > _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ > Von: Squeak-dev > im Auftrag von Levente Uzonyi > > Gesendet: Montag, 12. April 2021 23:47:28 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] Mail daemon problems with Unicode? > Hi Christoph, > > It's more likely that squeaksource doesn't handle WideStrings in commit > messages properly. > Also, I discourage the use of emojis in commit messages. Yours appears as > a question mark in my image, which changes the meaning of the message > quite a bit: > > Removes #testHandlerFromAction from expectedFailures because it now finally works ? > > > Levente > > On Mon, 12 Apr 2021, Thiede, Christoph wrote: > > > > > Hi all, > > > > > > do the mail daemons that are responsible for informing the list about new inbox/trunk versions (probably a part of SqueakSource) have a problem with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but as > far > > as I can see, a notification email did not arrive. However, older and newer versions were announced as usual. > > > > > > Here is the header of the relevant version: > > > > > > --- > > > > Name: Tests-ct.449 > > Author: ct > > Time: 12 April 2021, 9:20:22.70324 pm > > UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 > > Ancestors: Tests-nice.447 > > > > Removes #testHandlerFromAction from expectedFailures because it now finally works 🎉 > > > > --- > > > > > > Best, > > > > Christoph > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 17:10:23 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 19:10:23 +0200 Subject: [squeak-dev] Mail daemon problems with Unicode? In-Reply-To: <4888392bd0b34b8397c38c3c7f1b9dfc@student.hpi.uni-potsdam.de> References: <124cbd37064a4d8bb15259601030f746@student.hpi.uni-potsdam.de> <4888392bd0b34b8397c38c3c7f1b9dfc@student.hpi.uni-potsdam.de> Message-ID: Le mar. 13 avr. 2021 à 19:00, Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de> a écrit : > > Or try https://source.squeak.org/inbox.html and click on News... > > Ouch. Sorry for that ... > > > Never mind, the server has already improved, but is not an example of continuous deployment, no matter how agile Squeak can be... Maintenance means lots of efforts from very few persons, so our attitude is kinda conservative. Losing the server is the last thing that we want (it happened in the past for squeaksource.com, for ever if a user put a Character value > 255 in its initials...). > Can't you remove it via Monticello? Or will the problem be solved just by > merging it and uploading another version on top of it? > I had thought of overloading a newer version, but I don't know what happens at image side, or whether or copy of overriden is kept or what... I prefer to let the authorities deal with it. > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Nicolas Cellier > *Gesendet:* Dienstag, 13. April 2021 18:51:02 > *An:* The general-purpose Squeak developers list > *Betreff:* Re: [squeak-dev] Mail daemon problems with Unicode? > > The fun of it is that the package cannot be browsed nor moved to treated > via web interface... > https://source.squeak.org/inbox/Tests-ct.449.diff > Or try https://source.squeak.org/inbox.html and click on News... > It will have to be removed manually (unless we fix more unicode at server > side...) > > Le lun. 12 avr. 2021 à 23:56, Levente Uzonyi a > écrit : > >> Hi Christoph, >> >> either that or the image could support unicode characters. :) >> Btw, my text-based email client doesn't support that character either. >> It shows an inverted question mark instead. >> >> >> Levente >> >> On Mon, 12 Apr 2021, Thiede, Christoph wrote: >> >> > >> > Hi Levente, >> > >> > >> > I see your point, but maybe it would be a better idea to choose another >> fallback character for unknown characters instead of sticking with these >> old character limitations. :-) That question mark has confused me already >> too >> > often. Maybe something like ??? or □? But we would need to patch all >> fonts in the image to make this possible ... >> > >> > >> > Best, >> > >> > Christoph >> > >> > >> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________ >> > Von: Squeak-dev im >> Auftrag von Levente Uzonyi >> > Gesendet: Montag, 12. April 2021 23:47:28 >> > An: The general-purpose Squeak developers list >> > Betreff: Re: [squeak-dev] Mail daemon problems with Unicode? >> > Hi Christoph, >> > >> > It's more likely that squeaksource doesn't handle WideStrings in commit >> > messages properly. >> > Also, I discourage the use of emojis in commit messages. Yours appears >> as >> > a question mark in my image, which changes the meaning of the message >> > quite a bit: >> > >> > Removes #testHandlerFromAction from expectedFailures because it now >> finally works ? >> > >> > >> > Levente >> > >> > On Mon, 12 Apr 2021, Thiede, Christoph wrote: >> > >> > > >> > > Hi all, >> > > >> > > >> > > do the mail daemons that are responsible for informing the list about >> new inbox/trunk versions (probably a part of SqueakSource) have a problem >> with Unicode? My inbox version Tests-ct.449 was uploaded to the inbox, but >> as >> > far >> > > as I can see, a notification email did not arrive. However, older and >> newer versions were announced as usual. >> > > >> > > >> > > Here is the header of the relevant version: >> > > >> > > >> > > --- >> > > >> > > Name: Tests-ct.449 >> > > Author: ct >> > > Time: 12 April 2021, 9:20:22.70324 pm >> > > UUID: f8408deb-6994-0e40-aff1-b3c551b424c4 >> > > Ancestors: Tests-nice.447 >> > > >> > > Removes #testHandlerFromAction from expectedFailures because it now >> finally works 🎉 >> > > >> > > --- >> > > >> > > >> > > Best, >> > > >> > > Christoph >> > > >> > > >> > > >> > >> > >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Apr 13 17:37:08 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 17:37:08 0000 Subject: [squeak-dev] The Inbox: Collections-ct.936.mcz Message-ID: A new version of Collections was added to project The Inbox: http://source.squeak.org/inbox/Collections-ct.936.mcz ==================== Summary ==================== Name: Collections-ct.936 Author: ct Time: 13 April 2021, 7:37:06.061492 pm UUID: 155ef92e-af0e-1644-8109-126a6a0d4c50 Ancestors: Collections-mt.935 Proposal: Adds #indexOf:[startingAt:]ifPresent:[ifAbsent:] on SequenceableCollection. See http://forum.world.st/BUG-Parser-does-not-detect-syntax-error-with-double-colon-tp5112572p5112854.html for a usage example. =============== Diff against Collections-mt.935 =============== Item was added: + ----- Method: SequenceableCollection>>indexOf:ifPresent: (in category 'accessing') ----- + indexOf: anElement ifPresent: indexBlock + + ^ self indexOf: anElement startingAt: 1 ifPresent: indexBlock! Item was added: + ----- Method: SequenceableCollection>>indexOf:startingAt:ifPresent: (in category 'accessing') ----- + indexOf: anElement startingAt: startIndex ifPresent: indexBlock + + ^ self indexOf: anElement startingAt: startIndex ifPresent: indexBlock ifAbsent: [0]! Item was added: + ----- Method: SequenceableCollection>>indexOf:startingAt:ifPresent:ifAbsent: (in category 'accessing') ----- + indexOf: anElement startingAt: startIndex ifPresent: indexBlock ifAbsent: exceptionBlock + + | index | + ^ (index := self indexOf: anElement startingAt: startIndex) = 0 + ifFalse: [indexBlock value: index] + ifTrue: [exceptionBlock value]! From commits at source.squeak.org Tue Apr 13 17:38:03 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 17:38:03 0000 Subject: [squeak-dev] The Inbox: CollectionsTests-ct.355.mcz Message-ID: A new version of CollectionsTests was added to project The Inbox: http://source.squeak.org/inbox/CollectionsTests-ct.355.mcz ==================== Summary ==================== Name: CollectionsTests-ct.355 Author: ct Time: 13 April 2021, 7:38:02.054492 pm UUID: 5d57fca7-6372-9c47-8c19-2cad3062c0de Ancestors: CollectionsTests-nice.354 Tests SequenceableCollection >> #indexOf:[startingAt:][ifPresent:][ifAbsent:]. Depends on Collections-ct.936. =============== Diff against CollectionsTests-nice.354 =============== Item was added: + ----- Method: SequenceableCollectionTest>>testIndexOf (in category 'tests - accessing') ----- + testIndexOf + + | values | + values := #(2 3 5 7 9). + + self assert: 2 equals: (values indexOf: 3). + self assert: 3 equals: (values indexOf: 5). + + self assert: 0 equals: (values indexOf: 1).! Item was added: + ----- Method: SequenceableCollectionTest>>testIndexOfIfAbsent (in category 'tests - accessing') ----- + testIndexOfIfAbsent + + | values | + values := #(2 3 5 7 9). + + self assert: 2 equals: (values indexOf: 3 ifAbsent: [self fail]). + self assert: 3 equals: (values indexOf: 5 ifAbsent: [self fail]). + + self assert: #notFound equals: (values indexOf: 1 ifAbsent: [#notFound]).! Item was added: + ----- Method: SequenceableCollectionTest>>testIndexOfIfPresent (in category 'tests - accessing') ----- + testIndexOfIfPresent + + | values | + values := #(2 3 5 7 9). + + self assert: 2 negated equals: (values indexOf: 3 ifPresent: [:index | index negated]). + self assert: 3 negated equals: (values indexOf: 5 ifPresent: #negated). + + self assert: 0 equals: (values indexOf: 1 ifPresent: [:index | self fail]).! Item was added: + ----- Method: SequenceableCollectionTest>>testIndexOfStartingAtIfAbsent (in category 'tests - accessing') ----- + testIndexOfStartingAtIfAbsent + + | values | + values := #(2 3 5 7 9). + + self assert: 3 equals: (values indexOf: 5 startingAt: 2 ifAbsent: [self fail]). + self assert: 3 equals: (values indexOf: 5 startingAt: 3 ifAbsent: [self fail]). + + self assert: #notFound equals: (values indexOf: 5 startingAt: 4 ifAbsent: [#notFound]).! Item was added: + ----- Method: SequenceableCollectionTest>>testIndexOfStartingAtIfPresent (in category 'tests - accessing') ----- + testIndexOfStartingAtIfPresent + + | values | + values := #(2 3 5 7 9). + + self assert: 3 negated equals: (values indexOf: 5 startingAt: 2 ifPresent: [:index | index negated]). + self assert: 3 negated equals: (values indexOf: 5 startingAt: 3 ifPresent: #negated). + + self assert: 0 equals: (values indexOf: 5 startingAt: 4 ifPresent: [self fail]).! Item was added: + ----- Method: SequenceableCollectionTest>>testIndexOfStartingAtIfPresentIfAsbent (in category 'tests - accessing') ----- + testIndexOfStartingAtIfPresentIfAsbent + + | values | + values := #(2 3 5 7 9). + + self assert: 3 negated equals: (values indexOf: 5 startingAt: 2 ifPresent: [:index | index negated] ifAbsent: [self fail]). + self assert: 3 negated equals: (values indexOf: 5 startingAt: 3 ifPresent: #negated ifAbsent: [self fail]). + + self assert: #notFound equals: (values indexOf: 5 startingAt: 4 ifPresent: [self fail] ifAbsent: [#notFound]).! From commits at source.squeak.org Tue Apr 13 17:39:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 17:39:40 0000 Subject: [squeak-dev] The Inbox: Tests-ct.451.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-ct.451.mcz ==================== Summary ==================== Name: Tests-ct.451 Author: ct Time: 13 April 2021, 7:39:38.492492 pm UUID: f87e67c6-9002-ee48-a8a0-9ee233d7b473 Ancestors: Tests-nice.450 Documents a long-known bug when parsing a message with multiple repetitions of a colon. See: http://forum.world.st/BUG-Parser-does-not-detect-syntax-error-with-double-colon-tp5112572.html =============== Diff against Tests-nice.450 =============== Item was added: + ----- Method: ParserTest>>testDoubleColonMessage (in category 'tests') ----- + testDoubleColonMessage + + self + should: [Parser new + parse: 'griffle foo bar:: baz' + class: UndefinedObject] + raise: SyntaxErrorNotification.! From commits at source.squeak.org Tue Apr 13 17:45:02 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 17:45:02 0000 Subject: [squeak-dev] The Inbox: Compiler-ct.457.mcz Message-ID: A new version of Compiler was added to project The Inbox: http://source.squeak.org/inbox/Compiler-ct.457.mcz ==================== Summary ==================== Name: Compiler-ct.457 Author: ct Time: 13 April 2021, 7:44:59.516492 pm UUID: 22e7ee9f-1b8a-054c-a950-a742690bc284 Ancestors: Compiler-nice.456 Fixes a long-known bug when parsing a message with multiple repetitions of a colon. See Tests-ct.451 and http://forum.world.st/BUG-Parser-does-not-detect-syntax-error-with-double-colon-tp5112572.html. Depends on Collections-ct.936. =============== Diff against Compiler-nice.456 =============== Item was changed: ----- Method: Parser>>expected: (in category 'error handling') ----- expected: aString "Notify a problem at token 'here'." + ^ self expected: aString at: hereMark + requestorOffset! - ^ self notify: aString , ' expected' at: hereMark + requestorOffset! Item was added: + ----- Method: Parser>>expected:at: (in category 'error handling') ----- + expected: aString at: location + + ^ self + notify: ('{1} expected' translated format: {aString}) + at: location! Item was changed: ----- Method: Parser>>messagePart:repeat: (in category 'expression types') ----- messagePart: level repeat: repeat | start receiver selector args precedence words keywordStart | [receiver := parseNode. (hereType == #keyword and: [level >= 3]) ifTrue: [start := self startOfNextToken. selector := WriteStream on: (String new: 32). args := OrderedCollection new. words := OrderedCollection new. [hereType == #keyword] whileTrue: [keywordStart := self startOfNextToken + requestorOffset. selector nextPutAll: self advance. words addLast: (keywordStart to: self endOfLastToken + requestorOffset). self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 2 repeat: true. args addLast: parseNode]. + + selector := selector readStream. + words do: [:word | + (selector next: word size - 1) + indexOf: $: ifPresent: [:index | + ^self expected: 'Argument' at: word start + index]. + selector skip: 1]. + selector := (Symbol lookup: selector contents) ifNil: [ self correctSelector: selector contents wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence := 3] ifFalse: [ (level >= 2 and: [hereType == #verticalBar]) ifTrue: [self transformAVerticalBarIntoABinarySelector]. (hereType == #binary and: [level >= 2]) ifTrue: [start := self startOfNextToken. selector := self advance asOctetString asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args := Array with: parseNode. precedence := 2] ifFalse: [hereType == #word ifTrue: [start := self startOfNextToken. selector := self advance. args := #(). words := OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). selector := (Symbol lookup: selector) ifNil: [ self correctSelector: selector wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence := 1] ifFalse: [^args notNil]]]. parseNode := MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! From Christoph.Thiede at student.hpi.uni-potsdam.de Tue Apr 13 17:49:53 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Tue, 13 Apr 2021 17:49:53 +0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1744.mcz In-Reply-To: References: Message-ID: Thanks for merging! :-) > + "For values between 0.0 and 1.0, answers a point that lies within the receiver's bounds. This method is a more general form of #center (meaning 0.5 at 0.5), #topLeft (meaning 0.0 at 0.0), #bottomCenter (meaning 0.5 at 1.0), etc. If can be useful for layout policies that want to position or resize their submorphs by fraction." Note that "aRectangle pointAtFraction: 0.5" would work as well, thanks to the polymorphy in Point >> #*. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Dienstag, 13. April 2021 14:36:15 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-mt.1744.mcz Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1744.mcz ==================== Summary ==================== Name: Morphic-mt.1744 Author: mt Time: 13 April 2021, 2:36:03.188381 pm UUID: 4f11bc72-a3e8-f641-bccd-13f087ce6464 Ancestors: Morphic-nice.1743, Morphic-ct.1528 Merges Morphic-ct.1528 with extended commentary. =============== Diff against Morphic-nice.1743 =============== Item was added: + ----- Method: Morph>>pointAtFraction: (in category 'geometry') ----- + pointAtFraction: relativePoint + "For values between 0.0 and 1.0, answers a point that lies within the receiver's bounds. This method is a more general form of #center (meaning 0.5 at 0.5), #topLeft (meaning 0.0 at 0.0), #bottomCenter (meaning 0.5 at 1.0), etc. If can be useful for layout policies that want to position or resize their submorphs by fraction." + + ^ self bounds pointAtFraction: relativePoint! -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Tue Apr 13 17:52:32 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Tue, 13 Apr 2021 12:52:32 -0500 (CDT) Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz In-Reply-To: References: Message-ID: <1618336352701-0.post@n4.nabble.com> Hi Nicolas, actually, ST80-ct.255 should have been moved into the treated inbox in favor of ST80-ct.256 as discussed in the thread. Nevertheless, thanks for integrating all these patches! :-) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From nicolas.cellier.aka.nice at gmail.com Tue Apr 13 19:08:27 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 13 Apr 2021 21:08:27 +0200 Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz In-Reply-To: <1618336352701-0.post@n4.nabble.com> References: <1618336352701-0.post@n4.nabble.com> Message-ID: Hi Christoph, yes, I saw that later, but then decided that your first attempt was OK, some kind of integrator privilege ;) If someone has a strong opinion about it, we can change it again, but IMO it's not worth it. The problem with our dev model is that it's been designed with very short cycles in mind. Once the contributions are rotting for more than a month or two, it's very inconvenient to retrieve the messages and discussion from the mailing list, while reviewing the changes in the image. I personally skip this step because the process is already too demanding. Unlike pull/merge requests in github/gitlab, we have no way to let a review process span multiple months, multiple commits, multiple steps (understand separate steps for loading into a live image like we do with MCM update maps), etc... Answering a mail in a cold thread (2 month later or more) does not make sense,see an example below... We also have to use a 3rd tool for moving the package: the source.squak.org web interface. I can guarantee that I have to re-login at each package review (logins are short lived). The way our site URL works, it means that I have to retrieve the page holding the exact version at each re-login. If 1st package letter is > M, it can be 10 clicks away... Plus the fact that I'm pretty sure that in the past, some packages that I previously moved to trunk or treated inbox did reappear in the inbox, that's somehow discouraging, just put a picture of me and Marcel faces here https://en.wikipedia.org/wiki/Dana%C3%AFdes#/media/File:Danaides_by_John_William_Waterhouse,_1903.jpg I'm generally satisfied with our lightweight model, except for the review and integration of inbox contributions. As example, yesterday, I wanted to reject https://source.squeak.org/inbox/Kernel_ct.1366.diff This is because (result := Compiler evaluate:... ifFail: [^nil]) is not the same as your proposal: there is a local return that exit the method in the former case, and an assignment of result with nil in the later case. I can see the diff on our site, but cannot add any annotation unlike github/gitlab. I may try to answer a mail that is about 6 month old, but IMO, it does not make much sense. This mail is not in my client anymore, so it means going thru some forum API with extra login etc... It's just not acceptable. Rejecting without a comment is not acceptable either. It's not fair for contributors, and not fair to ourselves: the reason why we reject is more important than the rejection itself: it is also information reusable for future contributions. If we really want to stick to our lghtweight model, i suggest that we add one more commit message when we move some package to treated, possibly with an automated link to original commit message in some mailing list. This way, I will have a chance to give some additional reason for rejection... I stop the rant here. Above all, I don't want to restrain the will to contribute. Having enthusiastic users overwhelming the inbox with fixes, ideas and enhancements is not the problem, it's a chance! Having too few people to perform the review with poor tools is the problem. We have to do something about it. In my eyes, the reviews done in the mailing list a few month ago are dead, they are not easily findable/usable/amendable. Thanks for bringing the subject, and please, continue to chanllenge us! Ideas for improving the process are wecome too. Le mar. 13 avr. 2021 à 19:52, Christoph Thiede a écrit : > > Hi Nicolas, > > actually, ST80-ct.255 should have been moved into the treated inbox in favor > of ST80-ct.256 as discussed in the thread. Nevertheless, thanks for > integrating all these patches! :-) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > From commits at source.squeak.org Tue Apr 13 20:17:52 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 20:17:52 0000 Subject: [squeak-dev] The Trunk: 60Deprecated-nice.95.mcz Message-ID: Nicolas Cellier uploaded a new version of 60Deprecated to project The Trunk: http://source.squeak.org/trunk/60Deprecated-nice.95.mcz ==================== Summary ==================== Name: 60Deprecated-nice.95 Author: nice Time: 13 April 2021, 10:17:44.93442 pm UUID: b9ef6a0f-b252-cb46-ae0c-aea4982aab49 Ancestors: 60Deprecated-dtl.93 Deprecate findInterned: in favour of more explicit lookup: Considering that: - findInterned: is a long standing selector, - some external package probably still use it, (refactoring browser is at this time of writing) - the image update mechanism might still use it during the transition, (depending on package load order) we prefer to use a simple flag rather than a Deprecation warning. =============== Diff against 60Deprecated-dtl.93 =============== Item was added: + ----- Method: Symbol class>>findInterned: (in category '*60Deprecated-instance creation') ----- + findInterned:aString + self flag: #deprecated. "use lookup: instead, they are synonym" + ^self lookup: aString! From commits at source.squeak.org Tue Apr 13 20:22:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 13 Apr 2021 20:22:26 0000 Subject: [squeak-dev] The Trunk: Collections-nice.936.mcz Message-ID: Nicolas Cellier uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-nice.936.mcz ==================== Summary ==================== Name: Collections-nice.936 Author: nice Time: 13 April 2021, 10:21:49.89342 pm UUID: 8d324920-b4ed-f84c-86e7-a4dcd3e7a1c9 Ancestors: Collections-mt.935 Move findInterned: to deprecated Comment a few essential class side selectors. =============== Diff against Collections-mt.935 =============== Item was changed: + ----- Method: Symbol class>>allSymbols (in category 'accessing') ----- - ----- Method: Symbol class>>allSymbols (in category 'access') ----- allSymbols "Answer all interned symbols" | originalNewSymbols originalSymbolTable | originalNewSymbols := NewSymbols. originalSymbolTable := SymbolTable. ^Array new: originalNewSymbols slowSize + originalSymbolTable slowSize streamContents:[ :stream | stream nextPutAll: originalNewSymbols; nextPutAll: originalSymbolTable ] ! Item was removed: - ----- Method: Symbol class>>findInterned: (in category 'instance creation') ----- - findInterned:aString - - self hasInterned:aString ifTrue:[:symbol| ^symbol]. - ^nil.! Item was changed: ----- Method: Symbol class>>intern: (in category 'instance creation') ----- intern: aStringOrSymbol + "Answer the unique Symbol formed with given String. + If it does not exist yet, create it and intern it in the NewSymbols. + Interning a Symbol should return the Symbol itself, no Symbol should be duplicated" | originalNewSymbols | originalNewSymbols := NewSymbols. ^(self lookup: aStringOrSymbol) ifNil:[ | aSymbol newNewSymbols | aStringOrSymbol isSymbol ifTrue:[ aSymbol := aStringOrSymbol. ] ifFalse:[ aSymbol := (aStringOrSymbol isOctetString ifTrue:[ByteSymbol] ifFalse:[WideSymbol]) new: aStringOrSymbol size. aSymbol string: aStringOrSymbol. aSymbol beReadOnlyObject. ]. newNewSymbols := originalNewSymbols copyWith: aSymbol. originalNewSymbols == NewSymbols ifTrue: [ NewSymbols := newNewSymbols. newNewSymbols size > 1000 ifTrue: [ self condenseNewSymbols ]. aSymbol ] ifFalse: [ "Some other process has modified the symbols. Try again." self intern: aStringOrSymbol ] ]! Item was changed: ----- Method: Symbol class>>lookup: (in category 'instance creation') ----- lookup: aStringOrSymbol + "Answer the unique Symbol formed with given String, if it exists. + Answer nil if no such Symbol does exist yet. + Looking up a Symbol should return the Symbol itself + - no Symbol should be duplicated + - every Symbol should be registered in one of the two Symbol tables" | originalNewSymbols originalSymbolTable | originalNewSymbols := NewSymbols. originalSymbolTable := SymbolTable. ^(originalSymbolTable like: aStringOrSymbol) ifNil: [ originalNewSymbols like: aStringOrSymbol ]! Item was changed: + ----- Method: Symbol class>>selectorsContaining: (in category 'accessing') ----- - ----- Method: Symbol class>>selectorsContaining: (in category 'access') ----- selectorsContaining: aString "Answer a list of selectors that contain aString within them. Case-insensitive. Does return symbols that begin with a capital letter." | size selectorList | selectorList := OrderedCollection new. (size := aString size) = 0 ifTrue: [ ^selectorList ]. self allSymbolTablesDo: [ :each | (each size >= size and: [ (each includesSubstring: aString caseSensitive: false) and: [ each numArgs ~= -1 ] ]) ifTrue: [ selectorList add: each ] ]. ^selectorList "Symbol selectorsContaining: 'scon'"! Item was changed: + ----- Method: Symbol class>>selectorsMatching: (in category 'accessing') ----- - ----- Method: Symbol class>>selectorsMatching: (in category 'access') ----- selectorsMatching: aStringPattern "Answer a list of selectors that match aStringPattern within them. Case-insensitive. Does return symbols that begin with a capital letter." | selectorList | selectorList := OrderedCollection new. aStringPattern isEmpty ifTrue: [ ^selectorList ]. self allSymbolTablesDo: [ :each | ((aStringPattern match: each) and: [ each numArgs ~= -1 ]) ifTrue: [selectorList add: each ] ]. ^selectorList "Symbol selectorsMatching: 'parse:*'"! Item was changed: + ----- Method: Symbol class>>thatStarts:skipping: (in category 'accessing') ----- - ----- Method: Symbol class>>thatStarts:skipping: (in category 'access') ----- thatStarts: leadingCharacters skipping: skipSym "Answer a selector symbol that starts with leadingCharacters. Symbols beginning with a lower-case letter handled directly here. Ignore case after first char. If skipSym is not nil, it is a previous answer; start searching after it. If no symbols are found, answer nil. Used by Alt-q (Command-q) routines" | size firstMatch key | size := leadingCharacters size. size = 0 ifTrue: [^skipSym ifNil: [#''] ifNotNil: [nil]]. firstMatch := leadingCharacters at: 1. size > 1 ifTrue: [key := leadingCharacters copyFrom: 2 to: size]. self allSymbolTablesDo: [:each | each size >= size ifTrue: [ ((each at: 1) == firstMatch and: [key == nil or: [(each findString: key startingAt: 2 caseSensitive: false) = 2]]) ifTrue: [^each] ] ] after: skipSym. ^nil "Symbol thatStarts: 'sf' skipping: nil" "Symbol thatStarts: 'sf' skipping: #sfpGetFile:with:with:with:with:with:with:with:with:" "Symbol thatStarts: 'candidate' skipping: nil" ! Item was changed: + ----- Method: Symbol class>>thatStartsCaseSensitive:skipping: (in category 'accessing') ----- - ----- Method: Symbol class>>thatStartsCaseSensitive:skipping: (in category 'access') ----- thatStartsCaseSensitive: leadingCharacters skipping: skipSym "Same as thatStarts:skipping: but caseSensitive" | size firstMatch key | size := leadingCharacters size. size = 0 ifTrue: [^skipSym ifNil: [#''] ifNotNil: [nil]]. firstMatch := leadingCharacters at: 1. size > 1 ifTrue: [key := leadingCharacters copyFrom: 2 to: size]. self allSymbolTablesDo: [:each | each size >= size ifTrue: [ ((each at: 1) == firstMatch and: [key == nil or: [(each findString: key startingAt: 2 caseSensitive: true) = 2]]) ifTrue: [^each] ] ] after: skipSym. ^nil ! From commits at source.squeak.org Wed Apr 14 07:17:10 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:17:10 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1749.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1749.mcz ==================== Summary ==================== Name: Morphic-mt.1749 Author: mt Time: 14 April 2021, 9:16:54.322665 am UUID: ef4ada4c-49e7-0e47-8666-65f157b4a83f Ancestors: Morphic-mt.1748 Fixes a small regression in halo dispatching, which concerns rendered morphs (i.e., the ones wrapped in TransformationMorph such as when rotated.) =============== Diff against Morphic-mt.1748 =============== Item was changed: ----- Method: MorphicHaloDispatcher>>dispatchHalo:transferInwardsFrom: (in category 'dispatching') ----- dispatchHalo: event transferInwardsFrom: currentTarget | localEvent world | + "Note that a halo usually attaches to the outermost (or top) renderer in a composition around the rendered morph. Thus, we have to lookup that inner (or rendered) morph first when transferring the halo inwards in the hierarchy of submorphs." + currentTarget renderedMorph submorphsDo: [:nextTarget | - currentTarget submorphsDo: [:nextTarget | localEvent := event transformedBy: (nextTarget transformedFrom: currentTarget). (nextTarget fullContainsPoint: localEvent position) ifTrue: [ ^ nextTarget wantsHaloFromClick ifTrue: [self invokeHalo: localEvent on: nextTarget] ifFalse: [self dispatchHalo: localEvent transferInwardsFrom: nextTarget]]]. "We're at the bottom most level; throw the event back up to the root to find recipient" event hand removeHalo. Preferences maintainHalos ifFalse: [ (world := currentTarget world) ifNil: [ ^ false ]. localEvent := event transformedBy: (currentTarget transformedFrom: world) inverseTransformation. world processEvent: localEvent resetHandlerFields]. ^ false! Item was changed: ----- Method: MorphicHaloDispatcher>>dispatchHalo:transferOutwardsFrom: (in category 'dispatching') ----- dispatchHalo: event transferOutwardsFrom: currentTarget | localEvent | + "Note that a halo usually handles composite renderers through the outermost (or top) renderer. So, we can directly use the renderer's owner to transfer a halo outwards in the hierarchy of morphs." + "self assert: [currentTarget == currentTarget topRendererOrSelf]." currentTarget owner ifNotNil: [:nextTarget | localEvent := event transformedBy: (currentTarget transformedFrom: nextTarget). "Never transfer halo to top-most world" ^ (nextTarget isWorldMorph not and: [nextTarget wantsHaloFromClick]) ifTrue: [self invokeHalo: localEvent on: nextTarget] ifFalse: [self dispatchHalo: localEvent transferOutwardsFrom: nextTarget]]. "We're at the top level; throw the event back in to find recipient" event hand removeHalo. currentTarget isWorldMorph ifTrue: [currentTarget processEvent: event copy resetHandlerFields]. ^ false! From commits at source.squeak.org Wed Apr 14 07:41:51 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:41:51 0000 Subject: [squeak-dev] The Trunk: Kernel-mt.1385.mcz Message-ID: Marcel Taeumel uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-mt.1385.mcz ==================== Summary ==================== Name: Kernel-mt.1385 Author: mt Time: 14 April 2021, 9:41:34.215665 am UUID: e4a24d49-fe9d-f043-b842-446b8af102e9 Ancestors: Kernel-nice.1384 Clean up and comment on the idiom #perform:orSendTo:. =============== Diff against Kernel-nice.1384 =============== Item was changed: ----- Method: Object>>perform:orSendTo: (in category 'message handling') ----- perform: selector orSendTo: otherTarget + "Generic callback for an object composition. If the receiver can respond, then perform the message send on itself. If not, delegate it to otherTarget. This can be useful for callbacks in model-view compositions where the model might be the receiver and the view be the otherTarget. Override this to provoke a message-not-understood exception or otherwise tweak the send." + + ^ (self respondsTo: selector) + ifTrue: [self perform: selector] + ifFalse: [otherTarget perform: selector]! - "If I wish to intercept and handle selector myself, do it; else send it to otherTarget" - ^ (self respondsTo: selector) ifTrue: [self perform: selector] ifFalse: [otherTarget perform: selector]! From commits at source.squeak.org Wed Apr 14 07:42:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:42:37 0000 Subject: [squeak-dev] The Trunk: Collections-mt.937.mcz Message-ID: Marcel Taeumel uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-mt.937.mcz ==================== Summary ==================== Name: Collections-mt.937 Author: mt Time: 14 April 2021, 9:42:31.313665 am UUID: b12c73f5-bd6f-0b48-878f-9f3f95d81faf Ancestors: Collections-nice.936 Complements Kernel-mt.1385 =============== Diff against Collections-nice.936 =============== Item was removed: - ----- Method: TranscriptStream>>perform:orSendTo: (in category 'model protocol') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ otherTarget perform: selector]! From commits at source.squeak.org Wed Apr 14 07:43:25 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:43:25 0000 Subject: [squeak-dev] The Trunk: EToys-mt.441.mcz Message-ID: Marcel Taeumel uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-mt.441.mcz ==================== Summary ==================== Name: EToys-mt.441 Author: mt Time: 14 April 2021, 9:43:07.259665 am UUID: b2a89067-de1f-2842-9cdf-c3dc005e4081 Ancestors: EToys-nice.440 Complements Kernel-mt.1385 =============== Diff against EToys-nice.440 =============== Item was removed: - ----- Method: PDA>>perform:orSendTo: (in category 'menus') ----- - perform: selector orSendTo: otherTarget - "This should be the default in Object" - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ otherTarget perform: selector]! From commits at source.squeak.org Wed Apr 14 07:44:01 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:44:01 0000 Subject: [squeak-dev] The Trunk: Monticello-mt.743.mcz Message-ID: Marcel Taeumel uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-mt.743.mcz ==================== Summary ==================== Name: Monticello-mt.743 Author: mt Time: 14 April 2021, 9:43:59.404665 am UUID: 42fc906d-c9da-0149-9243-5acea0cf7c9e Ancestors: Monticello-nice.742 Complements Kernel-mt.1385 =============== Diff against Monticello-nice.742 =============== Item was removed: - ----- Method: MCCodeTool>>perform:orSendTo: (in category 'menus') ----- - perform: selector orSendTo: otherTarget - - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ super perform: selector orSendTo: otherTarget]! Item was removed: - ----- Method: MCOperationsBrowser>>perform:orSendTo: (in category 'ui') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ otherTarget perform: selector]! Item was removed: - ----- Method: MCTool>>perform:orSendTo: (in category 'morphic ui') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ otherTarget perform: selector]! From commits at source.squeak.org Wed Apr 14 07:44:56 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:44:56 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1750.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1750.mcz ==================== Summary ==================== Name: Morphic-mt.1750 Author: mt Time: 14 April 2021, 9:44:42.500665 am UUID: 242a7945-b715-9540-8714-f2111eddeed1 Ancestors: Morphic-mt.1749 Complements Kernel-mt.1385 =============== Diff against Morphic-mt.1749 =============== Item was removed: - ----- Method: AbstractHierarchicalList>>perform:orSendTo: (in category 'message handling') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ otherTarget perform: selector]! From commits at source.squeak.org Wed Apr 14 07:45:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:45:26 0000 Subject: [squeak-dev] The Trunk: Network-mt.247.mcz Message-ID: Marcel Taeumel uploaded a new version of Network to project The Trunk: http://source.squeak.org/trunk/Network-mt.247.mcz ==================== Summary ==================== Name: Network-mt.247 Author: mt Time: 14 April 2021, 9:45:23.119665 am UUID: 688fc950-a2b2-d346-93a5-018e53bc45c5 Ancestors: Network-nice.246 Complements Kernel-mt.1385 =============== Diff against Network-nice.246 =============== Item was removed: - ----- Method: MailComposition>>perform:orSendTo: (in category 'private') ----- - perform: selector orSendTo: otherTarget - - (self respondsTo: selector) - ifTrue: [^self perform: selector] - ifFalse: [^otherTarget perform: selector] - - ! From commits at source.squeak.org Wed Apr 14 07:46:19 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:46:19 0000 Subject: [squeak-dev] The Trunk: SMLoader-mt.94.mcz Message-ID: Marcel Taeumel uploaded a new version of SMLoader to project The Trunk: http://source.squeak.org/trunk/SMLoader-mt.94.mcz ==================== Summary ==================== Name: SMLoader-mt.94 Author: mt Time: 14 April 2021, 9:46:17.413665 am UUID: 9f954356-f52c-064c-9011-2229f808750f Ancestors: SMLoader-cmm.93 Complements Kernel-mt.1385 =============== Diff against SMLoader-cmm.93 =============== Item was removed: - ----- Method: SMLoader>>perform:orSendTo: (in category 'interface') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ super perform: selector orSendTo: otherTarget]! Item was removed: - ----- Method: SMLoaderPlus>>perform:orSendTo: (in category 'interface') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - ^ (self respondsTo: selector) - ifTrue: [self perform: selector] - ifFalse: [super perform: selector orSendTo: otherTarget]! From commits at source.squeak.org Wed Apr 14 07:47:35 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:47:35 0000 Subject: [squeak-dev] The Trunk: ST80-mt.267.mcz Message-ID: Marcel Taeumel uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-mt.267.mcz ==================== Summary ==================== Name: ST80-mt.267 Author: mt Time: 14 April 2021, 9:47:30.788665 am UUID: ce924c12-c725-fc42-98e1-a68fc4017dbb Ancestors: ST80-nice.266 Complements Kernel-mt.1385 =============== Diff against ST80-nice.266 =============== Item was removed: - ----- Method: PluggableTest>>perform:orSendTo: (in category 'menu commands') ----- - perform: sel orSendTo: otherObject - (self respondsTo: sel) ifTrue: [self perform: sel] ifFalse: [otherObject perform: sel]! From commits at source.squeak.org Wed Apr 14 07:48:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:48:20 0000 Subject: [squeak-dev] The Trunk: SUnitGUI-mt.83.mcz Message-ID: Marcel Taeumel uploaded a new version of SUnitGUI to project The Trunk: http://source.squeak.org/trunk/SUnitGUI-mt.83.mcz ==================== Summary ==================== Name: SUnitGUI-mt.83 Author: mt Time: 14 April 2021, 9:48:19.570665 am UUID: ac91f00f-0b54-c54e-8b71-900544976563 Ancestors: SUnitGUI-eem.82 Complements Kernel-mt.1385 =============== Diff against SUnitGUI-eem.82 =============== Item was removed: - ----- Method: TestRunner>>perform:orSendTo: (in category 'private') ----- - perform: selector orSendTo: otherTarget - "" - - ^ (self respondsTo: selector) - ifTrue: [ self perform: selector ] - ifFalse: [ super perform: selector orSendTo: otherTarget ].! From commits at source.squeak.org Wed Apr 14 07:49:08 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 07:49:08 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1039.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1039.mcz ==================== Summary ==================== Name: Tools-mt.1039 Author: mt Time: 14 April 2021, 9:49:00.579665 am UUID: 187951a8-2af2-f048-a6f3-4f8a7f62d7ec Ancestors: Tools-nice.1038 Complements Kernel-mt.1385 =============== Diff against Tools-nice.1038 =============== Item was removed: - ----- Method: PointerFinder>>perform:orSendTo: (in category 'message handling') ----- - perform: selector orSendTo: otherTarget - selector == #inspectObject ifTrue: [^ self inspectObject]. - selector == #searchAgain ifTrue: [^ self searchAgain]. - ^ super perform: selector orSendTo: otherTarget! Item was removed: - ----- Method: ProcessBrowser>>perform:orSendTo: (in category 'message handling') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ super perform: selector orSendTo: otherTarget]! Item was removed: - ----- Method: StringHolder>>perform:orSendTo: (in category '*Tools-code pane menu') ----- - perform: selector orSendTo: otherTarget - "Selector was just chosen from a menu by a user. If can respond, then - perform it on myself. If not, send it to otherTarget, presumably the - editPane from which the menu was invoked." - - (self respondsTo: selector) - ifTrue: [^ self perform: selector] - ifFalse: [^ otherTarget perform: selector]! From marcel.taeumel at hpi.de Wed Apr 14 08:02:45 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 14 Apr 2021 10:02:45 +0200 Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz In-Reply-To: References: <1618336352701-0.post@n4.nabble.com> Message-ID: Hi Nicolas. > I may try to answer a mail that is about 6 month old, but IMO, it does > not make much sense. > This mail is not in my client anymore, so it means going thru some > forum API with extra login etc... > It's just not acceptable. I find both ways manageable. It doesn't take too much time for me. Yet, I see the benefit of a platform with integrated tools such as GitHub. It should be possible to write a small tool (or extension to Monticello) to make a comment (via e-mail?) on an inbox version using the mailing list and the matching entry there.  No need to move all the data to a new platform where the tools are --- just add the missing tools. IMO the better cost-value ratio. ... Any takers? Christoph? :-D Best, Marcel  Am 13.04.2021 21:08:52 schrieb Nicolas Cellier : Hi Christoph, yes, I saw that later, but then decided that your first attempt was OK, some kind of integrator privilege ;) If someone has a strong opinion about it, we can change it again, but IMO it's not worth it. The problem with our dev model is that it's been designed with very short cycles in mind. Once the contributions are rotting for more than a month or two, it's very inconvenient to retrieve the messages and discussion from the mailing list, while reviewing the changes in the image. I personally skip this step because the process is already too demanding. Unlike pull/merge requests in github/gitlab, we have no way to let a review process span multiple months, multiple commits, multiple steps (understand separate steps for loading into a live image like we do with MCM update maps), etc... Answering a mail in a cold thread (2 month later or more) does not make sense,see an example below... We also have to use a 3rd tool for moving the package: the source.squak.org web interface. I can guarantee that I have to re-login at each package review (logins are short lived). The way our site URL works, it means that I have to retrieve the page holding the exact version at each re-login. If 1st package letter is > M, it can be 10 clicks away... Plus the fact that I'm pretty sure that in the past, some packages that I previously moved to trunk or treated inbox did reappear in the inbox, that's somehow discouraging, just put a picture of me and Marcel faces here https://en.wikipedia.org/wiki/Dana%C3%AFdes#/media/File:Danaides_by_John_William_Waterhouse,_1903.jpg I'm generally satisfied with our lightweight model, except for the review and integration of inbox contributions. As example, yesterday, I wanted to reject https://source.squeak.org/inbox/Kernel_ct.1366.diff This is because (result := Compiler evaluate:... ifFail: [^nil]) is not the same as your proposal: there is a local return that exit the method in the former case, and an assignment of result with nil in the later case. I can see the diff on our site, but cannot add any annotation unlike github/gitlab. I may try to answer a mail that is about 6 month old, but IMO, it does not make much sense. This mail is not in my client anymore, so it means going thru some forum API with extra login etc... It's just not acceptable. Rejecting without a comment is not acceptable either. It's not fair for contributors, and not fair to ourselves: the reason why we reject is more important than the rejection itself: it is also information reusable for future contributions. If we really want to stick to our lghtweight model, i suggest that we add one more commit message when we move some package to treated, possibly with an automated link to original commit message in some mailing list. This way, I will have a chance to give some additional reason for rejection... I stop the rant here. Above all, I don't want to restrain the will to contribute. Having enthusiastic users overwhelming the inbox with fixes, ideas and enhancements is not the problem, it's a chance! Having too few people to perform the review with poor tools is the problem. We have to do something about it. In my eyes, the reviews done in the mailing list a few month ago are dead, they are not easily findable/usable/amendable. Thanks for bringing the subject, and please, continue to chanllenge us! Ideas for improving the process are wecome too. Le mar. 13 avr. 2021 à 19:52, Christoph Thiede a écrit : > > Hi Nicolas, > > actually, ST80-ct.255 should have been moved into the treated inbox in favor > of ST80-ct.256 as discussed in the thread. Nevertheless, thanks for > integrating all these patches! :-) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Apr 14 08:04:53 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 14 Apr 2021 10:04:53 +0200 Subject: [squeak-dev] The Trunk: Morphic-mt.1744.mcz In-Reply-To: References: Message-ID: Hi Christoph. > Note that "aRectangle pointAtFraction: 0.5" would work as well, thanks to the polymorphy in Point >> #*. You might want to add those special cases to the tests. I added some tests about #pointAtFraction: to RectangleTest. Best, Marcel Am 13.04.2021 19:50:03 schrieb Thiede, Christoph : Thanks for merging! :-) > +        "For values between 0.0 and 1.0, answers a point that lies within the receiver's bounds. This method is a more general form of #center (meaning 0.5 at 0.5), #topLeft (meaning 0.0 at 0.0), #bottomCenter (meaning 0.5 at 1.0), etc. If can be useful for layout policies that want to position or resize their submorphs by fraction." Note that "aRectangle pointAtFraction: 0.5" would work as well, thanks to the polymorphy in Point >> #*. Best, Christoph Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Dienstag, 13. April 2021 14:36:15 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-mt.1744.mcz   Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1744.mcz [http://source.squeak.org/trunk/Morphic-mt.1744.mcz] ==================== Summary ==================== Name: Morphic-mt.1744 Author: mt Time: 13 April 2021, 2:36:03.188381 pm UUID: 4f11bc72-a3e8-f641-bccd-13f087ce6464 Ancestors: Morphic-nice.1743, Morphic-ct.1528 Merges Morphic-ct.1528 with extended commentary. =============== Diff against Morphic-nice.1743 =============== Item was added: + ----- Method: Morph>>pointAtFraction: (in category 'geometry') ----- + pointAtFraction: relativePoint +        "For values between 0.0 and 1.0, answers a point that lies within the receiver's bounds. This method is a more general form of #center (meaning 0.5 at 0.5), #topLeft (meaning 0.0 at 0.0), #bottomCenter (meaning 0.5 at 1.0), etc. If can be useful for layout policies that want to position or resize their submorphs by fraction." + +        ^ self bounds pointAtFraction: relativePoint! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Apr 14 08:09:42 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 14 Apr 2021 10:09:42 +0200 Subject: [squeak-dev] The Inbox: Compiler-ct.457.mcz In-Reply-To: References: Message-ID: Hi Christoph. > Depends on Collections-ct.936. Please try to avoid connecting bug fixes to (unrelated) proposals. Instead, try to fix the bugs with the available means. This way, your fixes can get merged faster. For your proposals, try to find examples that can improve code readability in general to promote an objective discussion. Best, Marcel Am 13.04.2021 19:45:09 schrieb commits at source.squeak.org : A new version of Compiler was added to project The Inbox: http://source.squeak.org/inbox/Compiler-ct.457.mcz ==================== Summary ==================== Name: Compiler-ct.457 Author: ct Time: 13 April 2021, 7:44:59.516492 pm UUID: 22e7ee9f-1b8a-054c-a950-a742690bc284 Ancestors: Compiler-nice.456 Fixes a long-known bug when parsing a message with multiple repetitions of a colon. See Tests-ct.451 and http://forum.world.st/BUG-Parser-does-not-detect-syntax-error-with-double-colon-tp5112572.html. Depends on Collections-ct.936. =============== Diff against Compiler-nice.456 =============== Item was changed: ----- Method: Parser>>expected: (in category 'error handling') ----- expected: aString "Notify a problem at token 'here'." + ^ self expected: aString at: hereMark + requestorOffset! - ^ self notify: aString , ' expected' at: hereMark + requestorOffset! Item was added: + ----- Method: Parser>>expected:at: (in category 'error handling') ----- + expected: aString at: location + + ^ self + notify: ('{1} expected' translated format: {aString}) + at: location! Item was changed: ----- Method: Parser>>messagePart:repeat: (in category 'expression types') ----- messagePart: level repeat: repeat | start receiver selector args precedence words keywordStart | [receiver := parseNode. (hereType == #keyword and: [level >= 3]) ifTrue: [start := self startOfNextToken. selector := WriteStream on: (String new: 32). args := OrderedCollection new. words := OrderedCollection new. [hereType == #keyword] whileTrue: [keywordStart := self startOfNextToken + requestorOffset. selector nextPutAll: self advance. words addLast: (keywordStart to: self endOfLastToken + requestorOffset). self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 2 repeat: true. args addLast: parseNode]. + + selector := selector readStream. + words do: [:word | + (selector next: word size - 1) + indexOf: $: ifPresent: [:index | + ^self expected: 'Argument' at: word start + index]. + selector skip: 1]. + selector := (Symbol lookup: selector contents) ifNil: [ self correctSelector: selector contents wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence := 3] ifFalse: [ (level >= 2 and: [hereType == #verticalBar]) ifTrue: [self transformAVerticalBarIntoABinarySelector]. (hereType == #binary and: [level >= 2]) ifTrue: [start := self startOfNextToken. selector := self advance asOctetString asSymbol. self primaryExpression ifFalse: [^self expected: 'Argument']. self messagePart: 1 repeat: true. args := Array with: parseNode. precedence := 2] ifFalse: [hereType == #word ifTrue: [start := self startOfNextToken. selector := self advance. args := #(). words := OrderedCollection with: (start + requestorOffset to: self endOfLastToken + requestorOffset). selector := (Symbol lookup: selector) ifNil: [ self correctSelector: selector wordIntervals: words exprInterval: (start to: self endOfLastToken) ifAbort: [ ^ self fail ] ]. precedence := 1] ifFalse: [^args notNil]]]. parseNode := MessageNode new receiver: receiver selector: selector arguments: args precedence: precedence from: encoder sourceRange: (start to: self endOfLastToken). repeat] whileTrue: []. ^true! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Apr 14 08:30:24 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 14 Apr 2021 10:30:24 +0200 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <20210412205610.GA33248@shell.msen.com> References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> <20210412205610.GA33248@shell.msen.com> Message-ID: Hi Dave, you could just add another version. No need to modify dtl.1225 :-) Best, Marcel Am 12.04.2021 22:56:16 schrieb David T. Lewis : On Mon, Apr 12, 2021 at 08:43:45AM +0200, Marcel Taeumel wrote: > > > Am 12.04.2021 um 04:11 schrieb David T. Lewis : > > > > > > On Sun, Apr 11, 2021 at 05:01:31PM +0200, Nicolas Cellier wrote: > >> Hi all, > >> it seems we have enough +1, let's just do it. > >> > > > > Done. > > Hi Dave. > > Thanks. Maybe also add a pointer to the discussion on this list. > Hi Marcel, Yes, I should have added a link to the discussion. I could save a fixed System-dtl.1225 to trunk, although I am afraid it may cause problems for the update stream for people who have already loaded that version number with a different UUID in their trunk update. If someone can confirm that it is safe to replace the existing System-dtl.1225 with another one that differs only by commit comment and UUID, then I'll copy it up to trunk. Otherwise I think I'll play it safe and leave it alone. Thanks, Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 14 08:38:51 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 08:38:51 0000 Subject: [squeak-dev] The Trunk: Tests-mt.451.mcz Message-ID: Marcel Taeumel uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-mt.451.mcz ==================== Summary ==================== Name: Tests-mt.451 Author: mt Time: 14 April 2021, 10:38:45.375489 am UUID: 2cef30f0-b2f4-b742-8105-48ecd3ec8650 Ancestors: Tests-nice.450 Adds commentary to CompilerExceptionsTest to explain how the "tests spec" for simulated user interactions look like. =============== Diff against Tests-nice.450 =============== Item was changed: ----- Method: CompilerExceptionsTest>>compiling:shouldRaise:andSelect:testing: (in category 'private') ----- compiling: sourceCode shouldRaise: exceptionClass andSelect: selectionMatch testing: tests + "Test behavior of the compiler for the given sourceCode and expected an exception of kind exceptionClass. Other arguments: + * selectionMatch is used to check the selection of the source text that is active when an exception has occured. Can be a text, an interval, or a predicate block. See #assertSelection:. + * tests is an array of associations representing pairs of reactions (key) to the exception and the assertion (value) that should be run afterward. + * The key can be a boolean for answering yes/no dialogs, a string for selecting a named option from a dialog window, or a one-arg block to handle the occuring exception in a different way (see #handlerBlockFor:). + * The value can be either a string that will be compared to the final compiler source code or a custom assertion block that will be evaluated after the compilation has terminated (see #testBlockFor:)." | referenceTest | referenceTest := [] -> []. (tests copyWithFirst: referenceTest) associationsDo: [:test | self should: [self compile: sourceCode] raise: exceptionClass thenDo: [:exception | self assertSelection: selectionMatch. previousSelection := self selectionInterval. (self handlerBlockFor: test key) cull: exception]. (self testBlockFor: test value) value].! From commits at source.squeak.org Wed Apr 14 09:19:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 09:19:46 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1751.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1751.mcz ==================== Summary ==================== Name: Morphic-mt.1751 Author: mt Time: 14 April 2021, 11:19:35.123489 am UUID: 8fa68c8f-44ca-4d4a-a9e7-f69619be782e Ancestors: Morphic-mt.1750 Slightly improve browsing and debugging of so-called "button actions" by also supporting #perform:orSendTo:, which yields #effectiveActionTarget and #effectiveActionSelector. (Note that this design is still to be improved. I refrained from adding the debug/browse interface for button actions to Morph. A next step might be to take a look at all implementors of #doButtonAction. Maybe this will generate some ideas.) =============== Diff against Morphic-mt.1750 =============== Item was removed: - ----- Method: MenuItemMorph>>browseAllImplementorsOfRealSelector (in category 'browse') ----- - browseAllImplementorsOfRealSelector - SystemNavigation default browseAllImplementorsOf: self realSelector localTo: target class! Item was changed: ----- Method: MenuItemMorph>>browseImplementationOfActionSelector (in category 'browse') ----- browseImplementationOfActionSelector | method | + method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. - method := target class lookupSelector: selector. ToolSet browse: method methodClass selector: method selector.! Item was changed: ----- Method: MenuItemMorph>>debugAction (in category 'browse') ----- debugAction (Process forBlock: [self doButtonAction] + runUntil: [:context | context selector = self effectiveActionSelector]) - runUntil: [:context | context selector = self selector]) debugWithTitle: ('Debug menu action "{1}" in model "{2}"' format: {self contents. self target printString}).! Item was added: + ----- Method: MenuItemMorph>>effectiveActionSelector (in category 'browse') ----- + effectiveActionSelector + + ^ self selector = #perform:orSendTo: + ifTrue: [self arguments first] + ifFalse: [self selector]! Item was added: + ----- Method: MenuItemMorph>>effectiveActionTarget (in category 'browse') ----- + effectiveActionTarget + + ^ (self selector = #perform:orSendTo: + and: [(self target respondsTo: self effectiveActionSelector) not]) + ifTrue: [self arguments second] + ifFalse: [self target]! Item was removed: - ----- Method: MenuItemMorph>>realSelector (in category 'browse') ----- - realSelector - selector == #perform:orSendTo: ifTrue: [^arguments first]. - ^selector! Item was changed: ----- Method: Morph>>doButtonAction (in category 'button') ----- doButtonAction + "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. It is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programmatically from user scripts."! - "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism. Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts"! Item was changed: ----- Method: PluggableButtonMorph>>browseImplementationOfActionSelector (in category 'debug menu') ----- browseImplementationOfActionSelector | method | + self updateArguments. + method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. - method := model class lookupSelector: actionSelector. ToolSet browse: method methodClass selector: method selector.! Item was changed: ----- Method: PluggableButtonMorph>>debugAction (in category 'debug menu') ----- debugAction + self updateArguments. + (Process + forBlock: [self doButtonAction] + runUntil: [:context | context selector = self effectiveActionSelector]) - forBlock: [self performAction] - runUntil: [:context | context selector = self actionSelector]) debugWithTitle: ('Debug button action "{1}" in model "{2}"' format: {self label. self target printString}).! Item was added: + ----- Method: PluggableButtonMorph>>doButtonAction (in category 'button') ----- + doButtonAction + + ^ self performAction! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionSelector (in category 'debug menu') ----- + effectiveActionSelector + + ^ self actionSelector = #perform:orSendTo: + ifTrue: [arguments first] + ifFalse: [self actionSelector]! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionTarget (in category 'debug menu') ----- + effectiveActionTarget + + ^ (self actionSelector = #perform:orSendTo: + and: [(self target respondsTo: self effectiveActionSelector) not]) + ifTrue: [arguments second] + ifFalse: [self target]! Item was changed: + ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout-properties') ----- hResizing: aSymbol "We adapt our minimum extent according to our resize behavior." self hResizing == aSymbol ifTrue: [^ self]. super hResizing: aSymbol. self updateMinimumExtent.! Item was changed: + ----- Method: PluggableButtonMorph>>performAction (in category 'event handling') ----- - ----- Method: PluggableButtonMorph>>performAction (in category 'accessing') ----- performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed. If the button's actionSelector takes any arguments, they are obtained dynamically by sending the argumentSelector to the argumentsProvider" askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]]. actionSelector ifNotNil: [actionSelector numArgs = 0 ifTrue: [model perform: actionSelector] ifFalse: + [self updateArguments. - [argumentsProvider ifNotNil: - [arguments := argumentsProvider perform: argumentsSelector]. model perform: actionSelector withArguments: arguments]]! Item was added: + ----- Method: PluggableButtonMorph>>updateArguments (in category 'updating') ----- + updateArguments + + argumentsProvider ifNil: [^ self]. + argumentsSelector ifNil: [^ self]. + arguments := argumentsProvider perform: argumentsSelector.! Item was changed: + ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout-properties') ----- vResizing: aSymbol "We adapt our minimum extent according to our resize behavior." self vResizing == aSymbol ifTrue: [^ self]. super vResizing: aSymbol. self updateMinimumExtent.! From commits at source.squeak.org Wed Apr 14 10:19:43 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:19:43 0000 Subject: [squeak-dev] The Inbox: Multilingual-ul.258.mcz Message-ID: Levente Uzonyi uploaded a new version of Multilingual to project The Inbox: http://source.squeak.org/inbox/Multilingual-ul.258.mcz ==================== Summary ==================== Name: Multilingual-ul.258 Author: ul Time: 14 April 2021, 12:00:20.264533 pm UUID: eebd5681-298a-4aba-aeb2-53019a774f4b Ancestors: Multilingual-nice.257 - implement MultiByteFileStream >> #basicSkipTo: - restore MultiByteFileStream >> #basicUpTo: based on the previously removed implementation and #basicSkipTo: =============== Diff against Multilingual-nice.257 =============== Item was added: + ----- Method: MultiByteFileStream>>basicSkipTo: (in category 'private basic') ----- + basicSkipTo: delimiter + "Set the access position of the receiver to be past the next occurrence of delimiter. Answer whether delimiter is found. Ignore both character encoding and line end conversion." + + collection ifNotNil: [ + [ + | delimiterPosition | + self atEnd ifTrue: [ ^false ]. + ((delimiterPosition := collection indexOf: delimiter startingAt: position + 1) > 0 + and: [ delimiterPosition <= readLimit ]) + ifTrue: [ + position := delimiterPosition. + ^true ]. + position := readLimit. + "make sure the next block is read from the file." + self basicNext = delimiter ifTrue: [ ^true ] ] repeat ]. + + "read buffering is disabled" + [ self atEnd ] whileFalse: [ self basicNext = delimiter ifTrue: [ ^true ] ]. + ^false! Item was added: + ----- Method: MultiByteFileStream>>basicUpTo: (in category 'private basic') ----- + basicUpTo: delimiter + "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of delimiter in the receiver. If delimiter is not in the collection, answer the entire rest of the receiver. Ignore both character encoding and line end conversion." + + | start end result | + collection ifNotNil: [ + (position < readLimit and: [ + (end := collection indexOf: delimiter startingAt: position + 1) > 0 and: [ + end <= readLimit ] ]) ifTrue: [ + ^collection copyFrom: position + 1 to: (position := end) - 1 ] ]. + start := self position. + self basicSkipTo: delimiter. + end := self position. + self position: start. + "File position may be set to a value greater than the file's size. Make sure the argument is not negative." + result := self basicNext: (end - start - 1 max: 0). + "Read the delimiter itself. Noop when #atEnd." + self basicNext. + ^result! From commits at source.squeak.org Wed Apr 14 10:20:05 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:20:05 0000 Subject: [squeak-dev] The Inbox: Collections-ul.938.mcz Message-ID: Levente Uzonyi uploaded a new version of Collections to project The Inbox: http://source.squeak.org/inbox/Collections-ul.938.mcz ==================== Summary ==================== Name: Collections-ul.938 Author: ul Time: 14 April 2021, 12:04:31.18204 pm UUID: 0ebddf60-7622-4708-976d-62ebea16aee5 Ancestors: Collections-mt.937 - implement PositionableStream >> #basicSkipTo: - make PositionableStream >> #basicUpTo: do what other #basic* methods do - use #streamContents: in PositionableStream >> #upTo: =============== Diff against Collections-mt.937 =============== Item was added: + ----- Method: PositionableStream>>basicSkipTo: (in category 'accessing - multibyte support') ----- + basicSkipTo: anObject + + ^self skipTo: anObject! Item was changed: + ----- Method: PositionableStream>>basicUpTo: (in category 'accessing - multibyte support') ----- - ----- Method: PositionableStream>>basicUpTo: (in category 'private basic') ----- basicUpTo: anObject + + ^self upTo: anObject! - "Answer a subcollection from the current access position to the - occurrence (if any, but not inclusive) of anObject in the receiver. If - anObject is not in the collection, answer the entire rest of the receiver." - | newStream element | - newStream := WriteStream on: (self collectionSpecies new: 100). - [self atEnd or: [(element := self basicNext) = anObject]] - whileFalse: [newStream nextPut: element]. - ^newStream contents! Item was changed: ----- Method: PositionableStream>>upTo: (in category 'accessing') ----- upTo: anObject "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of anObject in the receiver. If anObject is not in the collection, answer the entire rest of the receiver." + + ^self collectionSpecies streamContents: [ :stream | + | element | + [self atEnd or: [(element := self next) = anObject]] + whileFalse: [stream nextPut: element]]! - | newStream element | - newStream := WriteStream on: (self collectionSpecies new: 100). - [self atEnd or: [(element := self next) = anObject]] - whileFalse: [newStream nextPut: element]. - ^newStream contents! From commits at source.squeak.org Wed Apr 14 10:20:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:20:20 0000 Subject: [squeak-dev] The Inbox: Collections-ul.939.mcz Message-ID: Levente Uzonyi uploaded a new version of Collections to project The Inbox: http://source.squeak.org/inbox/Collections-ul.939.mcz ==================== Summary ==================== Name: Collections-ul.939 Author: ul Time: 14 April 2021, 12:06:29.592182 pm UUID: 3b540268-794a-4f47-81e1-74816f0ca4d7 Ancestors: Collections-mt.937 - replace custom symbol creation methods, #string and #pvtAt:put: with #copyFrom: in Symbol class >> #intern: - remove the now unused private methods =============== Diff against Collections-mt.937 =============== Item was removed: - ----- Method: ByteSymbol>>pvtAt:put: (in category 'private') ----- - pvtAt: index put: aCharacter - "Primitive. Store the Character in the field of the receiver indicated by the index. - Fail if the index is not an Integer or is out of bounds, or if the argument is not a - Character, or the Character's code is outside the 0-255 range, or if the receiver - is read-only. Essential. See Object documentation whatIsAPrimitive." - - - aCharacter isCharacter ifFalse: - [^self errorImproperStore]. - index isInteger - ifTrue: - [ec == #'no modification' ifTrue: - [^thisContext modificationForbiddenFor: self at: index putCharacter: aCharacter]. - self errorSubscriptBounds: index] - ifFalse: [self errorNonIntegerIndex]! Item was removed: - ----- Method: ByteSymbol>>string: (in category 'private') ----- - string: aString - 1 to: aString size do: [:j | self pvtAt: j put: (aString at: j)]. - ^self! Item was changed: ----- Method: Symbol class>>intern: (in category 'instance creation') ----- intern: aStringOrSymbol "Answer the unique Symbol formed with given String. If it does not exist yet, create it and intern it in the NewSymbols. Interning a Symbol should return the Symbol itself, no Symbol should be duplicated" | originalNewSymbols | originalNewSymbols := NewSymbols. ^(self lookup: aStringOrSymbol) ifNil:[ | aSymbol newNewSymbols | aStringOrSymbol isSymbol ifTrue:[ aSymbol := aStringOrSymbol. ] ifFalse:[ aSymbol := (aStringOrSymbol isOctetString ifTrue:[ByteSymbol] ifFalse:[WideSymbol]) new: aStringOrSymbol size. + aSymbol + copyFrom: aStringOrSymbol; + beReadOnlyObject. - aSymbol string: aStringOrSymbol. - aSymbol beReadOnlyObject. ]. newNewSymbols := originalNewSymbols copyWith: aSymbol. originalNewSymbols == NewSymbols ifTrue: [ NewSymbols := newNewSymbols. newNewSymbols size > 1000 ifTrue: [ self condenseNewSymbols ]. aSymbol ] ifFalse: [ "Some other process has modified the symbols. Try again." self intern: aStringOrSymbol ] ]! Item was removed: - ----- Method: Symbol>>string: (in category 'private') ----- - string: aString - - 1 to: aString size do: [:j | super at: j put: (aString at: j)]. - ^self ! Item was removed: - ----- Method: WideSymbol>>pvtAt:put: (in category 'private') ----- - pvtAt: index put: aCharacter - "Primitive. Store the Character in the field of the receiver indicated by - the index. Fail if the index is not an Integer or is out of bounds, or if - the argument is not a Character, or if the receiver is read-only. - Essential. See Object documentation whatIsAPrimitive." - - - aCharacter isCharacter ifFalse: - [^self errorImproperStore]. - index isInteger - ifTrue: - [ec == #'no modification' ifTrue: - [^thisContext modificationForbiddenFor: self at: index putCharacter: aCharacter]. - self errorSubscriptBounds: index] - ifFalse: [self errorNonIntegerIndex]! Item was removed: - ----- Method: WideSymbol>>string: (in category 'private') ----- - string: aString - 1 to: aString size do: [:j | self pvtAt: j put: (aString at: j) asInteger]. - ^self! From commits at source.squeak.org Wed Apr 14 10:21:17 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:21:17 0000 Subject: [squeak-dev] The Inbox: KernelTests-ul.400.mcz Message-ID: Levente Uzonyi uploaded a new version of KernelTests to project The Inbox: http://source.squeak.org/inbox/KernelTests-ul.400.mcz ==================== Summary ==================== Name: KernelTests-ul.400 Author: ul Time: 14 April 2021, 12:14:51.757056 pm UUID: 6234d088-bf14-4d00-8734-dde043b756ba Ancestors: KernelTests-nice.399 WriteBarrierTest changes: - removed symbol mutator methods - both #testMutateByteSymbolUsingPrivateAtPut and #testMutateWideSymbolUsingPrivateAtPut reference a non-existent #privateAt:put: method, and make the accessed symbol permanently writeable - with the removal of #pvtAt:put: from ByteSymbol and WideSymbol, the tests seem to be unnecessary (see Collections-ul.939) - fix copy-paste error in #testMutateObjectInstVarUsingBasicAtPut: test #basicAt:put: instead of #at:put: - avoid having MirrorPrimitives in Undeclared by removing direct references to it in WriteBarrierTest. Perhaps MirrorPrimitives should be moved to the Trunk from VMMaker - use temporaries in CompiledMethodComparisonTest >> #testHash to improve legibility =============== Diff against KernelTests-nice.399 =============== Item was changed: ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- testHash | ai | ai := CompiledMethod allInstances. "We assume here that if two CompiledMethods are equal then they have the same size and header." (ai groupBy: [ :method | { method size. method header } ]) values replace: [ :each | each asArray ]; do: [ :methods | 1 to: methods size do: [ :i | + | firstMethod | + firstMethod := methods at: i. i to: methods size do: [ :j | + | secondMethod | + secondMethod := methods at: j. + firstMethod = secondMethod ifTrue: [ + self assert: firstMethod hash equals: secondMethod hash ] ] ] ] - (methods at: i) = (methods at: j) ifTrue: [ - self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] displayingProgress: 'Testing hashes'. self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! Item was changed: ----- Method: WriteBarrierTest>>expectedFailures (in category 'expected failures') ----- expectedFailures Smalltalk supportsReadOnlyObjects ifFalse: [^self class testSelectors]. ^#( testMutateByteArrayUsingDoubleAtPut testMutateByteArrayUsingFloatAtPut ), + (self mirrorPrimitives - ((Smalltalk classNamed: #MirrorPrimitives) ifNil: [#(testBasicProxyReadOnly testBasicProxyWritable testSetIsReadOnlySuccessProxy)] ifNotNil: [#()])! Item was added: + ----- Method: WriteBarrierTest>>mirrorPrimitives (in category 'tests - helper') ----- + mirrorPrimitives + + ^Smalltalk classNamed: #MirrorPrimitives! Item was changed: ----- Method: WriteBarrierTest>>testBasicProxyReadOnly (in category 'tests - proxy') ----- testBasicProxyReadOnly self alwaysReadOnlyObjects do: [ :each | + self assert: (self mirrorPrimitives isObjectReadOnly: each) equals: true ]! - self assert: (MirrorPrimitives isObjectReadOnly: each) equals: true ]! Item was changed: ----- Method: WriteBarrierTest>>testBasicProxyWritable (in category 'tests - proxy') ----- testBasicProxyWritable self alwaysWritableObjects , self maybeReadOnlyObjects do: [ :each | + self assert: (self mirrorPrimitives isObjectReadOnly: each) equals: false ]! - self assert: (MirrorPrimitives isObjectReadOnly: each) equals: false ]! Item was removed: - ----- Method: WriteBarrierTest>>testMutateByteSymbolUsingPrivateAtPut (in category 'tests - object') ----- - testMutateByteSymbolUsingPrivateAtPut - | guineaPig | - [guineaPig := #hello. - guineaPig beReadOnlyObject. - - self - should: ((guineaPig class includesSelector: #pvtAt:put:) - ifTrue: [[ guineaPig perform: #pvtAt:put: with: 1 with: $q ]] "Squeak refuses to compile non-self sends of pvt* selectors." - ifFalse: [[ guineaPig privateAt: 1 put: $q ]]) - raise: ModificationForbidden ] - ensure: - [ guineaPig beWritableObject ]. - - self assert: guineaPig first equals: $h! Item was changed: ----- Method: WriteBarrierTest>>testMutateObjectInstVarUsingBasicAtPut (in category 'tests - object') ----- testMutateObjectInstVarUsingBasicAtPut | guineaPig | guineaPig := Array new: 5. guineaPig beReadOnlyObject. self should: [ guineaPig basicAt: 1 put: #test ] raise: ModificationForbidden. + [ guineaPig basicAt: 1 put: #test ] - [ guineaPig at: 1 put: #test ] on: ModificationForbidden do: [:modification | self assert: modification fieldIndex equals: 1. modification object beWritableObject. modification retryModification ]. self assert: guineaPig first equals: #test! Item was removed: - ----- Method: WriteBarrierTest>>testMutateWideSymbolUsingPrivateAtPut (in category 'tests - object') ----- - testMutateWideSymbolUsingPrivateAtPut - | guineaPig | - [ guineaPig := ('hello', (Character codePoint: 8002) asString) asSymbol. - guineaPig beReadOnlyObject. - - self - should: ((guineaPig class includesSelector: #pvtAt:put:) - ifTrue: [[ guineaPig perform: #pvtAt:put: with: 1 with: $A ]] "Squeak refuses to compile non-self sends of pvt* selectors." - ifFalse: [[ guineaPig privateAt: 1 put: $A ]]) - raise: ModificationForbidden ] - ensure: [ guineaPig beWritableObject ]. - - self assert: guineaPig first equals: $h! Item was changed: ----- Method: WriteBarrierTest>>testProxyObject:initialState:tuples: (in category 'tests - helper') ----- testProxyObject: object initialState: initialState tuples: tuples self testObject: object initialState: initialState tuples: tuples setReadOnlyBlock: [ :value | + self mirrorPrimitives makeObject: object readOnly: value ]! - MirrorPrimitives makeObject: object readOnly: value ]! From commits at source.squeak.org Wed Apr 14 10:22:09 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:22:09 0000 Subject: [squeak-dev] The Inbox: System-ul.1227.mcz Message-ID: Levente Uzonyi uploaded a new version of System to project The Inbox: http://source.squeak.org/inbox/System-ul.1227.mcz ==================== Summary ==================== Name: System-ul.1227 Author: ul Time: 14 April 2021, 12:18:21.030941 pm UUID: f2db8914-3046-4620-9c86-aa697acafff2 Ancestors: System-mt.1226 - do not modify the System package when generating preference accessors =============== Diff against System-mt.1226 =============== Item was changed: ----- Method: Preferences class>>compileAccessorForPreference: (in category 'private') ----- compileAccessorForPreference: aPreference "Compile an accessor method for the given preference" self class compileSilently: ( '{1} ^self valueOfFlag: {2} ifAbsent: [ {3} ]' format: { aPreference name asString. aPreference name asSymbol printString. aPreference defaultValue storeString }) + classified: '*autogenerated - standard queries'! - classified: 'standard queries'! From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 14 10:25:08 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 14 Apr 2021 10:25:08 +0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1751.mcz In-Reply-To: References: Message-ID: <33e41b5ded384590816403a6340c0ce0@student.hpi.uni-potsdam.de> Thank you for improving this! I already had a similar hack in my image for some time, but your solution is cleaner, of course. When putting further efforts into this construction site, I would like to kindly ask you again to take a look at System-ct.1149. :-) In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. > I refrained from adding the debug/browse interface for button actions to Morph. I don't really see the problem here, Morph includes a lot of functionalities that are only used by certain subclasses. Anyway, could this be worth a trait, TMorphWithAction, or something similar? On the other hand, one morph might support multiple actions, so a generic solution would have its advantages ... Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 14. April 2021 11:19:46 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-mt.1751.mcz Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1751.mcz ==================== Summary ==================== Name: Morphic-mt.1751 Author: mt Time: 14 April 2021, 11:19:35.123489 am UUID: 8fa68c8f-44ca-4d4a-a9e7-f69619be782e Ancestors: Morphic-mt.1750 Slightly improve browsing and debugging of so-called "button actions" by also supporting #perform:orSendTo:, which yields #effectiveActionTarget and #effectiveActionSelector. (Note that this design is still to be improved. I refrained from adding the debug/browse interface for button actions to Morph. A next step might be to take a look at all implementors of #doButtonAction. Maybe this will generate some ideas.) =============== Diff against Morphic-mt.1750 =============== Item was removed: - ----- Method: MenuItemMorph>>browseAllImplementorsOfRealSelector (in category 'browse') ----- - browseAllImplementorsOfRealSelector - SystemNavigation default browseAllImplementorsOf: self realSelector localTo: target class! Item was changed: ----- Method: MenuItemMorph>>browseImplementationOfActionSelector (in category 'browse') ----- browseImplementationOfActionSelector | method | + method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. - method := target class lookupSelector: selector. ToolSet browse: method methodClass selector: method selector.! Item was changed: ----- Method: MenuItemMorph>>debugAction (in category 'browse') ----- debugAction (Process forBlock: [self doButtonAction] + runUntil: [:context | context selector = self effectiveActionSelector]) - runUntil: [:context | context selector = self selector]) debugWithTitle: ('Debug menu action "{1}" in model "{2}"' format: {self contents. self target printString}).! Item was added: + ----- Method: MenuItemMorph>>effectiveActionSelector (in category 'browse') ----- + effectiveActionSelector + + ^ self selector = #perform:orSendTo: + ifTrue: [self arguments first] + ifFalse: [self selector]! Item was added: + ----- Method: MenuItemMorph>>effectiveActionTarget (in category 'browse') ----- + effectiveActionTarget + + ^ (self selector = #perform:orSendTo: + and: [(self target respondsTo: self effectiveActionSelector) not]) + ifTrue: [self arguments second] + ifFalse: [self target]! Item was removed: - ----- Method: MenuItemMorph>>realSelector (in category 'browse') ----- - realSelector - selector == #perform:orSendTo: ifTrue: [^arguments first]. - ^selector! Item was changed: ----- Method: Morph>>doButtonAction (in category 'button') ----- doButtonAction + "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. It is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programmatically from user scripts."! - "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism. Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts"! Item was changed: ----- Method: PluggableButtonMorph>>browseImplementationOfActionSelector (in category 'debug menu') ----- browseImplementationOfActionSelector | method | + self updateArguments. + method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. - method := model class lookupSelector: actionSelector. ToolSet browse: method methodClass selector: method selector.! Item was changed: ----- Method: PluggableButtonMorph>>debugAction (in category 'debug menu') ----- debugAction + self updateArguments. + (Process + forBlock: [self doButtonAction] + runUntil: [:context | context selector = self effectiveActionSelector]) - forBlock: [self performAction] - runUntil: [:context | context selector = self actionSelector]) debugWithTitle: ('Debug button action "{1}" in model "{2}"' format: {self label. self target printString}).! Item was added: + ----- Method: PluggableButtonMorph>>doButtonAction (in category 'button') ----- + doButtonAction + + ^ self performAction! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionSelector (in category 'debug menu') ----- + effectiveActionSelector + + ^ self actionSelector = #perform:orSendTo: + ifTrue: [arguments first] + ifFalse: [self actionSelector]! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionTarget (in category 'debug menu') ----- + effectiveActionTarget + + ^ (self actionSelector = #perform:orSendTo: + and: [(self target respondsTo: self effectiveActionSelector) not]) + ifTrue: [arguments second] + ifFalse: [self target]! Item was changed: + ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout-properties') ----- hResizing: aSymbol "We adapt our minimum extent according to our resize behavior." self hResizing == aSymbol ifTrue: [^ self]. super hResizing: aSymbol. self updateMinimumExtent.! Item was changed: + ----- Method: PluggableButtonMorph>>performAction (in category 'event handling') ----- - ----- Method: PluggableButtonMorph>>performAction (in category 'accessing') ----- performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed. If the button's actionSelector takes any arguments, they are obtained dynamically by sending the argumentSelector to the argumentsProvider" askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]]. actionSelector ifNotNil: [actionSelector numArgs = 0 ifTrue: [model perform: actionSelector] ifFalse: + [self updateArguments. - [argumentsProvider ifNotNil: - [arguments := argumentsProvider perform: argumentsSelector]. model perform: actionSelector withArguments: arguments]]! Item was added: + ----- Method: PluggableButtonMorph>>updateArguments (in category 'updating') ----- + updateArguments + + argumentsProvider ifNil: [^ self]. + argumentsSelector ifNil: [^ self]. + arguments := argumentsProvider perform: argumentsSelector.! Item was changed: + ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout-properties') ----- vResizing: aSymbol "We adapt our minimum extent according to our resize behavior." self vResizing == aSymbol ifTrue: [^ self]. super vResizing: aSymbol. self updateMinimumExtent.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 14 10:26:58 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:26:58 0000 Subject: [squeak-dev] The Trunk: System-ul.1227.mcz Message-ID: Nicolas Cellier uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-ul.1227.mcz ==================== Summary ==================== Name: System-ul.1227 Author: ul Time: 14 April 2021, 12:18:21.030941 pm UUID: f2db8914-3046-4620-9c86-aa697acafff2 Ancestors: System-mt.1226 - do not modify the System package when generating preference accessors =============== Diff against System-mt.1226 =============== Item was changed: ----- Method: Preferences class>>compileAccessorForPreference: (in category 'private') ----- compileAccessorForPreference: aPreference "Compile an accessor method for the given preference" self class compileSilently: ( '{1} ^self valueOfFlag: {2} ifAbsent: [ {3} ]' format: { aPreference name asString. aPreference name asSymbol printString. aPreference defaultValue storeString }) + classified: '*autogenerated - standard queries'! - classified: 'standard queries'! From marcel.taeumel at hpi.de Wed Apr 14 10:33:34 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 14 Apr 2021 12:33:34 +0200 Subject: [squeak-dev] The Trunk: Morphic-mt.1751.mcz In-Reply-To: <33e41b5ded384590816403a6340c0ce0@student.hpi.uni-potsdam.de> References: <33e41b5ded384590816403a6340c0ce0@student.hpi.uni-potsdam.de> Message-ID: >  I think that only checking the selector but not the receiver of the context is a too weak criterion Sure, we could check both. > Anyway, could this be worth a trait, TMorphWithAction, or something similar? I suppose not. There is not much redundancy here and the class inheritance is simply extended via cross-cutting protocols and selectors, which can easily be retrieved via senders/implementors; verifiable through tests. As soon as the shared aspect gets more complex, I would vote for object composition like LayoutPolicy. Best, Marcel Am 14.04.2021 12:25:22 schrieb Thiede, Christoph : Thank you for improving this! I already had a similar hack in my image for some time, but your solution is cleaner, of course. When putting further efforts into this construction site, I would like to kindly ask you again to take a look at System-ct.1149. :-) In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. > I refrained from adding the debug/browse interface for button actions to Morph. I don't really see the problem here, Morph includes a lot of functionalities that are only used by certain subclasses. Anyway, could this be worth a trait, TMorphWithAction, or something similar? On the other hand, one morph might support multiple actions, so a generic solution would have its advantages ... Best, Christoph [http://www.hpi.de/] Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 14. April 2021 11:19:46 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-mt.1751.mcz   Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1751.mcz [http://source.squeak.org/trunk/Morphic-mt.1751.mcz] ==================== Summary ==================== Name: Morphic-mt.1751 Author: mt Time: 14 April 2021, 11:19:35.123489 am UUID: 8fa68c8f-44ca-4d4a-a9e7-f69619be782e Ancestors: Morphic-mt.1750 Slightly improve browsing and debugging of so-called "button actions" by also supporting #perform:orSendTo:, which yields #effectiveActionTarget and #effectiveActionSelector. (Note that this design is still to be improved. I refrained from adding the debug/browse interface for button actions to Morph. A next step might be to take a look at all implementors of #doButtonAction. Maybe this will generate some ideas.) =============== Diff against Morphic-mt.1750 =============== Item was removed: - ----- Method: MenuItemMorph>>browseAllImplementorsOfRealSelector (in category 'browse') ----- - browseAllImplementorsOfRealSelector -        SystemNavigation default browseAllImplementorsOf: self realSelector localTo: target class! Item was changed:   ----- Method: MenuItemMorph>>browseImplementationOfActionSelector (in category 'browse') -----   browseImplementationOfActionSelector            | method | +        method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. -        method := target class lookupSelector: selector.          ToolSet browse: method methodClass selector: method selector.! Item was changed:   ----- Method: MenuItemMorph>>debugAction (in category 'browse') -----   debugAction            (Process                  forBlock: [self doButtonAction] +                runUntil: [:context | context selector = self effectiveActionSelector]) -                runUntil: [:context | context selector = self selector])                          debugWithTitle: ('Debug menu action "{1}" in model "{2}"' format: {self contents. self target printString}).! Item was added: + ----- Method: MenuItemMorph>>effectiveActionSelector (in category 'browse') ----- + effectiveActionSelector +        +        ^ self selector = #perform:orSendTo: +                ifTrue: [self arguments first] +                ifFalse: [self selector]! Item was added: + ----- Method: MenuItemMorph>>effectiveActionTarget (in category 'browse') ----- + effectiveActionTarget + +        ^ (self selector = #perform:orSendTo: +                and: [(self target respondsTo: self effectiveActionSelector) not]) +                        ifTrue: [self arguments second] +                        ifFalse: [self target]! Item was removed: - ----- Method: MenuItemMorph>>realSelector (in category 'browse') ----- - realSelector -        selector == #perform:orSendTo: ifTrue: [^arguments first]. -        ^selector! Item was changed:   ----- Method: Morph>>doButtonAction (in category 'button') -----   doButtonAction +        "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing.  Note that there are several ways -- too many ways -- for morphs to have button-like actions. It is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programmatically from user scripts."! -        "If the receiver has a button-action defined, do it now.  The default button action of any morph is, well, to do nothing.  Note that there are several ways -- too many ways -- for morphs to have button-like actions.  This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism.  Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts"! Item was changed:   ----- Method: PluggableButtonMorph>>browseImplementationOfActionSelector (in category 'debug menu') -----   browseImplementationOfActionSelector            | method | +        self updateArguments. +        method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. -        method := model class lookupSelector: actionSelector.          ToolSet browse: method methodClass selector: method selector.! Item was changed:   ----- Method: PluggableButtonMorph>>debugAction (in category 'debug menu') -----   debugAction   +        self updateArguments. +          (Process +                forBlock: [self doButtonAction] +                runUntil: [:context | context selector = self effectiveActionSelector]) -                forBlock: [self performAction] -                runUntil: [:context | context selector = self actionSelector])                          debugWithTitle: ('Debug button action "{1}" in model "{2}"' format: {self label. self target printString}).! Item was added: + ----- Method: PluggableButtonMorph>>doButtonAction (in category 'button') ----- + doButtonAction + +        ^ self performAction! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionSelector (in category 'debug menu') ----- + effectiveActionSelector +        +        ^ self actionSelector = #perform:orSendTo: +                ifTrue: [arguments first] +                ifFalse: [self actionSelector]! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionTarget (in category 'debug menu') ----- + effectiveActionTarget + +        ^ (self actionSelector = #perform:orSendTo: +                and: [(self target respondsTo: self effectiveActionSelector) not]) +                        ifTrue: [arguments second] +                        ifFalse: [self target]! Item was changed: + ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout-properties') -----   hResizing: aSymbol          "We adapt our minimum extent according to our resize behavior."                   self hResizing == aSymbol ifTrue: [^ self].          super hResizing: aSymbol.          self updateMinimumExtent.! Item was changed: + ----- Method: PluggableButtonMorph>>performAction (in category 'event handling') ----- - ----- Method: PluggableButtonMorph>>performAction (in category 'accessing') -----   performAction          "Inform the model that this button has been pressed. Sent by the controller when this button is pressed. If the button's actionSelector takes any arguments, they are obtained dynamically by sending the argumentSelector to the argumentsProvider"            askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].          actionSelector ifNotNil:                  [actionSelector numArgs = 0                          ifTrue:                                  [model perform: actionSelector]                          ifFalse: +                                [self updateArguments. -                                [argumentsProvider ifNotNil: -                                        [arguments := argumentsProvider perform: argumentsSelector].                                          model perform: actionSelector withArguments: arguments]]! Item was added: + ----- Method: PluggableButtonMorph>>updateArguments (in category 'updating') ----- + updateArguments + +        argumentsProvider ifNil: [^ self]. +        argumentsSelector ifNil: [^ self]. +        arguments := argumentsProvider perform: argumentsSelector.! Item was changed: + ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout-properties') -----   vResizing: aSymbol          "We adapt our minimum extent according to our resize behavior."                   self vResizing == aSymbol ifTrue: [^ self].          super vResizing: aSymbol.          self updateMinimumExtent.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 14 10:43:56 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:43:56 0000 Subject: [squeak-dev] The Trunk: Multilingual-ul.258.mcz Message-ID: Nicolas Cellier uploaded a new version of Multilingual to project The Trunk: http://source.squeak.org/trunk/Multilingual-ul.258.mcz ==================== Summary ==================== Name: Multilingual-ul.258 Author: ul Time: 14 April 2021, 12:00:20.264533 pm UUID: eebd5681-298a-4aba-aeb2-53019a774f4b Ancestors: Multilingual-nice.257 - implement MultiByteFileStream >> #basicSkipTo: - restore MultiByteFileStream >> #basicUpTo: based on the previously removed implementation and #basicSkipTo: =============== Diff against Multilingual-nice.257 =============== Item was added: + ----- Method: MultiByteFileStream>>basicSkipTo: (in category 'private basic') ----- + basicSkipTo: delimiter + "Set the access position of the receiver to be past the next occurrence of delimiter. Answer whether delimiter is found. Ignore both character encoding and line end conversion." + + collection ifNotNil: [ + [ + | delimiterPosition | + self atEnd ifTrue: [ ^false ]. + ((delimiterPosition := collection indexOf: delimiter startingAt: position + 1) > 0 + and: [ delimiterPosition <= readLimit ]) + ifTrue: [ + position := delimiterPosition. + ^true ]. + position := readLimit. + "make sure the next block is read from the file." + self basicNext = delimiter ifTrue: [ ^true ] ] repeat ]. + + "read buffering is disabled" + [ self atEnd ] whileFalse: [ self basicNext = delimiter ifTrue: [ ^true ] ]. + ^false! Item was added: + ----- Method: MultiByteFileStream>>basicUpTo: (in category 'private basic') ----- + basicUpTo: delimiter + "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of delimiter in the receiver. If delimiter is not in the collection, answer the entire rest of the receiver. Ignore both character encoding and line end conversion." + + | start end result | + collection ifNotNil: [ + (position < readLimit and: [ + (end := collection indexOf: delimiter startingAt: position + 1) > 0 and: [ + end <= readLimit ] ]) ifTrue: [ + ^collection copyFrom: position + 1 to: (position := end) - 1 ] ]. + start := self position. + self basicSkipTo: delimiter. + end := self position. + self position: start. + "File position may be set to a value greater than the file's size. Make sure the argument is not negative." + result := self basicNext: (end - start - 1 max: 0). + "Read the delimiter itself. Noop when #atEnd." + self basicNext. + ^result! From commits at source.squeak.org Wed Apr 14 10:52:52 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:52:52 0000 Subject: [squeak-dev] The Trunk: Collections-ul.938.mcz Message-ID: Nicolas Cellier uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-ul.938.mcz ==================== Summary ==================== Name: Collections-ul.938 Author: ul Time: 14 April 2021, 12:04:31.18204 pm UUID: 0ebddf60-7622-4708-976d-62ebea16aee5 Ancestors: Collections-mt.937 - implement PositionableStream >> #basicSkipTo: - make PositionableStream >> #basicUpTo: do what other #basic* methods do - use #streamContents: in PositionableStream >> #upTo: =============== Diff against Collections-mt.937 =============== Item was added: + ----- Method: PositionableStream>>basicSkipTo: (in category 'accessing - multibyte support') ----- + basicSkipTo: anObject + + ^self skipTo: anObject! Item was changed: + ----- Method: PositionableStream>>basicUpTo: (in category 'accessing - multibyte support') ----- - ----- Method: PositionableStream>>basicUpTo: (in category 'private basic') ----- basicUpTo: anObject + + ^self upTo: anObject! - "Answer a subcollection from the current access position to the - occurrence (if any, but not inclusive) of anObject in the receiver. If - anObject is not in the collection, answer the entire rest of the receiver." - | newStream element | - newStream := WriteStream on: (self collectionSpecies new: 100). - [self atEnd or: [(element := self basicNext) = anObject]] - whileFalse: [newStream nextPut: element]. - ^newStream contents! Item was changed: ----- Method: PositionableStream>>upTo: (in category 'accessing') ----- upTo: anObject "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of anObject in the receiver. If anObject is not in the collection, answer the entire rest of the receiver." + + ^self collectionSpecies streamContents: [ :stream | + | element | + [self atEnd or: [(element := self next) = anObject]] + whileFalse: [stream nextPut: element]]! - | newStream element | - newStream := WriteStream on: (self collectionSpecies new: 100). - [self atEnd or: [(element := self next) = anObject]] - whileFalse: [newStream nextPut: element]. - ^newStream contents! From commits at source.squeak.org Wed Apr 14 10:55:43 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:55:43 0000 Subject: [squeak-dev] The Trunk: Collections-ul.939.mcz Message-ID: Nicolas Cellier uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-ul.939.mcz ==================== Summary ==================== Name: Collections-ul.939 Author: ul Time: 14 April 2021, 12:06:29.592182 pm UUID: 3b540268-794a-4f47-81e1-74816f0ca4d7 Ancestors: Collections-mt.937 - replace custom symbol creation methods, #string and #pvtAt:put: with #copyFrom: in Symbol class >> #intern: - remove the now unused private methods =============== Diff against Collections-mt.937 =============== Item was removed: - ----- Method: ByteSymbol>>pvtAt:put: (in category 'private') ----- - pvtAt: index put: aCharacter - "Primitive. Store the Character in the field of the receiver indicated by the index. - Fail if the index is not an Integer or is out of bounds, or if the argument is not a - Character, or the Character's code is outside the 0-255 range, or if the receiver - is read-only. Essential. See Object documentation whatIsAPrimitive." - - - aCharacter isCharacter ifFalse: - [^self errorImproperStore]. - index isInteger - ifTrue: - [ec == #'no modification' ifTrue: - [^thisContext modificationForbiddenFor: self at: index putCharacter: aCharacter]. - self errorSubscriptBounds: index] - ifFalse: [self errorNonIntegerIndex]! Item was removed: - ----- Method: ByteSymbol>>string: (in category 'private') ----- - string: aString - 1 to: aString size do: [:j | self pvtAt: j put: (aString at: j)]. - ^self! Item was changed: ----- Method: Symbol class>>intern: (in category 'instance creation') ----- intern: aStringOrSymbol "Answer the unique Symbol formed with given String. If it does not exist yet, create it and intern it in the NewSymbols. Interning a Symbol should return the Symbol itself, no Symbol should be duplicated" | originalNewSymbols | originalNewSymbols := NewSymbols. ^(self lookup: aStringOrSymbol) ifNil:[ | aSymbol newNewSymbols | aStringOrSymbol isSymbol ifTrue:[ aSymbol := aStringOrSymbol. ] ifFalse:[ aSymbol := (aStringOrSymbol isOctetString ifTrue:[ByteSymbol] ifFalse:[WideSymbol]) new: aStringOrSymbol size. + aSymbol + copyFrom: aStringOrSymbol; + beReadOnlyObject. - aSymbol string: aStringOrSymbol. - aSymbol beReadOnlyObject. ]. newNewSymbols := originalNewSymbols copyWith: aSymbol. originalNewSymbols == NewSymbols ifTrue: [ NewSymbols := newNewSymbols. newNewSymbols size > 1000 ifTrue: [ self condenseNewSymbols ]. aSymbol ] ifFalse: [ "Some other process has modified the symbols. Try again." self intern: aStringOrSymbol ] ]! Item was removed: - ----- Method: Symbol>>string: (in category 'private') ----- - string: aString - - 1 to: aString size do: [:j | super at: j put: (aString at: j)]. - ^self ! Item was removed: - ----- Method: WideSymbol>>pvtAt:put: (in category 'private') ----- - pvtAt: index put: aCharacter - "Primitive. Store the Character in the field of the receiver indicated by - the index. Fail if the index is not an Integer or is out of bounds, or if - the argument is not a Character, or if the receiver is read-only. - Essential. See Object documentation whatIsAPrimitive." - - - aCharacter isCharacter ifFalse: - [^self errorImproperStore]. - index isInteger - ifTrue: - [ec == #'no modification' ifTrue: - [^thisContext modificationForbiddenFor: self at: index putCharacter: aCharacter]. - self errorSubscriptBounds: index] - ifFalse: [self errorNonIntegerIndex]! Item was removed: - ----- Method: WideSymbol>>string: (in category 'private') ----- - string: aString - 1 to: aString size do: [:j | self pvtAt: j put: (aString at: j) asInteger]. - ^self! From commits at source.squeak.org Wed Apr 14 10:57:31 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 10:57:31 0000 Subject: [squeak-dev] The Trunk: KernelTests-ul.400.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-ul.400.mcz ==================== Summary ==================== Name: KernelTests-ul.400 Author: ul Time: 14 April 2021, 12:14:51.757056 pm UUID: 6234d088-bf14-4d00-8734-dde043b756ba Ancestors: KernelTests-nice.399 WriteBarrierTest changes: - removed symbol mutator methods - both #testMutateByteSymbolUsingPrivateAtPut and #testMutateWideSymbolUsingPrivateAtPut reference a non-existent #privateAt:put: method, and make the accessed symbol permanently writeable - with the removal of #pvtAt:put: from ByteSymbol and WideSymbol, the tests seem to be unnecessary (see Collections-ul.939) - fix copy-paste error in #testMutateObjectInstVarUsingBasicAtPut: test #basicAt:put: instead of #at:put: - avoid having MirrorPrimitives in Undeclared by removing direct references to it in WriteBarrierTest. Perhaps MirrorPrimitives should be moved to the Trunk from VMMaker - use temporaries in CompiledMethodComparisonTest >> #testHash to improve legibility =============== Diff against KernelTests-nice.399 =============== Item was changed: ----- Method: CompiledMethodComparisonTest>>testHash (in category 'tests') ----- testHash | ai | ai := CompiledMethod allInstances. "We assume here that if two CompiledMethods are equal then they have the same size and header." (ai groupBy: [ :method | { method size. method header } ]) values replace: [ :each | each asArray ]; do: [ :methods | 1 to: methods size do: [ :i | + | firstMethod | + firstMethod := methods at: i. i to: methods size do: [ :j | + | secondMethod | + secondMethod := methods at: j. + firstMethod = secondMethod ifTrue: [ + self assert: firstMethod hash equals: secondMethod hash ] ] ] ] - (methods at: i) = (methods at: j) ifTrue: [ - self assert: (methods at: i) hash equals: (methods at: j) hash ] ] ] ] displayingProgress: 'Testing hashes'. self assert: (ai collect: [ :cm | cm hash ] as: Set) size * 2 >= ai asSet size! Item was changed: ----- Method: WriteBarrierTest>>expectedFailures (in category 'expected failures') ----- expectedFailures Smalltalk supportsReadOnlyObjects ifFalse: [^self class testSelectors]. ^#( testMutateByteArrayUsingDoubleAtPut testMutateByteArrayUsingFloatAtPut ), + (self mirrorPrimitives - ((Smalltalk classNamed: #MirrorPrimitives) ifNil: [#(testBasicProxyReadOnly testBasicProxyWritable testSetIsReadOnlySuccessProxy)] ifNotNil: [#()])! Item was added: + ----- Method: WriteBarrierTest>>mirrorPrimitives (in category 'tests - helper') ----- + mirrorPrimitives + + ^Smalltalk classNamed: #MirrorPrimitives! Item was changed: ----- Method: WriteBarrierTest>>testBasicProxyReadOnly (in category 'tests - proxy') ----- testBasicProxyReadOnly self alwaysReadOnlyObjects do: [ :each | + self assert: (self mirrorPrimitives isObjectReadOnly: each) equals: true ]! - self assert: (MirrorPrimitives isObjectReadOnly: each) equals: true ]! Item was changed: ----- Method: WriteBarrierTest>>testBasicProxyWritable (in category 'tests - proxy') ----- testBasicProxyWritable self alwaysWritableObjects , self maybeReadOnlyObjects do: [ :each | + self assert: (self mirrorPrimitives isObjectReadOnly: each) equals: false ]! - self assert: (MirrorPrimitives isObjectReadOnly: each) equals: false ]! Item was removed: - ----- Method: WriteBarrierTest>>testMutateByteSymbolUsingPrivateAtPut (in category 'tests - object') ----- - testMutateByteSymbolUsingPrivateAtPut - | guineaPig | - [guineaPig := #hello. - guineaPig beReadOnlyObject. - - self - should: ((guineaPig class includesSelector: #pvtAt:put:) - ifTrue: [[ guineaPig perform: #pvtAt:put: with: 1 with: $q ]] "Squeak refuses to compile non-self sends of pvt* selectors." - ifFalse: [[ guineaPig privateAt: 1 put: $q ]]) - raise: ModificationForbidden ] - ensure: - [ guineaPig beWritableObject ]. - - self assert: guineaPig first equals: $h! Item was changed: ----- Method: WriteBarrierTest>>testMutateObjectInstVarUsingBasicAtPut (in category 'tests - object') ----- testMutateObjectInstVarUsingBasicAtPut | guineaPig | guineaPig := Array new: 5. guineaPig beReadOnlyObject. self should: [ guineaPig basicAt: 1 put: #test ] raise: ModificationForbidden. + [ guineaPig basicAt: 1 put: #test ] - [ guineaPig at: 1 put: #test ] on: ModificationForbidden do: [:modification | self assert: modification fieldIndex equals: 1. modification object beWritableObject. modification retryModification ]. self assert: guineaPig first equals: #test! Item was removed: - ----- Method: WriteBarrierTest>>testMutateWideSymbolUsingPrivateAtPut (in category 'tests - object') ----- - testMutateWideSymbolUsingPrivateAtPut - | guineaPig | - [ guineaPig := ('hello', (Character codePoint: 8002) asString) asSymbol. - guineaPig beReadOnlyObject. - - self - should: ((guineaPig class includesSelector: #pvtAt:put:) - ifTrue: [[ guineaPig perform: #pvtAt:put: with: 1 with: $A ]] "Squeak refuses to compile non-self sends of pvt* selectors." - ifFalse: [[ guineaPig privateAt: 1 put: $A ]]) - raise: ModificationForbidden ] - ensure: [ guineaPig beWritableObject ]. - - self assert: guineaPig first equals: $h! Item was changed: ----- Method: WriteBarrierTest>>testProxyObject:initialState:tuples: (in category 'tests - helper') ----- testProxyObject: object initialState: initialState tuples: tuples self testObject: object initialState: initialState tuples: tuples setReadOnlyBlock: [ :value | + self mirrorPrimitives makeObject: object readOnly: value ]! - MirrorPrimitives makeObject: object readOnly: value ]! From marcel.taeumel at hpi.de Wed Apr 14 10:59:39 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 14 Apr 2021 12:59:39 +0200 Subject: [squeak-dev] The Inbox: System-ct.1149.mcz In-Reply-To: References: Message-ID: Hi Christoph, hi all. I would like to continue the discussion about this proposal based on the current Trunk #20404 and http://forum.world.st/The-Trunk-Morphic-mt-1751-mcz-tp5128614p5128621.html [http://forum.world.st/The-Trunk-Morphic-mt-1751-mcz-tp5128614p5128621.html]. At the moment, we have a "#...ContextThat:" lookup in Processor(Scheduler) to find the signaler context of an exception. This proposal includes such a lookup for manually constructed and (explicitly) simulated processes via Process. As a client, I think that Process class >> #forBlock:runUntil: is sufficient. Especially that check for #isTerminated with an interactive notice might not be wanted in all cases. Hmm... Best, Marcel Am 29.03.2020 14:36:22 schrieb commits at source.squeak.org : Christoph Thiede uploaded a new version of System to project The Inbox: http://source.squeak.org/inbox/System-ct.1149.mcz ==================== Summary ==================== Name: System-ct.1149 Author: ct Time: 29 March 2020, 1:35:58.40756 pm UUID: 1bf6e87f-fc73-7747-af4d-df3e339a0627 Ancestors: System-ul.1148 Proposal: Add some convenience methods for debugging blocks. See examples in #debugFromContextThat:title:. While I know that we already talked about the sense of convenience methods that are not actually used in the base system, I think that these ones actually add value and should be used in the base system. We are experiencing an ascending number of methods that implement "debugging of a specific action", such as "debug action" and "debug get-list invocation" in Morphic, or "debug test" in SUnit (see SUnit-ct.125). As they have little duplication at the moment, it is also hard to make them more convenient: For example, if you try to debug a test case that overrides #performTest in a way that it does not actually invoke the test selector; or for another example, if you try to debug the action of a morphic button that we do not support properly at the moment (e. g. the buttons in a UserDialogBox), the current approach opens a debugger on a terminated process on #newProcess. If we follow this suggestion to refactor that behavior into one place, this will allow us to be a bit smarter and mo re convenient, as you can see in the edge case in #debugFromContextThat:title:. My follow-up proposal would thus be to call this convenience methods from all implementors of #debugAction & Co. This commit also tries to solve the issue mentioned in [1]. However, I'm not sure whether BlockClosure is the optimal place for this. I am open for your suggestions to move this somewhere else, for example into Debugger, Process or ToolSet. [1] http://forum.world.st/The-Inbox-Morphic-ct-1590-mcz-tp5106996p5107059.html =============== Diff against System-ul.1148 =============== Item was added: + ----- Method: BlockClosure>>debug (in category '*System-debugging') ----- + debug + + ^ self debugWithTitle: nil! Item was added: + ----- Method: BlockClosure>>debugFromContextThat: (in category '*System-debugging') ----- + debugFromContextThat: contextBlock + + ^ self debugFromContextThat: contextBlock title: nil! Item was added: + ----- Method: BlockClosure>>debugFromContextThat:title: (in category '*System-debugging') ----- + debugFromContextThat: contextBlock title: title + "Evaluate the receiver on a new process (synchronously). Once the contextBlock criterium is satisfied, open a debugger on that process. If the criterium is never satisfied until the process terminates, offer the user to debug the receiver again without waiting for contextBlock again. + + [self halt] debug. + [15 factorial] debugWithTitle: 'Fun with Math!!'. + [self inform: #foo] debugFromContextThat: [:ctxt | ctxt receiver isMorph] title: 'Debug dialog invocation'. + [15 factorial] debugFromContextThat: [:ctxt | ctxt selector = #+]." + + | process | + process := self newProcess. + process runUntil: contextBlock. + process isTerminated ifTrue: [ + ^ (self confirm: 'Did not reach the desired piece of code.\Would you like to debug the whole process again?' withCRs translated) + ifTrue: [self debugWithTitle: title] + ifFalse: [self]]. + ^ process debugWithTitle: title! Item was added: + ----- Method: BlockClosure>>debugWithTitle: (in category '*System-debugging') ----- + debugWithTitle: title + + ^ self + debugFromContextThat: [:ctx | ctx closure == self] + title: title! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Apr 14 11:03:41 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 14 Apr 2021 13:03:41 +0200 Subject: [squeak-dev] The Trunk: Morphic-mt.1751.mcz In-Reply-To: <33e41b5ded384590816403a6340c0ce0@student.hpi.uni-potsdam.de> References: <33e41b5ded384590816403a6340c0ce0@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, > In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. Can you give me 1 example? :-) Since we begin directly with calling the target ... how should anything interfere? Are you thinking about MethodWrappers? Best, Marcel Am 14.04.2021 12:25:22 schrieb Thiede, Christoph : Thank you for improving this! I already had a similar hack in my image for some time, but your solution is cleaner, of course. When putting further efforts into this construction site, I would like to kindly ask you again to take a look at System-ct.1149. :-) In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. > I refrained from adding the debug/browse interface for button actions to Morph. I don't really see the problem here, Morph includes a lot of functionalities that are only used by certain subclasses. Anyway, could this be worth a trait, TMorphWithAction, or something similar? On the other hand, one morph might support multiple actions, so a generic solution would have its advantages ... Best, Christoph [http://www.hpi.de/] Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 14. April 2021 11:19:46 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-mt.1751.mcz   Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1751.mcz [http://source.squeak.org/trunk/Morphic-mt.1751.mcz] ==================== Summary ==================== Name: Morphic-mt.1751 Author: mt Time: 14 April 2021, 11:19:35.123489 am UUID: 8fa68c8f-44ca-4d4a-a9e7-f69619be782e Ancestors: Morphic-mt.1750 Slightly improve browsing and debugging of so-called "button actions" by also supporting #perform:orSendTo:, which yields #effectiveActionTarget and #effectiveActionSelector. (Note that this design is still to be improved. I refrained from adding the debug/browse interface for button actions to Morph. A next step might be to take a look at all implementors of #doButtonAction. Maybe this will generate some ideas.) =============== Diff against Morphic-mt.1750 =============== Item was removed: - ----- Method: MenuItemMorph>>browseAllImplementorsOfRealSelector (in category 'browse') ----- - browseAllImplementorsOfRealSelector -        SystemNavigation default browseAllImplementorsOf: self realSelector localTo: target class! Item was changed:   ----- Method: MenuItemMorph>>browseImplementationOfActionSelector (in category 'browse') -----   browseImplementationOfActionSelector            | method | +        method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. -        method := target class lookupSelector: selector.          ToolSet browse: method methodClass selector: method selector.! Item was changed:   ----- Method: MenuItemMorph>>debugAction (in category 'browse') -----   debugAction            (Process                  forBlock: [self doButtonAction] +                runUntil: [:context | context selector = self effectiveActionSelector]) -                runUntil: [:context | context selector = self selector])                          debugWithTitle: ('Debug menu action "{1}" in model "{2}"' format: {self contents. self target printString}).! Item was added: + ----- Method: MenuItemMorph>>effectiveActionSelector (in category 'browse') ----- + effectiveActionSelector +        +        ^ self selector = #perform:orSendTo: +                ifTrue: [self arguments first] +                ifFalse: [self selector]! Item was added: + ----- Method: MenuItemMorph>>effectiveActionTarget (in category 'browse') ----- + effectiveActionTarget + +        ^ (self selector = #perform:orSendTo: +                and: [(self target respondsTo: self effectiveActionSelector) not]) +                        ifTrue: [self arguments second] +                        ifFalse: [self target]! Item was removed: - ----- Method: MenuItemMorph>>realSelector (in category 'browse') ----- - realSelector -        selector == #perform:orSendTo: ifTrue: [^arguments first]. -        ^selector! Item was changed:   ----- Method: Morph>>doButtonAction (in category 'button') -----   doButtonAction +        "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing.  Note that there are several ways -- too many ways -- for morphs to have button-like actions. It is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programmatically from user scripts."! -        "If the receiver has a button-action defined, do it now.  The default button action of any morph is, well, to do nothing.  Note that there are several ways -- too many ways -- for morphs to have button-like actions.  This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism.  Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts"! Item was changed:   ----- Method: PluggableButtonMorph>>browseImplementationOfActionSelector (in category 'debug menu') -----   browseImplementationOfActionSelector            | method | +        self updateArguments. +        method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. -        method := model class lookupSelector: actionSelector.          ToolSet browse: method methodClass selector: method selector.! Item was changed:   ----- Method: PluggableButtonMorph>>debugAction (in category 'debug menu') -----   debugAction   +        self updateArguments. +          (Process +                forBlock: [self doButtonAction] +                runUntil: [:context | context selector = self effectiveActionSelector]) -                forBlock: [self performAction] -                runUntil: [:context | context selector = self actionSelector])                          debugWithTitle: ('Debug button action "{1}" in model "{2}"' format: {self label. self target printString}).! Item was added: + ----- Method: PluggableButtonMorph>>doButtonAction (in category 'button') ----- + doButtonAction + +        ^ self performAction! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionSelector (in category 'debug menu') ----- + effectiveActionSelector +        +        ^ self actionSelector = #perform:orSendTo: +                ifTrue: [arguments first] +                ifFalse: [self actionSelector]! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionTarget (in category 'debug menu') ----- + effectiveActionTarget + +        ^ (self actionSelector = #perform:orSendTo: +                and: [(self target respondsTo: self effectiveActionSelector) not]) +                        ifTrue: [arguments second] +                        ifFalse: [self target]! Item was changed: + ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout-properties') -----   hResizing: aSymbol          "We adapt our minimum extent according to our resize behavior."                   self hResizing == aSymbol ifTrue: [^ self].          super hResizing: aSymbol.          self updateMinimumExtent.! Item was changed: + ----- Method: PluggableButtonMorph>>performAction (in category 'event handling') ----- - ----- Method: PluggableButtonMorph>>performAction (in category 'accessing') -----   performAction          "Inform the model that this button has been pressed. Sent by the controller when this button is pressed. If the button's actionSelector takes any arguments, they are obtained dynamically by sending the argumentSelector to the argumentsProvider"            askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].          actionSelector ifNotNil:                  [actionSelector numArgs = 0                          ifTrue:                                  [model perform: actionSelector]                          ifFalse: +                                [self updateArguments. -                                [argumentsProvider ifNotNil: -                                        [arguments := argumentsProvider perform: argumentsSelector].                                          model perform: actionSelector withArguments: arguments]]! Item was added: + ----- Method: PluggableButtonMorph>>updateArguments (in category 'updating') ----- + updateArguments + +        argumentsProvider ifNil: [^ self]. +        argumentsSelector ifNil: [^ self]. +        arguments := argumentsProvider perform: argumentsSelector.! Item was changed: + ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout-properties') -----   vResizing: aSymbol          "We adapt our minimum extent according to our resize behavior."                   self vResizing == aSymbol ifTrue: [^ self].          super vResizing: aSymbol.          self updateMinimumExtent.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 14 12:17:01 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 12:17:01 0000 Subject: [squeak-dev] The Trunk: Collections-ul.940.mcz Message-ID: Levente Uzonyi uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-ul.940.mcz ==================== Summary ==================== Name: Collections-ul.940 Author: ul Time: 14 April 2021, 2:16:42.453337 pm UUID: 00bf6645-78aa-472a-a4f1-5115492fc00e Ancestors: Collections-ul.939, Collections-ul.938 - merge =============== Diff against Collections-ul.939 =============== Item was added: + ----- Method: PositionableStream>>basicSkipTo: (in category 'accessing - multibyte support') ----- + basicSkipTo: anObject + + ^self skipTo: anObject! Item was changed: + ----- Method: PositionableStream>>basicUpTo: (in category 'accessing - multibyte support') ----- - ----- Method: PositionableStream>>basicUpTo: (in category 'private basic') ----- basicUpTo: anObject + + ^self upTo: anObject! - "Answer a subcollection from the current access position to the - occurrence (if any, but not inclusive) of anObject in the receiver. If - anObject is not in the collection, answer the entire rest of the receiver." - | newStream element | - newStream := WriteStream on: (self collectionSpecies new: 100). - [self atEnd or: [(element := self basicNext) = anObject]] - whileFalse: [newStream nextPut: element]. - ^newStream contents! Item was changed: ----- Method: PositionableStream>>upTo: (in category 'accessing') ----- upTo: anObject "Answer a subcollection from the current access position to the occurrence (if any, but not inclusive) of anObject in the receiver. If anObject is not in the collection, answer the entire rest of the receiver." + + ^self collectionSpecies streamContents: [ :stream | + | element | + [self atEnd or: [(element := self next) = anObject]] + whileFalse: [stream nextPut: element]]! - | newStream element | - newStream := WriteStream on: (self collectionSpecies new: 100). - [self atEnd or: [(element := self next) = anObject]] - whileFalse: [newStream nextPut: element]. - ^newStream contents! From commits at source.squeak.org Wed Apr 14 12:26:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 12:26:40 0000 Subject: [squeak-dev] The Trunk: Kernel-ct.1364.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-ct.1364.mcz ==================== Summary ==================== Name: Kernel-ct.1364 Author: ct Time: 12 November 2020, 4:48:28.956502 pm UUID: 564764e7-f95f-8a40-b95a-67241eced1f9 Ancestors: Kernel-eem.1361 Fixes primitive comments in BlockClosure >> (cull:){3,4}. See http://forum.world.st/The-Trunk-Kernel-eem-1355-mcz-td5124164.html. =============== Diff against Kernel-eem.1361 =============== Item was changed: ----- Method: BlockClosure>>cull:cull:cull: (in category 'evaluating') ----- cull: firstArg cull: secondArg cull: thirdArg "Activate the receiver, with three or less arguments." + "Handle the three argument case primitively" - "Handle the two argument case primitively" numArgs >= 2 ifTrue: [ numArgs >= 3 ifTrue: [ ^self value: firstArg value: secondArg value: thirdArg ]. ^self value: firstArg value: secondArg ]. numArgs = 1 ifTrue: [ ^self value: firstArg ]. ^self value! Item was changed: ----- Method: BlockClosure>>cull:cull:cull:cull: (in category 'evaluating') ----- cull: firstArg cull: secondArg cull: thirdArg cull: fourthArg "Activate the receiver, with four or less arguments." + "Handle the four argument case primitively" - "Handle the two argument case primitively" numArgs >= 3 ifTrue: [ numArgs >= 4 ifTrue: [ ^self value: firstArg value: secondArg value: thirdArg value: fourthArg ]. ^self value: firstArg value: secondArg value: thirdArg ]. numArgs = 2 ifTrue: [ ^self value: firstArg value: secondArg ]. numArgs = 1 ifTrue: [ ^self value: firstArg ]. ^self value! From commits at source.squeak.org Wed Apr 14 12:38:22 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 12:38:22 0000 Subject: [squeak-dev] The Inbox: Collections-mt.938.mcz Message-ID: A new version of Collections was added to project The Inbox: http://source.squeak.org/inbox/Collections-mt.938.mcz ==================== Summary ==================== Name: Collections-mt.938 Author: mt Time: 14 April 2021, 2:38:21.265628 pm UUID: d109bde4-42a6-e840-803c-e4e80b98a74d Ancestors: Collections-mt.937 Proposal. Add a #joinSeparatedBy: that does not end up as a string. The current alternative would be #gather (#(1 2 3 4 5) gather: [:each | {each . $x}]) allButLast. Not sure whether a non-sequenceable version in Collection makes sense. We have had that discussion about #join etc. being not useful for uncertain output order. Some benchmarks: [ ((1 to: 1000) gather: [:num | {num . $x}]) allButLast ] bench. '22,000 per second. 45.5 microseconds per run. 13.09738 % GC time.' [ (1 to: 1000) collect: [:num | num] separatedBy: [$x] ] bench. '26,000 per second. 38.5 microseconds per run. 1.73965 % GC time.' =============== Diff against Collections-mt.937 =============== Item was added: + ----- Method: Collection>>collect:separatedBy: (in category 'enumerating') ----- + collect: elementBlock separatedBy: separatorBlock + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." + + | newCollection | + newCollection := self species new. + self + do: [:each | newCollection add: (elementBlock value: each)] + separatedBy: [:each | newCollection add: separatorBlock value]. + ^ newCollection! Item was added: + ----- Method: SequenceableCollection>>collect:separatedBy: (in category 'enumerating') ----- + collect: elementBlock separatedBy: separatorBlock + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." + + | newCollection | + newCollection := self species new: self size *2 -1. + 1 to: self size do: [:index | + index = 1 ifFalse: [newCollection at: (index-1 *2) put: separatorBlock value]. + newCollection at: (index-1 *2)+1 put: (elementBlock value: (self at: index))]. + ^ newCollection! From commits at source.squeak.org Wed Apr 14 12:51:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 12:51:12 0000 Subject: [squeak-dev] The Inbox: Collections-mt.941.mcz Message-ID: A new version of Collections was added to project The Inbox: http://source.squeak.org/inbox/Collections-mt.941.mcz ==================== Summary ==================== Name: Collections-mt.941 Author: mt Time: 14 April 2021, 2:51:04.673628 pm UUID: 93df256c-2d6c-e246-87aa-4296ff9c993d Ancestors: Collections-ul.940 (Not a) proposal. In #do:separatedBy: optionally provide the elements around that separation to the block. Looks like an interleaved combination of #do: and #overlappingPairsDo:. Here is a (not convincing) example: (1 to: 20) do: [:num | Transcript showln: num] separatedBy: [:a :b | Transcript showln: a+b] Maybe this is something. Haven't found a good example yet. =============== Diff against Collections-ul.940 =============== Item was changed: ----- Method: Collection>>do:separatedBy: (in category 'enumerating') ----- do: elementBlock separatedBy: separatorBlock "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between." + | beforeFirst lastSeen | - | beforeFirst | beforeFirst := true. self do: [:each | beforeFirst ifTrue: [beforeFirst := false] + ifFalse: [separatorBlock cull: lastSeen cull: each]. + elementBlock value: each. + lastSeen := each]! - ifFalse: [separatorBlock value]. - elementBlock value: each]! Item was changed: ----- Method: SequenceableCollection>>do:separatedBy: (in category 'enumerating') ----- do: elementBlock separatedBy: separatorBlock "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between." + | lastSeen | 1 to: self size do: [:index | + index = 1 ifFalse: [separatorBlock cull: lastSeen cull: (self at: index)]. + lastSeen := self at: index. + elementBlock value: lastSeen]! - index = 1 ifFalse: [separatorBlock value]. - elementBlock value: (self at: index)]! From commits at source.squeak.org Wed Apr 14 12:53:36 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 12:53:36 0000 Subject: [squeak-dev] The Trunk: Kernel-ct.1383.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-ct.1383.mcz ==================== Summary ==================== Name: Kernel-ct.1383 Author: ct Time: 20 March 2021, 7:21:02.280742 pm UUID: b1953f95-408a-aa4a-9108-cc1dc355e9d1 Ancestors: Kernel-mt.1381 Fixes simulation of the #perform:... primitives 83, 84, and 100 for all edge cases. If the primitive is called with the wrong arguments, the primitive must fail but not the simulator. For further reference, see also the implementation of primitive 188 (primitiveExecuteMethodArgsArray) just a few lines below. :-) Tests have been provided in KernelTests-ct.395. Reuploaded to fix mirror variant of primitive 100. Now it's finally possible to debug MirrorPrimitiveTests>>#testMirrorPerform. Replaces Kernel-ct.1367, which can be moved into the treated inbox. =============== Diff against Kernel-mt.1381 =============== Item was changed: ----- Method: Context>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and arguments are given as arguments to this message. If successful, push result and return resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes execution needs to be intercepted and simulated to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug interesting code, such as the debugger itself. Hence use primitive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" primitiveIndex = 19 ifTrue: [ [self notify: ('The code being simulated is trying to control a process ({1}). Process controlling cannot be simulated. If you proceed, things may happen outside the observable area of the simulator.' translated format: {meth reference})] ifCurtailed: [self push: nil "Cheap fix of the context's internal state"]]. ((primitiveIndex between: 201 and: 222) and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: [(primitiveIndex = 206 or: [primitiveIndex = 208]) ifTrue: "[Full]BlockClosure>>valueWithArguments:" [^receiver simulateValueWithArguments: arguments first caller: self]. ((primitiveIndex between: 201 and: 209) "[Full]BlockClosure>>value[:value:...]" or: [primitiveIndex between: 221 and: 222]) ifTrue: "[Full]BlockClosure>>valueNoContextSwitch[:]" [^receiver simulateValueWithArguments: arguments caller: self]]. primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [| selector | + selector := arguments at: 1 ifAbsent: + [^ self class primitiveFailTokenFor: #'bad argument']. + arguments size - 1 = selector numArgs ifFalse: + [^ self class primitiveFailTokenFor: #'bad number of arguments']. + ^self send: selector to: receiver with: arguments allButFirst]. - [^self send: arguments first to: receiver with: arguments allButFirst]. primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [| selector args | + arguments size = 2 ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + selector := arguments first. + args := arguments second. + args isArray ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + args size = selector numArgs ifFalse: + [^ self class primitiveFailTokenFor: #'bad number of arguments']. + ^self send: selector to: receiver with: args]. - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [| rcvr selector args superclass | + arguments size + caseOf: { + [3] -> [ + rcvr := receiver. + selector := arguments first. + args := arguments second. + superclass := arguments third]. + [4] -> ["mirror primitive" + rcvr := arguments first. + selector := arguments second. + args := arguments third. + superclass := arguments fourth] } + otherwise: [^ self class primitiveFailTokenFor: #'bad argument']. + args isArray ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + args size = selector numArgs ifFalse: + [^ self class primitiveFailTokenFor: #'bad number of arguments']. + ((self objectClass: rcvr) includesBehavior: superclass) ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + ^self send: selector to: rcvr with: args lookupIn: superclass]. - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: [| effective | effective := Processor activeProcess effectiveProcess. "active == effective" value := primitiveIndex = 186 ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. ^(self isPrimFailToken: value) ifTrue: [value] ifFalse: [self push: value]]. primitiveIndex = 188 ifTrue: "Object>>withArgs:executeMethod: CompiledMethod class>>receiver:withArguments:executeMethod: VMMirror>>ifFail:object:with:executeMethod: et al" [| n args methodArg thisReceiver | ((n := arguments size) between: 2 and: 4) ifFalse: [^self class primitiveFailTokenFor: #'unsupported operation']. ((self objectClass: (args := arguments at: n - 1)) == Array and: [(self objectClass: (methodArg := arguments at: n)) includesBehavior: CompiledMethod]) ifFalse: [^self class primitiveFailTokenFor: #'bad argument']. methodArg numArgs = args size ifFalse: [^self class primitiveFailTokenFor: #'bad number of arguments']. thisReceiver := arguments at: n - 2 ifAbsent: [receiver]. methodArg primitive > 0 ifTrue: [methodArg isQuick ifTrue: [^self push: (methodArg valueWithReceiver: thisReceiver arguments: args)]. ^self doPrimitive: methodArg primitive method: meth receiver: thisReceiver args: args]. ^Context sender: self receiver: thisReceiver method: methodArg arguments: args]. primitiveIndex = 118 ifTrue: "[receiver:]tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 3 and: [(self objectClass: arguments second) == SmallInteger and: [(self objectClass: arguments last) == Array]]) ifTrue: [^self doPrimitive: arguments second method: meth receiver: arguments first args: arguments last]. (arguments size = 2 and: [(self objectClass: arguments first) == SmallInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^self class primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] ifFalse: "should use self receiver: receiver tryPrimitive: primitiveIndex withArgs: arguments but this is only in later VMs (and appears to be broken)" [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. ^(self isPrimFailToken: value) ifTrue: [value] ifFalse: [self push: value]! From commits at source.squeak.org Wed Apr 14 12:56:58 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 12:56:58 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1386.mcz ==================== Summary ==================== Name: Kernel-nice.1386 Author: nice Time: 14 April 2021, 2:56:48.575456 pm UUID: e7612c01-14d8-0940-87fe-45e2fb4d2719 Ancestors: Kernel-mt.1385, Kernel-ct.1383, Kernel-ct.1364 Merge commit. Note that Kernel-ct.1383 supersedes Kernel-ct.1382 and removes the annoying warning. Kernel-mt.1385: Clean up and comment on the idiom #perform:orSendTo:. Kernel-ct.1383: Fixes simulation of the #perform:... primitives 83, 84, and 100 for all edge cases. If the primitive is called with the wrong arguments, the primitive must fail but not the simulator. Kernel-ct.1364: Fixes primitive comments in BlockClosure >> (cull:){3,4}. =============== Diff against Kernel-mt.1385 =============== Item was changed: ----- Method: BlockClosure>>cull:cull:cull: (in category 'evaluating') ----- cull: firstArg cull: secondArg cull: thirdArg "Activate the receiver, with three or less arguments." + "Handle the three argument case primitively" - "Handle the two argument case primitively" numArgs >= 2 ifTrue: [ numArgs >= 3 ifTrue: [ ^self value: firstArg value: secondArg value: thirdArg ]. ^self value: firstArg value: secondArg ]. numArgs = 1 ifTrue: [ ^self value: firstArg ]. ^self value! Item was changed: ----- Method: BlockClosure>>cull:cull:cull:cull: (in category 'evaluating') ----- cull: firstArg cull: secondArg cull: thirdArg cull: fourthArg "Activate the receiver, with four or less arguments." + "Handle the four argument case primitively" - "Handle the two argument case primitively" numArgs >= 3 ifTrue: [ numArgs >= 4 ifTrue: [ ^self value: firstArg value: secondArg value: thirdArg value: fourthArg ]. ^self value: firstArg value: secondArg value: thirdArg ]. numArgs = 2 ifTrue: [ ^self value: firstArg value: secondArg ]. numArgs = 1 ifTrue: [ ^self value: firstArg ]. ^self value! Item was changed: ----- Method: Context>>doPrimitive:method:receiver:args: (in category 'private') ----- doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and arguments are given as arguments to this message. If successful, push result and return resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes execution needs to be intercepted and simulated to avoid execution running away." | value | "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents the debugger from entering various run-away activities such as spawning a new process, etc. Injudicious use results in the debugger not being able to debug interesting code, such as the debugger itself. Hence use primitive 19 with care :-)" "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" + primitiveIndex = 19 ifTrue: [ - (primitiveIndex = 19 or: [primitiveIndex >= 85 and: [primitiveIndex <= 88] "control primitives"]) ifTrue: [ [self notify: ('The code being simulated is trying to control a process ({1}). Process controlling cannot be simulated. If you proceed, things may happen outside the observable area of the simulator.' translated format: {meth reference})] ifCurtailed: [self push: nil "Cheap fix of the context's internal state"]]. ((primitiveIndex between: 201 and: 222) and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: [(primitiveIndex = 206 or: [primitiveIndex = 208]) ifTrue: "[Full]BlockClosure>>valueWithArguments:" [^receiver simulateValueWithArguments: arguments first caller: self]. ((primitiveIndex between: 201 and: 209) "[Full]BlockClosure>>value[:value:...]" or: [primitiveIndex between: 221 and: 222]) ifTrue: "[Full]BlockClosure>>valueNoContextSwitch[:]" [^receiver simulateValueWithArguments: arguments caller: self]]. primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" + [| selector | + selector := arguments at: 1 ifAbsent: + [^ self class primitiveFailTokenFor: #'bad argument']. + arguments size - 1 = selector numArgs ifFalse: + [^ self class primitiveFailTokenFor: #'bad number of arguments']. + ^self send: selector to: receiver with: arguments allButFirst]. - [^self send: arguments first to: receiver with: arguments allButFirst]. primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" + [| selector args | + arguments size = 2 ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + selector := arguments first. + args := arguments second. + args isArray ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + args size = selector numArgs ifFalse: + [^ self class primitiveFailTokenFor: #'bad number of arguments']. + ^self send: selector to: receiver with: args]. - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" + [| rcvr selector args superclass | + arguments size + caseOf: { + [3] -> [ + rcvr := receiver. + selector := arguments first. + args := arguments second. + superclass := arguments third]. + [4] -> ["mirror primitive" + rcvr := arguments first. + selector := arguments second. + args := arguments third. + superclass := arguments fourth] } + otherwise: [^ self class primitiveFailTokenFor: #'bad argument']. + args isArray ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + args size = selector numArgs ifFalse: + [^ self class primitiveFailTokenFor: #'bad number of arguments']. + ((self objectClass: rcvr) includesBehavior: superclass) ifFalse: + [^ self class primitiveFailTokenFor: #'bad argument']. + ^self send: selector to: rcvr with: args lookupIn: superclass]. - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. "Mutex>>primitiveEnterCriticalSection Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: + [| effective | + effective := Processor activeProcess effectiveProcess. + "active == effective" + value := primitiveIndex = 186 + ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] + ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. - [value := primitiveIndex = 186 - ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: Processor activeProcess] - ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: Processor activeProcess]. ^(self isPrimFailToken: value) ifTrue: [value] ifFalse: [self push: value]]. primitiveIndex = 188 ifTrue: "Object>>withArgs:executeMethod: CompiledMethod class>>receiver:withArguments:executeMethod: VMMirror>>ifFail:object:with:executeMethod: et al" [| n args methodArg thisReceiver | ((n := arguments size) between: 2 and: 4) ifFalse: [^self class primitiveFailTokenFor: #'unsupported operation']. ((self objectClass: (args := arguments at: n - 1)) == Array and: [(self objectClass: (methodArg := arguments at: n)) includesBehavior: CompiledMethod]) ifFalse: [^self class primitiveFailTokenFor: #'bad argument']. methodArg numArgs = args size ifFalse: [^self class primitiveFailTokenFor: #'bad number of arguments']. thisReceiver := arguments at: n - 2 ifAbsent: [receiver]. methodArg primitive > 0 ifTrue: [methodArg isQuick ifTrue: [^self push: (methodArg valueWithReceiver: thisReceiver arguments: args)]. ^self doPrimitive: methodArg primitive method: meth receiver: thisReceiver args: args]. ^Context sender: self receiver: thisReceiver method: methodArg arguments: args]. primitiveIndex = 118 ifTrue: "[receiver:]tryPrimitive:withArgs:; avoid recursing in the VM" [(arguments size = 3 and: [(self objectClass: arguments second) == SmallInteger and: [(self objectClass: arguments last) == Array]]) ifTrue: [^self doPrimitive: arguments second method: meth receiver: arguments first args: arguments last]. (arguments size = 2 and: [(self objectClass: arguments first) == SmallInteger and: [(self objectClass: arguments last) == Array]]) ifFalse: [^self class primitiveFailTokenFor: nil]. ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. value := primitiveIndex = 120 "FFI method" ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] ifFalse: [primitiveIndex = 117 "named primitives" ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] ifFalse: "should use self receiver: receiver tryPrimitive: primitiveIndex withArgs: arguments but this is only in later VMs (and appears to be broken)" [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. ^(self isPrimFailToken: value) ifTrue: [value] ifFalse: [self push: value]! From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 14 15:10:52 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 14 Apr 2021 15:10:52 +0000 Subject: [squeak-dev] The Inbox: Collections-mt.941.mcz In-Reply-To: References: Message-ID: <59aa1c03c70145c3bda80d86d3c796d8@student.hpi.uni-potsdam.de> Nice idea! Hmm... I can't figure out a real example, maybe something like this? (1 to: 20) asArray shuffled do: [:ea | Transcript show: ea] separatedBy: [:prev :next | Transcript show: ( prev <=> next caseOf: { [-1] -> [#<]. [0] -> [#=]. [1] -> [#>]} )] Still, the example is rather fictive ... Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 14. April 2021 14:51:12 An: squeak-dev at lists.squeakfoundation.org Betreff: [squeak-dev] The Inbox: Collections-mt.941.mcz A new version of Collections was added to project The Inbox: http://source.squeak.org/inbox/Collections-mt.941.mcz ==================== Summary ==================== Name: Collections-mt.941 Author: mt Time: 14 April 2021, 2:51:04.673628 pm UUID: 93df256c-2d6c-e246-87aa-4296ff9c993d Ancestors: Collections-ul.940 (Not a) proposal. In #do:separatedBy: optionally provide the elements around that separation to the block. Looks like an interleaved combination of #do: and #overlappingPairsDo:. Here is a (not convincing) example: (1 to: 20) do: [:num | Transcript showln: num] separatedBy: [:a :b | Transcript showln: a+b] Maybe this is something. Haven't found a good example yet. =============== Diff against Collections-ul.940 =============== Item was changed: ----- Method: Collection>>do:separatedBy: (in category 'enumerating') ----- do: elementBlock separatedBy: separatorBlock "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between." + | beforeFirst lastSeen | - | beforeFirst | beforeFirst := true. self do: [:each | beforeFirst ifTrue: [beforeFirst := false] + ifFalse: [separatorBlock cull: lastSeen cull: each]. + elementBlock value: each. + lastSeen := each]! - ifFalse: [separatorBlock value]. - elementBlock value: each]! Item was changed: ----- Method: SequenceableCollection>>do:separatedBy: (in category 'enumerating') ----- do: elementBlock separatedBy: separatorBlock "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between." + | lastSeen | 1 to: self size do: [:index | + index = 1 ifFalse: [separatorBlock cull: lastSeen cull: (self at: index)]. + lastSeen := self at: index. + elementBlock value: lastSeen]! - index = 1 ifFalse: [separatorBlock value]. - elementBlock value: (self at: index)]! -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Wed Apr 14 15:21:42 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed, 14 Apr 2021 17:21:42 +0200 Subject: [squeak-dev] The Trunk: Kernel-ct.1383.mcz In-Reply-To: References: Message-ID: Hi all, it seems that it solves the failing tests for primitive 84 and 100. But I still get a problem with testPrimitive83. The test fails, and if I click on it in the TestRunner, the image crash (SEGV) - at least on windows. There is a SqueakDebug.log though, and it seems that we try to send the message 83... I don't know if you can reproduce or not, but help would be highly appreciated. Christoph, do you have a clue? Le mer. 14 avr. 2021 à 14:53, a écrit : > > Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > http://source.squeak.org/trunk/Kernel-ct.1383.mcz > > ==================== Summary ==================== > > Name: Kernel-ct.1383 > Author: ct > Time: 20 March 2021, 7:21:02.280742 pm > UUID: b1953f95-408a-aa4a-9108-cc1dc355e9d1 > Ancestors: Kernel-mt.1381 > > Fixes simulation of the #perform:... primitives 83, 84, and 100 for all edge cases. If the primitive is called with the wrong arguments, the primitive must fail but not the simulator. > > For further reference, see also the implementation of primitive 188 (primitiveExecuteMethodArgsArray) just a few lines below. :-) > > Tests have been provided in KernelTests-ct.395. Reuploaded to fix mirror variant of primitive 100. Now it's finally possible to debug MirrorPrimitiveTests>>#testMirrorPerform. Replaces Kernel-ct.1367, which can be moved into the treated inbox. > > =============== Diff against Kernel-mt.1381 =============== > > Item was changed: > ----- Method: Context>>doPrimitive:method:receiver:args: (in category 'private') ----- > doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments > "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and > arguments are given as arguments to this message. If successful, push result and return > resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes > execution needs to be intercepted and simulated to avoid execution running away." > > | value | > "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents > the debugger from entering various run-away activities such as spawning a new > process, etc. Injudicious use results in the debugger not being able to debug > interesting code, such as the debugger itself. Hence use primitive 19 with care :-)" > "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" > primitiveIndex = 19 ifTrue: [ > [self notify: ('The code being simulated is trying to control a process ({1}). Process controlling cannot be simulated. If you proceed, things may happen outside the observable area of the simulator.' translated format: {meth reference})] > ifCurtailed: [self push: nil "Cheap fix of the context's internal state"]]. > > ((primitiveIndex between: 201 and: 222) > and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: > [(primitiveIndex = 206 > or: [primitiveIndex = 208]) ifTrue: "[Full]BlockClosure>>valueWithArguments:" > [^receiver simulateValueWithArguments: arguments first caller: self]. > ((primitiveIndex between: 201 and: 209) "[Full]BlockClosure>>value[:value:...]" > or: [primitiveIndex between: 221 and: 222]) ifTrue: "[Full]BlockClosure>>valueNoContextSwitch[:]" > [^receiver simulateValueWithArguments: arguments caller: self]]. > > primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" > + [| selector | > + selector := arguments at: 1 ifAbsent: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + arguments size - 1 = selector numArgs ifFalse: > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > + ^self send: selector to: receiver with: arguments allButFirst]. > - [^self send: arguments first to: receiver with: arguments allButFirst]. > primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" > + [| selector args | > + arguments size = 2 ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + selector := arguments first. > + args := arguments second. > + args isArray ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + args size = selector numArgs ifFalse: > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > + ^self send: selector to: receiver with: args]. > - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. > primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" > + [| rcvr selector args superclass | > + arguments size > + caseOf: { > + [3] -> [ > + rcvr := receiver. > + selector := arguments first. > + args := arguments second. > + superclass := arguments third]. > + [4] -> ["mirror primitive" > + rcvr := arguments first. > + selector := arguments second. > + args := arguments third. > + superclass := arguments fourth] } > + otherwise: [^ self class primitiveFailTokenFor: #'bad argument']. > + args isArray ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + args size = selector numArgs ifFalse: > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > + ((self objectClass: rcvr) includesBehavior: superclass) ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + ^self send: selector to: rcvr with: args lookupIn: superclass]. > - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. > > "Mutex>>primitiveEnterCriticalSection > Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" > (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: > [| effective | > effective := Processor activeProcess effectiveProcess. > "active == effective" > value := primitiveIndex = 186 > ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] > ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. > ^(self isPrimFailToken: value) > ifTrue: [value] > ifFalse: [self push: value]]. > > primitiveIndex = 188 ifTrue: "Object>>withArgs:executeMethod: > CompiledMethod class>>receiver:withArguments:executeMethod: > VMMirror>>ifFail:object:with:executeMethod: et al" > [| n args methodArg thisReceiver | > ((n := arguments size) between: 2 and: 4) ifFalse: > [^self class primitiveFailTokenFor: #'unsupported operation']. > ((self objectClass: (args := arguments at: n - 1)) == Array > and: [(self objectClass: (methodArg := arguments at: n)) includesBehavior: CompiledMethod]) ifFalse: > [^self class primitiveFailTokenFor: #'bad argument']. > methodArg numArgs = args size ifFalse: > [^self class primitiveFailTokenFor: #'bad number of arguments']. > thisReceiver := arguments at: n - 2 ifAbsent: [receiver]. > methodArg primitive > 0 ifTrue: > [methodArg isQuick ifTrue: > [^self push: (methodArg valueWithReceiver: thisReceiver arguments: args)]. > ^self doPrimitive: methodArg primitive method: meth receiver: thisReceiver args: args]. > ^Context > sender: self > receiver: thisReceiver > method: methodArg > arguments: args]. > > primitiveIndex = 118 ifTrue: "[receiver:]tryPrimitive:withArgs:; avoid recursing in the VM" > [(arguments size = 3 > and: [(self objectClass: arguments second) == SmallInteger > and: [(self objectClass: arguments last) == Array]]) ifTrue: > [^self doPrimitive: arguments second method: meth receiver: arguments first args: arguments last]. > (arguments size = 2 > and: [(self objectClass: arguments first) == SmallInteger > and: [(self objectClass: arguments last) == Array]]) ifFalse: > [^self class primitiveFailTokenFor: nil]. > ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. > > value := primitiveIndex = 120 "FFI method" > ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] > ifFalse: > [primitiveIndex = 117 "named primitives" > ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] > ifFalse: "should use self receiver: receiver tryPrimitive: primitiveIndex withArgs: arguments but this is only in later VMs (and appears to be broken)" > [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. > > ^(self isPrimFailToken: value) > ifTrue: [value] > ifFalse: [self push: value]! > > From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 14 16:21:03 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 14 Apr 2021 16:21:03 +0000 Subject: [squeak-dev] The Trunk: Kernel-ct.1383.mcz In-Reply-To: References: , Message-ID: <019d7f3b377a4008850ee280d533de7a@student.hpi.uni-potsdam.de> Hi Nicolas, hi Eliot, hi all, this appears to be a merge coordination error again. Originally, in KernelTests-ct.382, I included a call to the primitive without arguments which makes the VM crash, see http://forum.world.st/The-Inbox-KernelTests-ct-382-mcz-tp5125776p5125777.html (the relevant line is + {}. "missing selector"). Others pointed out correctly that this was a nonsense test, so I uploaded KernelTests-ct.383 as a replacement which removed the relevant lines. But take attention to the diff in the mail on squeak-dev which appears to be erroneous. However, somehow the changes from KernelTests-ct.382 but not KernelTests-ct.383 have made their way into KernelTests-eem.396. Eliot, was this an incident or by attempt? :-) Long story short: By merging KernelTests-ct.383 into the trunk, too, the CI should pass again. But please double-check the diff in Monticello before approving it. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Mittwoch, 14. April 2021 17:21:42 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Kernel-ct.1383.mcz Hi all, it seems that it solves the failing tests for primitive 84 and 100. But I still get a problem with testPrimitive83. The test fails, and if I click on it in the TestRunner, the image crash (SEGV) - at least on windows. There is a SqueakDebug.log though, and it seems that we try to send the message 83... I don't know if you can reproduce or not, but help would be highly appreciated. Christoph, do you have a clue? Le mer. 14 avr. 2021 à 14:53, a écrit : > > Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > http://source.squeak.org/trunk/Kernel-ct.1383.mcz > > ==================== Summary ==================== > > Name: Kernel-ct.1383 > Author: ct > Time: 20 March 2021, 7:21:02.280742 pm > UUID: b1953f95-408a-aa4a-9108-cc1dc355e9d1 > Ancestors: Kernel-mt.1381 > > Fixes simulation of the #perform:... primitives 83, 84, and 100 for all edge cases. If the primitive is called with the wrong arguments, the primitive must fail but not the simulator. > > For further reference, see also the implementation of primitive 188 (primitiveExecuteMethodArgsArray) just a few lines below. :-) > > Tests have been provided in KernelTests-ct.395. Reuploaded to fix mirror variant of primitive 100. Now it's finally possible to debug MirrorPrimitiveTests>>#testMirrorPerform. Replaces Kernel-ct.1367, which can be moved into the treated inbox. > > =============== Diff against Kernel-mt.1381 =============== > > Item was changed: > ----- Method: Context>>doPrimitive:method:receiver:args: (in category 'private') ----- > doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments > "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and > arguments are given as arguments to this message. If successful, push result and return > resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes > execution needs to be intercepted and simulated to avoid execution running away." > > | value | > "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents > the debugger from entering various run-away activities such as spawning a new > process, etc. Injudicious use results in the debugger not being able to debug > interesting code, such as the debugger itself. Hence use primitive 19 with care :-)" > "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" > primitiveIndex = 19 ifTrue: [ > [self notify: ('The code being simulated is trying to control a process ({1}). Process controlling cannot be simulated. If you proceed, things may happen outside the observable area of the simulator.' translated format: {meth reference})] > ifCurtailed: [self push: nil "Cheap fix of the context's internal state"]]. > > ((primitiveIndex between: 201 and: 222) > and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: > [(primitiveIndex = 206 > or: [primitiveIndex = 208]) ifTrue: "[Full]BlockClosure>>valueWithArguments:" > [^receiver simulateValueWithArguments: arguments first caller: self]. > ((primitiveIndex between: 201 and: 209) "[Full]BlockClosure>>value[:value:...]" > or: [primitiveIndex between: 221 and: 222]) ifTrue: "[Full]BlockClosure>>valueNoContextSwitch[:]" > [^receiver simulateValueWithArguments: arguments caller: self]]. > > primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" > + [| selector | > + selector := arguments at: 1 ifAbsent: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + arguments size - 1 = selector numArgs ifFalse: > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > + ^self send: selector to: receiver with: arguments allButFirst]. > - [^self send: arguments first to: receiver with: arguments allButFirst]. > primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" > + [| selector args | > + arguments size = 2 ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + selector := arguments first. > + args := arguments second. > + args isArray ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + args size = selector numArgs ifFalse: > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > + ^self send: selector to: receiver with: args]. > - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. > primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" > + [| rcvr selector args superclass | > + arguments size > + caseOf: { > + [3] -> [ > + rcvr := receiver. > + selector := arguments first. > + args := arguments second. > + superclass := arguments third]. > + [4] -> ["mirror primitive" > + rcvr := arguments first. > + selector := arguments second. > + args := arguments third. > + superclass := arguments fourth] } > + otherwise: [^ self class primitiveFailTokenFor: #'bad argument']. > + args isArray ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + args size = selector numArgs ifFalse: > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > + ((self objectClass: rcvr) includesBehavior: superclass) ifFalse: > + [^ self class primitiveFailTokenFor: #'bad argument']. > + ^self send: selector to: rcvr with: args lookupIn: superclass]. > - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. > > "Mutex>>primitiveEnterCriticalSection > Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" > (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: > [| effective | > effective := Processor activeProcess effectiveProcess. > "active == effective" > value := primitiveIndex = 186 > ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] > ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. > ^(self isPrimFailToken: value) > ifTrue: [value] > ifFalse: [self push: value]]. > > primitiveIndex = 188 ifTrue: "Object>>withArgs:executeMethod: > CompiledMethod class>>receiver:withArguments:executeMethod: > VMMirror>>ifFail:object:with:executeMethod: et al" > [| n args methodArg thisReceiver | > ((n := arguments size) between: 2 and: 4) ifFalse: > [^self class primitiveFailTokenFor: #'unsupported operation']. > ((self objectClass: (args := arguments at: n - 1)) == Array > and: [(self objectClass: (methodArg := arguments at: n)) includesBehavior: CompiledMethod]) ifFalse: > [^self class primitiveFailTokenFor: #'bad argument']. > methodArg numArgs = args size ifFalse: > [^self class primitiveFailTokenFor: #'bad number of arguments']. > thisReceiver := arguments at: n - 2 ifAbsent: [receiver]. > methodArg primitive > 0 ifTrue: > [methodArg isQuick ifTrue: > [^self push: (methodArg valueWithReceiver: thisReceiver arguments: args)]. > ^self doPrimitive: methodArg primitive method: meth receiver: thisReceiver args: args]. > ^Context > sender: self > receiver: thisReceiver > method: methodArg > arguments: args]. > > primitiveIndex = 118 ifTrue: "[receiver:]tryPrimitive:withArgs:; avoid recursing in the VM" > [(arguments size = 3 > and: [(self objectClass: arguments second) == SmallInteger > and: [(self objectClass: arguments last) == Array]]) ifTrue: > [^self doPrimitive: arguments second method: meth receiver: arguments first args: arguments last]. > (arguments size = 2 > and: [(self objectClass: arguments first) == SmallInteger > and: [(self objectClass: arguments last) == Array]]) ifFalse: > [^self class primitiveFailTokenFor: nil]. > ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. > > value := primitiveIndex = 120 "FFI method" > ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] > ifFalse: > [primitiveIndex = 117 "named primitives" > ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] > ifFalse: "should use self receiver: receiver tryPrimitive: primitiveIndex withArgs: arguments but this is only in later VMs (and appears to be broken)" > [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. > > ^(self isPrimFailToken: value) > ifTrue: [value] > ifFalse: [self push: value]! > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 14 16:44:39 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 16:44:39 0000 Subject: [squeak-dev] The Trunk: KernelTests-nice.401.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.401.mcz ==================== Summary ==================== Name: KernelTests-nice.401 Author: nice Time: 14 April 2021, 6:44:29.769889 pm UUID: b726ca09-62ef-fc40-ae2b-4bdb0a57c490 Ancestors: KernelTests-ul.400 Remove the tests simulating primitive perform: &al without selector. They make not much sense and make the VM crash. =============== Diff against KernelTests-ul.400 =============== Item was changed: ----- Method: ContextTest>>testPrimitive100 (in category 'tests') ----- testPrimitive100 { {#isNil. {}. Object}. "valid 0-arg message" {#=. {true}. UndefinedObject}. "valid unary message" {#ifNil:ifNotNil:. {[2]. [:x | x]}. Object}. "valid binary message" - {}. "missing selector" {#isNil}. "missing arguments" {#isNil. 'not an array'}. "invalid arguments" {#isNil. {}}. "missing lookupClass" {#isNil. {'excess arg'}. Object}. "too many arguments" {#=. {}. UndefinedObject}. "missing argument" {#isNil. {}. Boolean}. "lookupClass not in inheritance chain" } do: [:args | self assert: (Context runSimulated: [nil tryPrimitive: 100 withArgs: args]) equals: (nil tryPrimitive: 100 withArgs: args)].! Item was changed: ----- Method: ContextTest>>testPrimitive83 (in category 'tests') ----- testPrimitive83 { {#isNil}. "valid 0-arg message" {#=. true}. "valid unary message" {#ifNil:ifNotNil:. [2]. [:x | x]}. "valid binary message" - {}. "missing selector" {#isNil. 'excess arg'}. "too many arguments" {#=}. "missing argument" } do: [:args | self assert: (Context runSimulated: [nil tryPrimitive: 83 withArgs: args]) equals: (nil tryPrimitive: 83 withArgs: args)].! Item was changed: ----- Method: ContextTest>>testPrimitive84 (in category 'tests') ----- testPrimitive84 { {#isNil. {}}. "valid 0-arg message" {#=. {true}}. "valid unary message" {#ifNil:ifNotNil:. {[2]. [:x | x]}}. "valid binary message" - {}. "missing selector" {#isNil}. "missing arguments" {#isNil. 'not an array'}. "invalid arguments" {#isNil. {'excess arg'}}. "too many arguments" {#=. {}}. "missing argument" } do: [:args | self assert: (Context runSimulated: [nil tryPrimitive: 84 withArgs: args]) equals: (nil tryPrimitive: 84 withArgs: args)].! From nicolas.cellier.aka.nice at gmail.com Wed Apr 14 16:46:18 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed, 14 Apr 2021 18:46:18 +0200 Subject: [squeak-dev] The Trunk: Kernel-ct.1383.mcz In-Reply-To: <019d7f3b377a4008850ee280d533de7a@student.hpi.uni-potsdam.de> References: <019d7f3b377a4008850ee280d533de7a@student.hpi.uni-potsdam.de> Message-ID: Thank you Christoph, done. I remember the discussion now. In the interim, I had moved Kernel-ct.1383.mcz to inbox because Eliot already merged... Le mer. 14 avr. 2021 à 18:21, Thiede, Christoph a écrit : > > Hi Nicolas, hi Eliot, hi all, > > > this appears to be a merge coordination error again. > > > Originally, in KernelTests-ct.382, I included a call to the primitive without arguments which makes the VM crash, see http://forum.world.st/The-Inbox-KernelTests-ct-382-mcz-tp5125776p5125777.html (the relevant line is + {}. "missing selector"). Others pointed out correctly that this was a nonsense test, so I uploaded KernelTests-ct.383 as a replacement which removed the relevant lines. But take attention to the diff in the mail on squeak-dev which appears to be erroneous. However, somehow the changes from KernelTests-ct.382 but not KernelTests-ct.383 have made their way into KernelTests-eem.396. Eliot, was this an incident or by attempt? :-) > > > Long story short: By merging KernelTests-ct.383 into the trunk, too, the CI should pass again. But please double-check the diff in Monticello before approving it. :-) > > > Best, > > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Nicolas Cellier > Gesendet: Mittwoch, 14. April 2021 17:21:42 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Trunk: Kernel-ct.1383.mcz > > Hi all, > it seems that it solves the failing tests for primitive 84 and 100. > But I still get a problem with testPrimitive83. > The test fails, and if I click on it in the TestRunner, the image > crash (SEGV) - at least on windows. > There is a SqueakDebug.log though, and it seems that we try to send > the message 83... > I don't know if you can reproduce or not, but help would be highly appreciated. > Christoph, do you have a clue? > > Le mer. 14 avr. 2021 à 14:53, a écrit : > > > > Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > > http://source.squeak.org/trunk/Kernel-ct.1383.mcz > > > > ==================== Summary ==================== > > > > Name: Kernel-ct.1383 > > Author: ct > > Time: 20 March 2021, 7:21:02.280742 pm > > UUID: b1953f95-408a-aa4a-9108-cc1dc355e9d1 > > Ancestors: Kernel-mt.1381 > > > > Fixes simulation of the #perform:... primitives 83, 84, and 100 for all edge cases. If the primitive is called with the wrong arguments, the primitive must fail but not the simulator. > > > > For further reference, see also the implementation of primitive 188 (primitiveExecuteMethodArgsArray) just a few lines below. :-) > > > > Tests have been provided in KernelTests-ct.395. Reuploaded to fix mirror variant of primitive 100. Now it's finally possible to debug MirrorPrimitiveTests>>#testMirrorPerform. Replaces Kernel-ct.1367, which can be moved into the treated inbox. > > > > =============== Diff against Kernel-mt.1381 =============== > > > > Item was changed: > > ----- Method: Context>>doPrimitive:method:receiver:args: (in category 'private') ----- > > doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments > > "Simulate a primitive method whose index is primitiveIndex. The simulated receiver and > > arguments are given as arguments to this message. If successful, push result and return > > resuming context, else ^ {errCode, PrimitiveFailToken}. Any primitive which provokes > > execution needs to be intercepted and simulated to avoid execution running away." > > > > | value | > > "Judicious use of primitive 19 (a null primitive that doesn't do anything) prevents > > the debugger from entering various run-away activities such as spawning a new > > process, etc. Injudicious use results in the debugger not being able to debug > > interesting code, such as the debugger itself. Hence use primitive 19 with care :-)" > > "SystemNavigation new browseAllSelect: [:m| m primitive = 19]" > > primitiveIndex = 19 ifTrue: [ > > [self notify: ('The code being simulated is trying to control a process ({1}). Process controlling cannot be simulated. If you proceed, things may happen outside the observable area of the simulator.' translated format: {meth reference})] > > ifCurtailed: [self push: nil "Cheap fix of the context's internal state"]]. > > > > ((primitiveIndex between: 201 and: 222) > > and: [(self objectClass: receiver) includesBehavior: BlockClosure]) ifTrue: > > [(primitiveIndex = 206 > > or: [primitiveIndex = 208]) ifTrue: "[Full]BlockClosure>>valueWithArguments:" > > [^receiver simulateValueWithArguments: arguments first caller: self]. > > ((primitiveIndex between: 201 and: 209) "[Full]BlockClosure>>value[:value:...]" > > or: [primitiveIndex between: 221 and: 222]) ifTrue: "[Full]BlockClosure>>valueNoContextSwitch[:]" > > [^receiver simulateValueWithArguments: arguments caller: self]]. > > > > primitiveIndex = 83 ifTrue: "afr 9/11/1998 19:50" "Object>>perform:[with:...]" > > + [| selector | > > + selector := arguments at: 1 ifAbsent: > > + [^ self class primitiveFailTokenFor: #'bad argument']. > > + arguments size - 1 = selector numArgs ifFalse: > > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > > + ^self send: selector to: receiver with: arguments allButFirst]. > > - [^self send: arguments first to: receiver with: arguments allButFirst]. > > primitiveIndex = 84 ifTrue: "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:" > > + [| selector args | > > + arguments size = 2 ifFalse: > > + [^ self class primitiveFailTokenFor: #'bad argument']. > > + selector := arguments first. > > + args := arguments second. > > + args isArray ifFalse: > > + [^ self class primitiveFailTokenFor: #'bad argument']. > > + args size = selector numArgs ifFalse: > > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > > + ^self send: selector to: receiver with: args]. > > - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (self objectClass: receiver)]. > > primitiveIndex = 100 ifTrue: "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:" > > + [| rcvr selector args superclass | > > + arguments size > > + caseOf: { > > + [3] -> [ > > + rcvr := receiver. > > + selector := arguments first. > > + args := arguments second. > > + superclass := arguments third]. > > + [4] -> ["mirror primitive" > > + rcvr := arguments first. > > + selector := arguments second. > > + args := arguments third. > > + superclass := arguments fourth] } > > + otherwise: [^ self class primitiveFailTokenFor: #'bad argument']. > > + args isArray ifFalse: > > + [^ self class primitiveFailTokenFor: #'bad argument']. > > + args size = selector numArgs ifFalse: > > + [^ self class primitiveFailTokenFor: #'bad number of arguments']. > > + ((self objectClass: rcvr) includesBehavior: superclass) ifFalse: > > + [^ self class primitiveFailTokenFor: #'bad argument']. > > + ^self send: selector to: rcvr with: args lookupIn: superclass]. > > - [^self send: arguments first to: receiver with: (arguments at: 2) lookupIn: (arguments at: 3)]. > > > > "Mutex>>primitiveEnterCriticalSection > > Mutex>>primitiveTestAndSetOwnershipOfCriticalSection" > > (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue: > > [| effective | > > effective := Processor activeProcess effectiveProcess. > > "active == effective" > > value := primitiveIndex = 186 > > ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective] > > ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective]. > > ^(self isPrimFailToken: value) > > ifTrue: [value] > > ifFalse: [self push: value]]. > > > > primitiveIndex = 188 ifTrue: "Object>>withArgs:executeMethod: > > CompiledMethod class>>receiver:withArguments:executeMethod: > > VMMirror>>ifFail:object:with:executeMethod: et al" > > [| n args methodArg thisReceiver | > > ((n := arguments size) between: 2 and: 4) ifFalse: > > [^self class primitiveFailTokenFor: #'unsupported operation']. > > ((self objectClass: (args := arguments at: n - 1)) == Array > > and: [(self objectClass: (methodArg := arguments at: n)) includesBehavior: CompiledMethod]) ifFalse: > > [^self class primitiveFailTokenFor: #'bad argument']. > > methodArg numArgs = args size ifFalse: > > [^self class primitiveFailTokenFor: #'bad number of arguments']. > > thisReceiver := arguments at: n - 2 ifAbsent: [receiver]. > > methodArg primitive > 0 ifTrue: > > [methodArg isQuick ifTrue: > > [^self push: (methodArg valueWithReceiver: thisReceiver arguments: args)]. > > ^self doPrimitive: methodArg primitive method: meth receiver: thisReceiver args: args]. > > ^Context > > sender: self > > receiver: thisReceiver > > method: methodArg > > arguments: args]. > > > > primitiveIndex = 118 ifTrue: "[receiver:]tryPrimitive:withArgs:; avoid recursing in the VM" > > [(arguments size = 3 > > and: [(self objectClass: arguments second) == SmallInteger > > and: [(self objectClass: arguments last) == Array]]) ifTrue: > > [^self doPrimitive: arguments second method: meth receiver: arguments first args: arguments last]. > > (arguments size = 2 > > and: [(self objectClass: arguments first) == SmallInteger > > and: [(self objectClass: arguments last) == Array]]) ifFalse: > > [^self class primitiveFailTokenFor: nil]. > > ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last]. > > > > value := primitiveIndex = 120 "FFI method" > > ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments] > > ifFalse: > > [primitiveIndex = 117 "named primitives" > > ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments] > > ifFalse: "should use self receiver: receiver tryPrimitive: primitiveIndex withArgs: arguments but this is only in later VMs (and appears to be broken)" > > [receiver tryPrimitive: primitiveIndex withArgs: arguments]]. > > > > ^(self isPrimFailToken: value) > > ifTrue: [value] > > ifFalse: [self push: value]! > > > > > > From nicolas.cellier.aka.nice at gmail.com Wed Apr 14 17:10:27 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed, 14 Apr 2021 19:10:27 +0200 Subject: [squeak-dev] The Trunk: MorphicTests-mt.65.mcz In-Reply-To: References: Message-ID: Hi Marcel, here is an attempt at answering an old mail (this one was still in my client). this breaks my preference... See below Le jeu. 17 sept. 2020 à 15:41, a écrit : > > Marcel Taeumel uploaded a new version of MorphicTests to project The Trunk: > http://source.squeak.org/trunk/MorphicTests-mt.65.mcz > > ==================== Summary ==================== > > Name: MorphicTests-mt.65 > Author: mt > Time: 17 September 2020, 3:41:47.157573 pm > UUID: 50b2cc27-06d5-5d40-936d-7b029ddc01b1 > Ancestors: MorphicTests-mt.64, MorphicTests-ct.61 > > Updates layout tests following MorphicTests-nice.61 (inbox->treated). Complements Morphic-mt.1683. Merges MorphicTests-ct.61 (inbox->trunk). > > =============== Diff against MorphicTests-mt.64 =============== > > Item was changed: > TestCase subclass: #MorphLayoutTest > + instanceVariableNames: 'reset' > - instanceVariableNames: '' > classVariableNames: '' > poolDictionaries: '' > category: 'MorphicTests-Layouts'! > > Item was removed: > - ----- Method: MorphLayoutTest>>testScrollPaneBarUpdate (in category 'tests') ----- > - testScrollPaneBarUpdate > - > - | oldPreferences | > - oldPreferences := ScrollPane useRetractableScrollBars. > - [| child container | > - ScrollPane useRetractableScrollBars: false. > - container := ScrollPane new color: Color green; extent: 300 @ 300; showVScrollBarOnlyWhenNeeded; showHScrollBarOnlyWhenNeeded. > - container scroller addMorphBack: (child := Morph new color: Color red; extent: 100 @ 100). > - > - self ensureLayout: container. > - self assert: container hScrollBar owner isNil. > - self assert: container vScrollBar owner isNil. > - > - child extent: 400 @ 100. > - self ensureLayout: container. > - self assert: container hScrollBar owner notNil. > - self assert: container vScrollBar owner isNil. > - > - child extent: 400 @ 400. > - self ensureLayout: container. > - self assert: container hScrollBar owner notNil. > - self assert: container hScrollBar owner notNil] > - ensure: [ScrollPane useRetractableScrollBars: oldPreferences]! > > Item was added: > + ----- Method: MorphicEventTests>>test02MouseOver (in category 'tests') ----- > + test02MouseOver > + > + | m1 m2 | > + m1 := MorphForEventTests new. > + m2 := MorphForEventTests new. > + > + m1 extent: 20 at 20; topLeft: 0 at 0. > + m2 extent: 20 at 20; topLeft: 40 at 0. > + > + m1 openInWorld: world. > + m2 openInWorld: world. > + > + hand handleEvent: (self redMouseDownAt: m1 center). > + hand handleEvent: (self redMouseUpAt: m1 center). > + hand handleEvent: (self redMouseDownAt: m2 center). > + hand handleEvent: (self redMouseUpAt: m2 center). > + > + self > + checkEventOrder: #(mouseMove mouseEnter mouseDown mouseUp mouseLeave) > + forEvents: m1 eventsDuringBubble > + ignoreMouseOver: true. > + > + self > + checkEventOrder: #(mouseMove mouseEnter mouseDown mouseUp) > + forEvents: m2 eventsDuringBubble > + ignoreMouseOver: true. > + ! > > Item was removed: > - ----- Method: MorphicEventTests>>test02MouserOver (in category 'tests') ----- > - test02MouserOver > - > - | m1 m2 | > - m1 := MorphForEventTests new. > - m2 := MorphForEventTests new. > - > - m1 extent: 20 at 20; topLeft: 0 at 0. > - m2 extent: 20 at 20; topLeft: 40 at 0. > - > - m1 openInWorld: world. > - m2 openInWorld: world. > - > - hand handleEvent: (self redMouseDownAt: m1 center). > - hand handleEvent: (self redMouseUpAt: m1 center). > - hand handleEvent: (self redMouseDownAt: m2 center). > - hand handleEvent: (self redMouseUpAt: m2 center). > - > - self > - checkEventOrder: #(mouseMove mouseEnter mouseDown mouseUp mouseLeave) > - forEvents: m1 eventsDuringBubble > - ignoreMouseOver: true. > - > - self > - checkEventOrder: #(mouseMove mouseEnter mouseDown mouseUp) > - forEvents: m2 eventsDuringBubble > - ignoreMouseOver: true. > - ! > > Item was changed: > TestCase subclass: #TableLayoutTest > + instanceVariableNames: 'container reset' > - instanceVariableNames: 'container' > classVariableNames: '' > poolDictionaries: '' > category: 'MorphicTests-Layouts'! > > Item was added: > + ----- Method: TableLayoutTest>>setUp (in category 'running') ----- > + setUp > + > + super setUp. > + > + reset := { > + ([:enable | [self useRetractableScrollBars: enable]] > + value: self useRetractableScrollBars) > + in: [:block | self useRetractableScrollBars: false]. > + }.! Hmph... This is brainfuck code... It should be: reset := { ([:enable | [self useRetractableScrollBars: enable]] value: self useRetractableScrollBars) in: [:block | self useRetractableScrollBars: false. block]. }. or just: reset := { ([:enable | [self useRetractableScrollBars: enable]] value: self useRetractableScrollBars) }. self useRetractableScrollBars: false > > Item was added: > + ----- Method: TableLayoutTest>>tearDown (in category 'running') ----- > + tearDown > + > + reset do: #value. > + super tearDown.! > > Item was changed: > ----- Method: TableLayoutTest>>testPluggableTextMorph (in category 'tests') ----- > testPluggableTextMorph > > + | ptm | > - | oldPreferences | > - oldPreferences := ScrollPane useRetractableScrollBars. > - [| ptm | > - ScrollPane useRetractableScrollBars: false. > ptm := PluggableTextMorph new > extent: 100 at 50; > setText: 'Hello World!! Hello World!! Hello World!! Hello World!!'; > wrapFlag: true. > + > - > container := self newContainer addMorphBack: ptm. > self ensureLayout: container. > self assert: 100 at 50 equals: container extent. > > self assert: ptm vIsScrollbarShowing. > self deny: ptm hIsScrollbarShowing. > > "Make it a one-liner." > ptm wrapFlag: false. > self ensureLayout: container. > self deny: ptm vIsScrollbarShowing. > self assert: ptm hIsScrollbarShowing. > > "Make it a one-liner without the horizontal scrollbar." > ptm hideScrollBarsIndefinitely. > self ensureLayout: container. > self deny: ptm vIsScrollbarShowing. > + self deny: ptm hIsScrollbarShowing. > - self deny: ptm hIsScrollbarShowing] > - ensure: [ScrollPane useRetractableScrollBars: oldPreferences]. > ! > > Item was changed: > ----- Method: TableLayoutTest>>testPluggableTextMorphScrollBarNotNeeded (in category 'tests') ----- > testPluggableTextMorphScrollBarNotNeeded > "The entire test might fit if the scroll bar would only disappear..." > > + | ptm | > - | oldPreferences | > - oldPreferences := ScrollPane useRetractableScrollBars. > - [| ptm | > - ScrollPane useRetractableScrollBars: false. > ptm := PluggableTextMorph new > extent: 100 at 50; > setText: 'Hello World!! Hello World!! \\\ Hello World!! Hello World!!' withCRs. > container := self newContainer addMorphBack: ptm. > > "Make it fit exactly first." > ptm hResizing: #shrinkWrap; vResizing: #shrinkWrap. > self ensureLayout: container. > ptm hResizing: #rigid; vResizing: #rigid. > ptm wrapFlag: true. > > "No scrollbars required." > self ensureLayout: container. > self deny: ptm vIsScrollbarShowing. > > "It wraps immediately." > ptm width: ptm width - 5. > self ensureLayout: container. > self assert: ptm vIsScrollbarShowing. > > "No scrollbars required." > ptm width: ptm width + 5. > self ensureLayout: container. > + self deny: ptm vIsScrollbarShowing.! > - self deny: ptm vIsScrollbarShowing] > - ensure: [ScrollPane useRetractableScrollBars: oldPreferences]! > > Item was added: > + ----- Method: TableLayoutTest>>testScrollPaneBarUpdate (in category 'tests - scroll panes') ----- > + testScrollPaneBarUpdate > + > + | child container | > + container := ScrollPane new color: Color green; extent: 300 @ 300; showVScrollBarOnlyWhenNeeded; showHScrollBarOnlyWhenNeeded. > + container scroller addMorphBack: (child := Morph new color: Color red; extent: 100 @ 100). > + > + self ensureLayout: container. > + self assert: container hScrollBar owner isNil. > + self assert: container vScrollBar owner isNil. > + > + child extent: 400 @ 100. > + self ensureLayout: container. > + self assert: container hScrollBar owner notNil. > + self assert: container vScrollBar owner isNil. > + > + child extent: 400 @ 400. > + self ensureLayout: container. > + self assert: container hScrollBar owner notNil. > + self assert: container hScrollBar owner notNil! > > Item was changed: > ----- Method: TableLayoutTest>>testScrollPaneShrinkWrap (in category 'tests') ----- > testScrollPaneShrinkWrap > > + | scroll scrollContent | > - | oldPreferences | > - oldPreferences := ScrollPane useRetractableScrollBars. > - [| scroll scrollContent | > - ScrollPane useRetractableScrollBars: false. > container := self newContainer > vResizing: #rigid; > addMorphBack: (self newMorph extent: 50 @ 50); > addMorphBack: (scroll := ScrollPane new > hResizing: #shrinkWrap; > vResizing: #spaceFill; > showVScrollBarOnlyWhenNeeded; > hideHScrollBarIndefinitely). > > " shrinkWrap the horizontal axis but scroll vertically " > scroll scroller > layoutPolicy: TableLayout new; > addMorphBack: (scrollContent := self newMorph extent: 200 @ 500). > > container extent: 1 @ 300. > self ensureLayout: container. > self assert: container left = (container layoutChanged; fullBounds; left). "Do not be jumpy." > self assert: (200 + scroll scrollBarThickness + scroll borderWidth) @ 300 equals: scroll extent. > > scrollContent extent: 300 @ 500. > self ensureLayout: container. > + self assert: (300 + scroll scrollBarThickness + scroll borderWidth) @ 300 equals: scroll extent! > - self assert: (300 + scroll scrollBarThickness + scroll borderWidth) @ 300 equals: scroll extent] > - ensure: [ScrollPane useRetractableScrollBars: oldPreferences]. > - ! > > Item was added: > + ----- Method: TableLayoutTest>>testScrollerFill (in category 'tests - scroll panes') ----- > + testScrollerFill > + "A scroll pane's scroller (i.e., the transform morph) has always #spaceFill behavior within the scroll pane's layout. Thus, submorphs (here: title and content) can themselves be #spaceFill. Embed a text morph to check height-for-width compatibility." > + > + | content title | > + container := ScrollPane new. > + > + container scroller > + layoutPolicy: TableLayout new; > + color: Color random; > + addMorphBack: (title := TextMorph new hResizing: #spaceFill; contents: 'Here comes an interesting title'); > + addMorphBack: (content := self newMorph extent: 400 @ 400; hResizing: #spaceFill). > + container extent: 50 @ 50. "Pick an extent so that the title must wrap!!" > + self ensureLayout: container. > + > + "container openInHand." > + > + container extent: 500 @ 500. > + self ensureLayout: container. > + self assert: 500 @ 500 equals: container extent. > + self assert: 500 - (container borderWidth * 2) @ 400 equals: content extent. > + > + container extent: 300 @ 300. > + self ensureLayout: container. > + self assert: 300 @ 300 equals: container extent. > + self assert: 300 - container borderWidth - container scrollBarThickness @ 400 equals: content extent! > > Item was added: > + ----- Method: TableLayoutTest>>testScrollerFillWithContainer (in category 'tests - scroll panes') ----- > + testScrollerFillWithContainer > + "A scroll pane's scroller (i.e., the transform morph) has always #spaceFill behavior within the scroll pane's layout. Thus, submorphs (here: title and content) can themselves be #spaceFill. Embed a text morph to check height-for-width compatibility. Add an extra container between scroller and title/content." > + > + | content title | > + container := ScrollPane new. > + > + container scroller > + layoutPolicy: TableLayout new; > + addMorphBack: (self newContainer > + hResizing: #spaceFill; > + vResizing: #spaceFill; > + listDirection: #topToBottom; > + addMorphBack: (title := TextMorph new hResizing: #spaceFill; contents: 'Here comes an interesting title'); > + addMorphBack: (content := self newMorph extent: 400 @ 400; hResizing: #spaceFill)). > + container extent: 50 @ 50. "Pick an extent so that the title must wrap!!" > + self ensureLayout: container. > + > + "container openInHand." > + > + container extent: 500 @ 500. > + self ensureLayout: container. > + self assert: 500 @ 500 equals: container extent. > + self assert: 500 - (container borderWidth * 2) @ 400 equals: content extent. > + > + container extent: 300 @ 300. > + self ensureLayout: container. > + self assert: 300 @ 300 equals: container extent. > + self assert: 300 - container borderWidth - container scrollBarThickness @ 400 equals: content extent! > > Item was changed: > ----- Method: TableLayoutTest>>testShrinkWrapScrollPaneAlwaysShowBars (in category 'tests') ----- > testShrinkWrapScrollPaneAlwaysShowBars > > + | scroll scrollContent | > - | oldPreferences | > - oldPreferences := ScrollPane useRetractableScrollBars. > - [| scroll scrollContent | > - ScrollPane useRetractableScrollBars: false. > container := self newContainer > vResizing: #shrinkWrap; > hResizing: #shrinkWrap; > addMorphBack: (scroll := ScrollPane new > hResizing: #shrinkWrap; > vResizing: #shrinkWrap; > alwaysShowHScrollBar; > alwaysShowVScrollBar). > > scroll scroller > layoutPolicy: TableLayout new; > addMorphBack: (scrollContent := self newMorph extent: 300 @ 300). > > self ensureLayout: container. > + self assert: (300 @ 300) + scroll scrollBarThickness + scroll borderWidth equals: container extent! > - self assert: (300 @ 300) + scroll scrollBarThickness + scroll borderWidth equals: container extent] > - ensure: [ScrollPane useRetractableScrollBars: oldPreferences]. > - ! > > Item was changed: > ----- Method: TableLayoutTest>>testSidebarAndScrollingView (in category 'tests - example layouts') ----- > testSidebarAndScrollingView > " construct a container that has a fixed size sidebar on the left and a scrolling window that adapts flexibly to the container's size " > > + | scrolling sidebar content title | > - | oldPreferences | > - oldPreferences := ScrollPane useRetractableScrollBars. > - [| scrolling sidebar content title | > - ScrollPane useRetractableScrollBars: false. > container := self newContainer > addMorphBack: (sidebar := self newMorph width: 200; hResizing: #rigid; vResizing: #spaceFill); > addMorphBack: (scrolling := ScrollPane new hResizing: #spaceFill; vResizing: #spaceFill). > > scrolling scroller > layoutPolicy: TableLayout new; > addMorphBack: (self newContainer > hResizing: #spaceFill; > vResizing: #spaceFill; > listDirection: #topToBottom; > addMorphBack: (title := TextMorph new hResizing: #spaceFill; contents: 'Here comes a title'); > addMorphBack: (content := self newMorph extent: 400 @ 400; hResizing: #spaceFill)). > + self ensureLayout: container. > + > "container openInHand." > > container extent: 500 @ 500. > self ensureLayout: container. > self assert: 200 @ 500 equals: sidebar extent. > self assert: 300 @ 500 equals: scrolling extent. > self assert: 300 - (scrolling borderWidth * 2) @ 400 equals: content extent. > > container extent: 300 @ 300. > self ensureLayout: container. > self assert: 200 @ 300 equals: sidebar extent. > self assert: 100 @ 300 equals: scrolling extent. > + self assert: 100 - scrolling borderWidth - scrolling scrollBarThickness @ 400 equals: content extent! > - self assert: 100 - scrolling borderWidth - scrolling scrollBarThickness @ 400 equals: content extent] > - ensure: [ScrollPane useRetractableScrollBars: oldPreferences]! > > Item was added: > + ----- Method: TableLayoutTest>>useRetractableScrollBars (in category 'running') ----- > + useRetractableScrollBars > + > + ^ ScrollPane classPool at: #UseRetractableScrollBars! > > Item was added: > + ----- Method: TableLayoutTest>>useRetractableScrollBars: (in category 'running') ----- > + useRetractableScrollBars: aBoolean > + "Re-implemented to avoid triggering #allSubInstancesDo:." > + > + ScrollPane classPool at: #UseRetractableScrollBars put: aBoolean.! > > From commits at source.squeak.org Wed Apr 14 17:14:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 17:14:15 0000 Subject: [squeak-dev] The Trunk: MorphicTests-nice.75.mcz Message-ID: Nicolas Cellier uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-nice.75.mcz ==================== Summary ==================== Name: MorphicTests-nice.75 Author: nice Time: 14 April 2021, 7:14:06.997889 pm UUID: d87c50dd-4e44-5242-9120-37e0452ca781 Ancestors: MorphicTests-eem.74 Fix loss of useRetractableScrollBars preference =============== Diff against MorphicTests-eem.74 =============== Item was changed: ----- Method: TableLayoutTest>>setUp (in category 'running') ----- setUp super setUp. - reset := { ([:enable | [self useRetractableScrollBars: enable]] value: self useRetractableScrollBars) + }. + self useRetractableScrollBars: false! - in: [:block | self useRetractableScrollBars: false]. - }.! From leves at caesar.elte.hu Wed Apr 14 17:17:42 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Wed, 14 Apr 2021 19:17:42 +0200 (CEST) Subject: [squeak-dev] The Inbox: Collections-mt.938.mcz In-Reply-To: References: Message-ID: Hi Marcel, Due to the flaw of OrderedCollection >> #new:, the code won't work with OrderedCollections (and its subclasses). This is the same issue Tim found with OrderedCollection and #streamContents: the other day. The current workaround is to use #ofSize: instead of #new: to create a non-empty instance with the given capacity. It would be great to change OrderedCollection class >> #new: to return a non-empty collection, and create a new method, e.g. #newWithCapacity: to create an empty collection with the given capacity, but I don't think it's possible to do that without breaking almost all existing programs out there. The code won't work with LinkedList either because of the same reason. So, that class will need its own implementation. The code also suffers from #collect:'s problem, which is its reliance on #species. #species is used for way too many things, and a single method cannot fit all those roles. The fix for that is #collect:as:, which lets the user decide what the class of the result should be. So, the question is: should there be #collect:as:separatedBy: too? Levente On Wed, 14 Apr 2021, commits at source.squeak.org wrote: > A new version of Collections was added to project The Inbox: > http://source.squeak.org/inbox/Collections-mt.938.mcz > > ==================== Summary ==================== > > Name: Collections-mt.938 > Author: mt > Time: 14 April 2021, 2:38:21.265628 pm > UUID: d109bde4-42a6-e840-803c-e4e80b98a74d > Ancestors: Collections-mt.937 > > Proposal. Add a #joinSeparatedBy: that does not end up as a string. > > The current alternative would be #gather > (#(1 2 3 4 5) gather: [:each | {each . $x}]) allButLast. > > Not sure whether a non-sequenceable version in Collection makes sense. We have had that discussion about #join etc. being not useful for uncertain output order. > > Some benchmarks: > > [ ((1 to: 1000) gather: [:num | {num . $x}]) allButLast ] bench. > '22,000 per second. 45.5 microseconds per run. 13.09738 % GC time.' > > [ (1 to: 1000) collect: [:num | num] separatedBy: [$x] ] bench. > '26,000 per second. 38.5 microseconds per run. 1.73965 % GC time.' > > =============== Diff against Collections-mt.937 =============== > > Item was added: > + ----- Method: Collection>>collect:separatedBy: (in category 'enumerating') ----- > + collect: elementBlock separatedBy: separatorBlock > + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." > + > + | newCollection | > + newCollection := self species new. > + self > + do: [:each | newCollection add: (elementBlock value: each)] > + separatedBy: [:each | newCollection add: separatorBlock value]. > + ^ newCollection! > > Item was added: > + ----- Method: SequenceableCollection>>collect:separatedBy: (in category 'enumerating') ----- > + collect: elementBlock separatedBy: separatorBlock > + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." > + > + | newCollection | > + newCollection := self species new: self size *2 -1. > + 1 to: self size do: [:index | > + index = 1 ifFalse: [newCollection at: (index-1 *2) put: separatorBlock value]. > + newCollection at: (index-1 *2)+1 put: (elementBlock value: (self at: index))]. > + ^ newCollection! From Patrick.Rein at hpi.de Wed Apr 14 18:11:17 2021 From: Patrick.Rein at hpi.de (Rein, Patrick) Date: Wed, 14 Apr 2021 18:11:17 +0000 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de>, Message-ID: <851aa19170fe4ea483f729dd6c0546d9@hpi.de> Hello everyone out there! To keep the tradition going, you hereby receive the annual campaigning reminder! We are really off to a great start! So far we have 5 candidates for 7 board seats. In the order they announced: Tim Rowledge Vanessa Freudenberg Craig Latta Marcel Taeumel David T. Lewis However, we could use at least TWO more candidates! If you are going to run this year, please announce soon! If you are not going to run please talk to people you know that you think would make a good board member and ask them to run! It's always nice to have more than 7 candidates! Also if your email has changed please let me know! We want to get as many people voting as possible! If you want to vote this year I encourage you to let me know so I can get you on the voters list. Be sure to get to know the candidates and ask them questions! Thank you for your participation in this year's election! All the best, Patrick ________________________________________ From: Squeak-dev on behalf of Chris Muller Sent: Tuesday, April 13, 2021 6:17:28 AM To: The general-purpose Squeak developers list Subject: Re: [squeak-dev] Squeak Oversight Board Election 2021 Hi all, Just FYI, I'm allocating 100% of my Squeak-energy this year to Magma 2 as well as various image explorations to attempt to expose the class library in various ways via GraphQL schemas. Some of this work would likely be mutually distracting if I were immersed in core Squeak development. For example, exploring whether Method Pragmas can be loadable from their own "extension" package, *on top* of existing methods.. Anyway, I do hope someone will consider running for 2021 in my stead. Anyone who does will get my vote. :) - Chris On Fri, Apr 2, 2021 at 3:10 AM Rein, Patrick > wrote: Hi All, It's that time again (although with a new person telling you this). Time to raise your voices and elect your leaders! Can you believe it's been over a year already? It's a time for you to stand up, help your community and volunteer to serve! Squeak wants you! Every year we elect the SOB (Squeak Oversight Board) consisting of seven members from our community. The current board members are: 1. Vanessa Freudenberg 2. Tim Rowledge 3. Marcel Taeumel 4. Craig Latta 5. David T. Lewis 6. Chris Muller 7. John-Reed Maffeo For more info on the board please see: https://squeakboard.wordpress.com/our-mission/ Everything about the election, including schedule and more, can be tracked here: http://wiki.squeak.org/squeak/6656 Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members and campaigning! Candidates should nominate themselves and start their campaign on the squeak-dev mailing list. Or if you nominate someone else, make sure that person really wants to run. :) I will not put anyone on the candidate list until that person makes it known on squeak-dev that he/she intends to run. During this period, the candidates should ideally present themselves on squeak-dev, unless they have already done so, and the community can ask questions. I encourage you to reach out to potential candidates, people that are active in the community and represent your views, and ask them to run. Some people will not run without encouragement. Also, I know that some people wait to the last minute to run for the board to see if others will run but please consider getting this year off to a faster start and just jump right in! The schedule and process are as follows: Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members and campaigning! Friday 16th of April 2021, 18.00 UTC: Candidate list is finalized. Friday 16th of April 2021, 19.00 UTC: Online election starts. Friday 30th of April 2021, 19.00 UTC: Online election ends. Results will be announced immediately after the election ends. The voting period is two week long and ballots are sent out via email. And how do you end up on the voter list? See below. :) IMPORTANT: New voters will NOT be added once the election is started. You MUST try to get on the voter list before the 16th of April 2021 or you will NOT be able to vote. If your Email has changed please try to make sure it is changed on the list of voters before the election starts. -------------------------- If you were invited to vote last year you are already on the voter list, no worries! If you are a new Squeaker and wish to vote you should do ONE of the following: * Get a "known" Squeaker to vouch for you. If a known Squeaker sends an email to voters (at) squeak.org giving me a name and email for you, then I will add you. * Send an email to voters (at) squeak.org yourself (and CC to squeak-dev if you like) with information/arguments showing me that you are indeed serious about voting and that you are indeed a Squeaker. When the voting period starts all voters will receive an email with instructions and a link to the voting website. If there are any further questions, just reply *in this thread* and I will closely track it - or send email to voters (at) squeak.org which is updated and points to me. ...so let's get on with it! All the best, Patrick Rein From commits at source.squeak.org Wed Apr 14 18:36:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 18:36:37 0000 Subject: [squeak-dev] The Trunk: MorphicTests-nice.76.mcz Message-ID: Nicolas Cellier uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-nice.76.mcz ==================== Summary ==================== Name: MorphicTests-nice.76 Author: nice Time: 14 April 2021, 8:36:28.728889 pm UUID: c2f02bb9-13ed-a74e-b5fa-f4f84b52ba01 Ancestors: MorphicTests-nice.75 Fix 3 tests =============== Diff against MorphicTests-nice.75 =============== Item was changed: ----- Method: MorphTest>>test10TransformKeepsLayer (in category 'tests - submorphs - layers') ----- test10TransformKeepsLayer + | transform | - | aMorph transform | - aMorph := Morph new. transform := morph addFlexShell. + morph morphicLayerNumber: 50. - aMorph morphicLayerNumber: 50. self assert: 50 equals: transform morphicLayerNumber. transform morphicLayerNumber: 20. self assert: 20 equals: transform morphicLayerNumber. + transform removeMorph: morph. - transform removeMorph: aMorph. transform morphicLayerNumber: 50. self + assert: 20 equals: morph morphicLayerNumber; - assert: 20 equals: aMorph morphicLayerNumber; assert: 50 equals: transform morphicLayerNumber! Item was changed: ----- Method: MorphTest>>test12ResetLayerToDefault (in category 'tests - submorphs - layers') ----- test12ResetLayerToDefault + | default | + default := morph morphicLayerNumber. - | aMorph default | - aMorph := Morph new. - default := aMorph morphicLayerNumber. + morph morphicLayerNumber: default * 2. + self deny: default equals: morph morphicLayerNumber. - aMorph morphicLayerNumber: default * 2. - self deny: default equals: aMorph morphicLayerNumber. morph morphicLayerNumber: nil. + self assert: default equals: morph morphicLayerNumber! - self assert: default equals: aMorph morphicLayerNumber! Item was changed: ----- Method: TableLayoutTest>>testCheckBoxGroup (in category 'tests - example layouts') ----- testCheckBoxGroup + | group groupContents labels boxHeight | - | group groupContents labels | labels := Dictionary new. group := self newContainer hResizing: #shrinkWrap; vResizing: #shrinkWrap; layoutPolicy: TableLayout new; listDirection: #topToBottom; layoutInset: 0; cellPositioning: #topLeft; borderStyle: (SimpleBorder color: Color black width: 2); yourself. group addMorphBack: (labels at: #groupLabel put: 'Favorite Ice Cream' asMorph). groupContents := self newContainer hResizing: #shrinkWrap; vResizing: #shrinkWrap; layoutPolicy: TableLayout new; listDirection: #topToBottom; cellGap: 0; cellPositioning: #topLeft; yourself. group addMorphBack: groupContents. + + boxHeight := 16. - #('Vanilla' 'Chocolate') withIndexDo: [:label :index | | checkBox | checkBox := self newContainer hResizing: #shrinkWrap; vResizing: #shrinkWrap; layoutPolicy: TableLayout new; listDirection: #rightToLeft; yourself. checkBox addMorphBack: (labels at: (#box, index asString) asSymbol put: label asMorph); + addMorphBack: (self newMorph extent: 16 at boxHeight; borderColor: Color black; borderWidth: 2). - addMorphBack: (self newMorph extent: 16 at 16; borderColor: Color black; borderWidth: 2). groupContents addMorphBack: checkBox]. self ensureLayout: group. self assert: (labels at: #groupLabel) width + (group borderWidth * 2) equals: group width. self assert: (labels at: #groupLabel) height + + ((labels at: #box1) height max: boxHeight) + + ((labels at: #box2) height max: boxHeight) - + (labels at: #box1) height - + (labels at: #box2) height + (group borderWidth * 2) equals: group height.! From commits at source.squeak.org Wed Apr 14 19:02:35 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 19:02:35 0000 Subject: [squeak-dev] The Trunk: Tests-ct.425.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-ct.425.mcz ==================== Summary ==================== Name: Tests-ct.425 Author: ct Time: 30 December 2019, 7:19:53.668602 pm UUID: fc85b43b-45f8-b340-b295-d43ee9de7a5f Ancestors: Tests-mt.424 Adds regression test for a compiler bug that was fixed in Compiler-ct.414 =============== Diff against Tests-mt.424 =============== Item was added: + ----- Method: CompilerTest>>testCascadeOnBlock (in category 'tests - syntax') ----- + testCascadeOnBlock + "Regression test. See http://forum.world.st/BUG-Cannot-compile-cascade-sent-to-block-td5108942.html" + + self + shouldnt: [Compiler + evaluate: '[true] whileFalse; whileFalse' + notifying: PluggableTextMorph new "dummy requestor"] + raise: Error. + self + assert: 2 + equals: (Compiler + evaluate: '| x | x := 0. [x := x + 1] doWhileTrue: [false]; doWhileFalse: [true]. x' + notifying: PluggableTextMorph new "dummy requestor").! From commits at source.squeak.org Wed Apr 14 19:45:14 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 19:45:14 0000 Subject: [squeak-dev] The Trunk: Tests-nice.452.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.452.mcz ==================== Summary ==================== Name: Tests-nice.452 Author: nice Time: 14 April 2021, 9:45:05.392889 pm UUID: 7da53a80-e416-0247-a611-d5b34fc56848 Ancestors: Tests-mt.451 Apply most of Tests-ct.436 but testNoSelectionNoScripts since it seems that this specific tests changes some global state (the mock package scripts) - original comment below. -- Fixes failing MCPackageTest >> #test{Load, Unload}Order which I originally introduced in Tests-ct.426. I had forgot to commit the mock preambles. Beside of that, it turned out that there was a lot of global state not properly sandboxed or reset by the MCTestCases. Enhance #clearPackageCache, fix implementations of #setUp/#tearDown methods, test MCSnapshotBrowser with and without scripts, and apply some minor refactoring. Remove accidentally added Tests-MonticelloMocks from organization. Please report any further global state if observed. =============== Diff against Tests-mt.451 =============== Item was changed: ----- Method: MCChangeNotificationTest>>tearDown (in category 'running') ----- tearDown + workingCopy unregister. + + ^ super tearDown! - super tearDown. - workingCopy unregister! Item was changed: ----- Method: MCClassDefinitionTest>>tearDown (in category 'running') ----- tearDown + Smalltalk at: 'MCMockClassC' ifPresent: [:c | c removeFromSystem]. + + ^ super tearDown! - super tearDown. - Smalltalk at: 'MCMockClassC' ifPresent: [:c | c removeFromSystem]! Item was changed: ----- Method: MCDictionaryRepositoryTest>>setUp (in category 'running') ----- setUp + + super setUp. + repository := MCDictionaryRepository new dictionary: self dictionary! Item was changed: ----- Method: MCDirectoryRepositoryTest>>setUp (in category 'running') ----- setUp + + super setUp. + repository := MCDirectoryRepository directory: self directory! Item was changed: ----- Method: MCDirectoryRepositoryTest>>tearDown (in category 'running') ----- tearDown + self directory recursiveDelete. + + ^ super tearDown! - super tearDown. - self directory recursiveDelete! Item was changed: ----- Method: MCEnvironmentLoadTest>>setUp (in category 'running') ----- setUp + + super setUp. + environment := Environment named: 'MCEnvironmentLoadTest'. "This is required in order to not importSelf more than once" environment stopObserving: environment. "This is required to make own declarations visible in environment" environment importSelf. "Import the required PoolDictionary used by the package" environment bindingOf: #MCMockAPoolDictionary ifAbsent: [environment from: Smalltalk globals import: #MCMockAPoolDictionary]. environment from: Smalltalk globals import: #(MCMock MCSnapshotTest Object).! Item was changed: ----- Method: MCEnvironmentLoadTest>>tearDown (in category 'running') ----- tearDown + (environment allClassesAndTraits sorted: [:a :b | (a allSuperclasses includes: b) or: [a name < b name]]) do: [:each | each removeFromSystem]. + + ^ super tearDown! - super tearDown! Item was changed: ----- Method: MCFileInTest>>setUp (in category 'running') ----- setUp + + super setUp. + expected := self mockSnapshot. stream := RWBinaryOrTextStream on: String new.! Item was changed: ----- Method: MCFileInTest>>tearDown (in category 'running') ----- tearDown - super tearDown. (diff isNil or: [diff isEmpty not]) ifTrue: [expected updatePackage: self mockPackage]. + SystemOrganizer default removeEmptyCategories. + + ^ super tearDown! - SystemOrganizer default removeEmptyCategories! Item was changed: ----- Method: MCInitializationTest>>tearDown (in category 'running') ----- tearDown + (MCWorkingCopy forPackage: self mockPackage) unregister. + + ^ super tearDown! - super tearDown. - (MCWorkingCopy forPackage: self mockPackage) unregister! Item was changed: ----- Method: MCMczInstallerTest>>setUp (in category 'running') ----- setUp + + super setUp. + expected := self mockVersion. self change: #one toReturn: 2.! Item was changed: ----- Method: MCMczInstallerTest>>tearDown (in category 'running') ----- tearDown - super tearDown. expected snapshot updatePackage: self mockPackage. + self deleteFile. + + ^ super tearDown! - self deleteFile.! Item was changed: ----- Method: MCMethodDefinitionTest>>setUp (in category 'running') ----- setUp + + super setUp. + extensionPackage := (MCWorkingCopy forPackage: (MCPackage named: 'FooBarBaz')). navigation := (Smalltalk hasClassNamed: #SystemNavigation) ifTrue: [(Smalltalk at: #SystemNavigation) new] ifFalse: [Smalltalk]. isModified := self ownPackage modified. overrideTimestamp := (self class >> #override) timeStamp! Item was changed: ----- Method: MCMethodDefinitionTest>>tearDown (in category 'running') ----- tearDown self restoreMocks. extensionPackage unregister. extensionPackage := nil. MCMockPackageInfo new mcPackage workingCopy unregister. self class compile: 'override ^ 1' classified: 'mocks' withStamp: overrideTimestamp notifying: nil. SystemOrganizer default removeEmptyCategories. self ownPackage modified: isModified. + + ^ super tearDown! - super tearDown - ! Item was added: + ----- Method: MCMockPackageInfo>>initialize (in category 'initialize-release') ----- + initialize + + super initialize. + + #(preamble postscript preambleOfRemoval postscriptOfRemoval) + do: [:selector | + self perform: selector asSimpleSetter with: selector asString].! Item was changed: ----- Method: MCPackageTest>>tearDown (in category 'running') ----- tearDown + self mockSnapshot install. + + ^ super tearDown! - super tearDown. - self mockSnapshot install! Item was changed: ----- Method: MCPatchTest>>setUp (in category 'running') ----- setUp + + | rev1 rev2 | + super setUp. + - |rev1 rev2| rev1 := MCSnapshotResource takeSnapshot. self change: #one toReturn: 2. rev2 := MCSnapshotResource takeSnapshot. patch := rev2 patchRelativeToBase: rev1. self change: #one toReturn: 1.! Item was changed: ----- Method: MCPatchTest>>tearDown (in category 'running') ----- tearDown + self restoreMocks. + + ^ super tearDown! - super tearDown. - self restoreMocks! Item was changed: ----- Method: MCSerializationTest>>tearDown (in category 'running') ----- tearDown + self restoreMocks. + + ^ super tearDown! - super tearDown.! Item was changed: ----- Method: MCSnapshotBrowserTest>>assertTextIs: (in category 'asserting') ----- assertTextIs: aString + ^ self assert: aString equals: self textMorph contents asString! - self assert: self textMorph contents = aString.! Item was changed: ----- Method: MCSnapshotBrowserTest>>setUp (in category 'running') ----- setUp + + super setUp. + "to not disturb the tests" originalAnnotationPanePref := Preferences annotationPanes. Preferences disable: #annotationPanes. model := MCSnapshotBrowser forSnapshot: MCSnapshotResource current snapshot. self buildWindow! Item was changed: ----- Method: MCSnapshotBrowserTest>>tearDown (in category 'running') ----- tearDown + originalAnnotationPanePref ifTrue: [Preferences enable: #annotationPanes]. + + ^ super tearDown! - super tearDown.! Item was changed: ----- Method: MCSnapshotBrowserTest>>testNoSelection (in category 'tests') ----- testNoSelection + + | text | self assertAListMatches: self allCategories. self denyAListIncludesAnyOf: self definedClasses. self denyAListIncludesAnyOf: self allProtocols. self denyAListIncludesAnyOf: self allMethods. + + text := self textMorph contents asString. + + #(preamble postscript preambleOfRemoval postscriptOfRemoval) + do: [:selector | + self assert: [text includesSubstring: selector]].! - "and if there I need to see the packages scripts (or none)" - self assertTextIs: '(package defines no scripts)'.! Item was changed: ----- Method: MCSnapshotTest>>setUp (in category 'running') ----- setUp + + super setUp. + snapshot := self mockSnapshot.! Item was changed: ----- Method: MCStWriterTest>>setUp (in category 'running') ----- setUp + + super setUp. + stream := RWBinaryOrTextStream on: String new. writer := MCStWriter on: stream. ! Item was changed: ----- Method: MCStWriterTest>>tearDown (in category 'running') ----- tearDown SystemOrganizer default removeEmptyCategories. + + ^ super tearDown ! - super tearDown ! Item was changed: ----- Method: MCTestCase>>clearPackageCache (in category 'running') ----- clearPackageCache "Remove all mock packages created during the tests from the package cache." + | directory cacheFiles cacheNames | - | directory | directory := MCCacheRepository default directory. + cacheNames := {self mockVersionName. self mockVersionInfo name}. + cacheFiles := cacheNames gather: [:name | + directory fileNamesMatching: name , '*']. + cacheFiles do: [:each | + directory deleteFileNamed: each].! - (directory fileNamesMatching: self mockVersionName, '*') do: [ :each | - directory deleteFileNamed: each ]! Item was added: + ----- Method: MCTestCase>>setUp (in category 'running') ----- + setUp + + super setUp. + + MCMockPackageInfo new register.! Item was changed: ----- Method: MCTestCase>>tearDown (in category 'running') ----- tearDown + self clearPackageCache. + "Environment current packageOrganizer unregisterPackageNamed: + MCSnapshotResource mockPackageName." + self flag: #todo. "Unfortunately breaks the tests" + + ^ super tearDown! - self clearPackageCache! Item was changed: ----- Method: MCVersionTest>>setUp (in category 'running') ----- setUp + + super setUp. + visited := OrderedCollection new.! Item was changed: ----- Method: MCWorkingCopyRenameTest>>setUp (in category 'running') ----- setUp + | repos1 repos2 | + super setUp. + repositoryGroup := MCRepositoryGroup new. workingCopy := MCWorkingCopy forPackage: self mockPackage. versions := Dictionary new. versions2 := Dictionary new. repos1 := MCDictionaryRepository new dictionary: versions. repos2 := MCDictionaryRepository new dictionary: versions2. repositoryGroup addRepository: repos1. repositoryGroup addRepository: repos2. MCRepositoryGroup default removeRepository: repos1; removeRepository: repos2. workingCopy repositoryGroup: repositoryGroup. savedInitials := Utilities authorInitialsPerSe. Utilities authorInitials: 'abc'.! Item was changed: ----- Method: MCWorkingCopyRenameTest>>tearDown (in category 'running') ----- tearDown + - super tearDown. workingCopy unregister. SystemOrganizer default removeEmptyCategories. MCSnapshotTest organization removeEmptyCategories. + Utilities authorInitials: savedInitials. + + ^ super tearDown! - Utilities authorInitials: savedInitials! Item was changed: ----- Method: MCWorkingCopyTest>>setUp (in category 'running') ----- setUp + | repos1 repos2 | + super setUp. + self clearPackageCache. repositoryGroup := MCRepositoryGroup new. workingCopy := MCWorkingCopy forPackage: self mockPackage. versions := Dictionary new. versions2 := Dictionary new. repos1 := MCDictionaryRepository new dictionary: versions. repos2 := MCDictionaryRepository new dictionary: versions2. repositoryGroup addRepository: repos1. repositoryGroup addRepository: repos2. MCRepositoryGroup default removeRepository: repos1; removeRepository: repos2. workingCopy repositoryGroup: repositoryGroup. savedInitials := Utilities authorInitialsPerSe. Utilities authorInitials: 'abc'.! Item was changed: ----- Method: MCWorkingCopyTest>>tearDown (in category 'running') ----- tearDown + - super tearDown. workingCopy unregister. self restoreMocks. SystemOrganizer default removeEmptyCategories. MCSnapshotTest organization removeEmptyCategories. + Utilities authorInitials: savedInitials. + + ^ super tearDown! - Utilities authorInitials: savedInitials! From commits at source.squeak.org Wed Apr 14 19:49:01 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 19:49:01 0000 Subject: [squeak-dev] The Trunk: Tests-nice.453.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.453.mcz ==================== Summary ==================== Name: Tests-nice.453 Author: nice Time: 14 April 2021, 9:48:52.082889 pm UUID: 48129d8e-693f-c446-866e-629cb1baced2 Ancestors: Tests-nice.452, Tests-ct.425 Merge Tests-ct.425 Adds regression test for a compiler bug that was fixed in Compiler-ct.414 =============== Diff against Tests-nice.452 =============== Item was added: + ----- Method: CompilerTest>>testCascadeOnBlock (in category 'tests - syntax') ----- + testCascadeOnBlock + "Regression test. See http://forum.world.st/BUG-Cannot-compile-cascade-sent-to-block-td5108942.html" + + self + shouldnt: [Compiler + evaluate: '[true] whileFalse; whileFalse' + notifying: PluggableTextMorph new "dummy requestor"] + raise: Error. + self + assert: 2 + equals: (Compiler + evaluate: '| x | x := 0. [x := x + 1] doWhileTrue: [false]; doWhileFalse: [true]. x' + notifying: PluggableTextMorph new "dummy requestor").! From commits at source.squeak.org Wed Apr 14 20:20:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 20:20:37 0000 Subject: [squeak-dev] The Trunk: Tools-mva.748.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mva.748.mcz ==================== Summary ==================== Name: Tools-mva.748 Author: mva Time: 15 March 2017, 4:58:37.421419 pm UUID: 8ef7567d-e7b4-4879-81de-6bce929e3bbf Ancestors: Tools-ul.747 fix selecting a directory in the left pane in a MVC project FileList on Mac and Linux (and it still works on Windows afterwards) =============== Diff against Tools-ul.747 =============== Item was changed: ----- Method: FileList>>volumeListIndex: (in category 'volume list and pattern') ----- volumeListIndex: index "Select the volume name having the given index." | delim path | volListIndex := index. index = 1 ifTrue: [self directory: (FileDirectory on: '')] ifFalse: [delim := directory pathNameDelimiter. path := String streamContents: [:strm | 2 to: index do: [:i | strm nextPutAll: (volList at: i) withBlanksTrimmed. i < index ifTrue: [strm nextPut: delim]]]. + self directory: (FileDirectory on: path)]. - self directory: (directory on: path)]. brevityState := #FileList. self addPath: path. self changed: #fileList. self changed: #contents. self updateButtonRow.! From commits at source.squeak.org Wed Apr 14 20:28:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 20:28:46 0000 Subject: [squeak-dev] The Trunk: Tools-tcj.834.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-tcj.834.mcz ==================== Summary ==================== Name: Tools-tcj.834 Author: tcj Time: 24 November 2018, 1:33:48.408468 am UUID: 1cf61cee-2719-46d5-be5c-bc5b25b43a19 Ancestors: Tools-eem.833 Add 'alphabetize' to Package Pane Browser's class category menu, as is found on standard Browser. =============== Diff against Tools-eem.833 =============== Item was changed: ----- Method: PackagePaneBrowser>>mainPackageMenu: (in category 'package list') ----- mainPackageMenu: aMenu "Answer a Menu of operations on class packages to be displayed when the operate menu button is pressed." ^aMenu addList: #( ('find class...' findClass) ('recent classes...' recent) - ('reorganize' editSystemCategories) + ('alphabetize' alphabetizeSystemCategories) + - ('update' updatePackages)); yourself. ! From commits at source.squeak.org Wed Apr 14 21:12:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 21:12:26 0000 Subject: [squeak-dev] The Trunk: Tools-ct.1006.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-ct.1006.mcz ==================== Summary ==================== Name: Tools-ct.1006 Author: ct Time: 24 October 2020, 12:15:14.188256 am UUID: f95dd0b3-94e1-2a4c-b66b-1870b1dc549c Ancestors: Tools-eem.1005 Complements Compiler-ct.449 (CompilationCue in SyntaxErrorNotification). Fixes syntax highlighting in SyntaxError window. =============== Diff against Tools-eem.1005 =============== Item was changed: ----- Method: SyntaxError>>aboutToStyle: (in category 'text menu support') ----- aboutToStyle: aStyler aStyler classOrMetaClass: self selectedClassOrMetaClass; + environment: notification environment; + context: notification context; parseAMethod: notification doitFlag not. ^ true! From commits at source.squeak.org Wed Apr 14 21:17:17 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 21:17:17 0000 Subject: [squeak-dev] The Trunk: Tools-ct.1020.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-ct.1020.mcz ==================== Summary ==================== Name: Tools-ct.1020 Author: ct Time: 12 December 2020, 11:33:05.41462 pm UUID: 0413bef6-8f81-9241-8f8b-47274aa31cd1 Ancestors: Tools-mt.1019 Fixes code styling in change sorters. Funnily, #aboutToStyle: was already implemented on ChangeSorter, only the toolbuilder method needed a small update ... :-) =============== Diff against Tools-mt.1019 =============== Item was changed: ----- Method: ChangeSorter>>buildWith:in:rect: (in category 'toolbuilder') ----- buildWith: builder in: window rect: rect | csListHeight msgListHeight csMsgListHeight listSpec textSpec | contents := ''. csListHeight := 0.25. msgListHeight := 0.25. csMsgListHeight := csListHeight + msgListHeight. listSpec := builder pluggableListSpec new. listSpec model: self; list: #changeSetList; getSelected: #currentCngSet; setSelected: #showChangeSetNamed:; menu: #changeSetMenu:shifted:; keyPress: #changeSetListKey:from:; dragItem: #dragChangeSet:; autoDeselect: false; frame: (((0 at 0 extent: 0.5 at csListHeight) scaleBy: rect extent) translateBy: rect origin). window children add: listSpec. listSpec := builder pluggableListSpec new. listSpec model: self; list: #classList; getSelected: #currentClassName; setSelected: #currentClassName:; menu: #classListMenu:shifted:; keyPress: #classListKey:from:; dragItem: #dragClass:; frame: (((0.5 at 0 extent: 0.5 at csListHeight) scaleBy: rect extent) translateBy: rect origin). window children add: listSpec. listSpec := builder pluggableListSpec new. listSpec model: self; list: #messageList; getSelected: #currentSelector; setSelected: #currentSelector:; menu: #messageMenu:shifted:; keyPress: #messageListKey:from:; dragItem: #dragMessage:; frame: (((0 at csListHeight extent: 1 at msgListHeight) scaleBy: rect extent) translateBy: rect origin). window children add: listSpec. + textSpec := builder pluggableCodePaneSpec new. - textSpec := builder pluggableTextSpec new. textSpec model: self; getText: #contents; setText: #contents:notifying:; selection: #contentsSelection; menu: #codePaneMenu:shifted:; frame: (((0 at csMsgListHeight corner: 1 at 1) scaleBy: rect extent) translateBy: rect origin). window children add: textSpec. ^window! From commits at source.squeak.org Wed Apr 14 21:21:06 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 21:21:06 0000 Subject: [squeak-dev] The Trunk: Tools-ct.1031.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-ct.1031.mcz ==================== Summary ==================== Name: Tools-ct.1031 Author: ct Time: 10 March 2021, 6:26:41.374559 pm UUID: 90289614-021a-254a-b67f-5612c973d257 Ancestors: Tools-mt.1030 Fixes styling in change sorters if no real method is selected. No need to invoke Shout on messages such as "method was removed". Using an instance variable for this to avoid duplication of the contents logic. =============== Diff against Tools-mt.1030 =============== Item was changed: CodeHolder subclass: #ChangeSorter + instanceVariableNames: 'parent myChangeSet currentClassName currentSelector priorChangeSetList contentsAreStyleable' - instanceVariableNames: 'parent myChangeSet currentClassName currentSelector priorChangeSetList' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! + !ChangeSorter commentStamp: 'ct 3/10/2021 18:24' prior: 0! - !ChangeSorter commentStamp: 'wiz 2/3/2010 23:38' prior: 0! I display a ChangeSet. Two of me are in a DualChangeSorter. aStringOrNil Instance Variables currentClassName: currentSelector: myChangeSet: parent: priorChangeSetList: + contentsAreStyleable currentClassName - string parseable into class-name [class] [class trait] needs to be fitlered by (self withoutItemAnnotation: currentClassName) to remove pakaging note currentSelector - string parseable into selector-name needs to be fitlered by (self withoutItemAnnotation: currentSelector) to remove pakaging note myChangeSet - name of current changeset parent -the dual changesorter that contains this one. Used for dealing with the other half. priorChangeSetList + - holds the current change set list. Used to detect changes in list when a newly generated list no long match the prior list.! - - holds the current change set list. Used to detect changes in list when a newly generated list no long match the prior list. - ! Item was changed: ----- Method: ChangeSorter>>aboutToStyle: (in category 'code pane') ----- aboutToStyle: aStyler "This is a notification that aStyler is about to re-style its text. Set the classOrMetaClass in aStyler, so that identifiers will be resolved correctly. Answer true to allow styling to proceed, or false to veto the styling" + contentsAreStyleable ~= false ifFalse: [^false]. - self isModeStyleable ifFalse: [^false]. - self currentSelector ifNil: [^false]. aStyler classOrMetaClass: self selectedClassOrMetaClass. ^true! Item was changed: ----- Method: ChangeSorter>>setContents (in category 'code pane') ----- setContents "return the source code that shows in the bottom pane" | sel class strm changeType | self clearUserEditFlag. + contentsAreStyleable := false. myChangeSet ifNil: [^ contents := String empty]. "should not happen but can" currentClassName ifNil: [^ contents := myChangeSet preambleString ifNil: [String empty]]. class := self selectedClassOrMetaClass. (sel := self selectedMessageName) == nil ifFalse: [changeType := (myChangeSet atSelector: (sel := sel asSymbol) class: class). changeType == #remove ifTrue: [^ contents := 'Method has been removed (see versions)']. changeType == #addedThenRemoved ifTrue: [^ contents := 'Added then removed (see versions)']. class ifNil: [^ contents := 'Method was added, but cannot be found!!']. (class includesSelector: sel) ifFalse: [^ contents := 'Method was added, but cannot be found!!']. + contentsAreStyleable := true. contents := class sourceCodeAt: sel. (#(prettyPrint prettyDiffs) includes: contentsSymbol) ifTrue: [contents := class prettyPrinterClass format: contents in: class notifying: nil]. + self showingAnyKindOfDiffs ifTrue: [ + contentsAreStyleable := false. + contents := self diffFromPriorSourceFor: contents]. - self showingAnyKindOfDiffs - ifTrue: [contents := self diffFromPriorSourceFor: contents]. ^ contents := contents asText makeSelectorBoldIn: class] ifTrue: [strm := WriteStream on: (String new: 100). (myChangeSet classChangeAt: (self withoutItemAnnotation: currentClassName)) do: [:each | each = #remove ifTrue: [strm nextPutAll: 'Entire class was removed.'; cr]. each = #addedThenRemoved ifTrue: [strm nextPutAll: 'Class was added then removed.']. each = #rename ifTrue: [strm nextPutAll: 'Class name was changed.'; cr]. each = #add ifTrue: [strm nextPutAll: 'Class definition was added.'; cr]. each = #change ifTrue: [strm nextPutAll: 'Class definition was changed.'; cr]. each = #reorganize ifTrue: [strm nextPutAll: 'Class organization was changed.'; cr]. each = #comment ifTrue: [strm nextPutAll: 'New class comment.'; cr. ]]. ^ contents := strm contents].! Item was changed: + (PackageInfo named: 'Tools') postscript: 'ChangeSorter allSubInstancesDo: [:sorter | + (sorter instVarNamed: ''contentsAreStyleable'') ifNil: [ + sorter instVarNamed: ''contentsAreStyleable'' put: true]].'! - (PackageInfo named: 'Tools') postscript: '(Smalltalk globals at: #ObjectsUnderInspection ifAbsent: [#()]) - do: [:objectUnderInspection | - ToolSet inspect: objectUnderInspection]. - Smalltalk globals removeKey: #ObjectsUnderInspection.'! From commits at source.squeak.org Wed Apr 14 21:41:59 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 14 Apr 2021 21:41:59 0000 Subject: [squeak-dev] The Trunk: Tools-nice.1040.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-nice.1040.mcz ==================== Summary ==================== Name: Tools-nice.1040 Author: nice Time: 14 April 2021, 11:41:49.287889 pm UUID: 30dc2572-5638-c849-a103-cd00af68fca7 Ancestors: Tools-mt.1039, Tools-tcj.834, Tools-mva.748, Tools-ct.1006, Tools-ct.1020, Tools-ct.1031 Merge commit Tools-mt.1039: Complements Kernel-mt.1385 Tools-tcj.834: Add 'alphabetize' to Package Pane Browser's class category menu, as is found on standard Browser. Tools-mva.748: fix selecting a directory in the left pane in a MVC project FileList on Mac and Linux (and it still works on Windows afterwards) Tools-ct.1006: Complements Compiler-ct.449 (CompilationCue in SyntaxErrorNotification). Fixes syntax highlighting in SyntaxError window. Tools-ct.1020: Fixes code styling in change sorters. Tools-ct.1031: Fixes styling in change sorters if no real method is selected. No need to invoke Shout on messages such as "method was removed". =============== Diff against Tools-mt.1039 =============== Item was changed: CodeHolder subclass: #ChangeSorter + instanceVariableNames: 'parent myChangeSet currentClassName currentSelector priorChangeSetList contentsAreStyleable' - instanceVariableNames: 'parent myChangeSet currentClassName currentSelector priorChangeSetList' classVariableNames: '' poolDictionaries: '' category: 'Tools-Changes'! + !ChangeSorter commentStamp: 'ct 3/10/2021 18:24' prior: 0! - !ChangeSorter commentStamp: 'wiz 2/3/2010 23:38' prior: 0! I display a ChangeSet. Two of me are in a DualChangeSorter. aStringOrNil Instance Variables currentClassName: currentSelector: myChangeSet: parent: priorChangeSetList: + contentsAreStyleable currentClassName - string parseable into class-name [class] [class trait] needs to be fitlered by (self withoutItemAnnotation: currentClassName) to remove pakaging note currentSelector - string parseable into selector-name needs to be fitlered by (self withoutItemAnnotation: currentSelector) to remove pakaging note myChangeSet - name of current changeset parent -the dual changesorter that contains this one. Used for dealing with the other half. priorChangeSetList + - holds the current change set list. Used to detect changes in list when a newly generated list no long match the prior list.! - - holds the current change set list. Used to detect changes in list when a newly generated list no long match the prior list. - ! Item was changed: ----- Method: ChangeSorter>>aboutToStyle: (in category 'code pane') ----- aboutToStyle: aStyler "This is a notification that aStyler is about to re-style its text. Set the classOrMetaClass in aStyler, so that identifiers will be resolved correctly. Answer true to allow styling to proceed, or false to veto the styling" + contentsAreStyleable ~= false ifFalse: [^false]. - self isModeStyleable ifFalse: [^false]. - self currentSelector ifNil: [^false]. aStyler classOrMetaClass: self selectedClassOrMetaClass. ^true! Item was changed: ----- Method: ChangeSorter>>buildWith:in:rect: (in category 'toolbuilder') ----- buildWith: builder in: window rect: rect | csListHeight msgListHeight csMsgListHeight listSpec textSpec | contents := ''. csListHeight := 0.25. msgListHeight := 0.25. csMsgListHeight := csListHeight + msgListHeight. listSpec := builder pluggableListSpec new. listSpec model: self; list: #changeSetList; getSelected: #currentCngSet; setSelected: #showChangeSetNamed:; menu: #changeSetMenu:shifted:; keyPress: #changeSetListKey:from:; dragItem: #dragChangeSet:; autoDeselect: false; frame: (((0 at 0 extent: 0.5 at csListHeight) scaleBy: rect extent) translateBy: rect origin). window children add: listSpec. listSpec := builder pluggableListSpec new. listSpec model: self; list: #classList; getSelected: #currentClassName; setSelected: #currentClassName:; menu: #classListMenu:shifted:; keyPress: #classListKey:from:; dragItem: #dragClass:; frame: (((0.5 at 0 extent: 0.5 at csListHeight) scaleBy: rect extent) translateBy: rect origin). window children add: listSpec. listSpec := builder pluggableListSpec new. listSpec model: self; list: #messageList; getSelected: #currentSelector; setSelected: #currentSelector:; menu: #messageMenu:shifted:; keyPress: #messageListKey:from:; dragItem: #dragMessage:; frame: (((0 at csListHeight extent: 1 at msgListHeight) scaleBy: rect extent) translateBy: rect origin). window children add: listSpec. + textSpec := builder pluggableCodePaneSpec new. - textSpec := builder pluggableTextSpec new. textSpec model: self; getText: #contents; setText: #contents:notifying:; selection: #contentsSelection; menu: #codePaneMenu:shifted:; frame: (((0 at csMsgListHeight corner: 1 at 1) scaleBy: rect extent) translateBy: rect origin). window children add: textSpec. ^window! Item was changed: ----- Method: ChangeSorter>>setContents (in category 'code pane') ----- setContents "return the source code that shows in the bottom pane" | sel class strm changeType | self clearUserEditFlag. + contentsAreStyleable := false. myChangeSet ifNil: [^ contents := String empty]. "should not happen but can" currentClassName ifNil: [^ contents := myChangeSet preambleString ifNil: [String empty]]. class := self selectedClassOrMetaClass. (sel := self selectedMessageName) == nil ifFalse: [changeType := (myChangeSet atSelector: (sel := sel asSymbol) class: class). changeType == #remove ifTrue: [^ contents := 'Method has been removed (see versions)']. changeType == #addedThenRemoved ifTrue: [^ contents := 'Added then removed (see versions)']. class ifNil: [^ contents := 'Method was added, but cannot be found!!']. (class includesSelector: sel) ifFalse: [^ contents := 'Method was added, but cannot be found!!']. + contentsAreStyleable := true. contents := class sourceCodeAt: sel. (#(prettyPrint prettyDiffs) includes: contentsSymbol) ifTrue: [contents := class prettyPrinterClass format: contents in: class notifying: nil]. + self showingAnyKindOfDiffs ifTrue: [ + contentsAreStyleable := false. + contents := self diffFromPriorSourceFor: contents]. - self showingAnyKindOfDiffs - ifTrue: [contents := self diffFromPriorSourceFor: contents]. ^ contents := contents asText makeSelectorBoldIn: class] ifTrue: [strm := WriteStream on: (String new: 100). (myChangeSet classChangeAt: (self withoutItemAnnotation: currentClassName)) do: [:each | each = #remove ifTrue: [strm nextPutAll: 'Entire class was removed.'; cr]. each = #addedThenRemoved ifTrue: [strm nextPutAll: 'Class was added then removed.']. each = #rename ifTrue: [strm nextPutAll: 'Class name was changed.'; cr]. each = #add ifTrue: [strm nextPutAll: 'Class definition was added.'; cr]. each = #change ifTrue: [strm nextPutAll: 'Class definition was changed.'; cr]. each = #reorganize ifTrue: [strm nextPutAll: 'Class organization was changed.'; cr]. each = #comment ifTrue: [strm nextPutAll: 'New class comment.'; cr. ]]. ^ contents := strm contents].! Item was changed: ----- Method: FileList>>volumeListIndex: (in category 'volume list and pattern') ----- volumeListIndex: index "Select the volume name having the given index." | delim path | volListIndex := index. index = 1 ifTrue: [self directory: (FileDirectory on: '')] ifFalse: [delim := directory pathNameDelimiter. path := String streamContents: [:strm | 2 to: index do: [:i | strm nextPutAll: (volList at: i) withBlanksTrimmed. i < index ifTrue: [strm nextPut: delim]]]. + self directory: (FileDirectory on: path)]. - self directory: (directory on: path)]. brevityState := #FileList. self addPath: path. self changed: #fileList. self changed: #contents. self updateButtonRow.! Item was changed: ----- Method: PackagePaneBrowser>>mainPackageMenu: (in category 'package list') ----- mainPackageMenu: aMenu "Answer a Menu of operations on class packages to be displayed when the operate menu button is pressed." ^aMenu addList: #( ('find class...' findClass) ('recent classes...' recent) - ('reorganize' editSystemCategories) + ('alphabetize' alphabetizeSystemCategories) + - ('update' updatePackages)); yourself. ! Item was changed: ----- Method: SyntaxError>>aboutToStyle: (in category 'text menu support') ----- aboutToStyle: aStyler aStyler classOrMetaClass: self selectedClassOrMetaClass; + environment: notification environment; + context: notification context; parseAMethod: notification doitFlag not. ^ true! Item was changed: + (PackageInfo named: 'Tools') postscript: 'ChangeSorter allSubInstancesDo: [:sorter | + (sorter instVarNamed: ''contentsAreStyleable'') ifNil: [ + sorter instVarNamed: ''contentsAreStyleable'' put: true]].'! - (PackageInfo named: 'Tools') postscript: '(Smalltalk globals at: #ObjectsUnderInspection ifAbsent: [#()]) - do: [:objectUnderInspection | - ToolSet inspect: objectUnderInspection]. - Smalltalk globals removeKey: #ObjectsUnderInspection.'! From jakres+squeak at gmail.com Wed Apr 14 22:38:23 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Thu, 15 Apr 2021 00:38:23 +0200 Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz In-Reply-To: References: <1618336352701-0.post@n4.nabble.com> Message-ID: Here is my workspace for getting all inbox messages for a start. It downloads the whole archive, which is probably not a good idea for everyone to do it, and could be optimized simply because the inbox has not existed as long as the list. The expressions themselves are also not particularly optimized. The squeak-dev-snapshot.dat file is around 500 MB. My Squeak process takes 2 GB of RAM now though, so I will clear the workspace bindings before saving this image, which I normally use for something else... wc := WebClient new. base := 'http://lists.squeakfoundation.org/pipermail/squeak-dev/'. r := wc httpGet: base. c := r content. m := '"([^"]+)"' asRegex. files := c regex: '\: > Hi Nicolas. > > > I may try to answer a mail that is about 6 month old, but IMO, it does > > not make much sense. > > This mail is not in my client anymore, so it means going thru some > > forum API with extra login etc... > > It's just not acceptable. > > I find both ways manageable. It doesn't take too much time for me. Yet, I > see the benefit of a platform with integrated tools such as GitHub. > > It should be possible to write a small tool (or extension to Monticello) > to make a comment (via e-mail?) on an inbox version using the mailing list > and the matching entry there. No need to move all the data to a new > platform where the tools are --- just add the missing tools. IMO the better > cost-value ratio. ... Any takers? Christoph? :-D > > Best, > Marcel > > Am 13.04.2021 21:08:52 schrieb Nicolas Cellier < > nicolas.cellier.aka.nice at gmail.com>: > Hi Christoph, > yes, I saw that later, > but then decided that your first attempt was OK, some kind of > integrator privilege ;) > If someone has a strong opinion about it, we can change it again, but > IMO it's not worth it. > > The problem with our dev model is that it's been designed with very > short cycles in mind. > Once the contributions are rotting for more than a month or two, it's > very inconvenient to retrieve the messages and discussion from the > mailing list, while reviewing the changes in the image. I personally > skip this step because the process is already too demanding. > Unlike pull/merge requests in github/gitlab, we have no way to let a > review process span multiple months, multiple commits, multiple steps > (understand separate steps for loading into a live image like we do > with MCM update maps), etc... > Answering a mail in a cold thread (2 month later or more) does not > make sense,see an example below... > > We also have to use a 3rd tool for moving the package: the > source.squak.org web interface. > I can guarantee that I have to re-login at each package review (logins > are short lived). > The way our site URL works, it means that I have to retrieve the page > holding the exact version at each re-login. > If 1st package letter is > M, it can be 10 clicks away... > Plus the fact that I'm pretty sure that in the past, some packages > that I previously moved to trunk or treated inbox did reappear in the > inbox, that's somehow discouraging, just put a picture of me and > Marcel faces here > > https://en.wikipedia.org/wiki/Dana%C3%AFdes#/media/File:Danaides_by_John_William_Waterhouse,_1903.jpg > I'm generally satisfied with our lightweight model, except for the > review and integration of inbox contributions. > > As example, yesterday, I wanted to reject > https://source.squeak.org/inbox/Kernel_ct.1366.diff > This is because (result := Compiler evaluate:... ifFail: [^nil]) is > not the same as your proposal: > there is a local return that exit the method in the former case, and > an assignment of result with nil in the later case. > I can see the diff on our site, but cannot add any annotation unlike > github/gitlab. > I may try to answer a mail that is about 6 month old, but IMO, it does > not make much sense. > This mail is not in my client anymore, so it means going thru some > forum API with extra login etc... > It's just not acceptable. > Rejecting without a comment is not acceptable either. > It's not fair for contributors, and not fair to ourselves: the reason > why we reject is more important than the rejection itself: it is also > information reusable for future contributions. > If we really want to stick to our lghtweight model, i suggest that we > add one more commit message when we move some package to treated, > possibly with an automated link to original commit message in some > mailing list. This way, I will have a chance to give some additional > reason for rejection... > > I stop the rant here. Above all, I don't want to restrain the will to > contribute. > Having enthusiastic users overwhelming the inbox with fixes, ideas and > enhancements is not the problem, it's a chance! > Having too few people to perform the review with poor tools is the > problem. We have to do something about it. > In my eyes, the reviews done in the mailing list a few month ago are > dead, they are not easily findable/usable/amendable. > Thanks for bringing the subject, and please, continue to chanllenge us! > Ideas for improving the process are wecome too. > > Le mar. 13 avr. 2021 à 19:52, Christoph Thiede > a écrit : > > > > Hi Nicolas, > > > > actually, ST80-ct.255 should have been moved into the treated inbox in > favor > > of ST80-ct.256 as discussed in the thread. Nevertheless, thanks for > > integrating all these patches! :-) > > > > Best, > > Christoph > > > > > > > > ----- > > Carpe Squeak! > > -- > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Wed Apr 14 23:57:47 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 01:57:47 +0200 Subject: [squeak-dev] Recursive errors Message-ID: Hi all, with the new exception handling, I have encountered some recursive error. Very hard to debug because the stack grows too fast. The origin is when trying to browse revisions of a removed method. I have a: MethodReference >>timestamp receiver: a MethodReference Parser >> #externalFunctionDeclaration UndefinedObject(Object)>>doesNotUnderstand: #timeStamp ... Debugger class>>openOn:context:label:contents:fullView: ... SmalltalkImage>>logError:inContext:to: ... Context>>printDetails: ... [] in Context>>printDetails: Context>>tempsAndValuesLimitedTo:indent: Context>>tempNames Context(InstructionStream)>>debuggerMap CompiledMethod>>debuggerMap receiver: (MCRepository class>>#browseMethodRevisionsService "a CompiledMethod(2459914)") receiver isInstalled ==> false !!! (because I did recompileAll at one point) DebuggerMethodMap class>>forMethod: ... CompiledMethod>>methodNode [source]: a Text for 'Vw6ilbntYC3Kf9Bz3g3T3YJ+J74W7Mmk9gPb... note that the source is broken, I don't know where it comes from, the compiledMethod is not installed... this context will catch SyntaxErrorNotificationSignal ... Parser>>parseCue:noPattern:ifFail: this context will catch ReparseAfterSourceEditing ... SyntaxErrorNotification(Exception)>>signal expected, the source is broken... ... Context>>handleSignal: Context>>handleSignal: ^2 consecutive handleSIgnal: here... the first one (parseCue:noPattern:ifFail:) only catch ReparseAfterSourceEditing the second one (methodNode) does catch our SyntaxErrorNotification on: SyntaxErrorNotification do: [:ex | ex return: self decompileWithTemps] ... CompiledMethod>>decompileWithTemps oh but this one tries to get the tempNames by parsing the source! let's go for a cycle... ... Parser>>parseCue:noPattern:ifFail: this context will catch ReparseAfterSourceEditing ... SyntaxErrorNotification(Exception)>>signal Context>>handleSignal: Context>>handleSignal: Context>>handleSignal: ouch, I have 3 of them now what happens? it's all normal, I now have 2 parseCue:... in the stack catching ReparseAfterSourceEditing the 3rd is catching SyntaxErrorNotification and retries parsing tempNames... and we're back to another cycle. ... tada, there's more than 1000 handleSignal: in the stack when I interrupted the process, and it's impossible to debug, and I thought the new exception handling had a problem... It doesn't so far. We have another problem with broken source for an uninstalled CompiledMethod, that tries to decompile using broken source... I'm happy that I'm not the root cause, but this is most annoying. IMO, if we decompile a block, we might want to find the temp names from the method source, but if we decompile a method, what's the point??? From nicolas.cellier.aka.nice at gmail.com Thu Apr 15 00:02:11 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 02:02:11 +0200 Subject: [squeak-dev] Recursive errors In-Reply-To: References: Message-ID: my snippet for inspecting (part of) the stack: | tmp list i | tmp := sender. list := Array new: 200. i := 0. [tmp sender == nil] whileFalse: [ list atWrap: (i := i+1) put: tmp. tmp := tmp sender]. ^{list. i} The stack was only about 150,000 deep, but our tools do not really scale at this depth... Le jeu. 15 avr. 2021 à 01:57, Nicolas Cellier a écrit : > > Hi all, > with the new exception handling, I have encountered some recursive error. > Very hard to debug because the stack grows too fast. > The origin is when trying to browse revisions of a removed method. > I have a: > > MethodReference >>timestamp > receiver: a MethodReference Parser >> #externalFunctionDeclaration > UndefinedObject(Object)>>doesNotUnderstand: #timeStamp > ... > Debugger class>>openOn:context:label:contents:fullView: > ... > SmalltalkImage>>logError:inContext:to: > ... > Context>>printDetails: > ... > [] in Context>>printDetails: > Context>>tempsAndValuesLimitedTo:indent: > Context>>tempNames > Context(InstructionStream)>>debuggerMap > CompiledMethod>>debuggerMap > receiver: (MCRepository class>>#browseMethodRevisionsService "a > CompiledMethod(2459914)") > receiver isInstalled ==> false !!! (because I did recompileAll at one point) > DebuggerMethodMap class>>forMethod: > ... > CompiledMethod>>methodNode > [source]: a Text for 'Vw6ilbntYC3Kf9Bz3g3T3YJ+J74W7Mmk9gPb... > note that the source is broken, I don't know where it comes from, > the compiledMethod is not installed... > this context will catch SyntaxErrorNotificationSignal > ... > Parser>>parseCue:noPattern:ifFail: > this context will catch ReparseAfterSourceEditing > ... > SyntaxErrorNotification(Exception)>>signal > expected, the source is broken... > ... > Context>>handleSignal: > Context>>handleSignal: > ^2 consecutive handleSIgnal: here... > the first one (parseCue:noPattern:ifFail:) only catch > ReparseAfterSourceEditing > the second one (methodNode) does catch our SyntaxErrorNotification > on: SyntaxErrorNotification > do: [:ex | ex return: self decompileWithTemps] > ... > CompiledMethod>>decompileWithTemps > oh but this one tries to get the tempNames by parsing the source! > let's go for a cycle... > ... > Parser>>parseCue:noPattern:ifFail: > this context will catch ReparseAfterSourceEditing > ... > SyntaxErrorNotification(Exception)>>signal > Context>>handleSignal: > Context>>handleSignal: > Context>>handleSignal: > ouch, I have 3 of them now > what happens? it's all normal, I now have 2 parseCue:... in the > stack catching ReparseAfterSourceEditing > the 3rd is catching SyntaxErrorNotification and retries parsing tempNames... > and we're back to another cycle. > ... > tada, there's more than 1000 handleSignal: in the stack when I > interrupted the process, and it's impossible to debug, and I thought > the new exception handling had a problem... > It doesn't so far. > We have another problem with broken source for an uninstalled > CompiledMethod, that tries to decompile using broken source... > > I'm happy that I'm not the root cause, but this is most annoying. > IMO, if we decompile a block, we might want to find the temp names > from the method source, but if we decompile a method, what's the > point??? From vanessa at codefrau.net Thu Apr 15 00:13:09 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Wed, 14 Apr 2021 17:13:09 -0700 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz In-Reply-To: <53352cd9abea4ff999373cc0b798f00c@student.hpi.uni-potsdam.de> References: <53352cd9abea4ff999373cc0b798f00c@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, Good idea, but is not quite that simple. The image "version number" does not uniquely identify a specific set of package versions. It's not enough to build a similar image again. To have somewhat reproducible builds (they're not bit-identical) you need to store the actual list of loaded package versions. The easiest way to do that would be using an MCM. Only when an explicit config map is deployed that indeed is a "fixed point" with a defined set of packages. MCMcmUpdater normally loads each explicit update map, plus then automatically updates the last map to the latest package versions. That is governed by the useLatestPackagesFrom: method. The latest config map appears to be http://source.squeak.org/trunk/update-mt.485.mcm A method for reproducible builds could take e.g. 'mt.485' as an argument and should produce an image with version number 20313: ((MCRepository trunk versionNamed: 'update-mt.485.mcm') dependencies collect: [:dep | dep versionInfo versionNumber]) sum –Vanessa– On Thu, Apr 8, 2021 at 1:37 PM Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de> wrote: > Please review! :-) > > > A concrete use case I was having in mind for this feature is to allow > arbitrary Squeak Trunk version numbers in smalltalkCI, see: > https://github.com/hpi-swa/smalltalkCI/pull/506 > > At the moment, it is WIP > - an unpolished prototype only, but the idea is that you could specify > something like Squeak64-18242 instead of Squeak64-trunk in the CI/CLI > args. > > Nevertheless, even if the proposal for SCI should get rejected, I think > this is a helpful feature because releases are quite rare in Squeak and I > find it important to tag certain states in the Trunk evolution. > > > To improve support for the SCI PR, I would also like to backport these > changes to 5.3 - there was only a single merge conflict, so if you agree > with this proposal, I can send you a changeset for 5.3. Thanks in advance! > :-) > > Best, > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von commits at source.squeak.org > *Gesendet:* Donnerstag, 8. April 2021 22:30:32 > *An:* squeak-dev at lists.squeakfoundation.org > *Betreff:* [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz > > A new version of MonticelloConfigurations was added to project The Inbox: > http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz > > ==================== Summary ==================== > > Name: MonticelloConfigurations-ct.166 > Author: ct > Time: 8 April 2021, 10:30:30.702818 pm > UUID: 6d887a86-fe0f-8e4c-a878-e40e8e612918 > Ancestors: MonticelloConfigurations-mt.165 > > Adds support in MCMcmUpdater to install updates up to a specified system > version number. This can be helpful when you want to bring an image into an > exact state of an alpha version. I.e., a bug report or a tool can refer to > Squeak6.0 Alpha #19570. Now it's possible to bring your 5.3 image into this > state by evaluating: > > MCMcmUpdater default doUpdate: true upToUpdate: 19570. > > Still, it is possible to install all updates or navigate forward to a > certain upstream version using the existing protocol: > > MCMcmUpdater default doUpdate: true. > MCMcmUpdater default doUpdate: true upTo: 470. > > Detailed changelog (anticlimax): > > - Added 'upToUpdate:' variant of update selectors on MCMcmUpdater. > - Refactored existing update selectors to deduplicate the logic for doing > a complete update (#doUpdate: etc.) versus installing all updates up to an > upstream version (#doUpdate:upTo: etc.). > - Added #currentSystemVersion and #totalSystemVersion on MCConfiguration > to determine the current resp. eventual system version as implied by the > update stream. > - Renamed (+ deprecated) #depsSatisfying:version(s)Do:displayingProgress: > due to misleading use of singular in the block keyword. > - Improved multilingual support for the updater. > - Improved documentation of the update protocol. > > Note that in some situations, a small number of follow-up updates will be > installed that go beyond the specified system version number. This is > caused by interdependencies between the target version and its > postdecessors when a definiton was moved from one package into another one. > See sender of MCReorganizationPreloader. > > =============== Diff against MonticelloConfigurations-mt.165 > =============== > > Item was added: > + ----- Method: MCConfiguration class>>ensureOpenTranscript:during: (in > category 'preferences') ----- > + ensureOpenTranscript: aBoolean during: aBlock > + > + | previous | > + previous := self ensureOpenTranscript. > + self ensureOpenTranscript: aBoolean. > + ^ aBlock ensure: [ > + self ensureOpenTranscript: previous]! > > Item was added: > + ----- Method: MCConfiguration>>currentSystemVersion (in category > 'updating') ----- > + currentSystemVersion > + "Answer the current system version found in my configuration (or > the associated working copy)." > + > + ^ self systemVersionForDeps: (self dependencies > + collect: [:dep | > + dep isFulfilledByAncestors > + ifTrue: [dep versionInfo] > + ifFalse: [dep package workingCopy > ancestors] ] )! > > Item was added: > + ----- Method: > MCConfiguration>>depsSatisfying:upToUpdate:versionsDo:displayingProgress: > (in category 'private') ----- > + depsSatisfying: selectBlock upToUpdate: anIntegerOrNil versionsDo: > versionBlock displayingProgress: progressString > + > + | count selectedVersions cleanWorkingCopies | > + self cacheAllFileNamesDuring: [ > + self repositories do: [ :eachRepository | > + MCRepositoryGroup default addRepository: > eachRepository ]. > + > + "First, download selected versions" > + count := 0. > + selectedVersions := OrderedCollection new. > + self withProgress: progressString in: self dependencies > do: [ :dep | | verName repo | > + verName := dep versionInfo name. > + self class extraProgressInfo ifTrue: > + [ ProgressNotification signal: '' extra: > ('Downloading {1}' translated format: {verName}) ]. > + repo := self repositories > + detect: [ :eachRepository | > eachRepository includesVersionNamed: verName ] > + ifNone: [ self logError: ('Version {1} > not found in any repository' translated format: {verName}). > + self logError: 'Aborting' > translated. > + ^ count ]. > + (selectBlock value: dep) ifTrue: [ | version | > + version := self versionNamed: verName > for: dep from: repo. > + version ifNil: [ self logError: ('Could > not download version {1} from {2}' translated format: {verName. repo > description}). > + self logError: 'Aborting' > translated. > + ^ count ]. > + dep package workingCopy > newRepositoryGroupIfDefault. "fix old working copies" > + dep package workingCopy repositoryGroup > addRepository: repo. > + selectedVersions add: version ] ]. > + > + "Then, process only those definitions that moved from one > package to another, to avoid order dependence" > + cleanWorkingCopies := MCWorkingCopy allManagers select: > + [ :wc | wc modified not and: > + [ selectedVersions anySatisfy: [ :v | wc > package = v package ] ] ]. > + MCReorganizationPreloader preloadMovesBetween: > selectedVersions. > + > + "Finally, load/merge selected versions" > + [:exit | self withProgress: progressString in: > selectedVersions do: [ :version | > + self logUpdate: version package with: version. > + self class extraProgressInfo ifTrue: > + [ ProgressNotification signal: '' extra: > ('Installing {1}' translated format: {version info name}) ]. > + versionBlock value: version. > + count := count + 1. > + anIntegerOrNil ifNotNil: [ > + self currentSystemVersion highestUpdate < > anIntegerOrNil ifFalse: exit. > + self flag: #optimization. "ct: By > customizing the system version computation, we could save redundant version > downloads above. However, because of the preloading stage, this might > become a bit more sophisticated." ] ]. > + ] valueWithExit. > + > + "Clean up packages made dirty by > MCReorganizationPreloader" > + cleanWorkingCopies > + select: [ :wc | wc modified ] > + thenDo: [ :wc | wc checkModified ]. > + ]. > + ^ count! > > Item was changed: > ----- Method: > MCConfiguration>>depsSatisfying:versionDo:displayingProgress: (in category > 'private') ----- > + depsSatisfying: selectBlock versionDo: versionBlock displayingProgress: > progressString > + > + self deprecated. > + ^ self > + depsSatisfying: selectBlock > + versionsDo: versionBlock > + displayingProgress: progressString! > - depsSatisfying: selectBlock versionDo: verBlock displayingProgress: > progressString > - | count selectedVersions cleanWorkingCopies | > - self cacheAllFileNamesDuring: [ > - self repositories do: [ :eachRepository | > - MCRepositoryGroup default addRepository: > eachRepository ]. > - "First, download selected versions" > - count := 0. > - selectedVersions := OrderedCollection new. > - self withProgress: progressString in: self dependencies > do: [ :dep | | verName repo | > - verName := dep versionInfo name. > - self class extraProgressInfo ifTrue: > - [ ProgressNotification signal: '' extra: > 'Downloading ' , verName ]. > - repo := self repositories > - detect: [ :eachRepository | > eachRepository includesVersionNamed: verName ] > - ifNone: [ self logError: 'Version ' , > verName , ' not found in any repository'. > - self logError: 'Aborting'. > - ^ count ]. > - (selectBlock value: dep) ifTrue: [ | version | > - version := self versionNamed: verName > for: dep from: repo. > - version ifNil: [ self logError: 'Could > not download version ' , verName , ' from ' , repo description. > - self logError: 'Aborting'. > - ^ count ]. > - dep package workingCopy > newRepositoryGroupIfDefault. "fix old working copies" > - dep package workingCopy repositoryGroup > addRepository: repo. > - selectedVersions add: version]]. > - "Then, process only those definitions that moved from one > package to another, to avoid order dependence" > - cleanWorkingCopies := MCWorkingCopy allManagers select: > - [ :wc | wc modified not and: > - [ selectedVersions anySatisfy: [ :v | wc > package = v package ] ] ]. > - MCReorganizationPreloader preloadMovesBetween: > selectedVersions. > - "Finally, load/merge selected versions" > - self withProgress: progressString in: selectedVersions > do: [ :version | > - self logUpdate: version package with: version. > - self class extraProgressInfo ifTrue: > - [ ProgressNotification signal: '' extra: > 'Installing ' , version info name ]. > - verBlock value: version. > - count := count + 1 ]. > - "Clean up packages made dirty by > MCReorganizationPreloader" > - cleanWorkingCopies > - select: [ :wc | wc modified ] > - thenDo: [ :wc | wc checkModified ]. > - ]. > - ^ count! > > Item was added: > + ----- Method: > MCConfiguration>>depsSatisfying:versionsDo:displayingProgress: (in category > 'private') ----- > + depsSatisfying: selectBlock versionsDo: versionBlock displayingProgress: > progressString > + > + ^ self > + depsSatisfying: selectBlock > + upToUpdate: nil > + versionsDo: versionBlock > + displayingProgress: progressString! > > Item was changed: > ----- Method: MCConfiguration>>load (in category 'actions') ----- > load > ^self depsSatisfying: [:dep | dep isCurrent not] > + versionsDo: [:ver | ver load] > + displayingProgress: 'loading packages' translated! > - versionDo: [:ver | ver load] > - displayingProgress: 'loading packages' > - ! > > Item was changed: > ----- Method: MCConfiguration>>merge (in category 'actions') ----- > merge > ^self depsSatisfying: [:dep | dep isFulfilledByAncestors not] > + versionsDo: [:ver | ver merge] > + displayingProgress: 'merging packages' translated! > - versionDo: [:ver | ver merge] > - displayingProgress: 'merging packages' > - ! > > Item was changed: > ----- Method: MCConfiguration>>setSystemVersion (in category 'updating') > ----- > setSystemVersion > - "Set the current system version date to the latest date found in > my configuration (or the associated working copy). Also set the highest > update number to the sum of version numbers in my configuration." > > + | newVersion | > + newVersion := self currentSystemVersion. > - | versionNumbers versionDates | > - versionNumbers := self dependencies collect: [:d | > - (d versionInfo name copyAfterLast: $.) asInteger]. > - versionDates := self dependencies collect: [:d | > - d versionInfo date > - ifNil: [d package workingCopy ancestors first > date]]. > SystemVersion current > + date: newVersion date; > + highestUpdate: newVersion highestUpdate.! > - date: versionDates max; > - highestUpdate: versionNumbers sum.! > > Item was added: > + ----- Method: MCConfiguration>>systemVersionForDeps: (in category > 'updating') ----- > + systemVersionForDeps: dependencies > + "Answer the system version that will be reached by loading the > passed dependencies." > + > + | versionNumbers versionDates | > + versionNumbers := dependencies collect: [:dep | > + dep isCollection > + ifFalse: [dep name versionNumber] > + ifTrue: [(dep collect: [:version | > + version name versionNumber]) > + ifEmpty: [0] > + ifNotEmpty: #max]]. > + versionDates := dependencies with: self dependencies collect: > [:dep :originalDep | > + (dep isCollection ifFalse: [dep date]) > + ifNil: [originalDep package workingCopy ancestors > + ifEmpty: [nil] > + ifNotEmpty: [:ancestors | > ancestors first date]]]. > + > + ^ SystemVersion new > + date: ((versionDates copyWithout: nil) > + ifEmpty: [nil] > + ifNotEmpty: #max); > + highestUpdate: versionNumbers sum! > > Item was added: > + ----- Method: MCConfiguration>>totalSystemVersion (in category > 'updating') ----- > + totalSystemVersion > + "Answer the total system version that will be reached by > upgrading the receiver." > + > + ^ self systemVersionForDeps: (self dependencies collect: > #versionInfo)! > > Item was changed: > ----- Method: MCConfiguration>>upgrade (in category 'actions') ----- > upgrade > + > + ^ self upgradeUpToUpdate: nil! > - ^self depsSatisfying: > - [:dep | dep isFulfilledByAncestors not] > - versionDo: > - [:ver | > - (self class upgradeIsMerge and: [ver shouldMerge]) > - ifFalse: [ver load] > - ifTrue: > - [[ver merge] > - on: MCNoChangesException > - do: [:req| req resume ] > - on: > MCMergeResolutionRequest > - do: [:request | > - request merger > conflicts isEmpty > - ifTrue: > [request resume: true] > - ifFalse: > [request pass]] > - on: Deprecation > - do: [:req| req resume ]]] > - displayingProgress: 'upgrading packages'! > > Item was added: > + ----- Method: MCConfiguration>>upgradeUpToUpdate: (in category > 'actions') ----- > + upgradeUpToUpdate: anIntegerOrNil > + > + ^ self > + depsSatisfying: [:dep | > + dep isFulfilledByAncestors not] > + upToUpdate: anIntegerOrNil > + versionsDo: [:ver | > + (self class upgradeIsMerge and: [ver shouldMerge]) > + ifFalse: [ver load] > + ifTrue: > + [[ver merge] > + on: MCNoChangesException > + do: [:req | req resume ] > + on: > MCMergeResolutionRequest > + do: [:request | > + request merger > conflicts isEmpty > + ifTrue: > [request resume: true] > + ifFalse: > [request pass]] > + on: Deprecation > + do: [:req | req resume ]]] > + displayingProgress: 'upgrading packages' translated! > > Item was added: > + ----- Method: MCMcmUpdater>>basicDoUpdate:do: (in category 'updating') > ----- > + basicDoUpdate: interactive do: aBlock > + "Update the image by evaluating aBlock. If this is the default > updater for the system, update the system version when complete. If > interactive, use a modal notifier, otherwise only update the transcript. > Flush all caches. If a previous download failed, this is often helpful." > + > + | config previousUpdateLevel | > + previousUpdateLevel := SystemVersion current highestUpdate. > + MCFileBasedRepository flushAllCaches. > + > + MCConfiguration ensureOpenTranscript: interactive during: [ > + config := aBlock value. > + > + config ifNil: [ > + interactive ifTrue: [^ self inform: 'Unable to > retrieve updates from remote repository.' translated]. > + Transcript cr; show: '========== Unable to > retrieve updates from remote repository. ==========' translated; cr. > + ^ self ]. > + > + MCMcmUpdater default == self > + ifTrue: [ > + config setSystemVersion. > + interactive ifTrue: [ > + self inform: (self > updateMessageFor: previousUpdateLevel)]. > + Transcript cr; > + show: '========== Update > completed: ' translated; > + show: previousUpdateLevel; > + show: ' -> ' ; > + show: SystemVersion current > highestUpdate; > + show: ' =========='; cr ] > + ifFalse: [ > + interactive > + ifTrue: [ self inform: 'Update > completed.' ]. > + Transcript cr; show: '========== Update > completed. ==========' translated; cr ] ].! > > Item was added: > + ----- Method: MCMcmUpdater>>basicUpdateFromRepositories:do: (in category > 'updating') ----- > + basicUpdateFromRepositories: repositoryUrls do: repositoryBlock > + > + | repos config | > + MCConfiguration upgradeIsMerge: true. > + "The list of repositories to consult in order" > + repos := repositoryUrls collect: [:url| > + MCRepositoryGroup default repositories > + detect: [:repo | repo description = url] > + ifNone: [ | repo | > + repo := MCHttpRepository location: url. > + MCRepositoryGroup default addRepository: > repo. > + repo]]. > + > + "The list of updates-author.version.mcm sorted by version" > + repos do: [:repo | > + config := repositoryBlock value: repo]. > + ^ config! > > Item was added: > + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:thenDo: (in > category 'updating') ----- > + basicUpdateFromRepository: aRepository thenDo: configBlock > + > + ^ self > + basicUpdateFromRepository: aRepository > + whileUpdatesSatisfy: [true] > + upToUpdate: nil > + thenDo: configBlock! > > Item was added: > + ----- Method: > MCMcmUpdater>>basicUpdateFromRepository:whileUpdatesSatisfy:upToUpdate:thenDo: > (in category 'updating') ----- > + basicUpdateFromRepository: aRepository whileUpdatesSatisfy: updateBlock > upToUpdate: anIntegerOrNil thenDo: configBlock > + > + | config | > + aRepository cacheAllFileNamesDuring: [ | updateList | > + updateList := self updateListFor: aRepository. > + "Proceed only if there are updates available at all." > + updateList ifNotEmpty: [ > + updateList := self refreshUpdateMapFor: > aRepository with: updateList. > + "Now process each update file. Check if we have > all dependencies and if not, load the entire configuration (this is mostly > to skip older updates quickly)" > + [:exit | updateList > + do: [:assoc | > + (updateBlock cull: assoc key > cull: assoc value) ifFalse: exit. > + ProgressNotification signal: '' > extra: ('Processing {1}' translated format: {assoc value}). > + config := aRepository > versionNamed: assoc value. > + anIntegerOrNil ifNotNil: [ > + config > currentSystemVersion highestUpdate <= anIntegerOrNil ifFalse: exit]. > + self updateFromConfig: config > upToUpdate: anIntegerOrNil. > + anIntegerOrNil ifNotNil: [ > + config > currentSystemVersion highestUpdate < config totalSystemVersion > highestUpdate ifTrue: exit]. > + self lastUpdateMap at: > aRepository description put: assoc key] > + displayingProgress: 'Processing > configurations' translated] valueWithExit. > + configBlock cull: config]]. > + ^ config! > > Item was changed: > ----- Method: MCMcmUpdater>>doUpdate: (in category 'updating') ----- > doUpdate: interactive > + "Update the image by loading all pending updates from the server." > - "Update the image by loading all pending updates from the server. > If this is > - the default updater for the system, update the system version > when complete. > - If interteractive use a modal notifier, otherwise only update the > transcript. > - Flush all caches. If a previous download failed this is often > helpful" > > + ^ self basicDoUpdate: interactive do: [ > + self updateFromRepository ]! > - | config previousUpdateLevel ensureTranscriptSetting | > - previousUpdateLevel := SystemVersion current highestUpdate. > - MCFileBasedRepository flushAllCaches. > - ensureTranscriptSetting := MCConfiguration ensureOpenTranscript. > - [ MCConfiguration ensureOpenTranscript: interactive. > - config := self updateFromRepository. > - config ifNil: [ > - interactive ifTrue: [ ^self inform: 'Unable to retrieve > updates from remote repository.' translated ]. > - Transcript cr; show: '========== Unable to retrieve > updates from remote repository. ==========' translated; cr. > - ^ self ]. > - MCMcmUpdater default == self > - ifTrue: [ > - config setSystemVersion. > - interactive ifTrue: [ > - self inform: (self updateMessageFor: > previousUpdateLevel)]. > - Transcript cr; > - show: '========== Update completed: ' > translated; > - show: previousUpdateLevel; > - show: ' -> ' ; > - show: SystemVersion current highestUpdate; > - show: ' =========='; cr ] > - ifFalse: [ > - interactive > - ifTrue: [ self inform: 'Update > completed.' ]. > - Transcript cr; show: '========== Update > completed. ==========' translated; cr ] ] > - ensure: [ MCConfiguration ensureOpenTranscript: > ensureTranscriptSetting]. > - > - ! > > Item was changed: > ----- Method: MCMcmUpdater>>doUpdate:upTo: (in category 'updating') ----- > doUpdate: interactive upTo: versionNumber > + "Update the image by loading all pending updates from the server > until update stream with the specified version number has been processed." > - "Update the image by loading all pending updates from the server. > If this is > - the default updater for the system, update the system version > when complete. > - If interteractive use a modal notifier, otherwise only update the > transcript. > - Flush all caches. If a previous download failed this is often > helpful" > > + ^ self basicDoUpdate: interactive do: [ > + self updateFromRepositories: {self repository} upTo: > versionNumber ]! > - | config previousUpdateLevel | > - previousUpdateLevel := SystemVersion current highestUpdate. > - MCFileBasedRepository flushAllCaches. > - config := self updateFromRepositories: { self repository } upTo: > versionNumber. > - config ifNil: [ > - interactive ifTrue: [ ^self inform: 'Unable to retrieve > updates from remote repository.' translated ]. > - Transcript cr; show: '========== Unable to retrieve > updates from remote repository. ==========' translated; cr. > - ^ self ]. > - MCMcmUpdater default == self > - ifTrue: [ > - config setSystemVersion. > - interactive ifTrue: [ > - self inform: (self updateMessageFor: > previousUpdateLevel)]. > - Transcript cr; > - show: '========== Update completed: ' > translated; > - show: previousUpdateLevel; > - show: ' -> ' ; > - show: SystemVersion current highestUpdate; > - show: ' =========='; cr ] > - ifFalse: [ > - interactive > - ifTrue: [ self inform: 'Update > completed.' ]. > - Transcript cr; show: '========== Update > completed. ==========' translated; cr ] > - ! > > Item was added: > + ----- Method: MCMcmUpdater>>doUpdate:upToUpdate: (in category > 'updating') ----- > + doUpdate: interactive upToUpdate: anIntegerOrNil > + "Update the image by loading all pending updates from the server > until the system version has reached at least anInteger. If anInteger is > nil, install all available updates." > + > + ^ self basicDoUpdate: interactive do: [ > + self updateFromRepositories: {self repository} > upToUpdate: anIntegerOrNil ]! > > Item was changed: > ----- Method: MCMcmUpdater>>doUpdateUpTo: (in category 'updating') ----- > doUpdateUpTo: versionNumber > + "Update the image by loading all pending updates from the server > until update stream with the specified version number has been processed." > - "Update the image by loading all pending updates from the server. > If this is > - the default updater for the system, update the system version > when complete. > - Flush all caches. If a previous download failed this is often > helpful" > > ^self doUpdate: true upTo: versionNumber > ! > > Item was changed: > ----- Method: MCMcmUpdater>>updateFromConfig: (in category 'updating') > ----- > updateFromConfig: config > > + ^ self updateFromConfig: config upToUpdate: nil! > - "Skip packages that were specifically unloaded" > - config dependencies: (config dependencies > - reject: [:dep| self class skipPackages includes: dep > package name]). > - self class updateMissingPackages ifFalse:[ > - "Skip packages that are not in the image" > - config dependencies: (config dependencies > - select: [:dep| dep package hasWorkingCopy])]. > - (config dependencies allSatisfy:[:dep| dep isFulfilled]) > - ifFalse:[config upgrade]. > - ! > > Item was added: > + ----- Method: MCMcmUpdater>>updateFromConfig:upToUpdate: (in category > 'updating') ----- > + updateFromConfig: config upToUpdate: anIntegerOrNil > + > + "Skip packages that were specifically unloaded" > + config dependencies: (config dependencies > + reject: [:dep | self class skipPackages includes: dep > package name]). > + self class updateMissingPackages ifFalse: [ > + "Skip packages that are not in the image" > + config dependencies: (config dependencies > + select: [:dep | dep package hasWorkingCopy])]. > + (config dependencies allSatisfy: [:dep | dep isFulfilled]) > + ifFalse: [config upgradeUpToUpdate: anIntegerOrNil].! > > Item was changed: > ----- Method: MCMcmUpdater>>updateFromRepositories:upTo: (in category > 'updating') ----- > updateFromRepositories: repositoryUrls upTo: versionNumber > + " > + MCMcmUpdater default updateFromRepositories: #(' > http://squeaksource.com/MCUpdateTest') upTo: 3 > + " > - "MCMcmUpdater updateFromRepositories: #( > - 'http://squeaksource.com/MCUpdateTest' > - )" > > + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | > + self updateFromRepository: repo upTo: versionNumber]! > - | repos config | > - MCConfiguration upgradeIsMerge: true. > - "The list of repositories to consult in order" > - repos := repositoryUrls collect:[:url| > - MCRepositoryGroup default repositories > - detect:[:r| r description = url] > - ifNone:[ | r | > - r := MCHttpRepository location: url user: > '' password: ''. > - MCRepositoryGroup default addRepository: > r. > - r]]. > - > - "The list of updates-author.version.mcm sorted by version" > - repos do:[ :r | config := self updateFromRepository: r upTo: > versionNumber]. > - ^config! > > Item was added: > + ----- Method: MCMcmUpdater>>updateFromRepositories:upToUpdate: (in > category 'updating') ----- > + updateFromRepositories: repositoryUrls upToUpdate: anIntegerOrNil > + " > + MCMcmUpdater default updateFromRepositories: #(' > http://squeaksource.com/MCUpdateTest') upToUpdate: 2130 > + " > + > + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | > + self updateFromRepository: repo upToUpdate: > anIntegerOrNil ]! > > Item was changed: > ----- Method: MCMcmUpdater>>updateFromRepository (in category > 'updating') ----- > updateFromRepository > > + ^ self updateFromRepository: self > getRepositoryFromRepositoryGroup! > - | config repo | > - repo := self getRepositoryFromRepositoryGroup. > - repo cacheAllFileNamesDuring: [ | updateList | > - updateList := self updateListFor: repo. > - "Proceed only if there are updates available at all." > - updateList ifNotEmpty: [ > - updateList := self refreshUpdateMapFor: repo > with: updateList. > - "Now process each update file. Check if we have > all dependencies and if not, > - load the entire configuration (this is mostly to > skip older updates quickly)" > - updateList do:[:assoc| > - ProgressNotification signal: '' extra: > 'Processing ', assoc value. > - config := repo versionNamed: assoc value. > - self updateFromConfig: config. > - self lastUpdateMap at: repo description > put: assoc key. > - ] displayingProgress: 'Processing configurations'. > - "We've loaded all the provided update > configurations. > - Use the latest configuration to update all the > remaining packages." > - (self useLatestPackagesFrom: repo) ifTrue: [ > - config updateFromRepositories. > - config upgrade]. > - ]]. > - ^ config > - ! > > Item was added: > + ----- Method: MCMcmUpdater>>updateFromRepository: (in category > 'updating') ----- > + updateFromRepository: aRepository > + > + ^ self basicUpdateFromRepository: aRepository thenDo: [:config | > + "We've loaded all the provided update configurations. Use > the latest configuration to update all the remaining packages." > + (self useLatestPackagesFrom: aRepository) ifTrue: [ > + config updateFromRepositories. > + config upgrade]]! > > Item was changed: > ----- Method: MCMcmUpdater>>updateFromRepository:upTo: (in category > 'updating') ----- > + updateFromRepository: aRepository upTo: versionNumber > - updateFromRepository: repository upTo: versionNumber > > + ^ self > + basicUpdateFromRepository: aRepository > + whileUpdatesSatisfy: [:updateVersion | updateVersion <= > versionNumber] > + upToUpdate: nil > + thenDo: []! > - | config | > - repository cacheAllFileNamesDuring: [ | updateList | > - updateList := self updateListFor: repository. > - "Proceed only if there are updates available at all." > - updateList ifNotEmpty: [ > - updateList := self refreshUpdateMapFor: > repository with: updateList. > - "Now process each update file. Check if we have > all dependencies and if not, > - load the entire configuration (this is mostly to > skip older updates quickly)" > - updateList do:[:assoc| > - assoc key > versionNumber ifTrue: > [^config]. > - ProgressNotification signal: '' extra: > 'Processing ', assoc value. > - config := repository versionNamed: assoc > value. > - self updateFromConfig: config. > - self lastUpdateMap at: repository > description put: assoc key. > - ] displayingProgress: 'Processing configurations'. > - ]]. > - ^config > - ! > > Item was added: > + ----- Method: MCMcmUpdater>>updateFromRepository:upToUpdate: (in > category 'updating') ----- > + updateFromRepository: aRepository upToUpdate: anIntegerOrNil > + > + ^ self > + basicUpdateFromRepository: aRepository > + whileUpdatesSatisfy: [true] > + upToUpdate: anIntegerOrNil > + thenDo: []! > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Apr 15 00:20:45 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 00:20:45 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1387.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1387.mcz ==================== Summary ==================== Name: Kernel-nice.1387 Author: nice Time: 15 April 2021, 2:20:34.212568 am UUID: 523bbb98-def1-bc48-8cb0-d2a1038a180e Ancestors: Kernel-nice.1386 Workaround recursive SyntaxErrorNotification occurring when trying to decompile broken source. We shouldn't have broken source, but if we have, we shouldn't exhaust memory and crash the VM while trying to open a Debugger. =============== Diff against Kernel-nice.1386 =============== Item was changed: ----- Method: CompiledMethod>>decompileWithTemps (in category 'decompiling') ----- decompileWithTemps "Return the decompiled parse tree that represents self, but with the temp names obtained either by compiling the sourcecode, or directly if the method has temps in its trailer." | class selector tempNames source | class := self methodClass ifNil: [Object]. selector := self selector ifNil: [self defaultSelector]. self holdsTempNames ifTrue: [tempNames := self tempNamesString] ifFalse: [| compiler | "No source file or no source (e.g. doits) and no temp names -- decompile without temp names " ((self fileIndex > 0 and: [(SourceFiles at: self fileIndex) isNil]) or: [(source := self getSourceFromFile) isNil]) ifTrue: [^self decompile]. compiler := class newCompiler. compiler parser encoderClass: self encoderClass. + tempNames := [(compiler - tempNames := (compiler parse: source asString in: class notifying: nil) generate: CompiledMethodTrailer empty; + schematicTempNamesString] on: SyntaxErrorNotification do: [:ex | nil]. + tempNames ifNil: ["broken source, give up tempNames" ^self decompile]]. - schematicTempNamesString]. ^(self decompilerClass new withTempNames: tempNames) decompile: selector in: class method: self methodForDecompile! From lewis at mail.msen.com Thu Apr 15 02:31:28 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Wed, 14 Apr 2021 22:31:28 -0400 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: References: <74DDA3D0-E109-440B-A794-415EC59E47D5@gmx.de> <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> <20210412205610.GA33248@shell.msen.com> Message-ID: <20210415023128.GA96590@shell.msen.com> On Wed, Apr 14, 2021 at 10:30:24AM +0200, Marcel Taeumel wrote: > Hi Dave, > > you could just add another version. No need to modify dtl.1225 :-) > Sorry, too late to do that now. But in case future readers of this list archive are interested, the discussion on squeak-dev is here: http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-April/214699.html The motivating issue for Seaside is: https://github.com/SeasideSt/Seaside/issues/1195 Dave > Best, > Marcel > Am 12.04.2021 22:56:16 schrieb David T. Lewis : > On Mon, Apr 12, 2021 at 08:43:45AM +0200, Marcel Taeumel wrote: > > > > > Am 12.04.2021 um 04:11 schrieb David T. Lewis : > > > > > > > > > On Sun, Apr 11, 2021 at 05:01:31PM +0200, Nicolas Cellier wrote: > > >> Hi all, > > >> it seems we have enough +1, let's just do it. > > >> > > > > > > Done. > > > > Hi Dave. > > > > Thanks. Maybe also add a pointer to the discussion on this list. > > > > Hi Marcel, > > Yes, I should have added a link to the discussion. I could save a > fixed System-dtl.1225 to trunk, although I am afraid it may cause > problems for the update stream for people who have already loaded > that version number with a different UUID in their trunk update. > > If someone can confirm that it is safe to replace the existing > System-dtl.1225 with another one that differs only by commit comment > and UUID, then I'll copy it up to trunk. Otherwise I think I'll > play it safe and leave it alone. > > Thanks, > Dave > > > From marcel.taeumel at hpi.de Thu Apr 15 07:39:57 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 15 Apr 2021 09:39:57 +0200 Subject: [squeak-dev] The Trunk: MorphicTests-nice.75.mcz In-Reply-To: References: Message-ID: Hi Nicolas. Thanks. We might want to think about a more generic way to specify system-wide preferences for tests. Maybe a new feature in TestCase (or SUnit). While I would never want to change such preferences in a specific test, I also see that the setUp-way (with that extra "reset" instVar) is quite cumbersome. Best, Marcel Am 14.04.2021 19:14:23 schrieb commits at source.squeak.org : Nicolas Cellier uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-nice.75.mcz ==================== Summary ==================== Name: MorphicTests-nice.75 Author: nice Time: 14 April 2021, 7:14:06.997889 pm UUID: d87c50dd-4e44-5242-9120-37e0452ca781 Ancestors: MorphicTests-eem.74 Fix loss of useRetractableScrollBars preference =============== Diff against MorphicTests-eem.74 =============== Item was changed: ----- Method: TableLayoutTest>>setUp (in category 'running') ----- setUp super setUp. - reset := { ([:enable | [self useRetractableScrollBars: enable]] value: self useRetractableScrollBars) + }. + self useRetractableScrollBars: false! - in: [:block | self useRetractableScrollBars: false]. - }.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Apr 15 07:47:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 07:47:15 0000 Subject: [squeak-dev] The Trunk: Kernel-jar.1386.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-jar.1386.mcz ==================== Summary ==================== Name: Kernel-jar.1386 Author: jar Time: 12 April 2021, 10:53:49.66946 pm UUID: 26cd98dc-59f6-0043-aa73-732e8144cf25 Ancestors: Kernel-nice.1384 Superseds Kernel-jar.1385 adding a little tweak and a comment; otherwise identical (Fix a list of termination bugs described in http://forum.world.st/Solving-multiple-termination-bugs-summary-amp-proposal-td5128285.html) =============== Diff against Kernel-nice.1384 =============== Item was changed: ----- Method: Process>>isSuspended (in category 'testing') ----- isSuspended + "A process is suspended if it is not active, not terminated and + not waiting in a scheduler or a semaphore queue." + + self isActiveProcess ifTrue: [^ false]. + ^myList isNil and: [self isTerminated not]! - "A process is suspended if it has been suspended with the suspend primitive. - It is distinguishable from the active process and a terminated process by - having a non-nil suspendedContext that is either not the bottom context - or has not reached its endPC." - ^nil == myList - and: [nil ~~ suspendedContext - and: [suspendedContext isBottomContext - ifTrue: [suspendedContext closure - ifNil: [suspendedContext methodClass ~~ Process - or: [suspendedContext selector ~~ #terminate]] - ifNotNil: [suspendedContext pc < suspendedContext closure endPC]] - ifFalse: [true]]]! Item was changed: ----- Method: Process>>isTerminated (in category 'testing') ----- isTerminated + "Answer if the receiver is terminated. A process is considered terminated + if the suspendedContext is the bottomContext and the pc is at the endPC" + - "Answer if the receiver is terminated, or at least terminating." self isActiveProcess ifTrue: [^ false]. + ^suspendedContext isNil or: [ + suspendedContext isBottomContext and: [ + suspendedContext isDead or: [suspendedContext atEnd]]]! - ^suspendedContext isNil - or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess. - If so, and the pc is at the endPC, the block has already sent and returned - from value and there is nothing more to do." - suspendedContext isBottomContext - and: [suspendedContext closure - ifNil: [suspendedContext methodClass == Process - and: [suspendedContext selector == #terminate]] - ifNotNil: [suspendedContext pc >= suspendedContext closure endPC]]]! Item was changed: ----- Method: Process>>terminate (in category 'changing process state') ----- terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating. If the process is in the middle of a critical: critical section, release it properly." + | ctxt unwindBlock oldList outerMost | + self isActiveProcess ifTrue: [ + "If terminating the active process, suspend it first and terminate it as a suspended process." + [self terminate] fork. + ^self suspend]. - | ctxt unwindBlock oldList | - self isActiveProcess ifTrue: - [ctxt := thisContext. - [ctxt := ctxt findNextUnwindContextUpTo: nil. - ctxt ~~ nil] whileTrue: - [(ctxt tempAt: 2) ifNil: - ["N.B. Unlike Context>>unwindTo: we do not set complete (tempAt: 2) to true." - unwindBlock := ctxt tempAt: 1. - thisContext terminateTo: ctxt. - unwindBlock value]]. - thisContext terminateTo: nil. - self suspend. - "If the process is resumed this will provoke a cannotReturn: error. - Would self debug: thisContext title: 'Resuming a terminated process' be better?" - ^self]. "Always suspend the process first so it doesn't accidentally get woken up. N.B. If oldList is a LinkedList then the process is runnable. If it is a Semaphore/Mutex et al then the process is blocked, and if it is nil then the process is already suspended." oldList := self suspend. suspendedContext ifNotNil: ["Release any method marked with the pragma. The argument is whether the process is runnable." self releaseCriticalSection: (oldList isNil or: [oldList class == LinkedList]). + "If terminating a process halfways through an unwind, try to complete that unwind block first; + if there are multiple such nested unwind blocks, try to complete the outer-most one; the inner + blocks will be completed in the process." + ctxt := suspendedContext. + [(ctxt := ctxt findNextUnwindContextUpTo: nil) isNil] whileFalse: + "Contexts under evaluation have already set their complete (tempAt: 2) to true." + [(ctxt tempAt:2) ifNotNil: [outerMost := ctxt]]. + outerMost ifNotNil: [ + "This is the outer-most unwind context currently under evaluation; + let's find an inner context executing outerMost's argument block (tempAt: 1)" + (suspendedContext findContextSuchThat: [:ctx | + ctx closure == (outerMost tempAt: 1)]) ifNotNil: [:inner | + "Let's finish the unfinished unwind context only (i.e. up to inner) and return here" + suspendedContext runUntilErrorOrReturnFrom: inner. + "Update the receiver's suspendedContext (the previous step reset its sender to nil); + return, if the execution stack reached its bottom (e.g. in case of non-local returns)." + (suspendedContext := outerMost sender) ifNil: [^self]]]. - "If terminating a process halfways through an unwind, try to complete that unwind block first." - (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: - [:outer| - (suspendedContext findContextSuchThat:[:c| c closure == (outer tempAt: 1)]) ifNotNil: - [:inner| "This is an unwind block currently under evaluation" - suspendedContext runUntilErrorOrReturnFrom: inner]]. + "Now all unwind blocks caught halfway through have been completed; + let's execute the ones still pending. Note: #findNextUnwindContextUpTo: starts + searching from the receiver's sender but the receiver itself may be an unwind context." + ctxt := suspendedContext. + ctxt isUnwindContext ifFalse: [ctxt := ctxt findNextUnwindContextUpTo: nil]. + [ctxt isNil] whileFalse: [ + (ctxt tempAt: 2) ifNil: [ + ctxt tempAt: 2 put: true. + unwindBlock := ctxt tempAt: 1. + "Create a context for the unwind block and execute it on the unwind block's stack. + Note: using #value instead of #runUntilErrorOrReturnFrom: would lead to executing + the unwind on the wrong stack preventing the correct execution of non-local returns." + suspendedContext := unwindBlock asContextWithSender: ctxt. + suspendedContext runUntilErrorOrReturnFrom: suspendedContext]. + ctxt := ctxt findNextUnwindContextUpTo: nil]. + + "Reset the context's pc and sender to nil for the benefit of isTerminated." + suspendedContext terminate]! - ctxt := self popTo: suspendedContext bottomContext. - ctxt == suspendedContext bottomContext ifFalse: - [self debugWithTitle: 'Unwind error during termination' translated full: false]. - "Set the context to its endPC for the benefit of isTerminated." - ctxt pc: ctxt endPC]! From commits at source.squeak.org Thu Apr 15 07:51:06 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 07:51:06 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1388.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1388.mcz ==================== Summary ==================== Name: Kernel-nice.1388 Author: nice Time: 15 April 2021, 9:51:03.805015 am UUID: fafa2e33-6cf3-4999-a032-82c58be72905 Ancestors: Kernel-nice.1387, Kernel-jar.1386 Merge Kernel-jar.1386 Fix a list of termination bugs described in http://forum.world.st/Solving-multiple-termination-bugs-summary-amp-proposal-td5128285.html =============== Diff against Kernel-nice.1387 =============== Item was changed: ----- Method: Process>>isSuspended (in category 'testing') ----- isSuspended + "A process is suspended if it is not active, not terminated and + not waiting in a scheduler or a semaphore queue." + + self isActiveProcess ifTrue: [^ false]. + ^myList isNil and: [self isTerminated not]! - "A process is suspended if it has been suspended with the suspend primitive. - It is distinguishable from the active process and a terminated process by - having a non-nil suspendedContext that is either not the bottom context - or has not reached its endPC." - ^nil == myList - and: [nil ~~ suspendedContext - and: [suspendedContext isBottomContext - ifTrue: [suspendedContext closure - ifNil: [suspendedContext methodClass ~~ Process - or: [suspendedContext selector ~~ #terminate]] - ifNotNil: [suspendedContext pc < suspendedContext closure endPC]] - ifFalse: [true]]]! Item was changed: ----- Method: Process>>isTerminated (in category 'testing') ----- isTerminated + "Answer if the receiver is terminated. A process is considered terminated + if the suspendedContext is the bottomContext and the pc is at the endPC" + - "Answer if the receiver is terminated, or at least terminating." self isActiveProcess ifTrue: [^ false]. + ^suspendedContext isNil or: [ + suspendedContext isBottomContext and: [ + suspendedContext isDead or: [suspendedContext atEnd]]]! - ^suspendedContext isNil - or: ["If the suspendedContext is the bottomContext it is the block in Process>>newProcess. - If so, and the pc is at the endPC, the block has already sent and returned - from value and there is nothing more to do." - suspendedContext isBottomContext - and: [suspendedContext closure - ifNil: [suspendedContext methodClass == Process - and: [suspendedContext selector == #terminate]] - ifNotNil: [suspendedContext pc >= suspendedContext closure endPC]]]! Item was changed: ----- Method: Process>>terminate (in category 'changing process state') ----- terminate "Stop the process that the receiver represents forever. Unwind to execute pending ensure:/ifCurtailed: blocks before terminating. If the process is in the middle of a critical: critical section, release it properly." + | ctxt unwindBlock oldList outerMost | + self isActiveProcess ifTrue: [ + "If terminating the active process, suspend it first and terminate it as a suspended process." + [self terminate] fork. + ^self suspend]. - | ctxt unwindBlock oldList | - self isActiveProcess ifTrue: - [ctxt := thisContext. - [ctxt := ctxt findNextUnwindContextUpTo: nil. - ctxt ~~ nil] whileTrue: - [(ctxt tempAt: 2) ifNil: - ["N.B. Unlike Context>>unwindTo: we do not set complete (tempAt: 2) to true." - unwindBlock := ctxt tempAt: 1. - thisContext terminateTo: ctxt. - unwindBlock value]]. - thisContext terminateTo: nil. - self suspend. - "If the process is resumed this will provoke a cannotReturn: error. - Would self debug: thisContext title: 'Resuming a terminated process' be better?" - ^self]. "Always suspend the process first so it doesn't accidentally get woken up. N.B. If oldList is a LinkedList then the process is runnable. If it is a Semaphore/Mutex et al then the process is blocked, and if it is nil then the process is already suspended." oldList := self suspend. suspendedContext ifNotNil: ["Release any method marked with the pragma. The argument is whether the process is runnable." self releaseCriticalSection: (oldList isNil or: [oldList class == LinkedList]). + "If terminating a process halfways through an unwind, try to complete that unwind block first; + if there are multiple such nested unwind blocks, try to complete the outer-most one; the inner + blocks will be completed in the process." + ctxt := suspendedContext. + [(ctxt := ctxt findNextUnwindContextUpTo: nil) isNil] whileFalse: + "Contexts under evaluation have already set their complete (tempAt: 2) to true." + [(ctxt tempAt:2) ifNotNil: [outerMost := ctxt]]. + outerMost ifNotNil: [ + "This is the outer-most unwind context currently under evaluation; + let's find an inner context executing outerMost's argument block (tempAt: 1)" + (suspendedContext findContextSuchThat: [:ctx | + ctx closure == (outerMost tempAt: 1)]) ifNotNil: [:inner | + "Let's finish the unfinished unwind context only (i.e. up to inner) and return here" + suspendedContext runUntilErrorOrReturnFrom: inner. + "Update the receiver's suspendedContext (the previous step reset its sender to nil); + return, if the execution stack reached its bottom (e.g. in case of non-local returns)." + (suspendedContext := outerMost sender) ifNil: [^self]]]. - "If terminating a process halfways through an unwind, try to complete that unwind block first." - (suspendedContext findNextUnwindContextUpTo: nil) ifNotNil: - [:outer| - (suspendedContext findContextSuchThat:[:c| c closure == (outer tempAt: 1)]) ifNotNil: - [:inner| "This is an unwind block currently under evaluation" - suspendedContext runUntilErrorOrReturnFrom: inner]]. + "Now all unwind blocks caught halfway through have been completed; + let's execute the ones still pending. Note: #findNextUnwindContextUpTo: starts + searching from the receiver's sender but the receiver itself may be an unwind context." + ctxt := suspendedContext. + ctxt isUnwindContext ifFalse: [ctxt := ctxt findNextUnwindContextUpTo: nil]. + [ctxt isNil] whileFalse: [ + (ctxt tempAt: 2) ifNil: [ + ctxt tempAt: 2 put: true. + unwindBlock := ctxt tempAt: 1. + "Create a context for the unwind block and execute it on the unwind block's stack. + Note: using #value instead of #runUntilErrorOrReturnFrom: would lead to executing + the unwind on the wrong stack preventing the correct execution of non-local returns." + suspendedContext := unwindBlock asContextWithSender: ctxt. + suspendedContext runUntilErrorOrReturnFrom: suspendedContext]. + ctxt := ctxt findNextUnwindContextUpTo: nil]. + + "Reset the context's pc and sender to nil for the benefit of isTerminated." + suspendedContext terminate]! - ctxt := self popTo: suspendedContext bottomContext. - ctxt == suspendedContext bottomContext ifFalse: - [self debugWithTitle: 'Unwind error during termination' translated full: false]. - "Set the context to its endPC for the benefit of isTerminated." - ctxt pc: ctxt endPC]! From commits at source.squeak.org Thu Apr 15 07:58:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 07:58:40 0000 Subject: [squeak-dev] The Trunk: KernelTests-nice.402.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.402.mcz ==================== Summary ==================== Name: KernelTests-nice.402 Author: nice Time: 15 April 2021, 9:58:38.391678 am UUID: 5a87f120-bb53-462e-afb4-162791294c16 Ancestors: KernelTests-nice.401 Replay (some) changes of KernelTests-ct.395 Tests simulation of #perform:... primitives 83, 84, and 100. Reuploaded to add another fixture for the mirror primitive variant of primitive 100. Corrected order of assertion arguments. =============== Diff against KernelTests-nice.401 =============== Item was changed: ----- Method: ContextTest>>testPrimitive100 (in category 'tests') ----- testPrimitive100 { {#isNil. {}. Object}. "valid 0-arg message" {#=. {true}. UndefinedObject}. "valid unary message" {#ifNil:ifNotNil:. {[2]. [:x | x]}. Object}. "valid binary message" + {{}. #=. {true}. SequenceableCollection}. "mirror primitive" {#isNil}. "missing arguments" {#isNil. 'not an array'}. "invalid arguments" {#isNil. {}}. "missing lookupClass" {#isNil. {'excess arg'}. Object}. "too many arguments" {#=. {}. UndefinedObject}. "missing argument" {#isNil. {}. Boolean}. "lookupClass not in inheritance chain" } do: [:args | self + assert: (nil tryPrimitive: 100 withArgs: args) + equals: (Context runSimulated: [nil tryPrimitive: 100 withArgs: args])].! - assert: (Context runSimulated: [nil tryPrimitive: 100 withArgs: args]) - equals: (nil tryPrimitive: 100 withArgs: args)].! Item was changed: ----- Method: ContextTest>>testPrimitive83 (in category 'tests') ----- testPrimitive83 { {#isNil}. "valid 0-arg message" {#=. true}. "valid unary message" {#ifNil:ifNotNil:. [2]. [:x | x]}. "valid binary message" {#isNil. 'excess arg'}. "too many arguments" {#=}. "missing argument" } do: [:args | self + assert: (nil tryPrimitive: 83 withArgs: args) + equals: (Context runSimulated: [nil tryPrimitive: 83 withArgs: args])].! - assert: (Context runSimulated: [nil tryPrimitive: 83 withArgs: args]) - equals: (nil tryPrimitive: 83 withArgs: args)].! Item was changed: ----- Method: ContextTest>>testPrimitive84 (in category 'tests') ----- testPrimitive84 { {#isNil. {}}. "valid 0-arg message" {#=. {true}}. "valid unary message" {#ifNil:ifNotNil:. {[2]. [:x | x]}}. "valid binary message" {#isNil}. "missing arguments" {#isNil. 'not an array'}. "invalid arguments" {#isNil. {'excess arg'}}. "too many arguments" {#=. {}}. "missing argument" } do: [:args | self + assert: (nil tryPrimitive: 84 withArgs: args) + equals: (Context runSimulated: [nil tryPrimitive: 84 withArgs: args])].! - assert: (Context runSimulated: [nil tryPrimitive: 84 withArgs: args]) - equals: (nil tryPrimitive: 84 withArgs: args)].! From marcel.taeumel at hpi.de Thu Apr 15 08:02:19 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 15 Apr 2021 10:02:19 +0200 Subject: [squeak-dev] The Inbox: Collections-mt.938.mcz In-Reply-To: References: Message-ID: Hi Levente. > It would be great to change OrderedCollection class >> #new: to return a > non-empty collection, and create a new method, e.g. #newWithCapacity: to > create an empty collection with the given capacity, but I don't think it's > possible to do that without breaking almost all existing programs out > there. I agree, given that most implementations of #new: cover array-like structures and thus expose the idea of "capacity" in client code. From personal experience, I tried, occasionally, to be clever ^_^ and pre-allocate some capacity in an OrderedCollection via #new:. Yet, I would not generalize this kind of anti-pattern. Maybe such a change would not be as severe as you fear. At least not for OrderedCollection. (Collection allSubclasses sorted: [:a :b | a name <= b name]) collect: [:each | each -> ([(each new: 10) size] ifError: [:m | m])] as: OrderedDictionary. Here are the results: 21x Error 27x 0 40x 10 1x 100 (Matrix) So, it looks like that your feeling is right. For Trunk, we could easily check whether the #new: cases cover the "0" or the "10". I suspect the latter because Array. For MethodDictionary, you added a #newForCapacity: in 2011. :-)  > So, the question is: should there be #collect:as:separatedBy: too? Yeah, looks like it. I will add it to the inbox. Best, Marcel Am 14.04.2021 19:17:55 schrieb Levente Uzonyi : Hi Marcel, Due to the flaw of OrderedCollection >> #new:, the code won't work with OrderedCollections (and its subclasses). This is the same issue Tim found with OrderedCollection and #streamContents: the other day. The current workaround is to use #ofSize: instead of #new: to create a non-empty instance with the given capacity. It would be great to change OrderedCollection class >> #new: to return a non-empty collection, and create a new method, e.g. #newWithCapacity: to create an empty collection with the given capacity, but I don't think it's possible to do that without breaking almost all existing programs out there. The code won't work with LinkedList either because of the same reason. So, that class will need its own implementation. The code also suffers from #collect:'s problem, which is its reliance on #species. #species is used for way too many things, and a single method cannot fit all those roles. The fix for that is #collect:as:, which lets the user decide what the class of the result should be. So, the question is: should there be #collect:as:separatedBy: too? Levente On Wed, 14 Apr 2021, commits at source.squeak.org wrote: > A new version of Collections was added to project The Inbox: > http://source.squeak.org/inbox/Collections-mt.938.mcz > > ==================== Summary ==================== > > Name: Collections-mt.938 > Author: mt > Time: 14 April 2021, 2:38:21.265628 pm > UUID: d109bde4-42a6-e840-803c-e4e80b98a74d > Ancestors: Collections-mt.937 > > Proposal. Add a #joinSeparatedBy: that does not end up as a string. > > The current alternative would be #gather > (#(1 2 3 4 5) gather: [:each | {each . $x}]) allButLast. > > Not sure whether a non-sequenceable version in Collection makes sense. We have had that discussion about #join etc. being not useful for uncertain output order. > > Some benchmarks: > > [ ((1 to: 1000) gather: [:num | {num . $x}]) allButLast ] bench. > '22,000 per second. 45.5 microseconds per run. 13.09738 % GC time.' > > [ (1 to: 1000) collect: [:num | num] separatedBy: [$x] ] bench. > '26,000 per second. 38.5 microseconds per run. 1.73965 % GC time.' > > =============== Diff against Collections-mt.937 =============== > > Item was added: > + ----- Method: Collection>>collect:separatedBy: (in category 'enumerating') ----- > + collect: elementBlock separatedBy: separatorBlock > + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." > + > + | newCollection | > + newCollection := self species new. > + self > + do: [:each | newCollection add: (elementBlock value: each)] > + separatedBy: [:each | newCollection add: separatorBlock value]. > + ^ newCollection! > > Item was added: > + ----- Method: SequenceableCollection>>collect:separatedBy: (in category 'enumerating') ----- > + collect: elementBlock separatedBy: separatorBlock > + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." > + > + | newCollection | > + newCollection := self species new: self size *2 -1. > + 1 to: self size do: [:index | > + index = 1 ifFalse: [newCollection at: (index-1 *2) put: separatorBlock value]. > + newCollection at: (index-1 *2)+1 put: (elementBlock value: (self at: index))]. > + ^ newCollection! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Apr 15 08:10:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 08:10:37 0000 Subject: [squeak-dev] The Inbox: Collections-mt.942.mcz Message-ID: A new version of Collections was added to project The Inbox: http://source.squeak.org/inbox/Collections-mt.942.mcz ==================== Summary ==================== Name: Collections-mt.942 Author: mt Time: 15 April 2021, 10:10:36.948715 am UUID: 663ded23-ec3c-44bf-9e67-8fe2384b94cc Ancestors: Collections-ul.940, Collections-mt.938 Updates the proposal with "as:" to let clients configure the collection class if #species does not fit. Thanks Levente (ul) for the tip! (Also merges from Collections-ul.940, which is current in Trunk.) =============== Diff against Collections-ul.940 =============== Item was added: + ----- Method: Collection>>collect:as:separatedBy: (in category 'enumerating') ----- + collect: elementBlock as: aClass separatedBy: separatorBlock + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." + + | newCollection | + newCollection := aClass new. + self + do: [:each | newCollection add: (elementBlock value: each)] + separatedBy: [:each | newCollection add: separatorBlock value]. + ^ newCollection! Item was added: + ----- Method: Collection>>collect:separatedBy: (in category 'enumerating') ----- + collect: elementBlock separatedBy: separatorBlock + + ^ self + collect: elementBlock + as: self species + separatedBy: separatorBlock! Item was added: + ----- Method: SequenceableCollection>>collect:as:separatedBy: (in category 'enumerating') ----- + collect: elementBlock as: aClass separatedBy: separatorBlock + "Evaluate the elementBlock for all elements in the receiver, and evaluate the separatorBlock between. Collect the resulting values of both blocks into a collection like the receiver. Answer the new collection." + + | newCollection | + newCollection := aClass ofSize: self size *2 -1. + 1 to: self size do: [:index | + index = 1 ifFalse: [newCollection at: (index-1 *2) put: separatorBlock value]. + newCollection at: (index-1 *2)+1 put: (elementBlock value: (self at: index))]. + ^ newCollection! From tonyg at leastfixedpoint.com Thu Apr 15 08:11:43 2021 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Thu, 15 Apr 2021 10:11:43 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: <14d442f8-badb-ac7e-3c08-1a586f9d58dd@leastfixedpoint.com> Hi everyone, I think I'd like to run for the board this year. I'm particularly interested in topics such as - actors and concurrency - namespacing and isolation - virtualization and securable image-to-image communication - data serialization formats (like JSON etc) - DSLs but recently I've also been working on making Squeak the heart of a prototype cellphone platform, involving the above but also supporting new input devices (e.g. multitouch touchscreen on Linux) and dealing with process management, Linux kernel APIs etc. Basically, I'm interested in the "operating system" side of Smalltalk. If I'm elected, I'd like to put my energy toward that general area. However, I've also got quite a bit of experience in infrastructure setup, care, and feeding, so I can contribute there also. Tony From marcel.taeumel at hpi.de Thu Apr 15 08:27:46 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 15 Apr 2021 10:27:46 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <14d442f8-badb-ac7e-3c08-1a586f9d58dd@leastfixedpoint.com> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <14d442f8-badb-ac7e-3c08-1a586f9d58dd@leastfixedpoint.com> Message-ID: Hi Tony! This is great! ^__^ Thank you. Best, Marcel Am 15.04.2021 10:11:52 schrieb Tony Garnock-Jones : Hi everyone, I think I'd like to run for the board this year. I'm particularly interested in topics such as - actors and concurrency - namespacing and isolation - virtualization and securable image-to-image communication - data serialization formats (like JSON etc) - DSLs but recently I've also been working on making Squeak the heart of a prototype cellphone platform, involving the above but also supporting new input devices (e.g. multitouch touchscreen on Linux) and dealing with process management, Linux kernel APIs etc. Basically, I'm interested in the "operating system" side of Smalltalk. If I'm elected, I'd like to put my energy toward that general area. However, I've also got quite a bit of experience in infrastructure setup, care, and feeding, so I can contribute there also. Tony -------------- next part -------------- An HTML attachment was scrubbed... URL: From giovanni at corriga.net Thu Apr 15 08:31:04 2021 From: giovanni at corriga.net (Giovanni Corriga) Date: Thu, 15 Apr 2021 09:31:04 +0100 Subject: [squeak-dev] UK Smalltalk User Group meeting - Wednesday April 28th Message-ID: The next meeting of the UK Smalltalk User Group will be on Wednesday, April 28th. Esteban Lorenzano will give us an update on Pharo: What's new? What is updated? What remains? This talk will present (and show working!) the Pharo 9 roadmap and principal changes made to Pharo since the release of the previous version. Esteban studied Computer Sciences at Universidad de Buenos Aires, and worked since 1994 in many object-oriented and low-level technologies in different software companies, serving in various positions from junior programmer to senior architect. In 2007 he co-founded Smallworks to offer Pharo-based agile development projects. Since 2012 he dedicated full time to developing the Pharo code and community. He works for the Pharo Consortium in Lille, France, as lead developer for Pharo and being responsible with the coordination of new releases and the implementation and maintenance of several Pharo libraries.Given the current COVID-19 restrictions, this will be an online meeting from home. If you'd like to join us, please sign up in advance on the meeting's Meetup page ( https://www.meetup.com/UKSTUG/events/cbklbryccgblc/ ) to receive the meeting details. Don’t forget to bring your laptop and drinks! -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Thu Apr 15 08:47:43 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 10:47:43 +0200 Subject: [squeak-dev] status of inbox Kernel-ct.1363 Message-ID: Hi all, again a good and difficult to analyze contribution. We mostly send runSimulated:contextAtEachStep: to thisContext, except in one case in base image: MessageTally tallySends: [3.14159 printString] This is effectively broken in trunk, and repaired after applying Kernel-ct.1363. Before I merge this, additional advice is welcome, this is a tough subject, breaking the Debugger would be the last thing we want to do. From marcel.taeumel at hpi.de Thu Apr 15 09:05:14 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 15 Apr 2021 11:05:14 +0200 Subject: [squeak-dev] status of inbox Kernel-ct.1363 In-Reply-To: References: Message-ID: Hi Nicolas, ct.1363 depends on ct.1362, the latter being easier to review. Maybe Christoph (ct) can point us to the "request" he mentioned in the message in 1363. Yet, it looks like Eliot (indirectly) approved this already: http://forum.world.st/The-Inbox-Kernel-ct-1362-mcz-tp5124354.html [http://forum.world.st/The-Inbox-Kernel-ct-1362-mcz-tp5124354.html] ..? Or at least he planned to look at this. (Let's hope that the words "branch commit" do not hide more dependencies. Not sure what it means here.) Best, Marcel Am 15.04.2021 10:48:09 schrieb Nicolas Cellier : Hi all, again a good and difficult to analyze contribution. We mostly send runSimulated:contextAtEachStep: to thisContext, except in one case in base image: MessageTally tallySends: [3.14159 printString] This is effectively broken in trunk, and repaired after applying Kernel-ct.1363. Before I merge this, additional advice is welcome, this is a tough subject, breaking the Debugger would be the last thing we want to do. -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Apr 15 09:29:53 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 09:29:53 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.290.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.290.mcz ==================== Summary ==================== Name: MorphicExtras-mt.290 Author: mt Time: 15 April 2021, 11:29:51.330715 am UUID: c43262a2-89ba-472b-8ad0-ad46d4e87412 Ancestors: MorphicExtras-mt.289 Merges Morphic-ct.1557 and 1558 into MorphicExtras. This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-mt.289 =============== Item was added: + ----- Method: LineMorph class>>exampleBackArrow (in category '*MorphicExtras-examples') ----- + exampleBackArrow + "LineMorph exampleBackArrow openInHand" + + ^ (LineMorph from: 12 @ 0 to: 0 @ 0 color: Color black width: 1) + makeForwardArrow; + yourself! Item was added: + ----- Method: SketchMorph class>>exampleMouseUpAction (in category '*MorphicExtras-examples') ----- + exampleMouseUpAction + "SketchMorph exampleMouseUpAction openInWorld" + + ^ (self withForm: Form squeakLogo) + addMouseUpActionWith: 'self inform: ''Carpe Squeak!!'''; + yourself! From commits at source.squeak.org Thu Apr 15 09:46:33 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 09:46:33 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.291.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.291.mcz ==================== Summary ==================== Name: MorphicExtras-mt.291 Author: mt Time: 15 April 2021, 11:46:31.400208 am UUID: a73067c7-c5a4-4d20-9981-c11affd02c65 Ancestors: MorphicExtras-mt.290, MorphicExtras-ct.260 Merges MorphicExtras-ct.260 with the updated postscript to update all existing instances of FrameRateMorph. =============== Diff against MorphicExtras-mt.290 =============== Item was changed: StringMorph subclass: #FrameRateMorph + instanceVariableNames: 'lastDisplayTime framesSinceLastDisplay updateInterval mSecsPerFrame framesPerSec' - instanceVariableNames: 'lastDisplayTime framesSinceLastDisplay' classVariableNames: '' poolDictionaries: '' category: 'MorphicExtras-Demo'! Item was added: + ----- Method: FrameRateMorph>>framesPerSec (in category 'accessing') ----- + framesPerSec + + ^ framesPerSec! Item was changed: ----- Method: FrameRateMorph>>initialize (in category 'initialization') ----- initialize "initialize the state of the receiver" super initialize. "" + lastDisplayTime := TimeStamp new. - lastDisplayTime := 0. framesSinceLastDisplay := 0. + self updateInterval: 500 milliSeconds. self font: (Preferences standardMenuFont emphasized: 1). ! Item was added: + ----- Method: FrameRateMorph>>mSecsPerFrame (in category 'accessing') ----- + mSecsPerFrame + + ^ mSecsPerFrame! Item was changed: ----- Method: FrameRateMorph>>step (in category 'stepping and presenter') ----- step "Compute and display (every half second or so) the current framerate" + | now timePassed newContents | - | now mSecs mSecsPerFrame framesPerSec newContents | framesSinceLastDisplay := framesSinceLastDisplay + 1. + now := TimeStamp now. + timePassed := now - lastDisplayTime. + (timePassed > self updateInterval) ifTrue: + [| mSecs | + mSecs := timePassed asMilliSeconds. + mSecsPerFrame := mSecs // framesSinceLastDisplay. - now := Time millisecondClockValue. - mSecs := now - lastDisplayTime. - (mSecs > 500 or: [mSecs < 0 "clock wrap-around"]) ifTrue: - [mSecsPerFrame := mSecs // framesSinceLastDisplay. framesPerSec := (framesSinceLastDisplay * 1000) // mSecs. newContents := mSecsPerFrame printString, ' mSecs (', framesPerSec printString, ' frame', (framesPerSec = 1 ifTrue: [''] ifFalse: ['s']), '/sec)'. self contents: newContents. lastDisplayTime := now. framesSinceLastDisplay := 0] ifFalse: ["Ensure at least one pixel is drawn per frame" Preferences higherPerformance ifTrue: [self invalidRect: (self position extent: 1 at 1)]]! Item was added: + ----- Method: FrameRateMorph>>updateInterval (in category 'accessing') ----- + updateInterval + + ^ updateInterval! Item was added: + ----- Method: FrameRateMorph>>updateInterval: (in category 'accessing') ----- + updateInterval: aNumber + + updateInterval := aNumber! Item was changed: + (PackageInfo named: 'MorphicExtras') postscript: 'FrameRateMorph allSubInstances do: [:frm | | wasStepping | + wasStepping := frm isStepping. + wasStepping ifTrue: [frm stopStepping]. + frm + instVarNamed: #lastDisplayTime + put: DateAndTime now; + updateInterval: 500 milliSeconds. + wasStepping ifTrue: [frm startStepping]].'! - (PackageInfo named: 'MorphicExtras') postscript: 'TrashCanMorph preserveTrash: Preferences preserveTrash. - TrashCanMorph slideDismissalsToTrash: Preferences slideDismissalsToTrash. - - Preferences removePreference: #preserveTrash. - Preferences removePreference: #slideDismissalsToTrash.'! From commits at source.squeak.org Thu Apr 15 09:47:08 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 09:47:08 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.260.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.260.mcz ==================== Summary ==================== Name: MorphicExtras-ct.260 Author: ct Time: 4 September 2019, 3:53:54.175698 pm UUID: cab65f78-e646-cc40-9d0f-c16114d1bb44 Ancestors: MorphicExtras-mt.259 Refactor FrameRateMorph: Add accessors for updateInterval and expose measure data. Use TimeStamp instead of Time to avoid clock wrap around. =============== Diff against MorphicExtras-mt.259 =============== Item was changed: StringMorph subclass: #FrameRateMorph + instanceVariableNames: 'lastDisplayTime framesSinceLastDisplay updateInterval mSecsPerFrame framesPerSec' - instanceVariableNames: 'lastDisplayTime framesSinceLastDisplay' classVariableNames: '' poolDictionaries: '' category: 'MorphicExtras-Demo'! Item was added: + ----- Method: FrameRateMorph>>framesPerSec (in category 'accessing') ----- + framesPerSec + + ^ framesPerSec! Item was changed: ----- Method: FrameRateMorph>>initialize (in category 'initialization') ----- initialize "initialize the state of the receiver" super initialize. "" + lastDisplayTime := TimeStamp new. - lastDisplayTime := 0. framesSinceLastDisplay := 0. + self updateInterval: 500 milliSeconds. self font: (Preferences standardMenuFont emphasized: 1). ! Item was added: + ----- Method: FrameRateMorph>>mSecsPerFrame (in category 'accessing') ----- + mSecsPerFrame + + ^ mSecsPerFrame! Item was changed: ----- Method: FrameRateMorph>>step (in category 'stepping and presenter') ----- step "Compute and display (every half second or so) the current framerate" + | now timePassed newContents | - | now mSecs mSecsPerFrame framesPerSec newContents | framesSinceLastDisplay := framesSinceLastDisplay + 1. + now := TimeStamp now. + timePassed := now - lastDisplayTime. + (timePassed > self updateInterval) ifTrue: + [| mSecs | + mSecs := timePassed asMilliSeconds. + mSecsPerFrame := mSecs // framesSinceLastDisplay. - now := Time millisecondClockValue. - mSecs := now - lastDisplayTime. - (mSecs > 500 or: [mSecs < 0 "clock wrap-around"]) ifTrue: - [mSecsPerFrame := mSecs // framesSinceLastDisplay. framesPerSec := (framesSinceLastDisplay * 1000) // mSecs. newContents := mSecsPerFrame printString, ' mSecs (', framesPerSec printString, ' frame', (framesPerSec = 1 ifTrue: [''] ifFalse: ['s']), '/sec)'. self contents: newContents. lastDisplayTime := now. framesSinceLastDisplay := 0] ifFalse: ["Ensure at least one pixel is drawn per frame" Preferences higherPerformance ifTrue: [self invalidRect: (self position extent: 1 at 1)]]! Item was added: + ----- Method: FrameRateMorph>>updateInterval (in category 'accessing') ----- + updateInterval + + ^ updateInterval! Item was added: + ----- Method: FrameRateMorph>>updateInterval: (in category 'accessing') ----- + updateInterval: aNumber + + updateInterval := aNumber! From nicolas.cellier.aka.nice at gmail.com Thu Apr 15 09:50:50 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 11:50:50 +0200 Subject: [squeak-dev] status of inbox Kernel-ct.1363 In-Reply-To: References: Message-ID: With the merge commit that would make 3 commits for a single method. My plan is to cherry pick the change on top of trunk with proper comment. With our tools, ownership is preserved anyway :) Le jeu. 15 avr. 2021 à 11:05, Marcel Taeumel a écrit : > Hi Nicolas, > > ct.1363 depends on ct.1362, the latter being easier to review. Maybe > Christoph (ct) can point us to the "request" he mentioned in the message in > 1363. Yet, it looks like Eliot (indirectly) approved this already: > http://forum.world.st/The-Inbox-Kernel-ct-1362-mcz-tp5124354.html ..? Or > at least he planned to look at this. > > (Let's hope that the words "branch commit" do not hide more dependencies. > Not sure what it means here.) > > Best, > Marcel > > Am 15.04.2021 10:48:09 schrieb Nicolas Cellier < > nicolas.cellier.aka.nice at gmail.com>: > Hi all, > again a good and difficult to analyze contribution. > We mostly send runSimulated:contextAtEachStep: to thisContext, except > in one case in base image: > > MessageTally tallySends: [3.14159 printString] > > This is effectively broken in trunk, and repaired after applying > Kernel-ct.1363. > Before I merge this, additional advice is welcome, this is a tough > subject, breaking the Debugger would be the last thing we want to do. > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Thu Apr 15 09:52:13 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 11:52:13 +0200 Subject: [squeak-dev] status of inbox Kernel-ct.1363 In-Reply-To: References: Message-ID: I mean authorship... Le jeu. 15 avr. 2021 à 11:50, Nicolas Cellier < nicolas.cellier.aka.nice at gmail.com> a écrit : > With the merge commit that would make 3 commits for a single method. My > plan is to cherry pick the change on top of trunk with proper comment. With > our tools, ownership is preserved anyway :) > > Le jeu. 15 avr. 2021 à 11:05, Marcel Taeumel a > écrit : > >> Hi Nicolas, >> >> ct.1363 depends on ct.1362, the latter being easier to review. Maybe >> Christoph (ct) can point us to the "request" he mentioned in the message in >> 1363. Yet, it looks like Eliot (indirectly) approved this already: >> http://forum.world.st/The-Inbox-Kernel-ct-1362-mcz-tp5124354.html ..? Or >> at least he planned to look at this. >> >> (Let's hope that the words "branch commit" do not hide more dependencies. >> Not sure what it means here.) >> >> Best, >> Marcel >> >> Am 15.04.2021 10:48:09 schrieb Nicolas Cellier < >> nicolas.cellier.aka.nice at gmail.com>: >> Hi all, >> again a good and difficult to analyze contribution. >> We mostly send runSimulated:contextAtEachStep: to thisContext, except >> in one case in base image: >> >> MessageTally tallySends: [3.14159 printString] >> >> This is effectively broken in trunk, and repaired after applying >> Kernel-ct.1363. >> Before I merge this, additional advice is welcome, this is a tough >> subject, breaking the Debugger would be the last thing we want to do. >> >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Thu Apr 15 11:07:27 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 15 Apr 2021 13:07:27 +0200 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz In-Reply-To: References: <53352cd9abea4ff999373cc0b798f00c@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, as Vanessa explained, updates up to a specific MCM in the current update map might work. This also would not apply to cross-release/trunk updates in general. But might work most of the time since we rarely update release repositories. Since we now also have comments in MCMs, a user might actually be able to pick the desired MCM from a list of not-yet-loaded ones. (Hmm... maybe approximating a list of versions from interpolating the build version between two MCMs might work ...) Best, Marcel Am 15.04.2021 02:13:34 schrieb Vanessa Freudenberg : Hi Christoph, Good idea, but is not quite that simple. The image "version number" does not uniquely identify a specific set of package versions. It's not enough to build a similar image again. To have somewhat reproducible builds (they're not bit-identical) you need to store the actual list of loaded package versions. The easiest way to do that would be using an MCM. Only when an explicit config map is deployed that indeed is a "fixed point" with a defined set of packages. MCMcmUpdater normally loads each explicit update map, plus then automatically updates the last map to the latest package versions. That is governed by the useLatestPackagesFrom: method. The latest config map appears to be http://source.squeak.org/trunk/update-mt.485.mcm [http://source.squeak.org/trunk/update-mt.485.mcm] A method for reproducible builds could take e.g. 'mt.485' as an argument and should produce an image with version number 20313: ((MCRepository trunk versionNamed: 'update-mt.485.mcm') dependencies collect: [:dep | dep versionInfo versionNumber]) sum –Vanessa– On Thu, Apr 8, 2021 at 1:37 PM Thiede, Christoph wrote: Please review! :-) A concrete use case I was having in mind for this feature is to allow arbitrary Squeak Trunk version numbers in smalltalkCI, see: https://github.com/hpi-swa/smalltalkCI/pull/506 [https://github.com/hpi-swa/smalltalkCI/pull/506] [https://github.com/hpi-swa/smalltalkCI/pull/506]At the moment, it is WIP - an unpolished prototype only, but the idea is that you could specify something like Squeak64-18242 instead of Squeak64-trunk in the CI/CLI args. Nevertheless, even if the proposal for SCI should get rejected, I think this is a helpful feature because releases are quite rare in Squeak and I find it important to tag certain states in the Trunk evolution. [http://www.hpi.de/] To improve support for the SCI PR, I would also like to backport these changes to 5.3 - there was only a single merge conflict, so if you agree with this proposal, I can send you a changeset for 5.3. Thanks in advance! :-) Best, Christoph Von: Squeak-dev im Auftrag von commits at source.squeak.org [mailto:commits at source.squeak.org] Gesendet: Donnerstag, 8. April 2021 22:30:32 An: squeak-dev at lists.squeakfoundation.org [mailto:squeak-dev at lists.squeakfoundation.org] Betreff: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz   A new version of MonticelloConfigurations was added to project The Inbox: http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz [http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz] ==================== Summary ==================== Name: MonticelloConfigurations-ct.166 Author: ct Time: 8 April 2021, 10:30:30.702818 pm UUID: 6d887a86-fe0f-8e4c-a878-e40e8e612918 Ancestors: MonticelloConfigurations-mt.165 Adds support in MCMcmUpdater to install updates up to a specified system version number. This can be helpful when you want to bring an image into an exact state of an alpha version. I.e., a bug report or a tool can refer to Squeak6.0 Alpha #19570. Now it's possible to bring your 5.3 image into this state by evaluating:         MCMcmUpdater default doUpdate: true upToUpdate: 19570. Still, it is possible to install all updates or navigate forward to a certain upstream version using the existing protocol:         MCMcmUpdater default doUpdate: true.         MCMcmUpdater default doUpdate: true upTo: 470. Detailed changelog (anticlimax): - Added 'upToUpdate:' variant of update selectors on MCMcmUpdater. - Refactored existing update selectors to deduplicate the logic for doing a complete update (#doUpdate: etc.) versus installing all updates up to an upstream version (#doUpdate:upTo: etc.). - Added #currentSystemVersion and #totalSystemVersion on MCConfiguration to determine the current resp. eventual system version as implied by the update stream. - Renamed (+ deprecated) #depsSatisfying:version(s)Do:displayingProgress: due to misleading use of singular in the block keyword. - Improved multilingual support for the updater. - Improved documentation of the update protocol. Note that in some situations, a small number of follow-up updates will be installed that go beyond the specified system version number. This is caused by interdependencies between the target version and its postdecessors when a definiton was moved from one package into another one. See sender of MCReorganizationPreloader. =============== Diff against MonticelloConfigurations-mt.165 =============== Item was added: + ----- Method: MCConfiguration class>>ensureOpenTranscript:during: (in category 'preferences') ----- + ensureOpenTranscript: aBoolean during: aBlock + +        | previous | +        previous := self ensureOpenTranscript. +        self ensureOpenTranscript: aBoolean. +        ^ aBlock ensure: [ +                self ensureOpenTranscript: previous]! Item was added: + ----- Method: MCConfiguration>>currentSystemVersion (in category 'updating') ----- + currentSystemVersion +        "Answer the current system version found in my configuration (or the associated working copy)." + +        ^ self systemVersionForDeps: (self dependencies +                collect: [:dep | +                        dep isFulfilledByAncestors +                                ifTrue: [dep versionInfo] +                                ifFalse: [dep package workingCopy ancestors] ] )! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:upToUpdate:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock upToUpdate: anIntegerOrNil versionsDo: versionBlock displayingProgress: progressString + +        | count selectedVersions cleanWorkingCopies | +        self cacheAllFileNamesDuring: [ +                self repositories do: [ :eachRepository | +                        MCRepositoryGroup default addRepository: eachRepository ]. +                +                "First, download selected versions" +                count := 0. +                selectedVersions := OrderedCollection new. +                self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | +                        verName := dep versionInfo name. +                        self class extraProgressInfo ifTrue: +                                [ ProgressNotification signal: '' extra: ('Downloading {1}' translated format: {verName}) ]. +                        repo := self repositories +                                detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] +                                ifNone:  [ self logError: ('Version {1} not found in any repository' translated format: {verName}). +                                        self logError: 'Aborting' translated. +                                        ^ count ]. +                        (selectBlock value: dep) ifTrue: [ | version | +                                version := self versionNamed: verName for: dep from: repo. +                                version ifNil: [ self logError: ('Could not download version {1} from {2}' translated format: {verName. repo description}). +                                        self logError: 'Aborting' translated. +                                        ^ count ]. +                                dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" +                                dep package workingCopy repositoryGroup addRepository: repo. +                                selectedVersions add: version ] ]. +                +                "Then, process only those definitions that moved from one package to another, to avoid order dependence" +                cleanWorkingCopies := MCWorkingCopy allManagers select: +                        [ :wc | wc modified not and: +                                [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. +                MCReorganizationPreloader preloadMovesBetween: selectedVersions. +                +                "Finally, load/merge selected versions" +                [:exit | self withProgress: progressString in: selectedVersions do: [ :version | +                        self logUpdate: version package with: version. +                        self class extraProgressInfo ifTrue: +                                [ ProgressNotification signal: '' extra: ('Installing {1}' translated format: {version info name}) ]. +                        versionBlock value: version. +                        count := count + 1. +                        anIntegerOrNil ifNotNil: [ +                                self currentSystemVersion highestUpdate < anIntegerOrNil ifFalse: exit. +                                self flag: #optimization. "ct: By customizing the system version computation, we could save redundant version downloads above. However, because of the preloading stage, this might become a bit more sophisticated." ] ]. +                ] valueWithExit. +                +                "Clean up packages made dirty by MCReorganizationPreloader" +                cleanWorkingCopies +                        select: [ :wc | wc modified ] +                        thenDo: [ :wc | wc checkModified ]. +        ]. +        ^ count! Item was changed:   ----- Method: MCConfiguration>>depsSatisfying:versionDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionDo: versionBlock displayingProgress: progressString + +        self deprecated. +        ^ self +                depsSatisfying: selectBlock +                versionsDo: versionBlock +                displayingProgress: progressString! - depsSatisfying: selectBlock versionDo: verBlock displayingProgress: progressString -        | count selectedVersions cleanWorkingCopies | -        self cacheAllFileNamesDuring: [ -                self repositories do: [ :eachRepository | -                        MCRepositoryGroup default addRepository: eachRepository ]. -                "First, download selected versions" -                count := 0. -                selectedVersions := OrderedCollection new. -                self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | -                        verName := dep versionInfo name. -                        self class extraProgressInfo ifTrue: -                                [ ProgressNotification signal: '' extra: 'Downloading ' , verName ]. -                        repo := self repositories -                                detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] -                                ifNone:  [ self logError: 'Version ' , verName , ' not found in any repository'. -                                        self logError: 'Aborting'. -                                        ^ count ]. -                        (selectBlock value: dep) ifTrue: [ | version | -                                version := self versionNamed: verName for: dep from: repo. -                                version ifNil: [ self logError: 'Could not download version ' , verName , ' from ' , repo description. -                                        self logError: 'Aborting'. -                                        ^ count ]. -                                dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" -                                dep package workingCopy repositoryGroup addRepository: repo. -                                selectedVersions add: version]]. -                "Then, process only those definitions that moved from one package to another, to avoid order dependence" -                cleanWorkingCopies := MCWorkingCopy allManagers select: -                        [ :wc | wc modified not and: -                                [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. -                MCReorganizationPreloader preloadMovesBetween: selectedVersions. -                "Finally, load/merge selected versions" -                self withProgress: progressString in: selectedVersions do: [ :version | -                        self logUpdate: version package with: version. -                        self class extraProgressInfo ifTrue: -                                [ ProgressNotification signal: '' extra: 'Installing ' , version info name ]. -                        verBlock value: version. -                        count := count + 1 ]. -                "Clean up packages made dirty by MCReorganizationPreloader" -                cleanWorkingCopies -                        select: [ :wc | wc modified ] -                        thenDo: [ :wc | wc checkModified ]. -        ]. -        ^ count! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionsDo: versionBlock displayingProgress: progressString + +        ^ self +                depsSatisfying: selectBlock +                upToUpdate: nil +                versionsDo: versionBlock +                displayingProgress: progressString! Item was changed:   ----- Method: MCConfiguration>>load (in category 'actions') -----   load          ^self depsSatisfying: [:dep | dep isCurrent not] +                versionsDo: [:ver | ver load] +                displayingProgress: 'loading packages' translated! -                versionDo: [:ver | ver load] -                displayingProgress: 'loading packages' - ! Item was changed:   ----- Method: MCConfiguration>>merge (in category 'actions') -----   merge          ^self depsSatisfying: [:dep | dep isFulfilledByAncestors not] +                versionsDo: [:ver | ver merge] +                displayingProgress: 'merging packages' translated! -                versionDo: [:ver | ver merge] -                displayingProgress: 'merging packages' - ! Item was changed:   ----- Method: MCConfiguration>>setSystemVersion (in category 'updating') -----   setSystemVersion -        "Set the current system version date to the latest date found in my configuration (or the associated working copy). Also set the highest update number to the sum of version numbers in my configuration."   +        | newVersion | +        newVersion := self currentSystemVersion. -        | versionNumbers versionDates | -        versionNumbers := self dependencies collect: [:d | -                (d versionInfo name copyAfterLast: $.) asInteger]. -        versionDates := self dependencies collect: [:d | -                d versionInfo date -                        ifNil: [d package workingCopy ancestors first date]].          SystemVersion current +                date: newVersion date; +                highestUpdate: newVersion highestUpdate.! -                date: versionDates max; -                highestUpdate: versionNumbers sum.! Item was added: + ----- Method: MCConfiguration>>systemVersionForDeps: (in category 'updating') ----- + systemVersionForDeps: dependencies +        "Answer the system version that will be reached by loading the passed dependencies." + +        | versionNumbers versionDates | +        versionNumbers := dependencies collect: [:dep | +                dep isCollection +                        ifFalse: [dep name versionNumber] +                        ifTrue: [(dep collect: [:version | +                                version name versionNumber]) +                                        ifEmpty: [0] +                                        ifNotEmpty: #max]]. +        versionDates := dependencies with: self dependencies collect: [:dep :originalDep | +                (dep isCollection ifFalse: [dep date]) +                        ifNil: [originalDep package workingCopy ancestors +                                        ifEmpty: [nil] +                                        ifNotEmpty: [:ancestors | ancestors first date]]]. +        +        ^ SystemVersion new +                date: ((versionDates copyWithout: nil) +                        ifEmpty: [nil] +                        ifNotEmpty: #max); +                highestUpdate: versionNumbers sum! Item was added: + ----- Method: MCConfiguration>>totalSystemVersion (in category 'updating') ----- + totalSystemVersion +        "Answer the total system version that will be reached by upgrading the receiver." + +        ^ self systemVersionForDeps: (self dependencies collect: #versionInfo)! Item was changed:   ----- Method: MCConfiguration>>upgrade (in category 'actions') -----   upgrade + +        ^ self upgradeUpToUpdate: nil! -        ^self depsSatisfying: -                        [:dep | dep isFulfilledByAncestors not] -                versionDo: -                        [:ver | -                        (self class upgradeIsMerge and: [ver shouldMerge]) -                                ifFalse: [ver load] -                                ifTrue: -                                        [[ver merge] -                                                on: MCNoChangesException -                                                do: [:req| req resume ] -                                                on: MCMergeResolutionRequest -                                                do: [:request | -                                                        request merger conflicts isEmpty -                                                                ifTrue: [request resume: true] -                                                                ifFalse: [request pass]] -                                                on: Deprecation -                                                do: [:req| req resume ]]] -                displayingProgress: 'upgrading packages'! Item was added: + ----- Method: MCConfiguration>>upgradeUpToUpdate: (in category 'actions') ----- + upgradeUpToUpdate: anIntegerOrNil + +        ^ self +                depsSatisfying: [:dep | +                        dep isFulfilledByAncestors not] +                upToUpdate: anIntegerOrNil +                versionsDo: [:ver | +                        (self class upgradeIsMerge and: [ver shouldMerge]) +                                ifFalse: [ver load] +                                ifTrue: +                                        [[ver merge] +                                                on: MCNoChangesException +                                                do: [:req | req resume ] +                                                on: MCMergeResolutionRequest +                                                do: [:request | +                                                        request merger conflicts isEmpty +                                                                ifTrue: [request resume: true] +                                                                ifFalse: [request pass]] +                                                on: Deprecation +                                                do: [:req | req resume ]]] +                displayingProgress: 'upgrading packages' translated! Item was added: + ----- Method: MCMcmUpdater>>basicDoUpdate:do: (in category 'updating') ----- + basicDoUpdate: interactive do: aBlock +        "Update the image by evaluating aBlock. If this is the default updater for the system, update the system version when complete. If interactive, use a modal notifier, otherwise only update the transcript. Flush all caches. If a previous download failed, this is often helpful." + +        | config previousUpdateLevel | +        previousUpdateLevel := SystemVersion current highestUpdate. +        MCFileBasedRepository flushAllCaches. +        +        MCConfiguration ensureOpenTranscript: interactive during: [ +                config := aBlock value. +        +                config ifNil: [ +                        interactive ifTrue: [^ self inform: 'Unable to retrieve updates from remote repository.' translated]. +                        Transcript cr; show: '==========  Unable to retrieve updates from remote repository. ==========' translated; cr. +                        ^ self ]. +        +                MCMcmUpdater default == self +                        ifTrue: [ +                                config setSystemVersion. +                                interactive ifTrue: [ +                                        self inform: (self updateMessageFor: previousUpdateLevel)]. +                                Transcript cr; +                                        show: '==========  Update completed:  ' translated; +                                        show: previousUpdateLevel; +                                        show: ' -> ' ; +                                        show: SystemVersion current highestUpdate; +                                        show: ' =========='; cr ] +                        ifFalse: [ +                                interactive +                                        ifTrue: [ self inform: 'Update completed.' ]. +                                Transcript cr; show: '==========  Update completed. ==========' translated; cr ] ].! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepositories:do: (in category 'updating') ----- + basicUpdateFromRepositories: repositoryUrls do: repositoryBlock + +        | repos config | +        MCConfiguration upgradeIsMerge: true. +        "The list of repositories to consult in order" +        repos := repositoryUrls collect: [:url|  +                MCRepositoryGroup default repositories +                        detect: [:repo | repo description = url] +                        ifNone: [ | repo | +                                repo := MCHttpRepository location: url. +                                MCRepositoryGroup default addRepository: repo. +                                repo]]. +        +        "The list of updates-author.version.mcm sorted by version" +        repos do: [:repo | +                config := repositoryBlock value: repo]. +        ^ config! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository thenDo: configBlock + +        ^ self +                basicUpdateFromRepository: aRepository +                whileUpdatesSatisfy: [true] +                upToUpdate: nil +                thenDo: configBlock! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:whileUpdatesSatisfy:upToUpdate:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository whileUpdatesSatisfy: updateBlock upToUpdate: anIntegerOrNil thenDo: configBlock + +        | config | +        aRepository cacheAllFileNamesDuring: [ | updateList | +                updateList := self updateListFor: aRepository. +                "Proceed only if there are updates available at all." +                updateList ifNotEmpty: [ +                        updateList := self refreshUpdateMapFor: aRepository with: updateList. +                        "Now process each update file. Check if we have all dependencies and if not, load the entire configuration (this is mostly to skip older updates quickly)" +                        [:exit | updateList +                                do: [:assoc | +                                        (updateBlock cull: assoc key cull: assoc value) ifFalse: exit. +                                        ProgressNotification signal: '' extra: ('Processing {1}' translated format: {assoc value}). +                                        config := aRepository versionNamed: assoc value. +                                        anIntegerOrNil ifNotNil: [ +                                                config currentSystemVersion highestUpdate <= anIntegerOrNil ifFalse: exit]. +                                        self updateFromConfig: config upToUpdate: anIntegerOrNil. +                                        anIntegerOrNil ifNotNil: [ +                                                config currentSystemVersion highestUpdate < config totalSystemVersion highestUpdate ifTrue: exit]. +                                        self lastUpdateMap at: aRepository description put: assoc key] +                                displayingProgress: 'Processing configurations' translated] valueWithExit. +                        configBlock cull: config]]. +        ^ config! Item was changed:   ----- Method: MCMcmUpdater>>doUpdate: (in category 'updating') -----   doUpdate: interactive +        "Update the image by loading all pending updates from the server." -        "Update the image by loading all pending updates from the server. If this is -        the default updater for the system, update the system version when complete. -        If interteractive use a modal notifier, otherwise only update the transcript. -        Flush all caches. If a previous download failed this is often helpful"   +        ^ self basicDoUpdate: interactive do: [ +                self updateFromRepository ]! -        | config previousUpdateLevel ensureTranscriptSetting | -        previousUpdateLevel := SystemVersion current highestUpdate. -        MCFileBasedRepository flushAllCaches.   -        ensureTranscriptSetting := MCConfiguration ensureOpenTranscript. -        [ MCConfiguration ensureOpenTranscript: interactive. -        config := self updateFromRepository. -        config ifNil: [ -                interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. -                Transcript cr; show: '==========  Unable to retrieve updates from remote repository. ==========' translated; cr. -                ^ self ]. -        MCMcmUpdater default == self -                ifTrue: [ -                        config setSystemVersion. -                        interactive ifTrue: [ -                                self inform: (self updateMessageFor: previousUpdateLevel)]. -                        Transcript cr; -                                show: '==========  Update completed:  ' translated; -                                show: previousUpdateLevel; -                                show: ' -> ' ; -                                show: SystemVersion current highestUpdate; -                                show: ' =========='; cr ] -                ifFalse: [ -                        interactive -                                ifTrue: [ self inform: 'Update completed.' ]. -                        Transcript cr; show: '==========  Update completed. ==========' translated; cr ] ] -                ensure: [ MCConfiguration ensureOpenTranscript: ensureTranscriptSetting]. - -        ! Item was changed:   ----- Method: MCMcmUpdater>>doUpdate:upTo: (in category 'updating') -----   doUpdate: interactive upTo: versionNumber +        "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." -        "Update the image by loading all pending updates from the server. If this is -        the default updater for the system, update the system version when complete. -        If interteractive use a modal notifier, otherwise only update the transcript. -        Flush all caches. If a previous download failed this is often helpful"   +        ^ self basicDoUpdate: interactive do: [ +                self updateFromRepositories: {self repository} upTo: versionNumber ]! -        | config previousUpdateLevel | -        previousUpdateLevel := SystemVersion current highestUpdate. -        MCFileBasedRepository flushAllCaches. -        config := self updateFromRepositories: { self repository } upTo: versionNumber. -        config ifNil: [ -                interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. -                Transcript cr; show: '==========  Unable to retrieve updates from remote repository. ==========' translated; cr. -                ^ self ]. -        MCMcmUpdater default == self -                ifTrue: [ -                        config setSystemVersion. -                        interactive ifTrue: [ -                                self inform: (self updateMessageFor: previousUpdateLevel)]. -                        Transcript cr; -                                show: '==========  Update completed:  ' translated; -                                show: previousUpdateLevel; -                                show: ' -> ' ; -                                show: SystemVersion current highestUpdate; -                                show: ' =========='; cr ] -                ifFalse: [ -                        interactive -                                ifTrue: [ self inform: 'Update completed.' ]. -                        Transcript cr; show: '==========  Update completed. ==========' translated; cr ] -        ! Item was added: + ----- Method: MCMcmUpdater>>doUpdate:upToUpdate: (in category 'updating') ----- + doUpdate: interactive upToUpdate: anIntegerOrNil +        "Update the image by loading all pending updates from the server until the system version has reached at least anInteger. If anInteger is nil, install all available updates." + +        ^ self basicDoUpdate: interactive do: [ +                self updateFromRepositories: {self repository} upToUpdate: anIntegerOrNil ]! Item was changed:   ----- Method: MCMcmUpdater>>doUpdateUpTo: (in category 'updating') -----   doUpdateUpTo: versionNumber +        "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." -        "Update the image by loading all pending updates from the server. If this is -        the default updater for the system, update the system version when complete. -        Flush all caches. If a previous download failed this is often helpful"            ^self doUpdate: true upTo: versionNumber   ! Item was changed:   ----- Method: MCMcmUpdater>>updateFromConfig: (in category 'updating') -----   updateFromConfig: config   +        ^ self updateFromConfig: config upToUpdate: nil! -        "Skip packages that were specifically unloaded" -        config dependencies: (config dependencies -                reject: [:dep| self class skipPackages includes: dep package name]). -        self class updateMissingPackages ifFalse:[ -                "Skip packages that are not in the image" -                config dependencies: (config dependencies -                        select: [:dep| dep package hasWorkingCopy])]. -        (config dependencies allSatisfy:[:dep| dep isFulfilled]) -                ifFalse:[config upgrade]. - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromConfig:upToUpdate: (in category 'updating') ----- + updateFromConfig: config upToUpdate: anIntegerOrNil + +        "Skip packages that were specifically unloaded" +        config dependencies: (config dependencies +                reject: [:dep | self class skipPackages includes: dep package name]). +        self class updateMissingPackages ifFalse: [ +                "Skip packages that are not in the image" +                config dependencies: (config dependencies +                        select: [:dep | dep package hasWorkingCopy])]. +        (config dependencies allSatisfy: [:dep | dep isFulfilled]) +                ifFalse: [config upgradeUpToUpdate: anIntegerOrNil].! Item was changed:   ----- Method: MCMcmUpdater>>updateFromRepositories:upTo: (in category 'updating') -----   updateFromRepositories: repositoryUrls upTo: versionNumber +        " +        MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest [http://squeaksource.com/MCUpdateTest]') upTo: 3 +        " -        "MCMcmUpdater updateFromRepositories: #( -                'http://squeaksource.com/MCUpdateTest [http://squeaksource.com/MCUpdateTest]' -        )"   +        ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | +                self updateFromRepository: repo upTo: versionNumber]! -        | repos config | -        MCConfiguration upgradeIsMerge: true. -        "The list of repositories to consult in order" -        repos := repositoryUrls collect:[:url| -                MCRepositoryGroup default repositories -                        detect:[:r| r description = url] -                        ifNone:[ | r | -                                r := MCHttpRepository location: url user: '' password: ''. -                                MCRepositoryGroup default addRepository: r. -                                r]]. - -        "The list of updates-author.version.mcm sorted by version" -        repos do:[ :r | config := self updateFromRepository: r upTo: versionNumber]. -        ^config! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepositories:upToUpdate: (in category 'updating') ----- + updateFromRepositories: repositoryUrls upToUpdate: anIntegerOrNil +        " +        MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest [http://squeaksource.com/MCUpdateTest]') upToUpdate: 2130 +        " + +        ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | +                self updateFromRepository: repo upToUpdate: anIntegerOrNil ]! Item was changed:   ----- Method: MCMcmUpdater>>updateFromRepository (in category 'updating') -----   updateFromRepository   +        ^ self updateFromRepository: self getRepositoryFromRepositoryGroup! -        | config repo | -        repo := self getRepositoryFromRepositoryGroup. -        repo cacheAllFileNamesDuring: [ | updateList | -                updateList := self updateListFor: repo. -                "Proceed only if there are updates available at all." -                updateList ifNotEmpty: [ -                        updateList := self refreshUpdateMapFor: repo with: updateList. -                        "Now process each update file. Check if we have all dependencies and if not, -                        load the entire configuration (this is mostly to skip older updates quickly)" -                        updateList do:[:assoc| -                                ProgressNotification signal: '' extra: 'Processing ', assoc value. -                                config := repo versionNamed: assoc value. -                                self updateFromConfig: config. -                                self lastUpdateMap at: repo description put: assoc key. -                        ] displayingProgress: 'Processing configurations'. -                        "We've loaded all the provided update configurations. -                        Use the latest configuration to update all the remaining packages." -                        (self useLatestPackagesFrom: repo) ifTrue: [ -                                config updateFromRepositories. -                                config upgrade]. -                ]]. -        ^ config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository: (in category 'updating') ----- + updateFromRepository: aRepository + +        ^ self basicUpdateFromRepository: aRepository thenDo: [:config | +                "We've loaded all the provided update configurations. Use the latest configuration to update all the remaining packages." +                (self useLatestPackagesFrom: aRepository) ifTrue: [ +                        config updateFromRepositories. +                        config upgrade]]! Item was changed:   ----- Method: MCMcmUpdater>>updateFromRepository:upTo: (in category 'updating') ----- + updateFromRepository: aRepository upTo: versionNumber - updateFromRepository: repository upTo: versionNumber   +        ^ self +                basicUpdateFromRepository: aRepository +                whileUpdatesSatisfy: [:updateVersion | updateVersion <= versionNumber] +                upToUpdate: nil +                thenDo: []! -        | config | -        repository cacheAllFileNamesDuring: [ | updateList | -                updateList := self updateListFor: repository. -                "Proceed only if there are updates available at all." -                updateList ifNotEmpty: [ -                        updateList := self refreshUpdateMapFor: repository with: updateList. -                        "Now process each update file. Check if we have all dependencies and if not, -                        load the entire configuration (this is mostly to skip older updates quickly)" -                        updateList do:[:assoc| -                                assoc key > versionNumber ifTrue: [^config]. -                                ProgressNotification signal: '' extra: 'Processing ', assoc value. -                                config := repository versionNamed: assoc value. -                                self updateFromConfig: config. -                                self lastUpdateMap at: repository description put: assoc key. -                        ] displayingProgress: 'Processing configurations'. -                ]]. -        ^config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository:upToUpdate: (in category 'updating') ----- + updateFromRepository: aRepository upToUpdate: anIntegerOrNil + +        ^ self +                basicUpdateFromRepository: aRepository +                whileUpdatesSatisfy: [true] +                upToUpdate: anIntegerOrNil +                thenDo: []! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Thu Apr 15 11:12:49 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 15 Apr 2021 13:12:49 +0200 Subject: [squeak-dev] Recursive errors In-Reply-To: References: Message-ID: Hi Nicolas. > IMO, if we decompile a block, we might want to find the temp names > from the method source, but if we decompile a method, what's the > point??? Hmm.. aren't there several "layers" of source code possible in a method trailer? See CompiledMethodTrailer class >> #trailerKinds. Even if you have to decompile a method, temp names might still be available from somewhere. Best, Marcel Am 15.04.2021 02:02:36 schrieb Nicolas Cellier : my snippet for inspecting (part of) the stack: | tmp list i | tmp := sender. list := Array new: 200. i := 0. [tmp sender == nil] whileFalse: [ list atWrap: (i := i+1) put: tmp. tmp := tmp sender]. ^{list. i} The stack was only about 150,000 deep, but our tools do not really scale at this depth... Le jeu. 15 avr. 2021 à 01:57, Nicolas Cellier a écrit : > > Hi all, > with the new exception handling, I have encountered some recursive error. > Very hard to debug because the stack grows too fast. > The origin is when trying to browse revisions of a removed method. > I have a: > > MethodReference >>timestamp > receiver: a MethodReference Parser >> #externalFunctionDeclaration > UndefinedObject(Object)>>doesNotUnderstand: #timeStamp > ... > Debugger class>>openOn:context:label:contents:fullView: > ... > SmalltalkImage>>logError:inContext:to: > ... > Context>>printDetails: > ... > [] in Context>>printDetails: > Context>>tempsAndValuesLimitedTo:indent: > Context>>tempNames > Context(InstructionStream)>>debuggerMap > CompiledMethod>>debuggerMap > receiver: (MCRepository class>>#browseMethodRevisionsService "a > CompiledMethod(2459914)") > receiver isInstalled ==> false !!! (because I did recompileAll at one point) > DebuggerMethodMap class>>forMethod: > ... > CompiledMethod>>methodNode > [source]: a Text for 'Vw6ilbntYC3Kf9Bz3g3T3YJ+J74W7Mmk9gPb... > note that the source is broken, I don't know where it comes from, > the compiledMethod is not installed... > this context will catch SyntaxErrorNotificationSignal > ... > Parser>>parseCue:noPattern:ifFail: > this context will catch ReparseAfterSourceEditing > ... > SyntaxErrorNotification(Exception)>>signal > expected, the source is broken... > ... > Context>>handleSignal: > Context>>handleSignal: > ^2 consecutive handleSIgnal: here... > the first one (parseCue:noPattern:ifFail:) only catch > ReparseAfterSourceEditing > the second one (methodNode) does catch our SyntaxErrorNotification > on: SyntaxErrorNotification > do: [:ex | ex return: self decompileWithTemps] > ... > CompiledMethod>>decompileWithTemps > oh but this one tries to get the tempNames by parsing the source! > let's go for a cycle... > ... > Parser>>parseCue:noPattern:ifFail: > this context will catch ReparseAfterSourceEditing > ... > SyntaxErrorNotification(Exception)>>signal > Context>>handleSignal: > Context>>handleSignal: > Context>>handleSignal: > ouch, I have 3 of them now > what happens? it's all normal, I now have 2 parseCue:... in the > stack catching ReparseAfterSourceEditing > the 3rd is catching SyntaxErrorNotification and retries parsing tempNames... > and we're back to another cycle. > ... > tada, there's more than 1000 handleSignal: in the stack when I > interrupted the process, and it's impossible to debug, and I thought > the new exception handling had a problem... > It doesn't so far. > We have another problem with broken source for an uninstalled > CompiledMethod, that tries to decompile using broken source... > > I'm happy that I'm not the root cause, but this is most annoying. > IMO, if we decompile a block, we might want to find the temp names > from the method source, but if we decompile a method, what's the > point??? -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Thu Apr 15 11:35:13 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 15 Apr 2021 13:35:13 +0200 Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz In-Reply-To: References: <1618336352701-0.post@n4.nabble.com> Message-ID: Hi Jakob, thanks for sharing! I did also spent some time and effort in processing pipermail/mailman: https://github.com/hpi-swa/squeak-history [https://github.com/hpi-swa/squeak-history] For Tweak, there is also manual scraping of (web.archive.org) HTML pages.  See #downloadTweak. Best, Marcel Am 15.04.2021 00:38:48 schrieb Jakob Reschke : Here is my workspace for getting all inbox messages for a start. It downloads the whole archive, which is probably not a good idea for everyone to do it, and could be optimized simply because the inbox has not existed as long as the list. The expressions themselves are also not particularly optimized. The squeak-dev-snapshot.dat file is around 500 MB. My Squeak process takes 2 GB of RAM now though, so I will clear the workspace bindings before saving this image, which I normally use for something else... wc := WebClient new. base := 'http://lists.squeakfoundation.org/pipermail/squeak-dev/ [http://lists.squeakfoundation.org/pipermail/squeak-dev/]'. r := wc httpGet: base. c := r content. m := '"([^"]+)"' asRegex. files := c regex: '\: Hi Nicolas. > I may try to answer a mail that is about 6 month old, but IMO, it does > not make much sense. > This mail is not in my client anymore, so it means going thru some > forum API with extra login etc... > It's just not acceptable. I find both ways manageable. It doesn't take too much time for me. Yet, I see the benefit of a platform with integrated tools such as GitHub. It should be possible to write a small tool (or extension to Monticello) to make a comment (via e-mail?) on an inbox version using the mailing list and the matching entry there.  No need to move all the data to a new platform where the tools are --- just add the missing tools. IMO the better cost-value ratio. ... Any takers? Christoph? :-D Best, Marcel  Am 13.04.2021 21:08:52 schrieb Nicolas Cellier : Hi Christoph, yes, I saw that later, but then decided that your first attempt was OK, some kind of integrator privilege ;) If someone has a strong opinion about it, we can change it again, but IMO it's not worth it. The problem with our dev model is that it's been designed with very short cycles in mind. Once the contributions are rotting for more than a month or two, it's very inconvenient to retrieve the messages and discussion from the mailing list, while reviewing the changes in the image. I personally skip this step because the process is already too demanding. Unlike pull/merge requests in github/gitlab, we have no way to let a review process span multiple months, multiple commits, multiple steps (understand separate steps for loading into a live image like we do with MCM update maps), etc... Answering a mail in a cold thread (2 month later or more) does not make sense,see an example below... We also have to use a 3rd tool for moving the package: the source.squak.org [http://source.squak.org] web interface. I can guarantee that I have to re-login at each package review (logins are short lived). The way our site URL works, it means that I have to retrieve the page holding the exact version at each re-login. If 1st package letter is > M, it can be 10 clicks away... Plus the fact that I'm pretty sure that in the past, some packages that I previously moved to trunk or treated inbox did reappear in the inbox, that's somehow discouraging, just put a picture of me and Marcel faces here https://en.wikipedia.org/wiki/Dana%C3%AFdes#/media/File:Danaides_by_John_William_Waterhouse,_1903.jpg [https://en.wikipedia.org/wiki/Dana%C3%AFdes#/media/File:Danaides_by_John_William_Waterhouse,_1903.jpg] I'm generally satisfied with our lightweight model, except for the review and integration of inbox contributions. As example, yesterday, I wanted to reject https://source.squeak.org/inbox/Kernel_ct.1366.diff [https://source.squeak.org/inbox/Kernel_ct.1366.diff] This is because (result := Compiler evaluate:... ifFail: [^nil]) is not the same as your proposal: there is a local return that exit the method in the former case, and an assignment of result with nil in the later case. I can see the diff on our site, but cannot add any annotation unlike github/gitlab. I may try to answer a mail that is about 6 month old, but IMO, it does not make much sense. This mail is not in my client anymore, so it means going thru some forum API with extra login etc... It's just not acceptable. Rejecting without a comment is not acceptable either. It's not fair for contributors, and not fair to ourselves: the reason why we reject is more important than the rejection itself: it is also information reusable for future contributions. If we really want to stick to our lghtweight model, i suggest that we add one more commit message when we move some package to treated, possibly with an automated link to original commit message in some mailing list. This way, I will have a chance to give some additional reason for rejection... I stop the rant here. Above all, I don't want to restrain the will to contribute. Having enthusiastic users overwhelming the inbox with fixes, ideas and enhancements is not the problem, it's a chance! Having too few people to perform the review with poor tools is the problem. We have to do something about it. In my eyes, the reviews done in the mailing list a few month ago are dead, they are not easily findable/usable/amendable. Thanks for bringing the subject, and please, continue to chanllenge us! Ideas for improving the process are wecome too. Le mar. 13 avr. 2021 à 19:52, Christoph Thiede a écrit : > > Hi Nicolas, > > actually, ST80-ct.255 should have been moved into the treated inbox in favor > of ST80-ct.256 as discussed in the thread. Nevertheless, thanks for > integrating all these patches! :-) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html [http://forum.world.st/Squeak-Dev-f45488.html] > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dev at stlutz.net Thu Apr 15 13:07:18 2021 From: dev at stlutz.net (stlutz) Date: Thu, 15 Apr 2021 08:07:18 -0500 (CDT) Subject: [squeak-dev] Methods with more than 15 arguments? In-Reply-To: References: Message-ID: <1618492038808-0.post@n4.nabble.com> codefrau wrote > Incidentally, which library/function specifically do you want to call? I am generating code to satisfy the OpenGL interface. The functions that are making trouble are also highly unlikely to ever be called, as they are part of outdated extensions (glLGPUCopyImageSubDataNVX, glMulticastCopyImageSubDataNV, glAsyncCopyImageSubDataNVX). That's also why I was asking and hoping for a simple solution, since it is not really worth it for me to dive deeper into this. I will probably simply ignore these methods and not generate them, and add a class comment noting their absence. Nicolas Cellier wrote > Eliot Miranda suggested to pass first 14 arguments as usual, and onlythe > last+excess arguments into an array, but nobody did work on > suchimplementation. I do not remember pros and cons either, need tovarious > scan mailing lists Yes, admittedly I had searched the mailing list(s) before posting and found this thread: http://forum.world.st/Methods-with-more-than-15-args-sketch-td4901127.html . I just wondered if anything happened in this regard that my Generic-Search-Engine-Fu could not uncover. -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Apr 15 13:34:53 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 13:34:53 0000 Subject: [squeak-dev] The Trunk: ST80-mt.268.mcz Message-ID: Marcel Taeumel uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-mt.268.mcz ==================== Summary ==================== Name: ST80-mt.268 Author: mt Time: 15 April 2021, 3:34:51.487875 pm UUID: d6b9c2fc-1c08-460f-ac5f-52dfe1a2d02d Ancestors: ST80-mt.267, ST80-ct.240 Merges ST80-ct.240, which is a dependency of some things in MorphicExtras, I am about to merge soon. (Not sure whether this version is complete. It describes some refactorings and speed-up, which is not present in this inbox version.) =============== Diff against ST80-mt.267 =============== Item was added: + ----- Method: Arc class>>center:radius:quadrant: (in category 'instance creation') ----- + center: aPoint radius: anInteger quadrant: section + + ^ self new + center: aPoint radius: anInteger quadrant: section; + yourself! Item was added: + ----- Method: Arc>>computeVertices: (in category 'displaying') ----- + computeVertices: size + + | dAngle dSin dCos point | + dAngle := (90 / (size - 1)) degreesToRadians. + dSin := dAngle sin. + dCos := dAngle cos. + point := (1 to: quadrant) + inject: 0 @ radius + into: [:p :i | p leftRotated]. + ^ (OrderedCollection new: size) + add: (center + point) rounded; + addAll: ((1 to: size - 1) collect: [:i | + point := point * dCos + (point * dSin) leftRotated. + (center + point) rounded]); + yourself! From commits at source.squeak.org Thu Apr 15 13:35:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 13:35:12 0000 Subject: [squeak-dev] The Trunk: ST80-ct.240.mcz Message-ID: Marcel Taeumel uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-ct.240.mcz ==================== Summary ==================== Name: ST80-ct.240 Author: ct Time: 21 September 2019, 5:13:06.268935 pm UUID: e9dee0c1-7bf7-0148-9bc5-9cec67d37dae Ancestors: ST80-mt.239 Refactor Arc display Extract method for the purpose of reuse and improve readability. Also introduce a convenience constructor. According to my tests with Arc example, the implementation also got a bit faster (before: 1.25/after: 1.14 ms/run). =============== Diff against ST80-mt.239 =============== Item was added: + ----- Method: Arc class>>center:radius:quadrant: (in category 'instance creation') ----- + center: aPoint radius: anInteger quadrant: section + + ^ self new + center: aPoint radius: anInteger quadrant: section; + yourself! Item was added: + ----- Method: Arc>>computeVertices: (in category 'displaying') ----- + computeVertices: size + + | dAngle dSin dCos point | + dAngle := (90 / (size - 1)) degreesToRadians. + dSin := dAngle sin. + dCos := dAngle cos. + point := (1 to: quadrant) + inject: 0 @ radius + into: [:p :i | p leftRotated]. + ^ (OrderedCollection new: size) + add: (center + point) rounded; + addAll: ((1 to: size - 1) collect: [:i | + point := point * dCos + (point * dSin) leftRotated. + (center + point) rounded]); + yourself! From craig at blackpagedigital.com Thu Apr 15 13:40:34 2021 From: craig at blackpagedigital.com (Craig Latta) Date: Thu, 15 Apr 2021 06:40:34 -0700 Subject: [squeak-dev] Recursive errors In-Reply-To: References: Message-ID: Hi Nicolas-- > with the new exception handling, I have encountered some recursive > error. Very hard to debug because the stack grows too fast. Sounds like you could debug this in the VM simulator? -C -- Craig Latta :: research computer scientist Black Page Digital :: Berkeley, California 663137D7940BF5C0AFC :: 1349FB2ADA32C4D5314CE From nicolas.cellier.aka.nice at gmail.com Thu Apr 15 14:09:51 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 16:09:51 +0200 Subject: [squeak-dev] Methods with more than 15 arguments? In-Reply-To: <1618492038808-0.post@n4.nabble.com> References: <1618492038808-0.post@n4.nabble.com> Message-ID: Le jeu. 15 avr. 2021 à 15:07, stlutz a écrit : > > codefrau wrote > Incidentally, which library/function specifically do you want to call? > > I am generating code to satisfy the OpenGL interface. The functions that are making trouble are also highly unlikely to ever be called, as they are part of outdated extensions (glLGPUCopyImageSubDataNVX, glMulticastCopyImageSubDataNV, glAsyncCopyImageSubDataNVX). That's also why I was asking and hoping for a simple solution, since it is not really worth it for me to dive deeper into this. I will probably simply ignore these methods and not generate them, and add a class comment noting their absence. > > Nicolas Cellier wrote > Eliot Miranda suggested to pass first 14 arguments as usual, and only the last+excess arguments into an array, but nobody did work on such implementation. I do not remember pros and cons either, need to various scan mailing lists > > Yes, admittedly I had searched the mailing list(s) before posting and found this thread: http://forum.world.st/Methods-with-more-than-15-args-sketch-td4901127.html. I just wondered if anything happened in this regard that my Generic-Search-Engine-Fu could not uncover. > ________________________________ > Sent from the Squeak - Dev mailing list archive at Nabble.com. > You can peek the SmallapackCompiler and use it in your interface class (declare compilerClass ^SmallapackCompiler at class side). That's the most simple thing that could possibly work. All code is MIT. From nicolas.cellier.aka.nice at gmail.com Thu Apr 15 14:19:41 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 16:19:41 +0200 Subject: [squeak-dev] Recursive errors In-Reply-To: References: Message-ID: Hi Craig, yes, I did not try that. This can be a solution once we know how to reproduce... Once the stack is high, it's too late, the interface gets unresponsive, so the simulation would only worsen. We would need some sort of recording debugger in order to produce the bug fast enough and then backtrack in a simulated env... I guess that an instrumented VM could do that. I wonder how hard such a project would be... Le jeu. 15 avr. 2021 à 15:40, Craig Latta a écrit : > > > Hi Nicolas-- > > > with the new exception handling, I have encountered some recursive > > error. Very hard to debug because the stack grows too fast. > > Sounds like you could debug this in the VM simulator? > > > -C > > -- > Craig Latta :: research computer scientist > Black Page Digital :: Berkeley, California > 663137D7940BF5C0AFC :: 1349FB2ADA32C4D5314CE > > > From lewis at mail.msen.com Thu Apr 15 14:25:55 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Thu, 15 Apr 2021 10:25:55 -0400 Subject: [squeak-dev] The Trunk: System-dtl.1225.mcz In-Reply-To: References: Message-ID: <20210415142555.GA75458@shell.msen.com> For reference, the discussion of this topic took place here: http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-April/214699.html The motivating concern for Seaside was this: https://github.com/SeasideSt/Seaside/issues/1195 Dave On Mon, Apr 12, 2021 at 01:50:57AM +0000, commits at source.squeak.org wrote: > David T. Lewis uploaded a new version of System to project The Trunk: > http://source.squeak.org/trunk/System-dtl.1225.mcz > > ==================== Summary ==================== > > Name: System-dtl.1225 > Author: dtl > Time: 11 April 2021, 9:50:52.898233 pm > UUID: a96e7afc-11cc-48c8-8e72-d63f6295e092 > Ancestors: System-tonyg.1224 > > Symbol>>asMutator is used by Seaside, do not deprecate it. Instead let it be a synonym for the preferred Symbol>>asSimpleSetter. > > =============== Diff against System-tonyg.1224 =============== > > Item was added: > + ----- Method: Symbol>>asMutator (in category '*System-Support') ----- > + asMutator > + "Synonym for asSimpleSetter, retained for support of external packages such as Seaside" > + > + ^ self asSimpleSetter! > > From lewis at mail.msen.com Thu Apr 15 14:31:27 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Thu, 15 Apr 2021 10:31:27 -0400 Subject: [squeak-dev] Revisiting the deprecation of #asMutator vs #asSimpleSetter in 5.3 (sorry) In-Reply-To: <20210415023128.GA96590@shell.msen.com> References: <7D834606-8837-4F82-83BC-BE396E600A5B@gmail.com> <20210411144538.GA17226@shell.msen.com> <20210412021157.GA98993@shell.msen.com> <20210412205610.GA33248@shell.msen.com> <20210415023128.GA96590@shell.msen.com> Message-ID: <20210415143127.GB75458@shell.msen.com> On Wed, Apr 14, 2021 at 10:31:28PM -0400, David T. Lewis wrote: > On Wed, Apr 14, 2021 at 10:30:24AM +0200, Marcel Taeumel wrote: > > Hi Dave, > > > > you could just add another version. No need to modify dtl.1225 :-) > > > > Sorry, too late to do that now. But in case future readers of this > list archive are interested, the discussion on squeak-dev is here: > > http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-April/214699.html > > The motivating issue for Seaside is: > > https://github.com/SeasideSt/Seaside/issues/1195 > > Dave > But of course adding this information to the current mail thread is completely pointless, d'oh! So I also added it to the "squeak-dev] The Trunk: System-dtl.1225.mcz" thread to give people a better chance of finding it in the future. Again, sorry for not putting this in the original commit message. Dave From commits at source.squeak.org Thu Apr 15 14:33:11 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:33:11 0000 Subject: [squeak-dev] The Trunk: Sound-mt.78.mcz Message-ID: Marcel Taeumel uploaded a new version of Sound to project The Trunk: http://source.squeak.org/trunk/Sound-mt.78.mcz ==================== Summary ==================== Name: Sound-mt.78 Author: mt Time: 15 April 2021, 4:33:10.347792 pm UUID: 5afe1765-de62-44e1-a8c6-d28e39654d5e Ancestors: Sound-eem.77, Sound-ct.69, Sound-ct.68 Merge. Sound-ct.69: Add convenience setter for MIDIScore. These values are strongly related and should in most cases be set at once. Sound-ct.68: Convenience constructor for TempoEvent =============== Diff against Sound-eem.77 =============== Item was changed: ----- Method: MIDIFileReader>>asScore (in category 'chunk reading') ----- asScore ^ MIDIScore new + tracks: tracks trackInfo: trackInfo; - tracks: tracks; - trackInfo: trackInfo; tempoMap: tempoMap; ticksPerQuarterNote: ticksPerQuarter; source: stream localName ! Item was added: + ----- Method: MIDIScore>>tracks:trackInfo: (in category 'accessing') ----- + tracks: trackList trackInfo: trackInfoList + + self tracks: trackList; trackInfo: trackInfoList.! Item was added: + ----- Method: TempoEvent class>>time:tempo: (in category 'instance creation') ----- + time: aTime tempo: aTempo + + ^ self new + time: aTime; + tempo: aTempo; + yourself! From commits at source.squeak.org Thu Apr 15 14:33:31 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:33:31 0000 Subject: [squeak-dev] The Trunk: Sound-ct.68.mcz Message-ID: Marcel Taeumel uploaded a new version of Sound to project The Trunk: http://source.squeak.org/trunk/Sound-ct.68.mcz ==================== Summary ==================== Name: Sound-ct.68 Author: ct Time: 21 September 2019, 5:20:22.324935 pm UUID: b8c8a1e8-1019-4142-952b-0d116b29f97a Ancestors: Sound-eem.66 Convenience constructor for TempoEvent =============== Diff against Sound-eem.66 =============== Item was added: + ----- Method: TempoEvent class>>time:tempo: (in category 'instance creation') ----- + time: aTime tempo: aTempo + + ^ self new + time: aTime; + tempo: aTempo; + yourself! From commits at source.squeak.org Thu Apr 15 14:33:35 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:33:35 0000 Subject: [squeak-dev] The Trunk: Sound-ct.69.mcz Message-ID: Marcel Taeumel uploaded a new version of Sound to project The Trunk: http://source.squeak.org/trunk/Sound-ct.69.mcz ==================== Summary ==================== Name: Sound-ct.69 Author: ct Time: 1 October 2019, 8:25:38.912339 pm UUID: b0d38e4d-1231-494f-8502-e1a631e232b3 Ancestors: Sound-eem.66 Add convenience setter for MIDIScore These values are strongly related and should in most cases be set at once. =============== Diff against Sound-eem.66 =============== Item was changed: ----- Method: MIDIFileReader>>asScore (in category 'chunk reading') ----- asScore ^ MIDIScore new + tracks: tracks trackInfo: trackInfo; - tracks: tracks; - trackInfo: trackInfo; tempoMap: tempoMap; ticksPerQuarterNote: ticksPerQuarter; source: stream localName ! Item was added: + ----- Method: MIDIScore>>tracks:trackInfo: (in category 'accessing') ----- + tracks: trackList trackInfo: trackInfoList + + self tracks: trackList; trackInfo: trackInfoList.! From commits at source.squeak.org Thu Apr 15 14:52:55 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:52:55 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.292.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.292.mcz ==================== Summary ==================== Name: MorphicExtras-mt.292 Author: mt Time: 15 April 2021, 4:52:52.171792 pm UUID: 5c15e20e-1712-4494-b519-18e3f9f6042b Ancestors: MorphicExtras-mt.291, MorphicExtras-ct.264, MorphicExtras-ct.265, MorphicExtras-ct.266, MorphicExtras-ct.268, MorphicExtras-ct.269, MorphicExtras-ct.271, MorphicExtras-ct.272, MorphicExtras-ct.273, MorphicExtras-ct.274, MorphicExtras-ct.275, MorphicExtras-ct.283, MorphicExtras-ct.284 Merge, merge, merge. Christoph (ct) put a lot of effort into restoring the examples from older Squeak releases, which had rich multimedia content to show off Squeak's features. Look out for the "*MorphicExtras-examples" protocol. And also take a look at the "MorphicExtras-Demo" class category. Note that, in the long term, unloading MorphicExtras should be possible without breaking progamming tools and thus a way to free up some resources and shrink the image file. This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-mt.291 =============== Item was added: + ----- Method: AnimatedImageMorph>>delays (in category 'accessing') ----- + delays + + ^ delays! Item was changed: + ----- Method: AnimatedImageMorph>>images (in category 'accessing') ----- - ----- Method: AnimatedImageMorph>>images (in category 'private') ----- images ^images! Item was added: + ----- Method: Bag>>asMorph (in category '*MorphicExtras-converting') ----- + asMorph + " + (Bag new in: [:bag | Smalltalk allClasses do: [:cls | bag add: cls name first]. bag]) + asMorph openInHand. + " + ^ HistogramMorph on: self! Item was added: + EllipseMorph subclass: #BannerMorph + instanceVariableNames: 'header contents' + classVariableNames: '' + poolDictionaries: '' + category: 'MorphicExtras-Demo'! + + !BannerMorph commentStamp: 'ct 9/7/2019 10:43' prior: 0! + I display a header and a contents text, arranged in an EllipseMorph in a flamboyant way. I use a ScreeningMorph and a BackgroundMorph to hinder the user to avert his gaze from me.! Item was added: + ----- Method: BannerMorph class>>example (in category 'examples') ----- + example + "BannerMorph example openInWorld" + + ^ self + header: 'Yes, you are ...' withCRs asTextFromHtml + contents: 'Live in Morphic' asUppercase asText! Item was added: + ----- Method: BannerMorph class>>header:contents: (in category 'instance creation') ----- + header: aStringOrText contents: anotherStringOrText + + ^ self basicNew + header: aStringOrText contents: anotherStringOrText; + initialize; + yourself! Item was added: + ----- Method: BannerMorph>>contents (in category 'accessing') ----- + contents + + ^ contents! Item was added: + ----- Method: BannerMorph>>createBackground (in category 'initialize-release') ----- + createBackground + + | fillMorph fillStyle | + fillStyle := GradientFillStyle colors: + ({Color red. Color green. Color blue} + in: [:colors | colors, colors reverse]). + fillStyle + origin: 0 @ 0; + direction: 150 @ 50. + fillMorph := (Morph new + fillStyle: fillStyle; + yourself). + ^ BackgroundMorph new + extent: 300 @ 130; + addMorph: fillMorph; + yourself! Item was added: + ----- Method: BannerMorph>>createContents (in category 'initialize-release') ----- + createContents + + | text | + text := self contents asText + addAttribute: TextEmphasis bold; + addAttribute: (TextFontReference toFont: + (StrikeFont familyName: #ComicPlain size: 39)); + asMorph. + text readOnly: true; flag: #ct. "We're no *that* life, yet :(" + ^ ScreeningMorph new + addMorph: (self createBackground + extent: text extent; + yourself); + addMorph: text; + showScreened; + cellPositioning: #center; + yourself! Item was added: + ----- Method: BannerMorph>>createHeader (in category 'initialize-release') ----- + createHeader + + | text | + text := (self header copyWithFirst: Character cr) asText + addAttribute: TextEmphasis bold; + addAttribute: (TextFontReference toFont: + (StrikeFont familyName: #Accula size: 29)); + yourself. + ^ text asMorph + centered; + fillsOwner: true; + yourself! Item was added: + ----- Method: BannerMorph>>header (in category 'accessing') ----- + header + + ^ header! Item was added: + ----- Method: BannerMorph>>header:contents: (in category 'accessing') ----- + header: aStringOrText contents: anotherStringOrText + + header := aStringOrText. + contents := anotherStringOrText.! Item was added: + ----- Method: BannerMorph>>initialize (in category 'initialize-release') ----- + initialize + + super initialize. + self extent: 300 @ 200. + self + changeProportionalLayout; + addMorph: (Morph new + color: Color transparent; + changeTableLayout; + listCentering: #center; wrapCentering: #center; + addMorph: self createContents; + yourself) + fullFrame: LayoutFrame fullFrame; + addMorph: self createHeader.! Item was added: + ----- Method: BannerMorph>>initializeToStandAlone (in category 'initialize-release') ----- + initializeToStandAlone + + self header: 'Introducing' contents: self class name. + super initializeToStandAlone.! Item was added: + ----- Method: CurveMorph class>>extraExampleArrow (in category '*MorphicExtras-examples') ----- + extraExampleArrow + "CurveMorph extraExampleArrow openInHand" + + | arrow | + arrow := CurveMorph + vertices: {200 @ 75. 35 @ 0. 40 @ 55. -55 @ 30} + color: Color veryDarkGray + borderWidth: 5 + borderColor: Color veryDarkGray. + arrow makeOpen; makeForwardArrow; beSmoothCurve. + arrow addHandles. + ^ arrow! Item was added: + ----- Method: CurveMorph class>>extraExampleTextFlow (in category '*MorphicExtras-examples') ----- + extraExampleTextFlow + "CurveMorph extraExampleTextFlow openInHand" + + | curve text | + curve := CurveMorph + vertices: {135 @ 270. 75 @ 200. 50 @ 150. 100 @ 100. 125 @ 150. 175 @ 100. 200 @ 150. 175 @ 200 . 115 @ 340} * RealEstateAgent scaleFactor + color: Color cyan + borderWidth: 25 * RealEstateAgent scaleFactor + borderColor: Color salmon. + curve makeOpen; beSmoothCurve. + text := ('Texts can also follow ........................................ an open curve. ' asText + , ('So morphic!!' asText + addAttribute: TextEmphasis italic; + addAttribute: (TextColor color: Color blue); + yourself)) + addAttribute: (TextFontChange fontNumber: (3.4 * RealEstateAgent scaleFactor) rounded); + asMorph. + text textColor: Color yellow. + curve addMorph: text. + text followCurve. + ^ curve! Item was changed: ----- Method: Flaps class>>newPaintingFlap (in category 'predefined flaps') ----- newPaintingFlap "Add a flap with the paint palette in it" | aFlap aFlapTab | + "Flaps reinstateDefaultFlaps. Flaps newPaintingFlap" - "Flaps reinstateDefaultFlaps. Flaps addPaintingFlap" aFlap := PasteUpMorph new borderWidth: 0. aFlap color: Color transparent. aFlap layoutPolicy: TableLayout new. aFlap hResizing: #shrinkWrap. aFlap vResizing: #shrinkWrap. aFlap cellPositioning: #topLeft. aFlap clipSubmorphs: false. aFlap beSticky. "really?!!" aFlap addMorphFront: PaintBoxMorph new. aFlap beFlap: true. aFlap fullBounds. "force layout" aFlapTab := FlapTab new referent: aFlap. aFlapTab setNameTo: 'Painting' translated. aFlapTab setProperty: #priorWording toValue: 'Paint' translated. aFlapTab useGraphicalTab. aFlapTab removeAllMorphs. aFlapTab setProperty: #paintingFlap toValue: true. aFlapTab addMorphFront: "(SketchMorph withForm: (ScriptingSystem formAtKey: #PaintingFlapPic))" self paintFlapButton. aFlapTab cornerStyle: #rounded. aFlapTab edgeToAdhereTo: #right. aFlapTab setToPopOutOnDragOver: false. aFlapTab setToPopOutOnMouseOver: false. aFlapTab on: #mouseUp send: #startOrFinishDrawing: to: aFlapTab. aFlapTab setBalloonText:'Click here to start or finish painting.' translated. aFlapTab fullBounds. "force layout" aFlapTab position: (0 at 6). self currentWorld addMorphFront: aFlapTab. ^ aFlapTab! Item was added: + ----- Method: Form class>>extraCook (in category '*MorphicExtras-sprites') ----- + extraCook + + ^ Imports default imports + at: #extraCook + ifAbsentPut: [ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self extraCookContents readStream) ]! Item was added: + ----- Method: Form class>>extraCookContents (in category '*MorphicExtras-sprites') ----- (excessive size, no diff calculated) Item was added: + ----- Method: Form class>>extraWizard (in category '*MorphicExtras-sprites') ----- + extraWizard + + ^ Imports default imports + at: #extraWizard + ifAbsentPut: [ Form fromBinaryStream: (Base64MimeConverter mimeDecodeToBytes: self extraWizardContents readStream) ]! Item was added: + ----- Method: Form class>>extraWizardContents (in category '*MorphicExtras-sprites') ----- + extraWizardContents + + ^ 'iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAA4UklEQVR4XuWdB1gT6fb//d37 + 33vvdsvaUOkoVZGekJCGnY6Iiljo2HvDQhFUioIi9k4HsaAIKihN3XVXd9e19wZY1oJAIJTz + P+8ALqEJmAA653nOE8hMMpPMZ06+7zlv6UJ/o7/R3+hvn4X5BmUbevtlKtD/m6C/fZbmE5w5 + CiEO8wvOSVkTkvsEH/9e4X/2mcf8ozPp/+3Q3z4PiIMyLXyDcgJqIC7wCcwuX+J9BmYtOg4u + Mw/BNM8EmOIW995mcqQ//b8t+lvnlRMBiRzvdZmbEOJnfsG5FSsDzsECr1RwnZUEU9zjG/hk + t7iyqa4HJ9L/m6O/dRrzXnt2EEbiLQjxW3RY5psObrMPw1SPhEYhbuBuceX2Dvv49P8m6W8d + bkO03eUXr0q55L/hPCDUsHj1aXCakdgykOu4o2vsUWuPpB/p/43S3zrM9A3mC0xH+5wjUdl7 + fRalj1sLch3pUTTJOWY4/b9V+luH2GDGPBsGe+ETt9lR4LXmLLjNOdxmmGt9kmtsMv2/Wfpb + u5sBc+5mI/bCd6Mt12KDLwWcpie2RlqA7cQdMM5xd0OgneLW0//bpb+1q+kazA9jmCwC4mNs + AsHOcRdMRkhRMrREVoDF2M3Ua1n85Q1hd4vdQf9vmP7WfpqZOW8FRubSWqBrnWO6CsxsQmH8 + lH3NAk0iszF3aTXQvGWNRe/Do62Pf0v/b5r+JlXT1nO3QgizRlr4l9s7RlSNc9wOYx12gP2U + vTBh6n6wm7QLbCZsAzPbULAcF06BXT9iE4lBICYwG5ksLDFiLVwx2S32oevMRJi5MLk2gv88 + 0SlSnv7fOP1NauYxOzrEfU5M8cqADFjpnwGe8442KymIRp7kEi0G9CTnKOAN9/4Q0XUMPV5+ + +32/GTL9tZbNXZJQigUYmL88lbzmhoNLlCb9v3X6m8TNOyBrDKbjHpCUHKn2uc850qbMhaNL + DHCHrxaTKCpqllF4CEP0SSNHzApa4Xe6ihxn+vxjxQ7OccPo/+3T3yQLc1DmDATsFYFsqfeZ + VmUx6ruV/RaEePEHmA2M55X+2E3hEh7GE32UspLh5NlzYkTkWPOxRG7vcpD+FUP6m+TMJzB7 + BVb9Skjlb6lPesvL143llZ2jwcR0pVh01jOafenf//7fbDyULPqWrl272lhaLr/lE5hVtQSr + jChZFtL/KtDfJGJ+QTnr14RUw0xkhksTHYpa6qSBWBdmzJCUDdGZOwUPpYVOoO6PPn2ottmo + JSuOv8ObiRzzGM9hc1f6Xw362yfZqoAsZ/zZF1V3Lsposndca1wwyk8MaB0Djxtduyvr4eGG + oG9C/w59HDm+q9uetb6BWaKlPmcKHKYd0af/FaG/tU1iBGWZ+YXkXq+Nym1t/DUK9Ei/utH5 + ep9++gTUfejzag7vK3ZT+ad7r16b/swvJGeXr+85+kdp+lsro/L6THPSb5nA7BuU88kSo76T + vHQt0KoatrF4yAASjEljEP0bdOv659Sjl6zVyoCz6vS/OvS3Vln88WsChPl5bbfPT+kp11RO + erj5ug9AKw0a/QQPW5uSM0P3auS0fkKnf487+lvrjD384Y8+ITlH/4E5WaIwE58w9QAwuUs+ + AK2mZfcAD21ZcwpK6LMaObUhNbDT3+hvLdTMIb8YrwnJiUeYq1avy4QZC45JHGZH1xjgj6zf + IHS/goe3RXdEn9bE6ZEGozn9rxL9rUW2fHWqwprgnDO1mpkMk5I0zFS6zk48XVfdf2NRGp6C + BnocunYTp+iAbkf/K0V/a5H5BWUHom6uJECTqpw0YCY+2npDA6B1jTzP4ykEEcXT1PkpyslO + 6dXzp4V8Ltve0FCvH/2vGP2t6ejsnUoyGkUEZlLAcJVwRkOsMWi2rgHQqKEf4mmMaOzctLQ0 + RuhoD46Xl5MtkJHp+05DQ/2FsrLiNZm+vffiZlX6Xz36WwNDmC8SmEnhZO7SFKnATLSz9fiI + D32e67oBc+6hJk5tQK9ePQ999dVXVZMnT4aAgADYtWsXdO/eHf7zn68e43b6p/Dob+LmG3Te + rhbmBSvSJA6yg3MUmI/d1CjIdQorJ5o4vUE12Y8AhHpO36+/8v3q/7q44f8CokLof/Xobw2B + Ds4mWQ1qZLakiydEYgwbE0B1ETWu6cDfBNCnmznFPuh96X+l6G8taQjaYWTOI0AvWnVKKpqZ + jFipLqIsbg7oX4bqz5aj/xWhv31adF6b4eofcr6SjAppbrRJ24GOxZyzLzW8igx8JSNTTAQr + UX4sqQ/0LT3jeUz6XxH62yfZEu+Th0h0XrX2XPUEiVKI0A5OkZQTuGunKrCfvIfS1Wy+Vy3Q + bw1Y813of0Xob222vgOWDnCbHX2b6qzvfUZqeefm+0Rv+RClh+jNH0v/q0J/a7NpDpnhPHHa + tmIC9OzFJzoEaNKno3a0twFz/hr6XxX6W5vNkLXgqLltIJa5s6k5mTsCaCJDTAQrqoFmLThM + /6tCf2uT6RjNm4G6tchEsBzmL0/uEJhr3XTUmlodfVXbePZA+l8d+lurTFt3/mQj9oLrtdp1 + +Bj/Fk3VJS23sNv8oWGorOpJ/+6h9LdWSg3M+RqxF1URiJicJTDSIrBDgZ4w7QBmO5ZTUOsz + 5y2i/xWiv7XYVNVn6GMkrCDwmI72g7EOO6nJFDtScpCbieSqyTmhrqf/lLn0t5aZorJDD0Pj + +RmkqDF+ylaY5hHfoSCLdSm1CqmVHfe0jebr0v9q0d+atX79Fn1jYDwvkEAz1W2PVEaifIpX + z6BEAS3UNZzjSf8rRn9r0vQMZ/XGn/IUAsw4x3CJTkUgKbdz3A0MTnVfD0P2gks9ZfS/p/+V + o781sL4DxvVAQMIJKDbjN8IynzOdDubqhuFBYAs+lMFfKw0yG0X/q0d/a2AunntWWNtvqHCd + GQkr/M+C84y2FFDiYKp7LDh5xqDujqH+Js9JumFYdyYlPaO5K+l/9ehvYjZnRbKyX0jub7V9 + nV3bMOjV2TMKtq1fDD/HjIEnqfrw4IQRnI+ygAOhM2HxonAJ9+v4Z/AsSqTL9L+C9LcP5hec + 7ecXnHN2TUhulZdfBrjPbZ1uJtF4T8g8eHDcCIqzVECYI+4l2SpQmMOA+9lLIT05GhISsyA6 + 5jwEBR0Ct5kxbQJ6olMkcIatqpUdRfS/ivQ3ynxDsidWLz2cA/OWHgFzm1AQjFgDxuxlYGC0 + EDS13ClXVp4EigoTKFfXcKWe0xrsAfqG8yFgoUOjIIv5LxwQ3V4BFQVHoUr4DKpKHoPwQRQ8 + z50FPyfMhIObfGC1V0Rbq4ZV+oy5Y+h/NWluXMESV1v7kPsskwUwUGUCyPQxh5+6D4fuPwpa + 7D278WG/95DmYUYv/XUkiO6vg4pX6VAl+hsqC29AxYPtIPptMoh+sYGyn23gbfY4iESwXWdE + tThK184ZPVR/7lr6X1Ga2n//w2L/+B33KAL5tjXwNubyMlx4cHSQGLwkWufs0oDfo9TgdTp5 + biCUXrEB0aPNUPHmIgL9Firf/AbldzaA6NJ4CuhaL75gC9kxc8CtBVBTS7vVRGnU0VH0v7I0 + tR++5e7q9oOg8lNhJm5qYNwgGqdu0gT5vjxQlecAT48F8x0M4fg2e3h8eQuUv7sKVWWvofJl + JpTf8EOIx4oBTVx40RaStnu1bGZ/l2gq42HEWviU/leWhvbjN9z13X7gl0gC5h5d+RA4W6cB + 0A6jjBrs27enKRgOHQvOk/0gZG0CbA8Og2Nb3eFaoiW8yrBCyWEtBvXrLHvw8QpvUUeo8VP3 + k45TZVjdpH+nf1pJja80dRHm95KAmbgcRuHzu9XFYH6cPAgGynEb3b93j1GgozUDhpn4gZry + VHzOFJQHCGAkczgkBI6B0oviUCeGzgFr6y1g77iPWmOlObjNx26qGsqYHUT/q0wT+9e/FL5D + 3ZyGQFdJCughA03gTbp4dE4J1cJozGt0/369LcFIZyHwWN6gMGCc2DbG4GGYu7YSAzpzjxPw + jDE1p7cImIylMHzUOhg3aQ+1vFtjetrWYWeuunr4v+h/tWlg337NnSIpkGt9mrlhA7mxxlO3 + yf0JxBzGCmAZLEW4LcS2MYcMg2dp4kBn7JwGbMNloDt4FmgMdAYluQkg398OhurMwsJKBDXL + Uj2oi3UN3L+j/9WmgWFkfiRZoPmwY7l2A6DHsJhN6O1hlMwwZfuC3pDZ0Kv7CLHtk81GiEkO + ksbb7+8ODN2FMETdAwYpTga5fmOhz0+jq9+v2zBQUXEE3jBfavBsNdDxlVZjt+nQ/2p/6Q3B + r02cJR2d1RQ4cDNBVQxmkqbr35vXpH4mkdbUxBdUlaY02H48zEwsOr/NsgUXu7mgh69RU5mG + 0d0eZHqZ441h2uj7yw6wBTZ3ZZWVffhi+l/xL9i+/g9bq+sP/IeSBnqYoTFV0q4L9N5V2vAT + Zj4a21+mtzkwUQtzmaso2VB32yB5U7iZZCkG9JPUccBlLARtDU8YqDgJZGVsoFePkS05t5ff + fs0LpP+V/1Kj8/e8/ZhzrpI00HamzAZyY5GjftMZkX62CPNKqoHXFyNt3W2jWcPhTaZ4hiNt + qyMYDJ0LmoNcQFG2+ehc31FeVaIX0//qf2kNwf+xJ0oq51zfbXgNgd6yGCN0t8YjNGnQmbJ9 + QEdzJvSsp5+XOY0Sy0OXXrSB9fNdqBQfkSetiM5iTn8C6ln+6b5Gn+u5//At3xNhfiwNmGtT + dvVL3q/TB8LhIC0ImK4LLlaGGHm5oKo4HGWIKZWlECDQ9fVzr+4CSN9mLhadX2aMhXGjPUFL + 1ZW6Efr2MqNy1q05v+//y/OnNbxnOV3+L3aunHzt/8/tuvz7WZr8pM/xs9g7hHG5/CU3eYJl + YGYVAKPM1oDpyIAPPmzUWjC33QwWY8MpH2MVKradw18NTPYyMDJeAtpDZ4KauhOVUVBQGA8D + +ttCn55jEERTCGqkSviPD4RX2aiN0+dBSuxG8F+9G6aOD0Sg7cXAMxrcMF13OcYeI7knqCqT + 6GyLUX94q2+4bv/l0aezUvr6QT3OrlUTW5Tx5vHew7JClM22L//JpOCU/OnHqf35tUDnn5Ad + mX9SdkJn/ky+QTmjfQKznfyCcxPR73mvz6r0WpMBC7xS2zjypF7hwjUWJk6LhHGOe8HafiuY + 22wCh4l+8FcStwmg1aD0CoJ6zx8qXqZBRckTeHnnNFw65gPbV9nCFEzTcfWGQey6MSCsVyHc + 4+OI0dkFVBQcavLVpq0GuiuW+GkB89OU/prkMSNIayt5zEvs0/fpyQEDC9LkjlyIUFx1IUJB + UJAmX/o0TW7cs1S5BRTQqXLx6Ps64+exc/RT9w3O3r8mJPcJgly1KuActe6Jy8ykdhnfR0ai + 3DnGagj0eS0o/cMBRA9DoeJ1LlQi0BUFKSC6teZDD7u3WdYN+nAUZtuA5/hpmKqbQhViSLqv + LZLoh285G794mO8c/MEkP03+8qvkXoyzwVrbf907wDg/VXYzwpqAj1vuHZKLuBCu6Pn8lILw + +SlZt2cn5aixagh47o1YxRMJy1UX5h/r0+EzxxubOv13issWVb/g7GAE+RHpnL9izVlYsCwJ + ps+NAreZkeC1cgt4ztlPjSYh4JGxfR6zD0p8fB/x5UtC4WLMGMg/pQOFmTW6+oIBlF1zh/In + u6Dy3e9QWfwQyp8lguj6skZ72NX6hQP2oD+4OjoP6GvdJrlBRehvuaG0iNAFqfJpCOit9GAF + nYxgrdgnR+VmPU+Tf5eXKncGPe/wioHT81Ply56lDFhKgC5I6aeL22+djxj46NAKjScYyd/k + pfRe2hHnvtgrtavP+vOzEOIXZNEeMvZv3rKTMM0jFkLXBkDk6iXwZPEoeLeEA2+sOfD3PB5c + n28DN/ys4f5WC0ib4w6p26eDF0bVlSvDpRa1583bDrtDV0P2sfVQcOsQFL+5BxWFN6D84Q4Q + /eHZJMz5p+2AqetWUxW0hd41VcG2Ac2jB9B5JwY4IdBFl2P6qGYED466ul/FGf8vxCh9tuCU + QnlWmMquvJMKlQhuKEbtVXkpA2xx+9P0kEF5x7zVn5HX3j/x06S3UT/2keZ56uoG/3vxyowf + VgXc6L3K9yzDOyjHEyNxCsqKcrI2IFmBynlGAkbkfRAbvgj+9B0Hb2cjyOPROXWcW/34dioH + Cjfh3w7oW/lw2WU8THWT/rReTtPjYdWaFIiLSYObWVvg/c/OVH9nUtquLXEXXxgLN5LdwGfx + RmAxlsAgbAz272tFlcvbCnS377hbadMoRFjT8lJkV59Zp+6QHaYZhZBmIbw7n5+Sr/xlu9Lp + u4mK5fj3NoR8B/r8vJPyL04FqpamBKg+xH2fPUvpJ9H1PVavXv2v6eHH/73a74+BKwLP2KwK + yVqM0XeXX0jOZYzE5avXZsJSn3RqxVYyi5HzjEQKlrVrQyBy9zLIH20Kb4bVA7kZf+vJgReb + htVIkPadU2Pm7EjYHLAZjm73hrMHl0BixBoI8t4Bs2YehhkzjlLu4hILZqODQHuwR5vyzzVA + b6MN0IfW9hyBmYx7f+xTZp8NGXzmXpJCdH6abBzq68c3YxWzL+9WFhWkysUgvHvQtz05rlBx + MkCtIjNs4DsE/AwCPfJTjr8y4KyuT1D2uiWrUrf7BuZsxaibjl6AEFd4+WVULlp5qoo07Dzm + HoGpHk2vZTLTeQ/8NmocvBnRcpgpR/h32nth9IzukIlipqK7eaLen34EAT7yAeS6TrYRn+Sw + F5iMRSDbz4b+QNe32PkqtvHLFPTnTvzv1wjqa4zSPtg43Hhlj+oR1Mn3qhuHcnczN6r8nX9S + 7hgBGiWH+4MjilXJfupVl/coV+WdlNv4LLnPR2fqmbvocFefoCwzn6Cc9d7B2WGYVtuBjbhM + lA15KBmKMKVWtmhlWtWcJSfAc/6x6tRaKyZE9HA+APHWc+Fns4lQMAUjtCWCOqplQD8NGAXr + 1gR3+AxILh6JNVAfbdbJPu7uiWBjvQl0MS/ep+do+gNdawmLVZft8RwwOj+1/1wE9t2NKCXP + zA2Drz88ongfc807MMMBOZsGvnt0TOEibt+HgIfejFUCBBruH1aEvFTZxWcj7cx8g3Nd/YKy + tyGgYX4h2Qcxwl7Avx+vXpf5aplPeinCCtWwHqVgJatGNRdt2+oko0FmKAoOCoQF83bCrrBV + sG/1ckjz94Ac68nwfJYpvODyoTCiGuZ3qzmQGz0NXDooOjc6QQ2C7Tn98EfBrnUPjySYOHE3 + FbnlsNBDa6B3eMgNTFiqtv1OxE+KCOtV1Me52aGaUTdiBpZjliMBIa64skcZrh5QuoTbj6Gn + XtmnAmnr1QD3rXyULLfBzoo9Y4y5/R37ibOFzp6BVc7TtyKwe/EnPBY9EcHtKDjiKHedGUVl + PlauCIc1qzeAl1s4RM1ZBOljnODqKBvwnxuM5xjbqearIzLEFWVIS6GujdzTpkXByOH+1BQM + tNXQsUtVhh9aouL05Hj/eQhw8dWDKlv/PKBajn/fxQbjX7fjlSB3s8ot/Ps4Pnfj4taBgGk7 + wL9fFaTK+svIyHyvpqapb2LCmc3j8X/m84dVCkzHgMDUGoaPmgqWdt4wblIoODjt7dDZ7muh + nVqTeyZZjenOmJt2jemUkzDWyhDPFsiQ+mA7Ou4DtvFSkK2J2LQCmljiUrWkcyHKUxDSq09P + KFz7eavGtYI0hQqE+Cw2AqvSAlQxRSeXS7Ia50IHwV9RygToh4+Oy86p+z6ysvKqJiYm4xHs + RD5fUICPVQg6sNg84HAR8mETsUy8DOwdsVTstK9DAf9cXLzR2Dqwp06NBB5nJZEiW2kF9C7X + vuzEpar7f92htBezG69+36eafztepQolxp9Edpxep1qCDcOHz1Lk32VsUIWHRxUBt11GDT29 + qffkcrkOfD4/DaHOQrgruVyEmsMFNtuEAtyEYwYmPDvgD3eC0ZaLwHZCMEyYuhMcXaPoD3Ij + Ps09AcE+REXs6a0Am7irS/xfbm6H5w0dGtGVPtJjgRIjabnab9ciFW/filMRng/XRGjl8xHo + sosRKvAkWQGwsQg54QPJ8yKM2L+35H0R5D0EaIHAFIjj3xituWBoZAh6+nqgo6sD2kO10YeC + vqEJsLm2MNJsLgX3JBf6w90o2B6H2hCxjwo9PQ8HKCiE0GdC9MjFKnYnfFULsZgC2WGD4W6i + MuSnyb3866Ay3I5XhDsJSnBljwpQ1cQ0udsfez82m62DAItqYa4FGqM2sE1MgMFggBHDCAwM + DUBXTxeG6gytgVsb/2cAi2ONcM+GsQ5hMMn5IP0lSj2w3VspRXDfMnf3w2sVFdO+pQ3USUtU + N/y8VaXyyh41+HWHOonGQgL4pR0qcCNGCW7FU3KjCCP0pebex8DAoA+PJ0iuC3N9J3CbELCZ + 1WCTqF0Ldy3Ytc5kjYEJ4+fBnNkR1NzL0uhY9Dm6c03DsaVg434id/dDAbQBertzjz5HV6hd + xGwHnNswBB4nY745RQEyggfB1UhleHRMEUh+GqGO/IjUmCMQiEfnppxEbBabTUFd6wRufQP9 + OpJEG0Ln6cG1GDac22UFO9fNhXlzt9Ef6to0X40MmT6jRcWZYg7nwgDaQB23RGXJoWXq5WcC + NeGX7SRKK0Cytxr8tpvIDQUiOcqxauja1Osx6upxOLxIjMBPWwJ0fTlSH27ii6cx4fVpPjxP + 5WJRhw034ljwy/7hkLp1HMQFTIUdK2ZByBIvWDp3I160XXihY2kLt0cLCjOenkeeurnF29EC + aOvB3/4ncbGqb5KXBpwJ1MKshhIc91GDP/crU9GZ9LjLPznAqrn30NTU/J++PrsHk8kcjqm7 + lQhqMgL7qKVgk4wI09j4A9Cbl7Gh/PwwykW5w6A4UwB5JzhwM5oJ1zbrwV+b9OAq+h9hBvB7 + mBFc2siC9PWjId7XEcKXLwD/Rb6weE4YZgoO0AJsJ4+PaewjVQh1Jm2i9H7Lb747ulL10pEV + GnB5tyolOe4nVcuNglS5i9d2fvNDa95PQ0Pje4RbXltbh2liwgtAwFMR3GcIcGVTUGPaD9N7 + HArs3B0cqLgw/IOXZmMZm0Tr/UZwI1yPgropJ7D/iaBfCWVQoKeutYBIb2fYtGwR+CwIgPmz + t3yxmvxD47HxzEfF1KkJ9NHTv2+R90xerVae4qcOuRGKcGW/PDw8Jg9kRMunvreurm4PDoev + bWjIMEd47zcXrR2s+VCYbioGNPHyLFMoSWRBcawxvMVIXbDXCB7sMIBbEfrNAl7X/wgzhF8R + 8nOBIyDBzwG2LJ+HkK+FOTO3fVGQk8ZjYxEb/3/r7p40gzZQX96jmLvJRREWWsjAAnMZ8Bor + AyEuMssleQwOhzMDI3Z+41ALYNsyPiUz6gMtOsOHskS2mAsTWFAUZwzvoo3hBUbvRzsN4DYC + fr2FgNdCfnEDByO5Jexf7QrrF6+i5MrUL0CXVxdokuo0Hon0SEqiDdDTh/U55cHvW+5pKgPz + RveDRZYyMHd0X4kveSArK9sbq4uzMSLn1QV6zAgB/J0qaABzBWrpsuOcBkA35aUIekm8MRTG + YCTfZwQPMZLf2ar/UblS169u0qdAT1tnAXtXu4PfwjXYANv32cONab9Kd/cEX1oA7crt5bLC + Tub9wQUqELVgEGRtViy9Gi17J/+krJk0jofR2gLz17m1QC9zaTw6l6OGLjts0mKgGwechYAb + w8sDDLi/Xb/VkZwAnhE4Cg6udgbfBWtg5oydn2UUJ5kRZ/fEQktLry+/ipge2M3wWoz822Oo + pZOWa8DJNaoPn56Qu4KVwuvSOqa6uoY8Qv07yo3KuAA+ldloIDdO89oMc1OAF6NUeRtVHcEJ + 4De3tBxu0vDMCRbA3lUesGD2ZtSskR80+BJMJRJN7uTRuUv59i7Ri/rJ6f/3iwY6P3VA9IND + SnmHlquXHfdWBwL2rXiqs/95rBaGSOu4ampqA4cJuNt+2y8or6gHNAG8LJkjUaAbA/w9Ru9X + BxnweFfrdPiVUCNIDrCFwMUrUJLshZXzAzGFOAoOrxkP61CPe0zf0ymBnuwWJ5zgHLVQc2j4 + lxmp/z7Re33eSYWi37YPepO8Sr0yN0wNjqxQJ/2j0zHTMRuhTpTm8YuijfqXnjMtaRCdzwmg + 7BBbqkA3BvjrSCY2NBmQj9mUx7sMKcg/BndW0HDYuXImpggXUtqbRPJMfO6gtytEeM3DaL4F + o3nnKeUj1BWObrEJdo4Rml8UzIVR38thASXvTqzyk+yNapVHlqveyggYVJWwULUsdtGggOep + faVeOi0/zBA0aAyil53ktivMH4P86e6Pw02KPYf8JsA5hLn+ttPrzVGD+6OWjek0YDu6xmVO + mBSj+sVF6Quzu7NO+qnG7nVVnrXJWvHNJhvFkjBrhQXtcezSFI5Xg8YgNhDLjph0CqDrw00y + KM8Q7uYyJ7+HGlKPjTmJ4IGLV4KLx0EKqo72Sa7xEV2kYR1t/gZdvtpu1WMgAv1ws40SbDRv + uh+HpAyC+/6n7JTJvgZAd4DcaC3YJBf+JpIBTxDuW800LAn4b6MYVL787tbqCE/K9+eDuVTf + lI5uRE52i71n5xTJ6fKl2iYrxQsE6DArealPLQVHDXuL0vmXGujnU7xOC3NTqUGiue9ta1yS + kOeFuA/x19gAJYUgAjrR2umYEty4dCm4dlz/kypH19ir5nYHh3yRQIdZyvsToDFS/7ZuTK9e + 0jxW5Sk1JSxtlzfIbnRCudFSJ5H7PZbpn9aTJaTAUxLHErsRinA/kl0h+12lUoJ82LB0GUbt + 6A6I1HGFDi5RPl8c0D7GvWwR5gr0JxstBlhI81hlh41MyusVVMozsZiSxP5sgRbT29HVertW + kpDcd1Opw2d7qvcjJfmTa62wQulXk+duV6iFDi6RX9Y809gYnIkwv95srShE+eEnzWOVnuS4 + tqTvxucONonYBFjSqaoECzvN7Uci+/XwarBT1lrDGiy9tyfYCLVoknOs0xcD9EazAdoI9E2q + YWghN12qQJ/mb+is6Tpp+N8HqxuHBN7mbgDSq/DRjmopQsCO8naCWTN2QHul+xDq1/bOMR7q + 6pe//UIahgrJ1TpaIUqaxxFl8JO/JP3cEie9BJsDui7Y76KrS/REf2cHD4Non2mwZpEfuHvu + bw+oSx1dYmNtx++coDTU4uvPG2hLheUEaJQdN6R5nPJMwdX6fZ87c7quo7wYG5N5KFlIvxPS + Wer0OjNYPCdUrC+JFMF+7+Ac5f1ZA73BQs4DiyuVKD3ypBqhswSvxfRzBp/+ADfjRGM/2VWt + scnonBNrbaisyPQZu2Gau3SnO5voEjNTU+czXSg/zEJ+EsL8Ar1Uajlos75fke6h4r3r6A90 + y6qVxmLFnMuhTIjycYIlczZSUVsa3Vup/h+usTGsEV7yn2HDsD9pGP5FZEeIRV9FaRzj/UGD + nvV72H1OBZUOz3djkYb0Enyw3UCsiHM+hE9p7YBF3jX57DiJyhJHt7hHthN22X5+UdpKIYkA + HWop7yWVHHQyU6tByi6N/kC3NlpTfbxRipDGI0n51VYrSRXyl41sSA6wg+CFM8HMaiGYWy8G + 2wnrYPyUCHB0jf6UaF2Gft3BKXrO5yQ75leXwOWkstJ/aRrXpAHQqfQH+pP7mGDkLophwsv9 + 1aV4ordTfPSBwWDWOAuYTBMwNuaCCWc0mA53hDGW88DKzhvsHEKo+QZbWjJHqN+Nm3ow6LMA + 2tu49zAKaEv5nVIpe6do6DcA+gSX/mBKWJaQ8vrlTUxgsdgIMasO2PXduBp0Fg84PHMQDJ8E + oy3mgvU4X7CbtBEcXSKbiNbxlaitr0+cEjuxs0sOa9TRzzEnfUEqETrZmN+gqCLlESp09RcH + 2TVzoFTPWkWmPSZzetc6mfCHPFfXyXPUdnzkcE2BxzeD4SMdwMxyFtiM94Pxk7eIyRZSNp/k + FDPf3iFmYOfMRZvLqSHQV0jqLtC8v5rEgT7OHt8A6C+8qNJhFcooNrRmurbm5k+pdVPTMTB8 + xFgYY+EK1nbLYdykDTDJJbLcxt43afDgwX07acVQfjsCXYINw3CJNwrTOCsaVAnpX1SRGtDD + hwkkAnUduCvJvIZksnsej+eDkmYsh8OREViEdvwAXGHuQKWybJ6LKEewuuIcZ0xlrik11izU + Sm72ZhvFqmDzPvMlXlQ5wwtuMGVBB11w0p952xx98HXSpXytiy7snKcHu+frU37Sz5DyNPRf + Qxnw5+Zqv7OdCXd3VPvTvcbwbF+1vzpoDG+iWJST9+5ooN9Es2GcuUASEJcTiPl8/lkmkzWT + zTax6nRR+H0GU1+UbfpLWSq3iprU5SS3UpTJ/1WUyRsV5azECbdVgjh31eMVZ1jDRBkcia0o + K0rnRTYYpdJhFTgWzBo7FPSGalGuPUQLtLQ+7ixDLWAbDqbcnDcELPjVPnGUNkwx04ap6DPx + feeO06F85WQdCHTXpXzrHD1I9jZol8/3FoG2txB8CsR5XC5/r5aWtgPqavNmuzM8ku1edpFl + IsrleYlyBf4VORyzdoMZ3Pr+u/w8P6LsGKdK7EsgP/2p3Nd39hkFXFqjDW8imaSPclXZUZPn + ZzZo20gE6HOCRDGgO7DsTTrlXw1nwLl1RpSf8DWEQyuqPWapASwYPxT0df4BmUDvbKkNjmOq + nQCsq90QeF3cz0jvHyf76NQ42W4tGNJpgCarMKC/R3+F/pjHE2QixBFaWkMnsVisBisJw5Ve + 3YQ/s03Ls7n2f2cYKFHtonPGGqJMQYzoFLeUauCjizL4RaKLvPaZVw9yGV+XpfHymrzQR0zK + GuQ6j7NPl98e8EkL05TFG/ZEoNPrTvkl6UllJOW3tjFgmPHgBrBOGq0NF0Oqu4Le2saEYayG + +4xkD4a9C/XhyiYG5elrjeCUvxGkonSJXWYAx70N2wfoGHbVeAt+IUqFmwjpYTabE66pqRWL + 4L6tgfcaWdUM3YvL5X501eDKyz37o2Q8LjrJBcrTefcqNmpblaVy/iw7XO/4GBxFadxXZdmc + WdIH+rj+f1FmXGll8v6xMJYp9ynHLYk3lC3PFOTWbRCKOmE/aALrkolDm5QcDhiZ38WwYLmj + TpP7WGEUbkl3Uel+DnZhSQJDYnKx9BR3YYMGfDqvvMlzwF93vN7n2yVKi/aqz8aDVrbi5zlH + lGjc41OOWXSYrY0/TX+JAd0JiyovsXFngdq4OR1NGoYC5uAmtxOZ8WSP8RcFdEmccVCrjp/I + LhKmcttnaJfIstePwnjj8y0+uXj9Ty51osbSxqzGNbGU3bHOV1R5fsCYauwRMDE1BVu2bIGE + hASwt7f/AGxOoBFwjaqBHjNmDCQmJkJ6ejpMnjyZeo7o5esRzC8K6MJoA2v81aloOTPGl8pX + 9+vebo1D0XFDb2zwiRo7mXdRTKqDOfV/Aut+2QVl3U++w5PZLIzQD8SAPtz5iipk/unxI4aA + trY2REVFwfPnz+HFixeQlJREwcrAht7jXQywEQwGHR0dSElJ+bBPcnIytY+hrha8OPBlAV26 + R7dXSbxxSgtl2yvhXlXT9sk/p2pxSjP450Qp3LKmRlrfC9eHPZNU4MCUgfByn+H2B5wu/5KA + BhtZnmX6vLMXVUj2I36ZLrCMmZCVlUWBSvzixYswFFN7oR7aVKf7xOW6wGQYwvnz5z/sQ/42 + wMzIRtxHGP9laWgqPRen79CiYx/n3MtPNtkkfZjPaH+H+eZjH5sy4O/9DNg2ThnCbZTgWpje + 30WnTXifDPQZBDq7DtA5pp22yvYGf6G8HIZAoN9SuH//PjwvKIADOzbAjtlDPgx4JdPzek0a + Aut9l8H169fh8ePHsDNsDe6jTe3T8Y1byQNdkshoEdBUoDrJrRDlmkZJN8NxQdAbc833P3ZC + hfizG+2sCqTnXe6qIVgAYX/yjEqlp7mjEOiXH3rZZQk6dZfM+9sMIMNfH7I220DutolwKYwL + z/eJj94m+6Sv0YP0DWaQtcUOU3rVfZQ7OsMhLaDL4rWXtuo80njvy7L40us/Lczh9ShL4fzR + ki6IJ+ZqUEAfmakGpckm70uyuAsqbqv80PZGIc8BJYdIbOrcTt7PmIzAJtGWQEpu8ub2IbCT + YVKd5/wlC7Qoi2NYegJzzq05hyR2WXm2IFJ6EXqK/P8rPsxqUfrlPEZmAvRe1NKUHjzOKUO5 + srcym6vTlmNXnOZPrTuekP6DYz8foMtz2byyM7zfWzu7FabuhGXp3DDpa+l440BMqzzCCCNq + 6mQebzWkgCZesLuOJkzGzEQG/6Yom2sEZ416thjoswh0zjCpLT1Bf2/w6/GuKEpb+ZOici7b + Aa/11TZ28a0siWfGt1va7u2egUNKE4wTUIJcbSzbQFJ3pGFIgP4zUOcdpu+qxER/GmZJsgRn + RBfYEypvq8q0Gmj6D72SdoR+3aZfcacB/32fyx1Sls0LRjYq6rJB8tDo5R+5kcg+b4RxzH0d + 0vMO78BTjQFdFEMahoMooKNt5faWxjFPNPgw5CcoBat95/jPyrM568ouD1IqOqv/9UeBJlXC + 1E5Y9kZpVYr591JMywkxj1y0WR/erR0Kb1F+NebvN+pBUYQBCPHmL41lUa//XIEuSWd8W5qi + xRFl8Q6K0vmFWKOoD2op/rJnoIc2edzjJsXoB3Bfsw7rSlp2inuoiYZhxcn5GkXV890p+lP7 + 7tWYiVH970Y/zDETatJFbAT8VpEtWFfxq+LwpoCmctCdqOz9PlQPXmHjN99aAR4bysB9xZ/g + zo8/ttx7dIUH6r0gz0weXi/ShOKdhp8N0O9zOGoVv+tOw6zTXVEar6pBR6NqmB+JVmuMI/sX + x+lxmwaaUyE6b+rVoX2j38XoW+EJ/yV+cqwqYYLx6WgnlZXUoFlzueAPX0CM/lhRtK4/vkbY + 5Ac7alKFEbgcZUle2WnekYoMwWHMamR1BqCFUcbwZsVgeIG/PgV2SvBwcB+40+3H1gHcnHdF + 7/4jPNTqTb3/qxlqULzNsCM09L2GjTv+ZMwNp4iyTV+UnWQG4fU5jxAXi05wKxp/D+PzeXs0 + lr2P1TD4kH7drdULn/+tiazGY8yEjOnwDv+vojXlhXFGi7GheAa/iN/KEpih5dED+gWM7qlR + Pa2BwpG1I7uKTQn1PtbAFve92+IvGX/CxIBu534cREq8CxgKjxn9KOAkBnALAL/XvzvkmctD + 4QbddstRCxNZN0TnBRGiC/xwUY4gpfycIA9/Qd+hRBS1pMsB6evzdL9eo5Pflyaqm+DnKK53 + A70pizPoXKPAC/cP6iWMN1Co/X+DhWzPTdaK78OsFa9uMu/bp8H+kQaaWN/fXxLHKv3ol4x6 + m0zM2BFAF2Ep/9kYObjbp1v7gdyI35XpDvljFSmNLvXPncQuxyJaCTUi6TC7xd0MEMxCDG5r + SvcO6d9soeygxggMgEdwf9TVzLCKeM2hXTq77eDKfLPJSiEHoRat5/dsNAVUeKRvt6e79O3/ + Psh40Gz/hfpAH22fjkmvF2vCfZWeHQpy/Yj9bLQcFG837GzzeVQVxTKvlCYxTcGiR4sGvUJo + v2/f7x/Su8vnYqt7dvl/YVZyu6pXyJJptj/Ho+06ox7vMsh5eYBRTiY6afDTWh/ow+3Q2AvT + g7u9unYemOtATTT2u7U6naIzVmEMs+Lpbj3/tzs0v8xFhOqaz6iuYzdbK1WEWbRsueS7vjLq + dyP0ZqJffbLLsJwsYEkAFx5qX6BfL9WCOz+1EuZu3eAvfLz03Xdw6ptv4NjXX8Nh9KQaP1TH + k/73P8rJdrJfGu5/EV939fvv4dYPP7QY7Kf8ASA8yGzP7Ac1ATsGnioMQE8fbTfwf7hNT78L + XWyu8fdkHcNybBge9R/+XYv7ctzerKF1PVQ78E6E/sv72wyqnu01gtKzgn8W2ZTiIkEkh9wa + mXFXRQUe2NvDk5074bS+PiQgqKcR0PPffgu/IaR/IKTXENLrdZz8/zs+/ytuz8H9yA1wGF93 + CD0ZAc/C58jrbnft+lGoX7qrSrWxKKyzgD9Ziu7+doNXd7fqbbkbqsTuQkdDoN+h395gNWBQ + a197Y6vusFtb9ELubTd4WHKGX/EBaCl2Kvp7rkZ1+qwZkG4jkLd694YHEyZA/qVLHzrp3/by + ooBti5S4ga+7jICfQ7iPItSJCPS95cvh7pAhmKvu0eTrHqj1guK9DMnOO1IDMEZiasJ0hJgs + c1F8N0L//O0tOlO70NnCrBXOI9DCFXq91Nv6HvkxbL2yTNN7UgcaG6bPRsg1C/I1BC0Tocsa + PfpD53wCdMHDh/A4NBRvBsno7uujRkHB06dQcOcOPAkPh3sY/e90797ovvm2ilRqUVKygkTi + O1sNKL+9Vf/1rS36sbfDB7t2ob916bLRUm5ndT5ats1rGAqTGCqiLNNL7QH0Y6N+jUJDtC2R + EUQapCPQf7FYFMj5v/8Oj9euhXsmJpSOllTj73FQ0IfIT900eMNcd3WFm439AnTvSpXRJfQr + VfVst2HZrQiDvD/CGdsubTIaRn+KxSXHewpoa4U2D6spitfvU55telbaQFMjTlYMEav+EZAz + EeQUlAFE1/4DEUbLPn2kmtG4x+fDs+RkeJ6fDwV//AE3tbTgaI1Grw924UY9SQFdjIWR9fQn + twnbZKP4ggCNOem0zaN69OjSBiv9q//XWP5OljDQUNbII6Wj52nAfeWfKJgvI8R/tiD7cF+h + Gzxj94IX42TgtYcsvJktB4VLFcT83WIFaturKf0hf3gfeGLQEx4odW+++og3zv3hw+GhkxP1 + PwGZNCRTEeprNedEdLQwUjLZDtJ1tDiBKdX1Jj9rwwh9GVN3ZIWsW6EW8tptfZ/yTNP49gCa + eBEWLkgnI6KZb38E5KcI8ZuZslDkrwQlQcogDFEBYeigat+sJu6bVKufx31KgpWhZL0yFAco + QeFKBXg5oR881ukJd3t+XIPfrpMpeaDRC4pQ60oq04Hv83dJrJEZ/cltwsIs5YNJoxC9LGj0 + T4ZtfZ+yM7wt7QV0nrXCR6F6OKgHvJzcH0oCEeIwBHXbYBDu04PSGAY20IyrPb6e1z4fy4TS + gwYg3KtT/bpwdSjZMBCK1yHcKxTguZ0MPNLo8dFsS21vvberJTfnHQL9oijGUJv+5DZhXoN+ + ILloSnZssJSb3Nb3EZ3hrWovoEklrtGcc0+MyMxelGQoCsBIvFULSg/oVwPa1ghJFvIhsEfj + jbBPF4Q7hoAwQhPhVoG/XQdQMuZe/+ajNum2WiqhMYn4OZ7Sn9qPRWkrhRwCND5ubXOEPs3z + aC+g8837N4T5px/hxViZalmxDUGONqJglMo5EMgx0gu3D4YSlCfvFsnDE6OeTWrtB4N6SkxD + YyHlZ/oT+1HZIRdKNQytFc8FmfVtU4cUUQrXst009NpBKCn+yfne69cVXjr2Q7gGYUTWkx7I + jYF9wICSJMVrleEFSpHGZMizYTIS64UnjGem0J/Yj9hGc9n1CDRpGN4JNZdjtOU9hEdMuO0F + tHCvLhQuV4CHaj3gse5PVKOvBBtzRPe2C8j1ZQDqbuFuHdTZg6hGaF2o7/buio1KFUq2SAjo + PfQn9uMNw2UIc+EmG6XSIEFPQZuyHOcEo9oLaBIZiT6mMhbEN6tXS4wOgFkM7EhDzKYow1OT + XlRPQCKDCsz7gnCntsSyHCVxjAD6E9uy9N1DIjs2Wsi2aTYc4WmOQbsBXetxqEvjO88EMBTU + sQzqBvtws6HOlmTnpHf7h/rRn9aWNQxP1zQM2zRnWWmKiQoFdDv1h+7MTqX+SIoQpRHJsEgw + ZVeGVcKD9Ke1JTraUj6opmGY05bXQxKjF5nCgP5AS/FGSWAVlsQZ+9Cf1hZY0JgByzfVNAzb + XC3MpT/QUgb6ZUk8cyL9aW2BrTPry0a5kRRqKR/SZqCzTYuqB8nSfwVZqQCdyHpSFG88lP60 + tpMh0FcooOm/xrd00pUJrKv0p6wdTZQpOEkBfZz+QEsF6Hjjk/SnrD2BPsvfTQGdwqU/gFIB + mrWT/pS1o5Wmc71I6o7+s49Kx0viGSvpT1l7Ruh0EwsK6FP0B1oaLkpgrqA/Ze1o70/qamDq + rpL+M/hLx4vjjX3pT1k7mjCdpyTKNi0QdfI1Vj7btB39c9Dta4UprJ6Y6chFqOkPoFQahfr0 + z0G3p0Fw3/+I0rn7qEwH/QGUsLOq6E9YRzQMz3Cd23MGUhqVvV/Tn66OqBYeZ7II0CL6F1ck + Xfa+R3+6OgLo1ardUUOXdMaFgz7zCJ1Bf7o6wIqOc3/AhuGvZJEh+oMo0bI3/UeqdJiOzuCF + lWcKqugPosSic8n7WMZU+pPVUbIjg8tHHV3Z0rU/6O8fA9r4ekkc/VN2HZe+W9T9m/Jc01f0 + z3RITG7Qf9hVh0fpXH6U6AT9G4YSkBuil1Hq5vQnqqN1dK7pMVEar5z+UH6y3MitOKAvT3+i + OoGVpXLv0x/KT8o9FwrjmXPoT1JnidKpnDP0B/OT5MaZ53u0fqI/SZ0F6CzTM9Sqp/SHs61A + Py5drWFPf5I6iVWcVZAtPWZym/5wftK0Z+XCBOMY+tPUSUx4iJVOfzA/FWp2Jf21dCew0njj + X+kPpCSkB7uiOM7Qnf5EdWRkTmBlYiu9gv5Atmn+jfMYDO7X6GgSnVOKt8r3oz9VHRmdE1jP + UP9VfWKjqJis+vQZQllFpu3CHPLF4jhmMP5d3lSnfdTHdwi04pM9MqeIIg31SmKNnEpi9Mbf + DlKWoz9RHWzFscyJeKFe1YHzOV68K41Vwpop+R4XHRw4sijGwBnhSMF9b+JN8pwA09mqeej5 + 6H+UxRtvLo7UH18ax3B4u0uzf83NfbOJ190vjGaY4Oc8Vgs4PvewOF5nAP0J6pRRmrkDL5AQ + /VdhAtOpMM5wBBW5/2nBF5QlaLjhc0WNFBWKX+/VdKn7fkUxRrolCczJ+LoIBPwkWUCnKNIg + sTjeKBx/omPwhjmNz13B7dcILOgPqBsAnawehf4e37eI8gRWYe22Rjyv5vX3sEF2Df//A6E7 + h+9/CD/H7sKYoSTqluIxb5QlGCfg8+vxefv3kYaKjcqvRKOVKCPS8TVva6J3Kb7f6bLIgVRK + rjDWUJNK0SUYv0KtTP8ljj8nK4xirKyB67fimOpRzAipP4JRUBt5yXAjYTxjSVuPkRLc939l + SUxNYSJjaEkiYwJxhH6qMI7pgyD5Ey+JZ66s3VbfixKMzMjrSxOM1CTarsDP9C5Gz604gbmY + /iR8QdbYwpGlCYb2ojijRcI4xqo3cUOs6f8t0d/ob/S3z8L+P1PYPpP1IB7GAAAAAElFTkSu + QmCC'! Item was added: + ----- Method: MIDIScore class>>extraExample (in category '*MorphicExtras-examples') ----- + extraExample + "(ScorePlayerMorph on: MIDIScore extraExample) openInWorld" + + | tracks | + tracks := self extraExampleTrackData collect: [:track | (ReferenceStream on: + (Base64MimeConverter mimeDecodeToBytes: track readStream)) next]. + ^ self new + tracks: tracks values trackInfo: tracks keys; + ticksPerQuarterNote: 96; + tempoMap: self extraExampleTempoMap; + yourself! Item was added: + ----- Method: MIDIScore class>>extraExampleTempoMap (in category '*MorphicExtras-examples') ----- + extraExampleTempoMap + + ^ {0->750000 . 26496->769230 . 26592->789473 . 26688->810810 . 26784->833333 . 26880->857142 . 26976->882352 . 27072->909090} + collect: [:tempoData | TempoEvent time: tempoData key tempo: tempoData value]! Item was added: + ----- Method: MIDIScore class>>extraExampleTrackData (in category '*MorphicExtras-examples') ----- (excessive size, no diff calculated) Item was added: + EllipseMorph subclass: #MovingEyeMorph + instanceVariableNames: 'inner iris' + classVariableNames: 'IrisSize' + poolDictionaries: '' + category: 'MorphicExtras-Demo'! Item was added: + ----- Method: MovingEyeMorph class>>color:irisColor: (in category 'instance creation') ----- + color: aColor irisColor: anotherColor + + ^ self new color: aColor irisColor: anotherColor! Item was added: + ----- Method: MovingEyeMorph class>>descriptionForPartsBin (in category 'parts bin') ----- + descriptionForPartsBin + ^ self partName: 'MovingEye' translatedNoop + categories: {'Just for Fun' translatedNoop} + documentation: 'An eye which follows the cursor' translatedNoop! Item was added: + ----- Method: MovingEyeMorph class>>extraExampleSqueakIsWatchingYou (in category 'examples') ----- + extraExampleSqueakIsWatchingYou + "MovingEyeMorph extraExampleSqueakIsWatchingYou openInHand" + + | logoMorph leftEye rightEye | + logoMorph := Form squeakLogo asMorph. + leftEye := self new + extent: logoMorph extent * (0.1 @ 0.15); + center: (logoMorph pointAtFraction: 0.39 @ 0.55); + yourself. + rightEye := self new + extent: logoMorph extent * (0.1 @ 0.15); + center: (logoMorph pointAtFraction: 0.59 @ 0.56); + yourself. + logoMorph addAllMorphs: {leftEye. rightEye}. + ^ logoMorph.! Item was added: + ----- Method: MovingEyeMorph class>>initialize (in category 'class initialization') ----- + initialize + " + MovingEyeMorph initialize + " + IrisSize := (0.42 at 0.50).! Item was added: + ----- Method: MovingEyeMorph>>color: (in category 'accessing') ----- + color: aColor + + super color: aColor. + + "Migrate old instances." + inner color: Color transparent. + + self keepIrisVisible.! Item was added: + ----- Method: MovingEyeMorph>>color:irisColor: (in category 'accessing') ----- + color: aColor irisColor: anotherColor + + self color: aColor. + self irisColor: anotherColor.! Item was added: + ----- Method: MovingEyeMorph>>defaultBorderWidth (in category 'accessing') ----- + defaultBorderWidth + + ^ 0! Item was added: + ----- Method: MovingEyeMorph>>defaultColor (in category 'initialization') ----- + defaultColor + "answer the default color/fill style for the receiver" + ^ Color black! Item was added: + ----- Method: MovingEyeMorph>>extent: (in category 'geometry') ----- + extent: aPoint + + super extent: aPoint. + inner extent: (self extent * ((1.0 at 1.0)-IrisSize)) asIntegerPoint. + iris extent: (self extent * IrisSize) asIntegerPoint. + inner position: (self center - (inner extent // 2)) asIntegerPoint. + ! Item was added: + ----- Method: MovingEyeMorph>>initialize (in category 'initialization') ----- + initialize + "initialize the state of the receiver" + super initialize. + "" + inner := EllipseMorph new. + inner color: Color transparent. + inner extent: (self extent * (1.0 @ 1.0 - IrisSize)) asIntegerPoint. + inner borderWidth: 0. + "" + iris := EllipseMorph new. + iris color: Color white. + iris extent: (self extent * IrisSize) asIntegerPoint. + "" + self addMorphCentered: inner. + inner addMorphCentered: iris. + "" + self extent: 26 @ 33! Item was added: + ----- Method: MovingEyeMorph>>irisColor (in category 'accessing') ----- + irisColor + + ^ iris color! Item was added: + ----- Method: MovingEyeMorph>>irisColor: (in category 'accessing') ----- + irisColor: aColor + + iris color: aColor. + + self keepIrisVisible.! Item was added: + ----- Method: MovingEyeMorph>>irisPos (in category 'accessing') ----- + irisPos + + ^ iris position! Item was added: + ----- Method: MovingEyeMorph>>irisPos: (in category 'accessing') ----- + irisPos: cp + + | a b theta x y | + theta := (cp - self center) theta. + a := inner width // 2. + b := inner height // 2. + x := a * (theta cos). + y := b * (theta sin). + iris position: ((x at y) asIntegerPoint) + self center - (iris extent // 2).! Item was added: + ----- Method: MovingEyeMorph>>keepIrisVisible (in category 'private') ----- + keepIrisVisible + + self color = self irisColor + ifTrue: [ + iris borderWidth: 1; + borderColor: self color makeForegroundColor] + ifFalse: [ + iris borderWidth: 0].! Item was added: + ----- Method: MovingEyeMorph>>step (in category 'stepping and presenter') ----- + step + | cp | + cp := self globalPointToLocal: self world primaryHand position. + (inner containsPoint: cp) + ifTrue: [iris position: (cp - (iris extent // 2))] + ifFalse: [self irisPos: cp].! Item was added: + ----- Method: MovingEyeMorph>>stepTime (in category 'testing') ----- + stepTime + + ^ 100.! Item was changed: ----- Method: PianoKeyboardMorph>>initialize (in category 'initialization') ----- initialize "initialize the state of the receiver" super initialize. "" whiteKeyColor := Color gray: 0.95. blackKeyColor := Color black. playingKeyColor := Color red. nOctaves := 6. self buildKeyboard. + soundPrototype := FMSound new.! - soundPrototype := FMSound brass1 duration: 9.9. - soundPrototype := FMSound new. - ! Item was added: + ----- Method: PianoKeyboardMorph>>initializeToStandAlone (in category 'initialization') ----- + initializeToStandAlone + + super initializeToStandAlone. + soundPrototype := FMSound brass1 duration: 9.9.! Item was added: + ----- Method: PolygonMorph class>>extraCircularVertices (in category '*MorphicExtras-examples') ----- + extraCircularVertices + + ^ ((Circle center: 400 @ 300 radius: 200 quadrant: 1) computeVertices: 5) reverse + , ((Circle center: 400 @ 300 radius: 200 quadrant: 4) computeVertices: 5) reverse + , ((Circle center: 400 @ 400 radius: 100 quadrant: 4) computeVertices: 5) + , ((Circle center: 400 @ 400 radius: 100 quadrant: 1) computeVertices: 5) + , ((Circle center: 400 @ 200 radius: 100 quadrant: 3) computeVertices: 5) reverse + , ((Circle center: 400 @ 200 radius: 100 quadrant: 2) computeVertices: 5) reverse! Item was added: + ----- Method: PolygonMorph class>>extraExampleTextFlow (in category '*MorphicExtras-examples') ----- + extraExampleTextFlow + "PolygonMorph extraExampleTextFlow openInHand" + + | polygon text obstacle | + polygon := self new. + polygon + setVertices: self extraCircularVertices; + extent: 309 asPoint; + beSmoothCurve; + color: Color lightGray; + addHandles. + + text := (TextMorph + string: 'TextMorphs can be chained together, causing their contents to flow between containers as either the contents or the containers change. If a TextMorph is embedded in another Morph, you can ask it to have fill the shape of that Morph. Moreover, you can ask it to avoid occlusions, in which case it will do its best to avoid collisions with siblings being in front of it. If a TextMorph is embedded in a CurveMorph, you can ask it to have the text follow the curve, as illustrated here.' asTextMorph + fontName: #BitstreamVeraSans + size: 14) + textColor: Color white; + fillsOwner: true; + yourself. + obstacle := StarMorph new + center: polygon center - (50 @ 25); + extent: 81 asPoint; + color: Color orchid; + yourself. + + polygon + addMorph: text; + addMorph: obstacle. + text centered. + text container avoidsOcclusions: true. + ^ polygon! Item was added: + ----- Method: PolygonMorph class>>extraExampleTrapeze (in category '*MorphicExtras-examples') ----- + extraExampleTrapeze + "PolygonMorph extraExampleTrapeze openInHand" + + | polygon text | + polygon := self new. + polygon + setVertices: {0 @ 100. 275 @ 100. 200 @ 0. 75 @ 0}; + addHandles ; + balloonText: 'Click and drag the handles to change my shape'. + text := 'Polygons can be closed or open, filled or empty as well as lined or convex and can have directed arrows, bevelled borders and last but not least adapted handles.' asTextFromHtml asMorph + beAllFont: (TextStyle default fontOfSize: 14); + fillsOwner: true; + yourself. + polygon addMorph: text. + text centered. + ^ polygon! Item was added: + ----- Method: PolygonMorph class>>extraExampleTrapezePlus (in category '*MorphicExtras-examples') ----- + extraExampleTrapezePlus + "PolygonMorph extraExampleTrapezePlus openInHand" + "Some additional decoration" + + ^ self extraExampleTrapeze + fillStyle: ((GradientFillStyle + ramp: { 0.0 -> Color orange. 0.7 -> Color magenta twiceLighter. 1.0 -> Color red muchLighter }) + origin: 0 @ 0; direction: 275 @ 100; + yourself); + borderWidth: 2; + borderColor: Color blue; + dashedBorder: {35. 20. Color yellow}; + yourself! Item was added: + ----- Method: RecordingControlsMorph class>>extraExample (in category '*MorphicExtras-examples') ----- + extraExample + "RecordingControlsMorph extraExample openInWorld" + + | example | + example := self new. + example recorder clearRecordedSound. + example recorder recordedSound add: SampledSound exampleBach. + ^ example! Item was added: + ----- Method: SampledSound class>>exampleBach (in category '*MorphicExtras-examples') ----- + exampleBach + "SampledSound exampleBach" + + | url | + url := 'http://upload.wikimedia.org/wikipedia/commons/4/4e/Bach_Brandenburg_4_coda_to_the_3rd_movement.wav'. + + ^ Imports default imports + at: #exampleBach + ifAbsentPut: [ + self notify: ('This action will download the following content:\\{1}\\Do you want to proceed?' translated withCRs format: {url}). + self fromWaveStream: (HTTPSocket httpGet: url)]! Item was added: + ----- Method: ScorePlayerMorph class>>extraExample (in category '*MorphicExtras-examples') ----- + extraExample + "ScorePlayerMorph extraExample openInHand" + + ^ self on: MIDIScore extraExample! Item was added: + ----- Method: ScorePlayerMorph class>>on: (in category 'system hookup') ----- + on: aScore + + | player | + player := ScorePlayer onScore: aScore. + ^ self new onScorePlayer: player! Item was added: + ----- Method: ScorePlayerMorph class>>openOn: (in category 'system hookup') ----- + openOn: aScore + + (self on: aScore) openInWorld.! Item was changed: ----- Method: ScorePlayerMorph>>addNewScore (in category 'menu') ----- addNewScore "Open a MIDI score and re-init controls..." | score player | score := MIDIScore new. score tracks: (Array with: Array new). score trackInfo: #('Instrument'). player := ScorePlayer onScore: score. + ^self onScorePlayer: player! - ^self onScorePlayer: player title: 'new'! Item was changed: ----- Method: ScorePlayerMorph>>addTrackToScore (in category 'menu') ----- addTrackToScore "add a instrument track to the current score" | score tracks trackInfo player | score := scorePlayer score. tracks := score tracks copyWith:#(). score tracks: tracks. trackInfo := score trackInfo copyWith: 'Instrument'. score trackInfo: trackInfo. player := ScorePlayer onScore: score. + ^self onScorePlayer: player! - ^self onScorePlayer: player title: 'new'! Item was changed: ----- Method: ScorePlayerMorph>>initialize (in category 'initialization') ----- initialize "initialize the state of the receiver" super initialize. "" self listDirection: #topToBottom; wrapCentering: #center; cellPositioning: #topCenter; hResizing: #shrinkWrap; vResizing: #shrinkWrap; layoutInset: 3; + onScorePlayer: ScorePlayer new initialize; - onScorePlayer: ScorePlayer new initialize title: ' '; extent: 20 @ 20 ! Item was added: + ----- Method: ScorePlayerMorph>>onScorePlayer: (in category 'initialization') ----- + onScorePlayer: aScorePlayer + + self onScorePlayer: aScorePlayer title: 'untitled'.! Item was added: + ----- Method: SketchMorph class>>extraExampleCook (in category '*MorphicExtras-examples') ----- + extraExampleCook + "SketchMorph extraExampleCook openInWorld" + + ^ (self withForm: Form extraCook) + addMouseUpActionWith: 'Form toothpaste: 30'; + balloonText: 'Click me and then drag the cursor over the screen'; + yourself! Item was added: + ----- Method: SketchMorph class>>extraExampleWizard (in category '*MorphicExtras-examples') ----- + extraExampleWizard + "SketchMorph extraExampleWizard openInWorld" + + ^ (self withForm: Form extraWizard) + addMouseUpActionWith: + (MessageSend receiver: Pen new selector: #web); + balloonText: 'Click me and then drag the cursor over the screen\(Trust me, I won''t turn you into a toad!!)' withCRs; + yourself! Item was added: + PolygonMorph subclass: #TetrisPieceMorph + instanceVariableNames: '' + classVariableNames: 'Colors Shapes Vertices' + poolDictionaries: '' + category: 'MorphicExtras-Demo'! + + !TetrisPieceMorph commentStamp: 'ct 10/1/2019 23:34' prior: 0! + I display a Tetris piece. By calling TetrisPieceMorph random, you can generate a new instance of me that is random in terms of shape, color, and rotation. + + My shapes are: #(i j l o s t z).! Item was added: + ----- Method: TetrisPieceMorph class>>initialize (in category 'class initialization') ----- + initialize + + super initialize. + Vertices := Dictionary new + at: #i put: { 0 @ 0. 0 @ 4. 1 @ 4. 1 @ 0 }; + at: #j put: { 1 @ 0. 1 @ 2. 0 @ 2. 0 @ 3. 2 @ 3. 2 @ 0 }; + at: #o put: { 0 @ 0. 0 @ 2. 2 @ 2. 2 @ 0 }; + at: #s put: { 0 @ 0. 0 @ 2. 1 @ 2. 1 @ 3. 2 @ 3. 2 @ 1. 1 @ 1. 1 @ 0 }; + at: #t put: { 1 @ 0. 1 @ 1. 0 @ 1. 0 @ 2. 3 @ 2. 3 @ 1. 2 @ 1. 2 @ 0 }; + yourself. + Vertices + at: #l put: ((Vertices at: #j) * (-1 @ 1)); + at: #z put: ((Vertices at: #s) * (-1 @ 1)). + Shapes := Vertices keys. + Colors := #(red green blue orange grape yellow) + collect: [:color | color -> (Color in: color) lighter paler] + as: Dictionary.! Item was added: + ----- Method: TetrisPieceMorph class>>random (in category 'instance creation') ----- + random + "TetrisPieceMorph random openInHand" + + ^ self + shape: Shapes atRandom + color: Colors atRandom + rotationDegrees: Random new next * 360! Item was added: + ----- Method: TetrisPieceMorph class>>shape:color:rotationDegrees: (in category 'instance creation') ----- + shape: aShapeSymbol color: aColor rotationDegrees: degrees + + ^ self new + shape: aShapeSymbol; + color: aColor; + rotationDegrees: degrees; + yourself! Item was added: + ----- Method: TetrisPieceMorph>>initialize (in category 'initialize-release') ----- + initialize + + super initialize. + self borderStyle: (RaisedBorder new width: 3).! Item was added: + ----- Method: TetrisPieceMorph>>shape: (in category 'initialize-release') ----- + shape: aShapeSymbol + + self setVertices: (Vertices at: aShapeSymbol) * 20 * RealEstateAgent scaleFactor.! From commits at source.squeak.org Thu Apr 15 14:53:55 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:53:55 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.264.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.264.mcz ==================== Summary ==================== Name: MorphicExtras-ct.264 Author: ct Time: 21 September 2019, 4:29:30.797719 pm UUID: 2cd520ce-9476-bb42-9bbb-7c4e0b62b361 Ancestors: MorphicExtras-mt.263 Update a comment in Flaps =============== Diff against MorphicExtras-mt.263 =============== Item was changed: ----- Method: Flaps class>>newPaintingFlap (in category 'predefined flaps') ----- newPaintingFlap "Add a flap with the paint palette in it" | aFlap aFlapTab | + "Flaps reinstateDefaultFlaps. Flaps newPaintingFlap" - "Flaps reinstateDefaultFlaps. Flaps addPaintingFlap" aFlap := PasteUpMorph new borderWidth: 0. aFlap color: Color transparent. aFlap layoutPolicy: TableLayout new. aFlap hResizing: #shrinkWrap. aFlap vResizing: #shrinkWrap. aFlap cellPositioning: #topLeft. aFlap clipSubmorphs: false. aFlap beSticky. "really?!!" aFlap addMorphFront: PaintBoxMorph new. aFlap setProperty: #flap toValue: true. aFlap fullBounds. "force layout" aFlapTab := FlapTab new referent: aFlap. aFlapTab setNameTo: 'Painting' translated. aFlapTab setProperty: #priorWording toValue: 'Paint' translated. aFlapTab useGraphicalTab. aFlapTab removeAllMorphs. aFlapTab setProperty: #paintingFlap toValue: true. aFlapTab addMorphFront: "(SketchMorph withForm: (ScriptingSystem formAtKey: #PaintingFlapPic))" self paintFlapButton. aFlapTab cornerStyle: #rounded. aFlapTab edgeToAdhereTo: #right. aFlapTab setToPopOutOnDragOver: false. aFlapTab setToPopOutOnMouseOver: false. aFlapTab on: #mouseUp send: #startOrFinishDrawing: to: aFlapTab. aFlapTab setBalloonText:'Click here to start or finish painting.' translated. aFlapTab fullBounds. "force layout" aFlapTab position: (0 at 6). self currentWorld addMorphFront: aFlapTab. ^ aFlapTab! From commits at source.squeak.org Thu Apr 15 14:54:02 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:02 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.265.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.265.mcz ==================== Summary ==================== Name: MorphicExtras-ct.265 Author: ct Time: 21 September 2019, 4:31:18.110719 pm UUID: ab3cc325-22f4-cd4b-b806-2125e4ed2e08 Ancestors: MorphicExtras-mt.263 Clean up PianoKeyboardMorph initialization =============== Diff against MorphicExtras-mt.263 =============== Item was changed: ----- Method: PianoKeyboardMorph>>initialize (in category 'initialization') ----- initialize "initialize the state of the receiver" super initialize. "" whiteKeyColor := Color gray: 0.95. blackKeyColor := Color black. playingKeyColor := Color red. nOctaves := 6. self buildKeyboard. + soundPrototype := FMSound new.! - soundPrototype := FMSound brass1 duration: 9.9. - soundPrototype := FMSound new. - ! Item was added: + ----- Method: PianoKeyboardMorph>>initializeToStandAlone (in category 'initialization') ----- + initializeToStandAlone + + super initializeToStandAlone. + soundPrototype := FMSound brass1 duration: 9.9.! From commits at source.squeak.org Thu Apr 15 14:54:07 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:07 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.266.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.266.mcz ==================== Summary ==================== Name: MorphicExtras-ct.266 Author: ct Time: 21 September 2019, 4:37:53.910719 pm UUID: 925300c8-ccdd-3e44-9274-d5ccf593822b Ancestors: MorphicExtras-mt.263 Refactor ScorePlayerMorph initialization As the current #onScorePlayer:title: implementation does not use the title, I think we can deprecate it? In this case, there are further senders in the image which need to be updated. If you confirm that, I will also move the method into *60Deprecated. Please note this commit also includes some convenience constructors apart from deprectations. =============== Diff against MorphicExtras-mt.263 =============== Item was added: + ----- Method: ScorePlayerMorph class>>on: (in category 'system hookup') ----- + on: aScore + + | player | + player := ScorePlayer onScore: aScore. + ^ self new onScorePlayer: player! Item was added: + ----- Method: ScorePlayerMorph class>>openOn: (in category 'system hookup') ----- + openOn: aScore + + (self on: aScore) openInWorld.! Item was changed: ----- Method: ScorePlayerMorph>>addNewScore (in category 'menu') ----- addNewScore "Open a MIDI score and re-init controls..." | score player | score := MIDIScore new. score tracks: (Array with: Array new). score trackInfo: #('Instrument'). player := ScorePlayer onScore: score. + ^self onScorePlayer: player! - ^self onScorePlayer: player title: 'new'! Item was changed: ----- Method: ScorePlayerMorph>>addTrackToScore (in category 'menu') ----- addTrackToScore "add a instrument track to the current score" | score tracks trackInfo player | score := scorePlayer score. tracks := score tracks copyWith:#(). score tracks: tracks. trackInfo := score trackInfo copyWith: 'Instrument'. score trackInfo: trackInfo. player := ScorePlayer onScore: score. + ^self onScorePlayer: player! - ^self onScorePlayer: player title: 'new'! Item was changed: ----- Method: ScorePlayerMorph>>initialize (in category 'initialization') ----- initialize "initialize the state of the receiver" super initialize. "" self listDirection: #topToBottom; wrapCentering: #center; cellPositioning: #topCenter; hResizing: #shrinkWrap; vResizing: #shrinkWrap; layoutInset: 3; + onScorePlayer: ScorePlayer new initialize; - onScorePlayer: ScorePlayer new initialize title: ' '; extent: 20 @ 20 ! Item was added: + ----- Method: ScorePlayerMorph>>onScorePlayer: (in category 'initialization') ----- + onScorePlayer: aScorePlayer + | divider col r | + scorePlayer := aScorePlayer. + scorePlayer ifNotNil: + [scorePlayer reset. + instrumentSelector := Array new: scorePlayer score tracks size]. + + self removeAllMorphs. + self addMorphBack: self makeControls. + scorePlayer ifNil: [^ self]. + + r := self makeRow + hResizing: #spaceFill; + vResizing: #shrinkWrap. + r addMorphBack: self rateControl; + addMorphBack: (Morph newBounds: (0 at 0 extent: 20 at 0) color: Color transparent); + addMorphBack: self volumeControl. + self addMorphBack: r. + self addMorphBack: self scrollControl. + + col := AlignmentMorph newColumn color: color; layoutInset: 0. + self addMorphBack: col. + 1 to: scorePlayer trackCount do: [:trackIndex | + divider := AlignmentMorph new + extent: 10 at 1; + layoutInset: 0; + borderStyle: (BorderStyle raised width: 1); + color: color; + hResizing: #spaceFill; + vResizing: #rigid. + col addMorphBack: divider. + col addMorphBack: (self trackControlsFor: trackIndex)]. + + LastMIDIPort ifNotNil: [ + "use the most recently set MIDI port" + scorePlayer openMIDIPort: LastMIDIPort].! Item was changed: ----- Method: ScorePlayerMorph>>onScorePlayer:title: (in category 'initialization') ----- onScorePlayer: aScorePlayer title: scoreName - | divider col r | - scorePlayer := aScorePlayer. - scorePlayer ifNotNil: - [scorePlayer reset. - instrumentSelector := Array new: scorePlayer score tracks size]. + self deprecated: 'Use #onScorePlayer:'. + ^ self onScorePlayer: aScorePlayer - self removeAllMorphs. - self addMorphBack: self makeControls. - scorePlayer ifNil: [^ self]. - - r := self makeRow - hResizing: #spaceFill; - vResizing: #shrinkWrap. - r addMorphBack: self rateControl; - addMorphBack: (Morph newBounds: (0 at 0 extent: 20 at 0) color: Color transparent); - addMorphBack: self volumeControl. - self addMorphBack: r. - self addMorphBack: self scrollControl. - - col := AlignmentMorph newColumn color: color; layoutInset: 0. - self addMorphBack: col. - 1 to: scorePlayer trackCount do: [:trackIndex | - divider := AlignmentMorph new - extent: 10 at 1; - layoutInset: 0; - borderStyle: (BorderStyle raised width: 1); - color: color; - hResizing: #spaceFill; - vResizing: #rigid. - col addMorphBack: divider. - col addMorphBack: (self trackControlsFor: trackIndex)]. - - LastMIDIPort ifNotNil: [ - "use the most recently set MIDI port" - scorePlayer openMIDIPort: LastMIDIPort]. ! From commits at source.squeak.org Thu Apr 15 14:54:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:12 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.267.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.267.mcz ==================== Summary ==================== Name: MorphicExtras-ct.267 Author: ct Time: 1 October 2019, 6:14:00.728339 pm UUID: 40f6b08c-c705-854d-9ec5-c28571b022d3 Ancestors: MorphicExtras-ul.266 Adds SketchMorph examples This commit is (the first) part of reconstruction of Objectland (also known as "The Worlds of Squeak"). Essential aims of this project are to revive the colorful collection of examples around the capacities of Squeak which was lastly delivered with Squeak 3.7, cast each example into code to provide a rich set of how-to examples to newbies in Squeak, and to integrate it into the ReleaseBuilder. Many further examples are coming soon. Stay tuned! =============== Diff against MorphicExtras-ul.266 =============== Item was added: + ----- Method: Form class>>extraCook (in category '*MorphicExtras-examples') ----- (excessive size, no diff calculated) Item was added: + ----- Method: Form class>>extraWizard (in category '*MorphicExtras-examples') ----- (excessive size, no diff calculated) Item was added: + ----- Method: SketchMorph class>>extraExampleCook (in category '*MorphicExtras-examples') ----- + extraExampleCook + "SketchMorph extraExampleCook openInWorld" + + ^ (self withForm: Form extraCook) + addMouseUpActionWith: 'Form toothpaste: 30'; + balloonText: 'Click me and then drag the cursor over the screen'; + yourself! Item was added: + ----- Method: SketchMorph class>>extraExampleWizard (in category '*MorphicExtras-examples') ----- + extraExampleWizard + "SketchMorph extraExampleWizard openInWorld" + + ^ (self withForm: Form extraWizard) + addMouseUpActionWith: + (MessageSend receiver: Pen new selector: #web); + balloonText: 'Click me and then drag the cursor over the screen\(Trust me, I won''t turn you into a toad!!)' withCRs; + yourself! From commits at source.squeak.org Thu Apr 15 14:54:17 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:17 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.268.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.268.mcz ==================== Summary ==================== Name: MorphicExtras-ct.268 Author: ct Time: 1 October 2019, 6:31:46.944339 pm UUID: 82578cf0-8147-8f47-9f9a-fd3b7aaad5c5 Ancestors: MorphicExtras-ct.267 Adds PolygonMorph examples Depends on ST80-ct.240. This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-ct.267 =============== Item was added: + ----- Method: PolygonMorph class>>extraCircularVertices (in category '*MorphicExtras-examples') ----- + extraCircularVertices + + ^ ((Circle center: 400 @ 300 radius: 200 quadrant: 1) computeVertices: 5) reverse + , ((Circle center: 400 @ 300 radius: 200 quadrant: 4) computeVertices: 5) reverse + , ((Circle center: 400 @ 400 radius: 100 quadrant: 4) computeVertices: 5) + , ((Circle center: 400 @ 400 radius: 100 quadrant: 1) computeVertices: 5) + , ((Circle center: 400 @ 200 radius: 100 quadrant: 3) computeVertices: 5) reverse + , ((Circle center: 400 @ 200 radius: 100 quadrant: 2) computeVertices: 5) reverse! Item was added: + ----- Method: PolygonMorph class>>extraExampleTextFlow (in category '*MorphicExtras-examples') ----- + extraExampleTextFlow + "PolygonMorph extraExampleTextFlow openInHand" + + | polygon text obstacle | + polygon := self new. + polygon + setVertices: self extraCircularVertices; + extent: 309 asPoint; + beSmoothCurve; + color: Color lightGray; + addHandles. + + text := (TextMorph + string: 'TextMorphs can be chained together, causing their contents to flow between containers as either the contents or the containers change. If a TextMorph is embedded in another Morph, you can ask it to have fill the shape of that Morph. Moreover, you can ask it to avoid occlusions, in which case it will do its best to avoid collisions with siblings being in front of it. If a TextMorph is embedded in a CurveMorph, you can ask it to have the text follow the curve, as illustrated here.' asTextMorph + fontName: #BitstreamVeraSans + size: 14) + textColor: Color white; + fillsOwner: true; + yourself. + obstacle := StarMorph new + center: polygon center - (50 @ 25); + extent: 81 asPoint; + color: Color orchid; + yourself. + + polygon + addMorph: text; + addMorph: obstacle. + text centered. + text container avoidsOcclusions: true. + ^ polygon! Item was added: + ----- Method: PolygonMorph class>>extraExampleTrapeze (in category '*MorphicExtras-examples') ----- + extraExampleTrapeze + "PolygonMorph extraExampleTrapeze openInHand" + + | polygon text | + polygon := self new. + polygon + setVertices: {0 @ 100. 275 @ 100. 200 @ 0. 75 @ 0}; + addHandles ; + balloonText: 'Click and drag the handles to change my shape'. + text := 'Polygons can be closed or open, filled or empty as well as lined or convex and can have directed arrows, bevelled borders and last but not least adapted handles.' asHtmlText asMorph + beAllFont: (TextStyle default fontOfSize: 14); + fillsOwner: true; + yourself. + polygon addMorph: text. + text centered. + ^ polygon! Item was added: + ----- Method: PolygonMorph class>>extraExampleTrapezePlus (in category '*MorphicExtras-examples') ----- + extraExampleTrapezePlus + "PolygonMorph extraExampleTrapezePlus openInHand" + "Some additional decoration" + + ^ self extraExampleTrapeze + fillStyle: ((GradientFillStyle + ramp: { 0.0 -> Color orange. 0.7 -> Color magenta twiceLighter. 1.0 -> Color red muchLighter }) + origin: 0 @ 0; direction: 275 @ 100; + yourself); + borderWidth: 2; + borderColor: Color blue; + dashedBorder: {35. 20. Color yellow}; + yourself! From commits at source.squeak.org Thu Apr 15 14:54:22 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:22 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.269.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.269.mcz ==================== Summary ==================== Name: MorphicExtras-ct.269 Author: ct Time: 1 October 2019, 6:33:51.583339 pm UUID: 99e1febf-d775-b743-9e00-1b95bab0bf68 Ancestors: MorphicExtras-ct.267 Adds CurveMorph examples. This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-ct.267 =============== Item was added: + ----- Method: CurveMorph class>>extraExampleArrow (in category '*MorphicExtras-examples') ----- + extraExampleArrow + "CurveMorph extraExampleArrow openInHand" + + | arrow | + arrow := CurveMorph + vertices: {200 @ 75. 35 @ 0. 40 @ 55. -55 @ 30} + color: Color veryDarkGray + borderWidth: 5 + borderColor: Color veryDarkGray. + arrow makeOpen; makeForwardArrow; beSmoothCurve. + arrow addHandles. + ^ arrow! Item was added: + ----- Method: CurveMorph class>>extraExampleTextFlow (in category '*MorphicExtras-examples') ----- + extraExampleTextFlow + "CurveMorph extraExampleTextFlow openInHand" + + | curve text | + curve := CurveMorph + vertices: {135 @ 270. 75 @ 200. 50 @ 150. 100 @ 100. 125 @ 150. 175 @ 100. 200 @ 150. 175 @ 200 . 115 @ 340} * RealEstateAgent scaleFactor + color: Color cyan + borderWidth: 25 * RealEstateAgent scaleFactor + borderColor: Color salmon. + curve makeOpen; beSmoothCurve. + text := ('Texts can also follow ........................................ an open curve. ' asText + , ('So morphic!!' asText + addAttribute: TextEmphasis italic; + addAttribute: (TextColor color: Color blue); + yourself)) + addAttribute: (TextFontChange fontNumber: (3.4 * RealEstateAgent scaleFactor) rounded); + asMorph. + text textColor: Color yellow. + curve addMorph: text. + text followCurve. + ^ curve! From commits at source.squeak.org Thu Apr 15 14:54:29 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:29 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.271.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.271.mcz ==================== Summary ==================== Name: MorphicExtras-ct.271 Author: ct Time: 1 October 2019, 8:34:14.776339 pm UUID: c725929f-54bd-d64d-8eb3-ebba10d204f4 Ancestors: MorphicExtras-ct.267 Add BannerMorph example to demonstrate ScreeningMorph, BackgroundMorph and other Morph techniques. This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-ct.267 =============== Item was added: + EllipseMorph subclass: #BannerMorph + instanceVariableNames: 'header contents' + classVariableNames: '' + poolDictionaries: '' + category: 'MorphicExtras-Demo'! + + !BannerMorph commentStamp: 'ct 9/7/2019 10:43' prior: 0! + I display a header and a contents text, arranged in an EllipseMorph in a flamboyant way. I use a ScreeningMorph and a BackgroundMorph to hinder the user to avert his gaze from me.! Item was added: + ----- Method: BannerMorph class>>example (in category 'examples') ----- + example + "BannerMorph example openInWorld" + + ^ self + header: 'Yes, you are ...' withCRs asHtmlText + contents: 'Live in Morphic' asUppercase asText! Item was added: + ----- Method: BannerMorph class>>header:contents: (in category 'instance creation') ----- + header: aStringOrText contents: anotherStringOrText + + ^ self basicNew + header: aStringOrText contents: anotherStringOrText; + initialize; + yourself! Item was added: + ----- Method: BannerMorph>>contents (in category 'accessing') ----- + contents + + ^ contents! Item was added: + ----- Method: BannerMorph>>createBackground (in category 'initialize-release') ----- + createBackground + + | fillMorph fillStyle | + fillStyle := GradientFillStyle colors: + ({Color red. Color green. Color blue} + in: [:colors | colors, colors reverse]). + fillStyle + origin: 0 @ 0; + direction: 150 @ 50. + fillMorph := (Morph new + fillStyle: fillStyle; + yourself). + ^ BackgroundMorph new + extent: 300 @ 130; + addMorph: fillMorph; + yourself! Item was added: + ----- Method: BannerMorph>>createContents (in category 'initialize-release') ----- + createContents + + | text | + text := self contents asText + addAttribute: TextEmphasis bold; + addAttribute: (TextFontReference toFont: + (StrikeFont familyName: #ComicPlain size: 39)); + asMorph. + text readOnly: true; flag: #ct. "We're no *that* life, yet :(" + ^ ScreeningMorph new + addMorph: (self createBackground + extent: text extent; + yourself); + addMorph: text; + showScreened; + cellPositioning: #center; + yourself! Item was added: + ----- Method: BannerMorph>>createHeader (in category 'initialize-release') ----- + createHeader + + | text | + text := (self header copyWithFirst: Character cr) asText + addAttribute: TextEmphasis bold; + addAttribute: (TextFontReference toFont: + (StrikeFont familyName: #Accula size: 29)); + yourself. + ^ text asMorph + centered; + fillsOwner: true; + yourself! Item was added: + ----- Method: BannerMorph>>header (in category 'accessing') ----- + header + + ^ header! Item was added: + ----- Method: BannerMorph>>header:contents: (in category 'accessing') ----- + header: aStringOrText contents: anotherStringOrText + + header := aStringOrText. + contents := anotherStringOrText.! Item was added: + ----- Method: BannerMorph>>initialize (in category 'initialize-release') ----- + initialize + + super initialize. + self extent: 300 @ 200. + self + changeProportionalLayout; + addMorph: (Morph new + color: Color transparent; + changeTableLayout; + listCentering: #center; wrapCentering: #center; + addMorph: self createContents; + yourself) + fullFrame: LayoutFrame fullFrame; + addMorph: self createHeader.! Item was added: + ----- Method: BannerMorph>>initializeToStandAlone (in category 'initialize-release') ----- + initializeToStandAlone + + self header: 'Introducing' contents: self class name. + super initializeToStandAlone.! From commits at source.squeak.org Thu Apr 15 14:54:33 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:33 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.272.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.272.mcz ==================== Summary ==================== Name: MorphicExtras-ct.272 Author: ct Time: 1 October 2019, 8:41:27.291339 pm UUID: cca75098-d7f2-1244-979f-65da19056be2 Ancestors: MorphicExtras-ct.267 Adds MovingEyeMorph example. This one is rather for fun, but I promise you it will visually upgrade Objectland a lot :-) Depends on Graphics-ct.422. This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-ct.267 =============== Item was added: + ----- Method: MovingEyeMorph class>>extraExampleSqueakIsWatchingYou (in category '*MorphicExtras-examples') ----- + extraExampleSqueakIsWatchingYou + "MovingEyeMorph extraExampleSqueakIsWatchingYou openInHand" + + ^ Form squeakIcon asMorph + addMorph: self new spec: (MorphSpec center: 0.39 @ 0.55 extent: 0.1 @ 0.15); + addMorph: self new spec: (MorphSpec center: 0.59 @ 0.56 extent: 0.1 @ 0.15); + yourself! From commits at source.squeak.org Thu Apr 15 14:54:38 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:38 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.273.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.273.mcz ==================== Summary ==================== Name: MorphicExtras-ct.273 Author: ct Time: 1 October 2019, 11:29:05.323339 pm UUID: 71c801ed-c4b5-1b40-bb37-e0de9f24b326 Ancestors: MorphicExtras-ct.267 Add RecordingControlsMorph example Depends on Sound-ct.70. This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-ct.267 =============== Item was added: + ----- Method: RecordingControlsMorph class>>extraExample (in category '*MorphicExtras-examples') ----- + extraExample + "RecordingControlsMorph extraExample openInWorld" + + | example | + example := self new. + example recorder clearRecordedSound. + example recorder recordedSound add: SampledSound exampleYesterday. + ^ example! From commits at source.squeak.org Thu Apr 15 14:54:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:46 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.274.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.274.mcz ==================== Summary ==================== Name: MorphicExtras-ct.274 Author: ct Time: 1 October 2019, 11:32:45.306339 pm UUID: bc7c8985-f585-c947-bc21-9e9a0009b9f6 Ancestors: MorphicExtras-ct.270 Add ScorePlayerMorph example This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-ct.267 =============== Item was added: + ----- Method: MIDIScore class>>extraExample (in category '*MorphicExtras-examples') ----- + extraExample + "(ScorePlayerMorph on: MIDIScore extraExample) openInWorld" + + | tracks | + tracks := self extraExampleTrackData collect: [:track | (ReferenceStream on: + (Base64MimeConverter mimeDecodeToBytes: track readStream)) next]. + ^ self new + tracks: tracks values trackInfo: tracks keys; + ticksPerQuarterNote: 96; + tempoMap: self extraExampleTempoMap; + yourself! Item was added: + ----- Method: MIDIScore class>>extraExampleTempoMap (in category '*MorphicExtras-examples') ----- + extraExampleTempoMap + + ^ {0->750000 . 26496->769230 . 26592->789473 . 26688->810810 . 26784->833333 . 26880->857142 . 26976->882352 . 27072->909090} + collect: [:tempoData | TempoEvent time: tempoData key tempo: tempoData value]! Item was added: + ----- Method: MIDIScore class>>extraExampleTrackData (in category '*MorphicExtras-examples') ----- (excessive size, no diff calculated) Item was added: + ----- Method: ScorePlayerMorph class>>extraExample (in category '*MorphicExtras-examples') ----- + extraExample + "ScorePlayerMorph extraExample openInHand" + + ^ self on: MIDIScore extraExample! From commits at source.squeak.org Thu Apr 15 14:54:51 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:51 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.275.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.275.mcz ==================== Summary ==================== Name: MorphicExtras-ct.275 Author: ct Time: 1 October 2019, 11:41:12.160339 pm UUID: 69cf49c3-5a24-dc40-82a5-df817f82984a Ancestors: MorphicExtras-ct.267 Adds TetrisPieceMorph example that illustrates usage of PolygonMorphs and random This commit is part of reconstruction of Objectland (also known as "The Worlds of Squeak"). For more information, see: http://forum.world.st/The-Inbox-MorphicExtras-ct-267-mcz-td5104764.html =============== Diff against MorphicExtras-ct.267 =============== Item was added: + PolygonMorph subclass: #TetrisPieceMorph + instanceVariableNames: '' + classVariableNames: 'Colors Shapes Vertices' + poolDictionaries: '' + category: 'MorphicExtras-Demo'! + + !TetrisPieceMorph commentStamp: 'ct 10/1/2019 23:34' prior: 0! + I display a Tetris piece. By calling TetrisPieceMorph random, you can generate a new instance of me that is random in terms of shape, color, and rotation. + + My shapes are: #(i j l o s t z).! Item was added: + ----- Method: TetrisPieceMorph class>>initialize (in category 'class initialization') ----- + initialize + + super initialize. + Vertices := Dictionary new + at: #i put: { 0 @ 0. 0 @ 4. 1 @ 4. 1 @ 0 }; + at: #j put: { 1 @ 0. 1 @ 2. 0 @ 2. 0 @ 3. 2 @ 3. 2 @ 0 }; + at: #o put: { 0 @ 0. 0 @ 2. 2 @ 2. 2 @ 0 }; + at: #s put: { 0 @ 0. 0 @ 2. 1 @ 2. 1 @ 3. 2 @ 3. 2 @ 1. 1 @ 1. 1 @ 0 }; + at: #t put: { 1 @ 0. 1 @ 1. 0 @ 1. 0 @ 2. 3 @ 2. 3 @ 1. 2 @ 1. 2 @ 0 }; + yourself. + Vertices + at: #l put: ((Vertices at: #j) * (-1 @ 1)); + at: #z put: ((Vertices at: #s) * (-1 @ 1)). + Shapes := Vertices keys. + Colors := #(red green blue orange grape yellow) + collect: [:color | color -> (Color in: color) lighter paler] + as: Dictionary.! Item was added: + ----- Method: TetrisPieceMorph class>>random (in category 'instance creation') ----- + random + "TetrisPieceMorph random openInHand" + + ^ self + shape: Shapes atRandom + color: Colors atRandom + rotationDegrees: Random new next * 360! Item was added: + ----- Method: TetrisPieceMorph class>>shape:color:rotationDegrees: (in category 'instance creation') ----- + shape: aShapeSymbol color: aColor rotationDegrees: degrees + + ^ self new + shape: aShapeSymbol; + color: aColor; + rotationDegrees: degrees; + yourself! Item was added: + ----- Method: TetrisPieceMorph>>initialize (in category 'initialize-release') ----- + initialize + + super initialize. + self borderStyle: (RaisedBorder new width: 3).! Item was added: + ----- Method: TetrisPieceMorph>>shape: (in category 'initialize-release') ----- + shape: aShapeSymbol + + self setVertices: (Vertices at: aShapeSymbol) * 20 * RealEstateAgent scaleFactor.! Item was changed: + (PackageInfo named: 'MorphicExtras') postscript: 'TetrisPieceMorph initialize. + '! - (PackageInfo named: 'MorphicExtras') postscript: 'TrashCanMorph preserveTrash: Preferences preserveTrash. - TrashCanMorph slideDismissalsToTrash: Preferences slideDismissalsToTrash. - - Preferences removePreference: #preserveTrash. - Preferences removePreference: #slideDismissalsToTrash.'! From commits at source.squeak.org Thu Apr 15 14:54:56 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:54:56 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.283.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.283.mcz ==================== Summary ==================== Name: MorphicExtras-ct.283 Author: ct Time: 1 November 2020, 2:13:44.005544 pm UUID: 50d9e7fa-55ad-4c4c-acd4-6ba27932b25a Ancestors: MorphicExtras-pre.279 Proposal: Override Bag >> #asMorph to create a HistogramMorph. Usage example: ((PackageInfo named: #Morphic) methods collect: [:method | method timeStamp findTokens ifEmpty: nil ifNotEmpty: #first] as: Bag) openAsMorph =============== Diff against MorphicExtras-pre.279 =============== Item was added: + ----- Method: Bag>>asMorph (in category '*MorphicExtras-converting') ----- + asMorph + + ^ HistogramMorph on: self! From commits at source.squeak.org Thu Apr 15 14:55:02 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:55:02 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-ct.284.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-ct.284.mcz ==================== Summary ==================== Name: MorphicExtras-ct.284 Author: ct Time: 22 November 2020, 5:55:08.221031 pm UUID: 530db7a0-100b-f443-8e3b-a5c742708f77 Ancestors: MorphicExtras-mt.280 Makes AnimatedImageMorph delays publicly accessible. In contrary to e.g. nextTime, delays are an essential part of an animated image, for instance when converting it into a different representation from an external client. =============== Diff against MorphicExtras-mt.280 =============== Item was added: + ----- Method: AnimatedImageMorph>>delays (in category 'accessing') ----- + delays + + ^ delays! Item was changed: + ----- Method: AnimatedImageMorph>>images (in category 'accessing') ----- - ----- Method: AnimatedImageMorph>>images (in category 'private') ----- images ^images! From commits at source.squeak.org Thu Apr 15 14:55:51 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 15 Apr 2021 14:55:51 0000 Subject: [squeak-dev] The Trunk: EToys-mt.442.mcz Message-ID: Marcel Taeumel uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-mt.442.mcz ==================== Summary ==================== Name: EToys-mt.442 Author: mt Time: 15 April 2021, 4:55:44.692792 pm UUID: 1c7fa45e-8000-494d-9769-8e9c042ea663 Ancestors: EToys-mt.441 Complements MorphicExtras-mt.292 =============== Diff against EToys-mt.441 =============== Item was removed: - EllipseMorph subclass: #MovingEyeMorph - instanceVariableNames: 'inner iris' - classVariableNames: 'IrisSize' - poolDictionaries: '' - category: 'Etoys-Squeakland-Morphic-Demo'! Item was removed: - ----- Method: MovingEyeMorph class>>color:irisColor: (in category 'instance creation') ----- - color: aColor irisColor: anotherColor - - ^ self new color: aColor irisColor: anotherColor! Item was removed: - ----- Method: MovingEyeMorph class>>descriptionForPartsBin (in category 'parts bin') ----- - descriptionForPartsBin - ^ self partName: 'MovingEye' translatedNoop - categories: {'Just for Fun' translatedNoop} - documentation: 'An eye which follows the cursor' translatedNoop! Item was removed: - ----- Method: MovingEyeMorph class>>initialize (in category 'class initialization') ----- - initialize - " - MovingEyeMorph initialize - " - IrisSize := (0.42 at 0.50).! Item was removed: - ----- Method: MovingEyeMorph>>color: (in category 'accessing') ----- - color: aColor - - super color: aColor. - - "Migrate old instances." - inner color: Color transparent. - - self keepIrisVisible.! Item was removed: - ----- Method: MovingEyeMorph>>color:irisColor: (in category 'accessing') ----- - color: aColor irisColor: anotherColor - - self color: aColor. - self irisColor: anotherColor.! Item was removed: - ----- Method: MovingEyeMorph>>defaultBorderWidth (in category 'accessing') ----- - defaultBorderWidth - - ^ 0! Item was removed: - ----- Method: MovingEyeMorph>>defaultColor (in category 'initialization') ----- - defaultColor - "answer the default color/fill style for the receiver" - ^ Color black! Item was removed: - ----- Method: MovingEyeMorph>>extent: (in category 'geometry') ----- - extent: aPoint - - super extent: aPoint. - inner extent: (self extent * ((1.0 at 1.0)-IrisSize)) asIntegerPoint. - iris extent: (self extent * IrisSize) asIntegerPoint. - inner position: (self center - (inner extent // 2)) asIntegerPoint. - ! Item was removed: - ----- Method: MovingEyeMorph>>initialize (in category 'initialization') ----- - initialize - "initialize the state of the receiver" - super initialize. - "" - inner := EllipseMorph new. - inner color: Color transparent. - inner extent: (self extent * (1.0 @ 1.0 - IrisSize)) asIntegerPoint. - inner borderWidth: 0. - "" - iris := EllipseMorph new. - iris color: Color white. - iris extent: (self extent * IrisSize) asIntegerPoint. - "" - self addMorphCentered: inner. - inner addMorphCentered: iris. - "" - self extent: 26 @ 33! Item was removed: - ----- Method: MovingEyeMorph>>irisColor (in category 'accessing') ----- - irisColor - - ^ iris color! Item was removed: - ----- Method: MovingEyeMorph>>irisColor: (in category 'accessing') ----- - irisColor: aColor - - iris color: aColor. - - self keepIrisVisible.! Item was removed: - ----- Method: MovingEyeMorph>>irisPos (in category 'accessing') ----- - irisPos - - ^ iris position! Item was removed: - ----- Method: MovingEyeMorph>>irisPos: (in category 'accessing') ----- - irisPos: cp - - | a b theta x y | - theta := (cp - self center) theta. - a := inner width // 2. - b := inner height // 2. - x := a * (theta cos). - y := b * (theta sin). - iris position: ((x at y) asIntegerPoint) + self center - (iris extent // 2).! Item was removed: - ----- Method: MovingEyeMorph>>keepIrisVisible (in category 'private') ----- - keepIrisVisible - - self color = self irisColor - ifTrue: [ - iris borderWidth: 1; - borderColor: self color makeForegroundColor] - ifFalse: [ - iris borderWidth: 0].! Item was removed: - ----- Method: MovingEyeMorph>>step (in category 'stepping and presenter') ----- - step - | cp | - cp := self globalPointToLocal: self world primaryHand position. - (inner containsPoint: cp) - ifTrue: [iris position: (cp - (iris extent // 2))] - ifFalse: [self irisPos: cp].! Item was removed: - ----- Method: MovingEyeMorph>>stepTime (in category 'testing') ----- - stepTime - - ^ 100.! From lewis at mail.msen.com Thu Apr 15 15:53:58 2021 From: lewis at mail.msen.com (David T. Lewis) Date: Thu, 15 Apr 2021 11:53:58 -0400 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.292.mcz In-Reply-To: References: Message-ID: <20210415155358.GA86205@shell.msen.com> On Thu, Apr 15, 2021 at 02:52:55PM +0000, commits at source.squeak.org wrote: > Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: > http://source.squeak.org/trunk/MorphicExtras-mt.292.mcz > > ==================== Summary ==================== > > Name: MorphicExtras-mt.292 > Author: mt > Time: 15 April 2021, 4:52:52.171792 pm > UUID: 5c15e20e-1712-4494-b519-18e3f9f6042b > Ancestors: MorphicExtras-mt.291, MorphicExtras-ct.264, MorphicExtras-ct.265, MorphicExtras-ct.266, MorphicExtras-ct.268, MorphicExtras-ct.269, MorphicExtras-ct.271, MorphicExtras-ct.272, MorphicExtras-ct.273, MorphicExtras-ct.274, MorphicExtras-ct.275, MorphicExtras-ct.283, MorphicExtras-ct.284 > > Merge, merge, merge. Christoph (ct) put a lot of effort into restoring > the examples from older Squeak releases, which had rich multimedia content > to show off Squeak's features. > This is really great! Thank you Christoph, and thank you Marcel for merging into trunk. :-)) Dave From vanessa at codefrau.net Thu Apr 15 16:13:45 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Thu, 15 Apr 2021 09:13:45 -0700 Subject: [squeak-dev] Methods with more than 15 arguments? In-Reply-To: <1618492038808-0.post@n4.nabble.com> References: <1618492038808-0.post@n4.nabble.com> Message-ID: On Thu, Apr 15, 2021 at 06:07 stlutz wrote: > codefrau wrote > Incidentally, which library/function specifically do you want to call? > > I am generating code to satisfy the OpenGL interface. The functions that > are making trouble are also highly unlikely to ever be called, as they are > part of outdated extensions (glLGPUCopyImageSubDataNVX, > glMulticastCopyImageSubDataNV, glAsyncCopyImageSubDataNVX). That's also > why I was asking and hoping for a simple solution, since it is not really > worth it for me to dive deeper into this. I will probably simply ignore > these methods and not generate them, and add a class comment noting their > absence. That makes sense. These are highly specialized extensions for multichannel VR rendering on NVIDIA hardware in an SLI configuration. Not worth extra effort, IMHO. –Vanessa– > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Thu Apr 15 16:24:53 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Thu, 15 Apr 2021 09:24:53 -0700 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz In-Reply-To: References: <53352cd9abea4ff999373cc0b798f00c@student.hpi.uni-potsdam.de> Message-ID: “Interpolating” would be unreliable IMHO. There is a direct correspondence from explicit MCMs to version numbers, but not three other way around. You could say “please build version 20313” which would succeed because there is a config that produces that number, but if you were asking for version 20314 then we wouldn’t know which package to update beyond the version given in the config. – Vanessa – On Thu, Apr 15, 2021 at 04:08 Marcel Taeumel wrote: > Hi Christoph, > > as Vanessa explained, updates up to a specific MCM in the current update > map might work. This also would not apply to cross-release/trunk updates in > general. But might work most of the time since we rarely update release > repositories. > > Since we now also have comments in MCMs, a user might actually be able to > pick the desired MCM from a list of not-yet-loaded ones. > > (Hmm... maybe approximating a list of versions from interpolating the > build version between two MCMs might work ...) > > Best, > Marcel > > Am 15.04.2021 02:13:34 schrieb Vanessa Freudenberg : > Hi Christoph, > > Good idea, but is not quite that simple. The image "version number" does > not uniquely identify a specific set of package versions. It's not enough > to build a similar image again. > > To have somewhat reproducible builds (they're not bit-identical) you need > to store the actual list of loaded package versions. The easiest way to do > that would be using an MCM. Only when an explicit config map is deployed > that indeed is a "fixed point" with a defined set of packages. > > MCMcmUpdater normally loads each explicit update map, plus then > automatically updates the last map to the latest package versions. That is > governed by the useLatestPackagesFrom: method. > > The latest config map appears to be > http://source.squeak.org/trunk/update-mt.485.mcm > > A method for reproducible builds could take e.g. 'mt.485' as an argument > and should produce an image with version number 20313: > > ((MCRepository trunk versionNamed: 'update-mt.485.mcm') dependencies > collect: [:dep | dep versionInfo versionNumber]) sum > > > –Vanessa– > > > On Thu, Apr 8, 2021 at 1:37 PM Thiede, Christoph < > Christoph.Thiede at student.hpi.uni-potsdam.de> wrote: > >> Please review! :-) >> >> >> A concrete use case I was having in mind for this feature is to allow >> arbitrary Squeak Trunk version numbers in smalltalkCI, see: >> https://github.com/hpi-swa/smalltalkCI/pull/506 >> >> At the moment, it is >> WIP - an unpolished prototype only, but the idea is that you could specify >> something like Squeak64-18242 instead of Squeak64-trunk in the CI/CLI >> args. >> >> Nevertheless, even if the proposal for SCI should get rejected, I think >> this is a helpful feature because releases are quite rare in Squeak and I >> find it important to tag certain states in the Trunk evolution. >> >> >> To improve support for the SCI PR, I would also like to backport these >> changes to 5.3 - there was only a single merge conflict, so if you agree >> with this proposal, I can send you a changeset for 5.3. Thanks in advance! >> :-) >> >> Best, >> Christoph >> ------------------------------ >> *Von:* Squeak-dev im >> Auftrag von commits at source.squeak.org >> *Gesendet:* Donnerstag, 8. April 2021 22:30:32 >> *An:* squeak-dev at lists.squeakfoundation.org >> *Betreff:* [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz >> >> A new version of MonticelloConfigurations was added to project The Inbox: >> http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz >> >> ==================== Summary ==================== >> >> Name: MonticelloConfigurations-ct.166 >> Author: ct >> Time: 8 April 2021, 10:30:30.702818 pm >> UUID: 6d887a86-fe0f-8e4c-a878-e40e8e612918 >> Ancestors: MonticelloConfigurations-mt.165 >> >> Adds support in MCMcmUpdater to install updates up to a specified system >> version number. This can be helpful when you want to bring an image into an >> exact state of an alpha version. I.e., a bug report or a tool can refer to >> Squeak6.0 Alpha #19570. Now it's possible to bring your 5.3 image into this >> state by evaluating: >> >> MCMcmUpdater default doUpdate: true upToUpdate: 19570. >> >> Still, it is possible to install all updates or navigate forward to a >> certain upstream version using the existing protocol: >> >> MCMcmUpdater default doUpdate: true. >> MCMcmUpdater default doUpdate: true upTo: 470. >> >> Detailed changelog (anticlimax): >> >> - Added 'upToUpdate:' variant of update selectors on MCMcmUpdater. >> - Refactored existing update selectors to deduplicate the logic for doing >> a complete update (#doUpdate: etc.) versus installing all updates up to an >> upstream version (#doUpdate:upTo: etc.). >> - Added #currentSystemVersion and #totalSystemVersion on MCConfiguration >> to determine the current resp. eventual system version as implied by the >> update stream. >> - Renamed (+ deprecated) #depsSatisfying:version(s)Do:displayingProgress: >> due to misleading use of singular in the block keyword. >> - Improved multilingual support for the updater. >> - Improved documentation of the update protocol. >> >> Note that in some situations, a small number of follow-up updates will be >> installed that go beyond the specified system version number. This is >> caused by interdependencies between the target version and its >> postdecessors when a definiton was moved from one package into another one. >> See sender of MCReorganizationPreloader. >> >> =============== Diff against MonticelloConfigurations-mt.165 >> =============== >> >> Item was added: >> + ----- Method: MCConfiguration class>>ensureOpenTranscript:during: (in >> category 'preferences') ----- >> + ensureOpenTranscript: aBoolean during: aBlock >> + >> + | previous | >> + previous := self ensureOpenTranscript. >> + self ensureOpenTranscript: aBoolean. >> + ^ aBlock ensure: [ >> + self ensureOpenTranscript: previous]! >> >> Item was added: >> + ----- Method: MCConfiguration>>currentSystemVersion (in category >> 'updating') ----- >> + currentSystemVersion >> + "Answer the current system version found in my configuration (or >> the associated working copy)." >> + >> + ^ self systemVersionForDeps: (self dependencies >> + collect: [:dep | >> + dep isFulfilledByAncestors >> + ifTrue: [dep versionInfo] >> + ifFalse: [dep package workingCopy >> ancestors] ] )! >> >> Item was added: >> + ----- Method: >> MCConfiguration>>depsSatisfying:upToUpdate:versionsDo:displayingProgress: >> (in category 'private') ----- >> + depsSatisfying: selectBlock upToUpdate: anIntegerOrNil versionsDo: >> versionBlock displayingProgress: progressString >> + >> + | count selectedVersions cleanWorkingCopies | >> + self cacheAllFileNamesDuring: [ >> + self repositories do: [ :eachRepository | >> + MCRepositoryGroup default addRepository: >> eachRepository ]. >> + >> + "First, download selected versions" >> + count := 0. >> + selectedVersions := OrderedCollection new. >> + self withProgress: progressString in: self dependencies >> do: [ :dep | | verName repo | >> + verName := dep versionInfo name. >> + self class extraProgressInfo ifTrue: >> + [ ProgressNotification signal: '' extra: >> ('Downloading {1}' translated format: {verName}) ]. >> + repo := self repositories >> + detect: [ :eachRepository | >> eachRepository includesVersionNamed: verName ] >> + ifNone: [ self logError: ('Version {1} >> not found in any repository' translated format: {verName}). >> + self logError: 'Aborting' >> translated. >> + ^ count ]. >> + (selectBlock value: dep) ifTrue: [ | version | >> + version := self versionNamed: verName >> for: dep from: repo. >> + version ifNil: [ self logError: ('Could >> not download version {1} from {2}' translated format: {verName. repo >> description}). >> + self logError: 'Aborting' >> translated. >> + ^ count ]. >> + dep package workingCopy >> newRepositoryGroupIfDefault. "fix old working copies" >> + dep package workingCopy repositoryGroup >> addRepository: repo. >> + selectedVersions add: version ] ]. >> + >> + "Then, process only those definitions that moved from >> one package to another, to avoid order dependence" >> + cleanWorkingCopies := MCWorkingCopy allManagers select: >> + [ :wc | wc modified not and: >> + [ selectedVersions anySatisfy: [ :v | wc >> package = v package ] ] ]. >> + MCReorganizationPreloader preloadMovesBetween: >> selectedVersions. >> + >> + "Finally, load/merge selected versions" >> + [:exit | self withProgress: progressString in: >> selectedVersions do: [ :version | >> + self logUpdate: version package with: version. >> + self class extraProgressInfo ifTrue: >> + [ ProgressNotification signal: '' extra: >> ('Installing {1}' translated format: {version info name}) ]. >> + versionBlock value: version. >> + count := count + 1. >> + anIntegerOrNil ifNotNil: [ >> + self currentSystemVersion highestUpdate >> < anIntegerOrNil ifFalse: exit. >> + self flag: #optimization. "ct: By >> customizing the system version computation, we could save redundant version >> downloads above. However, because of the preloading stage, this might >> become a bit more sophisticated." ] ]. >> + ] valueWithExit. >> + >> + "Clean up packages made dirty by >> MCReorganizationPreloader" >> + cleanWorkingCopies >> + select: [ :wc | wc modified ] >> + thenDo: [ :wc | wc checkModified ]. >> + ]. >> + ^ count! >> >> Item was changed: >> ----- Method: >> MCConfiguration>>depsSatisfying:versionDo:displayingProgress: (in category >> 'private') ----- >> + depsSatisfying: selectBlock versionDo: versionBlock displayingProgress: >> progressString >> + >> + self deprecated. >> + ^ self >> + depsSatisfying: selectBlock >> + versionsDo: versionBlock >> + displayingProgress: progressString! >> - depsSatisfying: selectBlock versionDo: verBlock displayingProgress: >> progressString >> - | count selectedVersions cleanWorkingCopies | >> - self cacheAllFileNamesDuring: [ >> - self repositories do: [ :eachRepository | >> - MCRepositoryGroup default addRepository: >> eachRepository ]. >> - "First, download selected versions" >> - count := 0. >> - selectedVersions := OrderedCollection new. >> - self withProgress: progressString in: self dependencies >> do: [ :dep | | verName repo | >> - verName := dep versionInfo name. >> - self class extraProgressInfo ifTrue: >> - [ ProgressNotification signal: '' extra: >> 'Downloading ' , verName ]. >> - repo := self repositories >> - detect: [ :eachRepository | >> eachRepository includesVersionNamed: verName ] >> - ifNone: [ self logError: 'Version ' , >> verName , ' not found in any repository'. >> - self logError: 'Aborting'. >> - ^ count ]. >> - (selectBlock value: dep) ifTrue: [ | version | >> - version := self versionNamed: verName >> for: dep from: repo. >> - version ifNil: [ self logError: 'Could >> not download version ' , verName , ' from ' , repo description. >> - self logError: 'Aborting'. >> - ^ count ]. >> - dep package workingCopy >> newRepositoryGroupIfDefault. "fix old working copies" >> - dep package workingCopy repositoryGroup >> addRepository: repo. >> - selectedVersions add: version]]. >> - "Then, process only those definitions that moved from >> one package to another, to avoid order dependence" >> - cleanWorkingCopies := MCWorkingCopy allManagers select: >> - [ :wc | wc modified not and: >> - [ selectedVersions anySatisfy: [ :v | wc >> package = v package ] ] ]. >> - MCReorganizationPreloader preloadMovesBetween: >> selectedVersions. >> - "Finally, load/merge selected versions" >> - self withProgress: progressString in: selectedVersions >> do: [ :version | >> - self logUpdate: version package with: version. >> - self class extraProgressInfo ifTrue: >> - [ ProgressNotification signal: '' extra: >> 'Installing ' , version info name ]. >> - verBlock value: version. >> - count := count + 1 ]. >> - "Clean up packages made dirty by >> MCReorganizationPreloader" >> - cleanWorkingCopies >> - select: [ :wc | wc modified ] >> - thenDo: [ :wc | wc checkModified ]. >> - ]. >> - ^ count! >> >> Item was added: >> + ----- Method: >> MCConfiguration>>depsSatisfying:versionsDo:displayingProgress: (in category >> 'private') ----- >> + depsSatisfying: selectBlock versionsDo: versionBlock >> displayingProgress: progressString >> + >> + ^ self >> + depsSatisfying: selectBlock >> + upToUpdate: nil >> + versionsDo: versionBlock >> + displayingProgress: progressString! >> >> Item was changed: >> ----- Method: MCConfiguration>>load (in category 'actions') ----- >> load >> ^self depsSatisfying: [:dep | dep isCurrent not] >> + versionsDo: [:ver | ver load] >> + displayingProgress: 'loading packages' translated! >> - versionDo: [:ver | ver load] >> - displayingProgress: 'loading packages' >> - ! >> >> Item was changed: >> ----- Method: MCConfiguration>>merge (in category 'actions') ----- >> merge >> ^self depsSatisfying: [:dep | dep isFulfilledByAncestors not] >> + versionsDo: [:ver | ver merge] >> + displayingProgress: 'merging packages' translated! >> - versionDo: [:ver | ver merge] >> - displayingProgress: 'merging packages' >> - ! >> >> Item was changed: >> ----- Method: MCConfiguration>>setSystemVersion (in category >> 'updating') ----- >> setSystemVersion >> - "Set the current system version date to the latest date found in >> my configuration (or the associated working copy). Also set the highest >> update number to the sum of version numbers in my configuration." >> >> + | newVersion | >> + newVersion := self currentSystemVersion. >> - | versionNumbers versionDates | >> - versionNumbers := self dependencies collect: [:d | >> - (d versionInfo name copyAfterLast: $.) asInteger]. >> - versionDates := self dependencies collect: [:d | >> - d versionInfo date >> - ifNil: [d package workingCopy ancestors first >> date]]. >> SystemVersion current >> + date: newVersion date; >> + highestUpdate: newVersion highestUpdate.! >> - date: versionDates max; >> - highestUpdate: versionNumbers sum.! >> >> Item was added: >> + ----- Method: MCConfiguration>>systemVersionForDeps: (in category >> 'updating') ----- >> + systemVersionForDeps: dependencies >> + "Answer the system version that will be reached by loading the >> passed dependencies." >> + >> + | versionNumbers versionDates | >> + versionNumbers := dependencies collect: [:dep | >> + dep isCollection >> + ifFalse: [dep name versionNumber] >> + ifTrue: [(dep collect: [:version | >> + version name versionNumber]) >> + ifEmpty: [0] >> + ifNotEmpty: #max]]. >> + versionDates := dependencies with: self dependencies collect: >> [:dep :originalDep | >> + (dep isCollection ifFalse: [dep date]) >> + ifNil: [originalDep package workingCopy ancestors >> + ifEmpty: [nil] >> + ifNotEmpty: [:ancestors | >> ancestors first date]]]. >> + >> + ^ SystemVersion new >> + date: ((versionDates copyWithout: nil) >> + ifEmpty: [nil] >> + ifNotEmpty: #max); >> + highestUpdate: versionNumbers sum! >> >> Item was added: >> + ----- Method: MCConfiguration>>totalSystemVersion (in category >> 'updating') ----- >> + totalSystemVersion >> + "Answer the total system version that will be reached by >> upgrading the receiver." >> + >> + ^ self systemVersionForDeps: (self dependencies collect: >> #versionInfo)! >> >> Item was changed: >> ----- Method: MCConfiguration>>upgrade (in category 'actions') ----- >> upgrade >> + >> + ^ self upgradeUpToUpdate: nil! >> - ^self depsSatisfying: >> - [:dep | dep isFulfilledByAncestors not] >> - versionDo: >> - [:ver | >> - (self class upgradeIsMerge and: [ver >> shouldMerge]) >> - ifFalse: [ver load] >> - ifTrue: >> - [[ver merge] >> - on: MCNoChangesException >> - do: [:req| req resume ] >> - on: >> MCMergeResolutionRequest >> - do: [:request | >> - request merger >> conflicts isEmpty >> - ifTrue: >> [request resume: true] >> - ifFalse: >> [request pass]] >> - on: Deprecation >> - do: [:req| req resume ]]] >> - displayingProgress: 'upgrading packages'! >> >> Item was added: >> + ----- Method: MCConfiguration>>upgradeUpToUpdate: (in category >> 'actions') ----- >> + upgradeUpToUpdate: anIntegerOrNil >> + >> + ^ self >> + depsSatisfying: [:dep | >> + dep isFulfilledByAncestors not] >> + upToUpdate: anIntegerOrNil >> + versionsDo: [:ver | >> + (self class upgradeIsMerge and: [ver >> shouldMerge]) >> + ifFalse: [ver load] >> + ifTrue: >> + [[ver merge] >> + on: MCNoChangesException >> + do: [:req | req resume ] >> + on: >> MCMergeResolutionRequest >> + do: [:request | >> + request merger >> conflicts isEmpty >> + ifTrue: >> [request resume: true] >> + ifFalse: >> [request pass]] >> + on: Deprecation >> + do: [:req | req resume >> ]]] >> + displayingProgress: 'upgrading packages' translated! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>basicDoUpdate:do: (in category 'updating') >> ----- >> + basicDoUpdate: interactive do: aBlock >> + "Update the image by evaluating aBlock. If this is the default >> updater for the system, update the system version when complete. If >> interactive, use a modal notifier, otherwise only update the transcript. >> Flush all caches. If a previous download failed, this is often helpful." >> + >> + | config previousUpdateLevel | >> + previousUpdateLevel := SystemVersion current highestUpdate. >> + MCFileBasedRepository flushAllCaches. >> + >> + MCConfiguration ensureOpenTranscript: interactive during: [ >> + config := aBlock value. >> + >> + config ifNil: [ >> + interactive ifTrue: [^ self inform: 'Unable to >> retrieve updates from remote repository.' translated]. >> + Transcript cr; show: '========== Unable to >> retrieve updates from remote repository. ==========' translated; cr. >> + ^ self ]. >> + >> + MCMcmUpdater default == self >> + ifTrue: [ >> + config setSystemVersion. >> + interactive ifTrue: [ >> + self inform: (self >> updateMessageFor: previousUpdateLevel)]. >> + Transcript cr; >> + show: '========== Update >> completed: ' translated; >> + show: previousUpdateLevel; >> + show: ' -> ' ; >> + show: SystemVersion current >> highestUpdate; >> + show: ' =========='; cr ] >> + ifFalse: [ >> + interactive >> + ifTrue: [ self inform: 'Update >> completed.' ]. >> + Transcript cr; show: '========== Update >> completed. ==========' translated; cr ] ].! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>basicUpdateFromRepositories:do: (in >> category 'updating') ----- >> + basicUpdateFromRepositories: repositoryUrls do: repositoryBlock >> + >> + | repos config | >> + MCConfiguration upgradeIsMerge: true. >> + "The list of repositories to consult in order" >> + repos := repositoryUrls collect: [:url| >> + MCRepositoryGroup default repositories >> + detect: [:repo | repo description = url] >> + ifNone: [ | repo | >> + repo := MCHttpRepository location: url. >> + MCRepositoryGroup default addRepository: >> repo. >> + repo]]. >> + >> + "The list of updates-author.version.mcm sorted by version" >> + repos do: [:repo | >> + config := repositoryBlock value: repo]. >> + ^ config! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:thenDo: (in >> category 'updating') ----- >> + basicUpdateFromRepository: aRepository thenDo: configBlock >> + >> + ^ self >> + basicUpdateFromRepository: aRepository >> + whileUpdatesSatisfy: [true] >> + upToUpdate: nil >> + thenDo: configBlock! >> >> Item was added: >> + ----- Method: >> MCMcmUpdater>>basicUpdateFromRepository:whileUpdatesSatisfy:upToUpdate:thenDo: >> (in category 'updating') ----- >> + basicUpdateFromRepository: aRepository whileUpdatesSatisfy: updateBlock >> upToUpdate: anIntegerOrNil thenDo: configBlock >> + >> + | config | >> + aRepository cacheAllFileNamesDuring: [ | updateList | >> + updateList := self updateListFor: aRepository. >> + "Proceed only if there are updates available at all." >> + updateList ifNotEmpty: [ >> + updateList := self refreshUpdateMapFor: >> aRepository with: updateList. >> + "Now process each update file. Check if we have >> all dependencies and if not, load the entire configuration (this is mostly >> to skip older updates quickly)" >> + [:exit | updateList >> + do: [:assoc | >> + (updateBlock cull: assoc key >> cull: assoc value) ifFalse: exit. >> + ProgressNotification signal: '' >> extra: ('Processing {1}' translated format: {assoc value}). >> + config := aRepository >> versionNamed: assoc value. >> + anIntegerOrNil ifNotNil: [ >> + config >> currentSystemVersion highestUpdate <= anIntegerOrNil ifFalse: exit]. >> + self updateFromConfig: config >> upToUpdate: anIntegerOrNil. >> + anIntegerOrNil ifNotNil: [ >> + config >> currentSystemVersion highestUpdate < config totalSystemVersion >> highestUpdate ifTrue: exit]. >> + self lastUpdateMap at: >> aRepository description put: assoc key] >> + displayingProgress: 'Processing >> configurations' translated] valueWithExit. >> + configBlock cull: config]]. >> + ^ config! >> >> Item was changed: >> ----- Method: MCMcmUpdater>>doUpdate: (in category 'updating') ----- >> doUpdate: interactive >> + "Update the image by loading all pending updates from the >> server." >> - "Update the image by loading all pending updates from the >> server. If this is >> - the default updater for the system, update the system version >> when complete. >> - If interteractive use a modal notifier, otherwise only update >> the transcript. >> - Flush all caches. If a previous download failed this is often >> helpful" >> >> + ^ self basicDoUpdate: interactive do: [ >> + self updateFromRepository ]! >> - | config previousUpdateLevel ensureTranscriptSetting | >> - previousUpdateLevel := SystemVersion current highestUpdate. >> - MCFileBasedRepository flushAllCaches. >> - ensureTranscriptSetting := MCConfiguration ensureOpenTranscript. >> - [ MCConfiguration ensureOpenTranscript: interactive. >> - config := self updateFromRepository. >> - config ifNil: [ >> - interactive ifTrue: [ ^self inform: 'Unable to retrieve >> updates from remote repository.' translated ]. >> - Transcript cr; show: '========== Unable to retrieve >> updates from remote repository. ==========' translated; cr. >> - ^ self ]. >> - MCMcmUpdater default == self >> - ifTrue: [ >> - config setSystemVersion. >> - interactive ifTrue: [ >> - self inform: (self updateMessageFor: >> previousUpdateLevel)]. >> - Transcript cr; >> - show: '========== Update completed: ' >> translated; >> - show: previousUpdateLevel; >> - show: ' -> ' ; >> - show: SystemVersion current >> highestUpdate; >> - show: ' =========='; cr ] >> - ifFalse: [ >> - interactive >> - ifTrue: [ self inform: 'Update >> completed.' ]. >> - Transcript cr; show: '========== Update >> completed. ==========' translated; cr ] ] >> - ensure: [ MCConfiguration ensureOpenTranscript: >> ensureTranscriptSetting]. >> - >> - ! >> >> Item was changed: >> ----- Method: MCMcmUpdater>>doUpdate:upTo: (in category 'updating') >> ----- >> doUpdate: interactive upTo: versionNumber >> + "Update the image by loading all pending updates from the server >> until update stream with the specified version number has been processed." >> - "Update the image by loading all pending updates from the >> server. If this is >> - the default updater for the system, update the system version >> when complete. >> - If interteractive use a modal notifier, otherwise only update >> the transcript. >> - Flush all caches. If a previous download failed this is often >> helpful" >> >> + ^ self basicDoUpdate: interactive do: [ >> + self updateFromRepositories: {self repository} upTo: >> versionNumber ]! >> - | config previousUpdateLevel | >> - previousUpdateLevel := SystemVersion current highestUpdate. >> - MCFileBasedRepository flushAllCaches. >> - config := self updateFromRepositories: { self repository } upTo: >> versionNumber. >> - config ifNil: [ >> - interactive ifTrue: [ ^self inform: 'Unable to retrieve >> updates from remote repository.' translated ]. >> - Transcript cr; show: '========== Unable to retrieve >> updates from remote repository. ==========' translated; cr. >> - ^ self ]. >> - MCMcmUpdater default == self >> - ifTrue: [ >> - config setSystemVersion. >> - interactive ifTrue: [ >> - self inform: (self updateMessageFor: >> previousUpdateLevel)]. >> - Transcript cr; >> - show: '========== Update completed: ' >> translated; >> - show: previousUpdateLevel; >> - show: ' -> ' ; >> - show: SystemVersion current >> highestUpdate; >> - show: ' =========='; cr ] >> - ifFalse: [ >> - interactive >> - ifTrue: [ self inform: 'Update >> completed.' ]. >> - Transcript cr; show: '========== Update >> completed. ==========' translated; cr ] >> - ! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>doUpdate:upToUpdate: (in category >> 'updating') ----- >> + doUpdate: interactive upToUpdate: anIntegerOrNil >> + "Update the image by loading all pending updates from the server >> until the system version has reached at least anInteger. If anInteger is >> nil, install all available updates." >> + >> + ^ self basicDoUpdate: interactive do: [ >> + self updateFromRepositories: {self repository} >> upToUpdate: anIntegerOrNil ]! >> >> Item was changed: >> ----- Method: MCMcmUpdater>>doUpdateUpTo: (in category 'updating') ----- >> doUpdateUpTo: versionNumber >> + "Update the image by loading all pending updates from the server >> until update stream with the specified version number has been processed." >> - "Update the image by loading all pending updates from the >> server. If this is >> - the default updater for the system, update the system version >> when complete. >> - Flush all caches. If a previous download failed this is often >> helpful" >> >> ^self doUpdate: true upTo: versionNumber >> ! >> >> Item was changed: >> ----- Method: MCMcmUpdater>>updateFromConfig: (in category 'updating') >> ----- >> updateFromConfig: config >> >> + ^ self updateFromConfig: config upToUpdate: nil! >> - "Skip packages that were specifically unloaded" >> - config dependencies: (config dependencies >> - reject: [:dep| self class skipPackages includes: dep >> package name]). >> - self class updateMissingPackages ifFalse:[ >> - "Skip packages that are not in the image" >> - config dependencies: (config dependencies >> - select: [:dep| dep package hasWorkingCopy])]. >> - (config dependencies allSatisfy:[:dep| dep isFulfilled]) >> - ifFalse:[config upgrade]. >> - ! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>updateFromConfig:upToUpdate: (in category >> 'updating') ----- >> + updateFromConfig: config upToUpdate: anIntegerOrNil >> + >> + "Skip packages that were specifically unloaded" >> + config dependencies: (config dependencies >> + reject: [:dep | self class skipPackages includes: dep >> package name]). >> + self class updateMissingPackages ifFalse: [ >> + "Skip packages that are not in the image" >> + config dependencies: (config dependencies >> + select: [:dep | dep package hasWorkingCopy])]. >> + (config dependencies allSatisfy: [:dep | dep isFulfilled]) >> + ifFalse: [config upgradeUpToUpdate: anIntegerOrNil].! >> >> Item was changed: >> ----- Method: MCMcmUpdater>>updateFromRepositories:upTo: (in category >> 'updating') ----- >> updateFromRepositories: repositoryUrls upTo: versionNumber >> + " >> + MCMcmUpdater default updateFromRepositories: #(' >> http://squeaksource.com/MCUpdateTest') upTo: 3 >> + " >> - "MCMcmUpdater updateFromRepositories: #( >> - 'http://squeaksource.com/MCUpdateTest' >> - )" >> >> + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | >> + self updateFromRepository: repo upTo: versionNumber]! >> - | repos config | >> - MCConfiguration upgradeIsMerge: true. >> - "The list of repositories to consult in order" >> - repos := repositoryUrls collect:[:url| >> - MCRepositoryGroup default repositories >> - detect:[:r| r description = url] >> - ifNone:[ | r | >> - r := MCHttpRepository location: url >> user: '' password: ''. >> - MCRepositoryGroup default addRepository: >> r. >> - r]]. >> - >> - "The list of updates-author.version.mcm sorted by version" >> - repos do:[ :r | config := self updateFromRepository: r upTo: >> versionNumber]. >> - ^config! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>updateFromRepositories:upToUpdate: (in >> category 'updating') ----- >> + updateFromRepositories: repositoryUrls upToUpdate: anIntegerOrNil >> + " >> + MCMcmUpdater default updateFromRepositories: #(' >> http://squeaksource.com/MCUpdateTest') upToUpdate: 2130 >> + " >> + >> + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | >> + self updateFromRepository: repo upToUpdate: >> anIntegerOrNil ]! >> >> Item was changed: >> ----- Method: MCMcmUpdater>>updateFromRepository (in category >> 'updating') ----- >> updateFromRepository >> >> + ^ self updateFromRepository: self >> getRepositoryFromRepositoryGroup! >> - | config repo | >> - repo := self getRepositoryFromRepositoryGroup. >> - repo cacheAllFileNamesDuring: [ | updateList | >> - updateList := self updateListFor: repo. >> - "Proceed only if there are updates available at all." >> - updateList ifNotEmpty: [ >> - updateList := self refreshUpdateMapFor: repo >> with: updateList. >> - "Now process each update file. Check if we have >> all dependencies and if not, >> - load the entire configuration (this is mostly to >> skip older updates quickly)" >> - updateList do:[:assoc| >> - ProgressNotification signal: '' extra: >> 'Processing ', assoc value. >> - config := repo versionNamed: assoc value. >> - self updateFromConfig: config. >> - self lastUpdateMap at: repo description >> put: assoc key. >> - ] displayingProgress: 'Processing >> configurations'. >> - "We've loaded all the provided update >> configurations. >> - Use the latest configuration to update all the >> remaining packages." >> - (self useLatestPackagesFrom: repo) ifTrue: [ >> - config updateFromRepositories. >> - config upgrade]. >> - ]]. >> - ^ config >> - ! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>updateFromRepository: (in category >> 'updating') ----- >> + updateFromRepository: aRepository >> + >> + ^ self basicUpdateFromRepository: aRepository thenDo: [:config | >> + "We've loaded all the provided update configurations. >> Use the latest configuration to update all the remaining packages." >> + (self useLatestPackagesFrom: aRepository) ifTrue: [ >> + config updateFromRepositories. >> + config upgrade]]! >> >> Item was changed: >> ----- Method: MCMcmUpdater>>updateFromRepository:upTo: (in category >> 'updating') ----- >> + updateFromRepository: aRepository upTo: versionNumber >> - updateFromRepository: repository upTo: versionNumber >> >> + ^ self >> + basicUpdateFromRepository: aRepository >> + whileUpdatesSatisfy: [:updateVersion | updateVersion <= >> versionNumber] >> + upToUpdate: nil >> + thenDo: []! >> - | config | >> - repository cacheAllFileNamesDuring: [ | updateList | >> - updateList := self updateListFor: repository. >> - "Proceed only if there are updates available at all." >> - updateList ifNotEmpty: [ >> - updateList := self refreshUpdateMapFor: >> repository with: updateList. >> - "Now process each update file. Check if we have >> all dependencies and if not, >> - load the entire configuration (this is mostly to >> skip older updates quickly)" >> - updateList do:[:assoc| >> - assoc key > versionNumber ifTrue: >> [^config]. >> - ProgressNotification signal: '' extra: >> 'Processing ', assoc value. >> - config := repository versionNamed: assoc >> value. >> - self updateFromConfig: config. >> - self lastUpdateMap at: repository >> description put: assoc key. >> - ] displayingProgress: 'Processing >> configurations'. >> - ]]. >> - ^config >> - ! >> >> Item was added: >> + ----- Method: MCMcmUpdater>>updateFromRepository:upToUpdate: (in >> category 'updating') ----- >> + updateFromRepository: aRepository upToUpdate: anIntegerOrNil >> + >> + ^ self >> + basicUpdateFromRepository: aRepository >> + whileUpdatesSatisfy: [true] >> + upToUpdate: anIntegerOrNil >> + thenDo: []! >> >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Thu Apr 15 16:30:22 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 15 Apr 2021 18:30:22 +0200 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.292.mcz In-Reply-To: <20210415155358.GA86205@shell.msen.com> References: <20210415155358.GA86205@shell.msen.com> Message-ID: Wow, the record merge! Thanks Christoph & Marcel! Le jeu. 15 avr. 2021 à 17:54, David T. Lewis a écrit : > > On Thu, Apr 15, 2021 at 02:52:55PM +0000, commits at source.squeak.org wrote: > > Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: > > http://source.squeak.org/trunk/MorphicExtras-mt.292.mcz > > > > ==================== Summary ==================== > > > > Name: MorphicExtras-mt.292 > > Author: mt > > Time: 15 April 2021, 4:52:52.171792 pm > > UUID: 5c15e20e-1712-4494-b519-18e3f9f6042b > > Ancestors: MorphicExtras-mt.291, MorphicExtras-ct.264, MorphicExtras-ct.265, MorphicExtras-ct.266, MorphicExtras-ct.268, MorphicExtras-ct.269, MorphicExtras-ct.271, MorphicExtras-ct.272, MorphicExtras-ct.273, MorphicExtras-ct.274, MorphicExtras-ct.275, MorphicExtras-ct.283, MorphicExtras-ct.284 > > > > Merge, merge, merge. Christoph (ct) put a lot of effort into restoring > > the examples from older Squeak releases, which had rich multimedia content > > to show off Squeak's features. > > > > > This is really great! Thank you Christoph, and thank you Marcel for merging into trunk. > > :-)) > > Dave > > From Patrick.Rein at hpi.de Thu Apr 15 17:02:14 2021 From: Patrick.Rein at hpi.de (Rein, Patrick) Date: Thu, 15 Apr 2021 17:02:14 +0000 Subject: [squeak-dev] SOB Election 2021: Opt-in for receiving voting mails | Extension of nomination period Message-ID: <378ae82c00c14c60b1b4053ed181de34@hpi.de> Hi everyone, tl;dr: To be able to vote in the upcoming SOB election please activate the email address you used for registering as a voter. To activate it go to https://civs1.civs.us/cgi-bin/opt_in.pl tl;dr2: To account for the opt-in, the nomination period is extended by one week. Voting will start at 19.00 UTC on Friday 23rd of April 2021. This year everything is a little different about the SOB election. Our election platform changed their email rules. This year, for you to vote on CIVS, you have to opt in to receiving emails from CIVS. This is necessary, as you will get a personalized voting link via email directly from CIVS. Please opt in to receiving emails from CIVS at https://civs1.civs.us/cgi-bin/opt_in.pl Otherwise you will NOT be able to vote! Everyone on the voters list will also get a personal email on this. If you have already opted in by then, you can ignore that email. Also, to allow for everyone to opt-in in time for the election to start, the nomination period is extended by one week. We will start voting at 19.00 UTC on Friday 23rd of April 2021. The end of the voting period is adjusted accordingly. Best wishes and keep the nominations coming! Patrick From tim at rowledge.org Thu Apr 15 23:14:35 2021 From: tim at rowledge.org (tim Rowledge) Date: Thu, 15 Apr 2021 16:14:35 -0700 Subject: [squeak-dev] The Inbox: Collections-mt.938.mcz In-Reply-To: References: Message-ID: <50AABFAA-A2C3-44FB-B960-F7F332CEE145@rowledge.org> It's worth remembering that that nextPutAl: etc code is only causing a problem in the 'special fast case' branch. The 'normal' case would be to iterate on the parameter and #add: to the recipient. OrderedCollection does *that* ok. I must admit to never having looked at LinkedList>#add: ... yup that would be fine too. The only collection hierarchy class I see which doesn't like #add: is Matrix, and I'm not utterly sure that it ought to be under Collection tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- People around her are at risk of second hand idiocy. From asqueaker at gmail.com Fri Apr 16 01:03:12 2021 From: asqueaker at gmail.com (Chris Muller) Date: Thu, 15 Apr 2021 20:03:12 -0500 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <14d442f8-badb-ac7e-3c08-1a586f9d58dd@leastfixedpoint.com> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <14d442f8-badb-ac7e-3c08-1a586f9d58dd@leastfixedpoint.com> Message-ID: Thanks, Patrick, for taking over the election this year. Since Tony is running, I've decided to renew my candidacy afterall. All, vote for me ahead of "None Of The Below" for the board to maintain the required odd number of members without needing to drop to 5 candidates. - Chris On Thu, Apr 15, 2021 at 3:11 AM Tony Garnock-Jones < tonyg at leastfixedpoint.com> wrote: > Hi everyone, > > I think I'd like to run for the board this year. > > I'm particularly interested in topics such as > > - actors and concurrency > - namespacing and isolation > - virtualization and securable image-to-image communication > - data serialization formats (like JSON etc) > - DSLs > > but recently I've also been working on making Squeak the heart of a > prototype cellphone platform, involving the above but also supporting > new input devices (e.g. multitouch touchscreen on Linux) and dealing > with process management, Linux kernel APIs etc. > > Basically, I'm interested in the "operating system" side of Smalltalk. > If I'm elected, I'd like to put my energy toward that general area. > However, I've also got quite a bit of experience in infrastructure > setup, care, and feeding, so I can contribute there also. > > Tony > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Fri Apr 16 01:18:48 2021 From: tim at rowledge.org (tim Rowledge) Date: Thu, 15 Apr 2021 18:18:48 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <14d442f8-badb-ac7e-3c08-1a586f9d58dd@leastfixedpoint.com> Message-ID: <42ACC50E-D6FC-40F0-8FDE-83A89F0FDE9B@rowledge.org> As a general point I'd like to urge some of the younger community members to stand for the board. We really need to make sure it doesn't become an old fogey club. Remember, this isn't some "wizards of code" thing where we meet to do Things Mankind Is Not Meant To Know - the board is mostly responsible for the administrivia of keeping the infrastructure running so we can run the community, along with caring for the integrity of the trunk and releases. If you're interested, possessed of a good organising memory and a talent for persuading people to Get On With It, please stand! tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Gargoyle (n.), olive-flavored mouthwash. From asqueaker at gmail.com Fri Apr 16 01:54:38 2021 From: asqueaker at gmail.com (Chris Muller) Date: Thu, 15 Apr 2021 20:54:38 -0500 Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz In-Reply-To: References: <1618336352701-0.post@n4.nabble.com> Message-ID: > > If 1st package letter is > M, it can be 10 clicks away... > You can reduce it to 1 using the Search function. Wildcards are accepted. > Plus the fact that I'm pretty sure that in the past, some packages > that I previously moved to trunk or treated inbox did reappear in the > inbox, I fixed that a while back. If it isn't, someone please let me know. I may try to answer a mail that is about 6 month old, but IMO, it does > not make much sense. > This mail is not in my client anymore, so it means going thru some > forum API with extra login etc... > Why isn't it in your client anymore? Email is mission-critical, it sounds like you've got your git set up better than your mail. Mail is the application optimized for having and organizing and archiving async discussions. Whether you want to ALSO have lengthy discussions in the SCM tool or not, I don't think you'll be absolved from needing to participate in the email discussions in any case. So, it would seem like it just introduces yet another place to have to look for and maintain.. > It's just not acceptable. > Would you get your email fixed before deciding? > Rejecting without a comment is not acceptable either. > It's not fair for contributors, and not fair to ourselves: the reason > why we reject is more important than the rejection itself: it is also > information reusable for future contributions. If we really want to stick to our lghtweight model, i suggest that we > add one more commit message when we move some package to treated, > possibly with an automated link to original commit message in some > mailing list. This way, I will have a chance to give some additional > reason for rejection... > The submitter won't be notified. I don't think that will provide the kind of "flow" you're looking for. There already aren't enough readers of the Inbox submissions, NO ONE reads Treated. It would just be creating objects (Strings) that would never be consumed. > I stop the rant here. Above all, I don't want to restrain the will to > contribute. > Having enthusiastic users overwhelming the inbox with fixes, ideas and > enhancements is not the problem, it's a chance! > Having too few people to perform the review with poor tools is the > problem. We have to do something about it. > In my eyes, the reviews done in the mailing list a few month ago are > dead, they are not easily findable/usable/amendable. > Thanks for bringing the subject, and please, continue to chanllenge us! > Ideas for improving the process are wecome too. > I think the problem is that trying to treat trunk development with Monticello the same as you do development with Git. > The problem with our dev model is that it's been designed with very > short cycles in mind. Git's was. Squeak+MC's wasn't, but we're forcing it to do that. It isn't surprising to me that using it this way isn't optimal. IMO, MC trunk commits were meant to be *tested and finished*, only after iterative refinement in the Inbox. It seems like little more than superficial tooling could greatly streamline it.. - Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: From leves at caesar.elte.hu Fri Apr 16 02:29:46 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Fri, 16 Apr 2021 04:29:46 +0200 (CEST) Subject: [squeak-dev] The Inbox: Collections-mt.938.mcz In-Reply-To: <50AABFAA-A2C3-44FB-B960-F7F332CEE145@rowledge.org> References: <50AABFAA-A2C3-44FB-B960-F7F332CEE145@rowledge.org> Message-ID: That's only the case, because the 'normal' branch has been fixed back in 2009 (see Collections-nice.116) to use #grownBy: and therefore #ofSize: instead of #new: to create the new instance of the underlying collection. Yet, we still don't have a test case convering this unusual usage of #streamContents:. Levente On Thu, 15 Apr 2021, tim Rowledge wrote: > It's worth remembering that that nextPutAl: etc code is only causing a problem in the 'special fast case' branch. The 'normal' case would be to iterate on the parameter and #add: to the recipient. OrderedCollection does *that* ok. I must admit to never having looked at LinkedList>#add: ... yup that would be fine too. The only collection hierarchy class I see which doesn't like #add: is Matrix, and I'm not utterly sure that it ought to be under Collection > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > Useful random insult:- People around her are at risk of second hand idiocy. From marcel.taeumel at hpi.de Fri Apr 16 07:48:20 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 09:48:20 +0200 Subject: [squeak-dev] The Trunk: ST80-nice.265.mcz In-Reply-To: References: <1618336352701-0.post@n4.nabble.com> Message-ID: Hi Chris. > I fixed that a while back.  If it isn't, someone please let me know. Looks good. It was like 3-4 weeks ago, right? No issues so far. Yet, I keep on moving the duplicates from inbox to treated if I find some. :-) Should be over soon. Best, Marcel Am 16.04.2021 03:55:25 schrieb Chris Muller : If 1st package letter is > M, it can be 10 clicks away... You can reduce it to 1 using the Search function.  Wildcards are accepted.   Plus the fact that I'm pretty sure that in the past, some packages that I previously moved to trunk or treated inbox did reappear in the inbox, I fixed that a while back.  If it isn't, someone please let me know. I may try to answer a mail that is about 6 month old, but IMO, it does not make much sense. This mail is not in my client anymore, so it means going thru some forum API with extra login etc... Why isn't it in your client anymore?  Email is mission-critical, it sounds like you've got your git set up better than your mail.  Mail is the application optimized for having and organizing and archiving async discussions.  Whether you want to ALSO have lengthy discussions in the SCM tool or not, I don't think you'll be absolved from needing to participate in the email discussions in any case.  So, it would seem like it just introduces yet another place to have to look for and maintain..   It's just not acceptable. Would you get your email fixed before deciding?   Rejecting without a comment is not acceptable either. It's not fair for contributors, and not fair to ourselves: the reason why we reject is more important than the rejection itself: it is also information reusable for future contributions.  If we really want to stick to our lghtweight model, i suggest that we add one more commit message when we move some package to treated, possibly with an automated link to original commit message in some mailing list. This way, I will have a chance to give some additional reason for rejection... The submitter won't be notified.  I don't think that will provide the kind of "flow" you're looking for.  There already aren't enough readers of the Inbox submissions, NO ONE reads Treated.  It would just be creating objects (Strings) that would never be consumed.   I stop the rant here. Above all, I don't want to restrain the will to contribute. Having enthusiastic users overwhelming the inbox with fixes, ideas and enhancements is not the problem, it's a chance! Having too few people to perform the review with poor tools is the problem. We have to do something about it. In my eyes, the reviews done in the mailing list a few month ago are dead, they are not easily findable/usable/amendable. Thanks for bringing the subject, and please, continue to chanllenge us! Ideas for improving the process are wecome too. I think the problem is that trying to treat trunk development with Monticello the same as you do development with Git. > The problem with our dev model is that it's been designed with very > short cycles in mind. Git's was.  Squeak+MC's wasn't, but we're forcing it to do that.  It isn't surprising to me that using it this way isn't optimal.  IMO, MC trunk commits were meant to be *tested and finished*, only after iterative refinement in the Inbox.  It seems like little more than superficial tooling could greatly streamline it..  - Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Fri Apr 16 08:08:59 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 10:08:59 +0200 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz In-Reply-To: References: <53352cd9abea4ff999373cc0b798f00c@student.hpi.uni-potsdam.de> Message-ID: Hmm... each package version has a timestamp. This means you can sort the versions created between two MCMs. From there you can compute an ordered list of potential build numbers. From that list, you might be able to pick one. :-) Still, unreliable and not worth the effort. Best, Marcel Am 15.04.2021 18:25:18 schrieb Vanessa Freudenberg : “Interpolating” would be unreliable IMHO. There is a direct correspondence from explicit MCMs to version numbers, but not three other way around. You could say “please build version 20313” which would succeed because there is a config that produces that number, but if you were asking for version 20314 then we wouldn’t know which package to update beyond the version given in the config.  – Vanessa – On Thu, Apr 15, 2021 at 04:08 Marcel Taeumel wrote: Hi Christoph, as Vanessa explained, updates up to a specific MCM in the current update map might work. This also would not apply to cross-release/trunk updates in general. But might work most of the time since we rarely update release repositories. Since we now also have comments in MCMs, a user might actually be able to pick the desired MCM from a list of not-yet-loaded ones. (Hmm... maybe approximating a list of versions from interpolating the build version between two MCMs might work ...) Best, Marcel Am 15.04.2021 02:13:34 schrieb Vanessa Freudenberg : Hi Christoph, Good idea, but is not quite that simple. The image "version number" does not uniquely identify a specific set of package versions. It's not enough to build a similar image again. To have somewhat reproducible builds (they're not bit-identical) you need to store the actual list of loaded package versions. The easiest way to do that would be using an MCM. Only when an explicit config map is deployed that indeed is a "fixed point" with a defined set of packages. MCMcmUpdater normally loads each explicit update map, plus then automatically updates the last map to the latest package versions. That is governed by the useLatestPackagesFrom: method. The latest config map appears to be http://source.squeak.org/trunk/update-mt.485.mcm [http://source.squeak.org/trunk/update-mt.485.mcm] A method for reproducible builds could take e.g. 'mt.485' as an argument and should produce an image with version number 20313: ((MCRepository trunk versionNamed: 'update-mt.485.mcm') dependencies collect: [:dep | dep versionInfo versionNumber]) sum –Vanessa– On Thu, Apr 8, 2021 at 1:37 PM Thiede, Christoph wrote: Please review! :-) A concrete use case I was having in mind for this feature is to allow arbitrary Squeak Trunk version numbers in smalltalkCI, see: https://github.com/hpi-swa/smalltalkCI/pull/506 [https://github.com/hpi-swa/smalltalkCI/pull/506] [https://github.com/hpi-swa/smalltalkCI/pull/506]At the moment, it is WIP - an unpolished prototype only, but the idea is that you could specify something like Squeak64-18242 instead of Squeak64-trunk in the CI/CLI args. Nevertheless, even if the proposal for SCI should get rejected, I think this is a helpful feature because releases are quite rare in Squeak and I find it important to tag certain states in the Trunk evolution. [http://www.hpi.de/] To improve support for the SCI PR, I would also like to backport these changes to 5.3 - there was only a single merge conflict, so if you agree with this proposal, I can send you a changeset for 5.3. Thanks in advance! :-) Best, Christoph Von: Squeak-dev im Auftrag von commits at source.squeak.org [mailto:commits at source.squeak.org] Gesendet: Donnerstag, 8. April 2021 22:30:32 An: squeak-dev at lists.squeakfoundation.org [mailto:squeak-dev at lists.squeakfoundation.org] Betreff: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz   A new version of MonticelloConfigurations was added to project The Inbox: http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz [http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz] ==================== Summary ==================== Name: MonticelloConfigurations-ct.166 Author: ct Time: 8 April 2021, 10:30:30.702818 pm UUID: 6d887a86-fe0f-8e4c-a878-e40e8e612918 Ancestors: MonticelloConfigurations-mt.165 Adds support in MCMcmUpdater to install updates up to a specified system version number. This can be helpful when you want to bring an image into an exact state of an alpha version. I.e., a bug report or a tool can refer to Squeak6.0 Alpha #19570. Now it's possible to bring your 5.3 image into this state by evaluating:         MCMcmUpdater default doUpdate: true upToUpdate: 19570. Still, it is possible to install all updates or navigate forward to a certain upstream version using the existing protocol:         MCMcmUpdater default doUpdate: true.         MCMcmUpdater default doUpdate: true upTo: 470. Detailed changelog (anticlimax): - Added 'upToUpdate:' variant of update selectors on MCMcmUpdater. - Refactored existing update selectors to deduplicate the logic for doing a complete update (#doUpdate: etc.) versus installing all updates up to an upstream version (#doUpdate:upTo: etc.). - Added #currentSystemVersion and #totalSystemVersion on MCConfiguration to determine the current resp. eventual system version as implied by the update stream. - Renamed (+ deprecated) #depsSatisfying:version(s)Do:displayingProgress: due to misleading use of singular in the block keyword. - Improved multilingual support for the updater. - Improved documentation of the update protocol. Note that in some situations, a small number of follow-up updates will be installed that go beyond the specified system version number. This is caused by interdependencies between the target version and its postdecessors when a definiton was moved from one package into another one. See sender of MCReorganizationPreloader. =============== Diff against MonticelloConfigurations-mt.165 =============== Item was added: + ----- Method: MCConfiguration class>>ensureOpenTranscript:during: (in category 'preferences') ----- + ensureOpenTranscript: aBoolean during: aBlock + +        | previous | +        previous := self ensureOpenTranscript. +        self ensureOpenTranscript: aBoolean. +        ^ aBlock ensure: [ +                self ensureOpenTranscript: previous]! Item was added: + ----- Method: MCConfiguration>>currentSystemVersion (in category 'updating') ----- + currentSystemVersion +        "Answer the current system version found in my configuration (or the associated working copy)." + +        ^ self systemVersionForDeps: (self dependencies +                collect: [:dep | +                        dep isFulfilledByAncestors +                                ifTrue: [dep versionInfo] +                                ifFalse: [dep package workingCopy ancestors] ] )! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:upToUpdate:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock upToUpdate: anIntegerOrNil versionsDo: versionBlock displayingProgress: progressString + +        | count selectedVersions cleanWorkingCopies | +        self cacheAllFileNamesDuring: [ +                self repositories do: [ :eachRepository | +                        MCRepositoryGroup default addRepository: eachRepository ]. +                +                "First, download selected versions" +                count := 0. +                selectedVersions := OrderedCollection new. +                self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | +                        verName := dep versionInfo name. +                        self class extraProgressInfo ifTrue: +                                [ ProgressNotification signal: '' extra: ('Downloading {1}' translated format: {verName}) ]. +                        repo := self repositories +                                detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] +                                ifNone:  [ self logError: ('Version {1} not found in any repository' translated format: {verName}). +                                        self logError: 'Aborting' translated. +                                        ^ count ]. +                        (selectBlock value: dep) ifTrue: [ | version | +                                version := self versionNamed: verName for: dep from: repo. +                                version ifNil: [ self logError: ('Could not download version {1} from {2}' translated format: {verName. repo description}). +                                        self logError: 'Aborting' translated. +                                        ^ count ]. +                                dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" +                                dep package workingCopy repositoryGroup addRepository: repo. +                                selectedVersions add: version ] ]. +                +                "Then, process only those definitions that moved from one package to another, to avoid order dependence" +                cleanWorkingCopies := MCWorkingCopy allManagers select: +                        [ :wc | wc modified not and: +                                [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. +                MCReorganizationPreloader preloadMovesBetween: selectedVersions. +                +                "Finally, load/merge selected versions" +                [:exit | self withProgress: progressString in: selectedVersions do: [ :version | +                        self logUpdate: version package with: version. +                        self class extraProgressInfo ifTrue: +                                [ ProgressNotification signal: '' extra: ('Installing {1}' translated format: {version info name}) ]. +                        versionBlock value: version. +                        count := count + 1. +                        anIntegerOrNil ifNotNil: [ +                                self currentSystemVersion highestUpdate < anIntegerOrNil ifFalse: exit. +                                self flag: #optimization. "ct: By customizing the system version computation, we could save redundant version downloads above. However, because of the preloading stage, this might become a bit more sophisticated." ] ]. +                ] valueWithExit. +                +                "Clean up packages made dirty by MCReorganizationPreloader" +                cleanWorkingCopies +                        select: [ :wc | wc modified ] +                        thenDo: [ :wc | wc checkModified ]. +        ]. +        ^ count! Item was changed:   ----- Method: MCConfiguration>>depsSatisfying:versionDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionDo: versionBlock displayingProgress: progressString + +        self deprecated. +        ^ self +                depsSatisfying: selectBlock +                versionsDo: versionBlock +                displayingProgress: progressString! - depsSatisfying: selectBlock versionDo: verBlock displayingProgress: progressString -        | count selectedVersions cleanWorkingCopies | -        self cacheAllFileNamesDuring: [ -                self repositories do: [ :eachRepository | -                        MCRepositoryGroup default addRepository: eachRepository ]. -                "First, download selected versions" -                count := 0. -                selectedVersions := OrderedCollection new. -                self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | -                        verName := dep versionInfo name. -                        self class extraProgressInfo ifTrue: -                                [ ProgressNotification signal: '' extra: 'Downloading ' , verName ]. -                        repo := self repositories -                                detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] -                                ifNone:  [ self logError: 'Version ' , verName , ' not found in any repository'. -                                        self logError: 'Aborting'. -                                        ^ count ]. -                        (selectBlock value: dep) ifTrue: [ | version | -                                version := self versionNamed: verName for: dep from: repo. -                                version ifNil: [ self logError: 'Could not download version ' , verName , ' from ' , repo description. -                                        self logError: 'Aborting'. -                                        ^ count ]. -                                dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" -                                dep package workingCopy repositoryGroup addRepository: repo. -                                selectedVersions add: version]]. -                "Then, process only those definitions that moved from one package to another, to avoid order dependence" -                cleanWorkingCopies := MCWorkingCopy allManagers select: -                        [ :wc | wc modified not and: -                                [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. -                MCReorganizationPreloader preloadMovesBetween: selectedVersions. -                "Finally, load/merge selected versions" -                self withProgress: progressString in: selectedVersions do: [ :version | -                        self logUpdate: version package with: version. -                        self class extraProgressInfo ifTrue: -                                [ ProgressNotification signal: '' extra: 'Installing ' , version info name ]. -                        verBlock value: version. -                        count := count + 1 ]. -                "Clean up packages made dirty by MCReorganizationPreloader" -                cleanWorkingCopies -                        select: [ :wc | wc modified ] -                        thenDo: [ :wc | wc checkModified ]. -        ]. -        ^ count! Item was added: + ----- Method: MCConfiguration>>depsSatisfying:versionsDo:displayingProgress: (in category 'private') ----- + depsSatisfying: selectBlock versionsDo: versionBlock displayingProgress: progressString + +        ^ self +                depsSatisfying: selectBlock +                upToUpdate: nil +                versionsDo: versionBlock +                displayingProgress: progressString! Item was changed:   ----- Method: MCConfiguration>>load (in category 'actions') -----   load          ^self depsSatisfying: [:dep | dep isCurrent not] +                versionsDo: [:ver | ver load] +                displayingProgress: 'loading packages' translated! -                versionDo: [:ver | ver load] -                displayingProgress: 'loading packages' - ! Item was changed:   ----- Method: MCConfiguration>>merge (in category 'actions') -----   merge          ^self depsSatisfying: [:dep | dep isFulfilledByAncestors not] +                versionsDo: [:ver | ver merge] +                displayingProgress: 'merging packages' translated! -                versionDo: [:ver | ver merge] -                displayingProgress: 'merging packages' - ! Item was changed:   ----- Method: MCConfiguration>>setSystemVersion (in category 'updating') -----   setSystemVersion -        "Set the current system version date to the latest date found in my configuration (or the associated working copy). Also set the highest update number to the sum of version numbers in my configuration."   +        | newVersion | +        newVersion := self currentSystemVersion. -        | versionNumbers versionDates | -        versionNumbers := self dependencies collect: [:d | -                (d versionInfo name copyAfterLast: $.) asInteger]. -        versionDates := self dependencies collect: [:d | -                d versionInfo date -                        ifNil: [d package workingCopy ancestors first date]].          SystemVersion current +                date: newVersion date; +                highestUpdate: newVersion highestUpdate.! -                date: versionDates max; -                highestUpdate: versionNumbers sum.! Item was added: + ----- Method: MCConfiguration>>systemVersionForDeps: (in category 'updating') ----- + systemVersionForDeps: dependencies +        "Answer the system version that will be reached by loading the passed dependencies." + +        | versionNumbers versionDates | +        versionNumbers := dependencies collect: [:dep | +                dep isCollection +                        ifFalse: [dep name versionNumber] +                        ifTrue: [(dep collect: [:version | +                                version name versionNumber]) +                                        ifEmpty: [0] +                                        ifNotEmpty: #max]]. +        versionDates := dependencies with: self dependencies collect: [:dep :originalDep | +                (dep isCollection ifFalse: [dep date]) +                        ifNil: [originalDep package workingCopy ancestors +                                        ifEmpty: [nil] +                                        ifNotEmpty: [:ancestors | ancestors first date]]]. +        +        ^ SystemVersion new +                date: ((versionDates copyWithout: nil) +                        ifEmpty: [nil] +                        ifNotEmpty: #max); +                highestUpdate: versionNumbers sum! Item was added: + ----- Method: MCConfiguration>>totalSystemVersion (in category 'updating') ----- + totalSystemVersion +        "Answer the total system version that will be reached by upgrading the receiver." + +        ^ self systemVersionForDeps: (self dependencies collect: #versionInfo)! Item was changed:   ----- Method: MCConfiguration>>upgrade (in category 'actions') -----   upgrade + +        ^ self upgradeUpToUpdate: nil! -        ^self depsSatisfying: -                        [:dep | dep isFulfilledByAncestors not] -                versionDo: -                        [:ver | -                        (self class upgradeIsMerge and: [ver shouldMerge]) -                                ifFalse: [ver load] -                                ifTrue: -                                        [[ver merge] -                                                on: MCNoChangesException -                                                do: [:req| req resume ] -                                                on: MCMergeResolutionRequest -                                                do: [:request | -                                                        request merger conflicts isEmpty -                                                                ifTrue: [request resume: true] -                                                                ifFalse: [request pass]] -                                                on: Deprecation -                                                do: [:req| req resume ]]] -                displayingProgress: 'upgrading packages'! Item was added: + ----- Method: MCConfiguration>>upgradeUpToUpdate: (in category 'actions') ----- + upgradeUpToUpdate: anIntegerOrNil + +        ^ self +                depsSatisfying: [:dep | +                        dep isFulfilledByAncestors not] +                upToUpdate: anIntegerOrNil +                versionsDo: [:ver | +                        (self class upgradeIsMerge and: [ver shouldMerge]) +                                ifFalse: [ver load] +                                ifTrue: +                                        [[ver merge] +                                                on: MCNoChangesException +                                                do: [:req | req resume ] +                                                on: MCMergeResolutionRequest +                                                do: [:request | +                                                        request merger conflicts isEmpty +                                                                ifTrue: [request resume: true] +                                                                ifFalse: [request pass]] +                                                on: Deprecation +                                                do: [:req | req resume ]]] +                displayingProgress: 'upgrading packages' translated! Item was added: + ----- Method: MCMcmUpdater>>basicDoUpdate:do: (in category 'updating') ----- + basicDoUpdate: interactive do: aBlock +        "Update the image by evaluating aBlock. If this is the default updater for the system, update the system version when complete. If interactive, use a modal notifier, otherwise only update the transcript. Flush all caches. If a previous download failed, this is often helpful." + +        | config previousUpdateLevel | +        previousUpdateLevel := SystemVersion current highestUpdate. +        MCFileBasedRepository flushAllCaches. +        +        MCConfiguration ensureOpenTranscript: interactive during: [ +                config := aBlock value. +        +                config ifNil: [ +                        interactive ifTrue: [^ self inform: 'Unable to retrieve updates from remote repository.' translated]. +                        Transcript cr; show: '==========  Unable to retrieve updates from remote repository. ==========' translated; cr. +                        ^ self ]. +        +                MCMcmUpdater default == self +                        ifTrue: [ +                                config setSystemVersion. +                                interactive ifTrue: [ +                                        self inform: (self updateMessageFor: previousUpdateLevel)]. +                                Transcript cr; +                                        show: '==========  Update completed:  ' translated; +                                        show: previousUpdateLevel; +                                        show: ' -> ' ; +                                        show: SystemVersion current highestUpdate; +                                        show: ' =========='; cr ] +                        ifFalse: [ +                                interactive +                                        ifTrue: [ self inform: 'Update completed.' ]. +                                Transcript cr; show: '==========  Update completed. ==========' translated; cr ] ].! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepositories:do: (in category 'updating') ----- + basicUpdateFromRepositories: repositoryUrls do: repositoryBlock + +        | repos config | +        MCConfiguration upgradeIsMerge: true. +        "The list of repositories to consult in order" +        repos := repositoryUrls collect: [:url|  +                MCRepositoryGroup default repositories +                        detect: [:repo | repo description = url] +                        ifNone: [ | repo | +                                repo := MCHttpRepository location: url. +                                MCRepositoryGroup default addRepository: repo. +                                repo]]. +        +        "The list of updates-author.version.mcm sorted by version" +        repos do: [:repo | +                config := repositoryBlock value: repo]. +        ^ config! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository thenDo: configBlock + +        ^ self +                basicUpdateFromRepository: aRepository +                whileUpdatesSatisfy: [true] +                upToUpdate: nil +                thenDo: configBlock! Item was added: + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:whileUpdatesSatisfy:upToUpdate:thenDo: (in category 'updating') ----- + basicUpdateFromRepository: aRepository whileUpdatesSatisfy: updateBlock upToUpdate: anIntegerOrNil thenDo: configBlock + +        | config | +        aRepository cacheAllFileNamesDuring: [ | updateList | +                updateList := self updateListFor: aRepository. +                "Proceed only if there are updates available at all." +                updateList ifNotEmpty: [ +                        updateList := self refreshUpdateMapFor: aRepository with: updateList. +                        "Now process each update file. Check if we have all dependencies and if not, load the entire configuration (this is mostly to skip older updates quickly)" +                        [:exit | updateList +                                do: [:assoc | +                                        (updateBlock cull: assoc key cull: assoc value) ifFalse: exit. +                                        ProgressNotification signal: '' extra: ('Processing {1}' translated format: {assoc value}). +                                        config := aRepository versionNamed: assoc value. +                                        anIntegerOrNil ifNotNil: [ +                                                config currentSystemVersion highestUpdate <= anIntegerOrNil ifFalse: exit]. +                                        self updateFromConfig: config upToUpdate: anIntegerOrNil. +                                        anIntegerOrNil ifNotNil: [ +                                                config currentSystemVersion highestUpdate < config totalSystemVersion highestUpdate ifTrue: exit]. +                                        self lastUpdateMap at: aRepository description put: assoc key] +                                displayingProgress: 'Processing configurations' translated] valueWithExit. +                        configBlock cull: config]]. +        ^ config! Item was changed:   ----- Method: MCMcmUpdater>>doUpdate: (in category 'updating') -----   doUpdate: interactive +        "Update the image by loading all pending updates from the server." -        "Update the image by loading all pending updates from the server. If this is -        the default updater for the system, update the system version when complete. -        If interteractive use a modal notifier, otherwise only update the transcript. -        Flush all caches. If a previous download failed this is often helpful"   +        ^ self basicDoUpdate: interactive do: [ +                self updateFromRepository ]! -        | config previousUpdateLevel ensureTranscriptSetting | -        previousUpdateLevel := SystemVersion current highestUpdate. -        MCFileBasedRepository flushAllCaches.   -        ensureTranscriptSetting := MCConfiguration ensureOpenTranscript. -        [ MCConfiguration ensureOpenTranscript: interactive. -        config := self updateFromRepository. -        config ifNil: [ -                interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. -                Transcript cr; show: '==========  Unable to retrieve updates from remote repository. ==========' translated; cr. -                ^ self ]. -        MCMcmUpdater default == self -                ifTrue: [ -                        config setSystemVersion. -                        interactive ifTrue: [ -                                self inform: (self updateMessageFor: previousUpdateLevel)]. -                        Transcript cr; -                                show: '==========  Update completed:  ' translated; -                                show: previousUpdateLevel; -                                show: ' -> ' ; -                                show: SystemVersion current highestUpdate; -                                show: ' =========='; cr ] -                ifFalse: [ -                        interactive -                                ifTrue: [ self inform: 'Update completed.' ]. -                        Transcript cr; show: '==========  Update completed. ==========' translated; cr ] ] -                ensure: [ MCConfiguration ensureOpenTranscript: ensureTranscriptSetting]. - -        ! Item was changed:   ----- Method: MCMcmUpdater>>doUpdate:upTo: (in category 'updating') -----   doUpdate: interactive upTo: versionNumber +        "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." -        "Update the image by loading all pending updates from the server. If this is -        the default updater for the system, update the system version when complete. -        If interteractive use a modal notifier, otherwise only update the transcript. -        Flush all caches. If a previous download failed this is often helpful"   +        ^ self basicDoUpdate: interactive do: [ +                self updateFromRepositories: {self repository} upTo: versionNumber ]! -        | config previousUpdateLevel | -        previousUpdateLevel := SystemVersion current highestUpdate. -        MCFileBasedRepository flushAllCaches. -        config := self updateFromRepositories: { self repository } upTo: versionNumber. -        config ifNil: [ -                interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. -                Transcript cr; show: '==========  Unable to retrieve updates from remote repository. ==========' translated; cr. -                ^ self ]. -        MCMcmUpdater default == self -                ifTrue: [ -                        config setSystemVersion. -                        interactive ifTrue: [ -                                self inform: (self updateMessageFor: previousUpdateLevel)]. -                        Transcript cr; -                                show: '==========  Update completed:  ' translated; -                                show: previousUpdateLevel; -                                show: ' -> ' ; -                                show: SystemVersion current highestUpdate; -                                show: ' =========='; cr ] -                ifFalse: [ -                        interactive -                                ifTrue: [ self inform: 'Update completed.' ]. -                        Transcript cr; show: '==========  Update completed. ==========' translated; cr ] -        ! Item was added: + ----- Method: MCMcmUpdater>>doUpdate:upToUpdate: (in category 'updating') ----- + doUpdate: interactive upToUpdate: anIntegerOrNil +        "Update the image by loading all pending updates from the server until the system version has reached at least anInteger. If anInteger is nil, install all available updates." + +        ^ self basicDoUpdate: interactive do: [ +                self updateFromRepositories: {self repository} upToUpdate: anIntegerOrNil ]! Item was changed:   ----- Method: MCMcmUpdater>>doUpdateUpTo: (in category 'updating') -----   doUpdateUpTo: versionNumber +        "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." -        "Update the image by loading all pending updates from the server. If this is -        the default updater for the system, update the system version when complete. -        Flush all caches. If a previous download failed this is often helpful"            ^self doUpdate: true upTo: versionNumber   ! Item was changed:   ----- Method: MCMcmUpdater>>updateFromConfig: (in category 'updating') -----   updateFromConfig: config   +        ^ self updateFromConfig: config upToUpdate: nil! -        "Skip packages that were specifically unloaded" -        config dependencies: (config dependencies -                reject: [:dep| self class skipPackages includes: dep package name]). -        self class updateMissingPackages ifFalse:[ -                "Skip packages that are not in the image" -                config dependencies: (config dependencies -                        select: [:dep| dep package hasWorkingCopy])]. -        (config dependencies allSatisfy:[:dep| dep isFulfilled]) -                ifFalse:[config upgrade]. - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromConfig:upToUpdate: (in category 'updating') ----- + updateFromConfig: config upToUpdate: anIntegerOrNil + +        "Skip packages that were specifically unloaded" +        config dependencies: (config dependencies +                reject: [:dep | self class skipPackages includes: dep package name]). +        self class updateMissingPackages ifFalse: [ +                "Skip packages that are not in the image" +                config dependencies: (config dependencies +                        select: [:dep | dep package hasWorkingCopy])]. +        (config dependencies allSatisfy: [:dep | dep isFulfilled]) +                ifFalse: [config upgradeUpToUpdate: anIntegerOrNil].! Item was changed:   ----- Method: MCMcmUpdater>>updateFromRepositories:upTo: (in category 'updating') -----   updateFromRepositories: repositoryUrls upTo: versionNumber +        " +        MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest [http://squeaksource.com/MCUpdateTest]') upTo: 3 +        " -        "MCMcmUpdater updateFromRepositories: #( -                'http://squeaksource.com/MCUpdateTest [http://squeaksource.com/MCUpdateTest]' -        )"   +        ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | +                self updateFromRepository: repo upTo: versionNumber]! -        | repos config | -        MCConfiguration upgradeIsMerge: true. -        "The list of repositories to consult in order" -        repos := repositoryUrls collect:[:url| -                MCRepositoryGroup default repositories -                        detect:[:r| r description = url] -                        ifNone:[ | r | -                                r := MCHttpRepository location: url user: '' password: ''. -                                MCRepositoryGroup default addRepository: r. -                                r]]. - -        "The list of updates-author.version.mcm sorted by version" -        repos do:[ :r | config := self updateFromRepository: r upTo: versionNumber]. -        ^config! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepositories:upToUpdate: (in category 'updating') ----- + updateFromRepositories: repositoryUrls upToUpdate: anIntegerOrNil +        " +        MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest [http://squeaksource.com/MCUpdateTest]') upToUpdate: 2130 +        " + +        ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | +                self updateFromRepository: repo upToUpdate: anIntegerOrNil ]! Item was changed:   ----- Method: MCMcmUpdater>>updateFromRepository (in category 'updating') -----   updateFromRepository   +        ^ self updateFromRepository: self getRepositoryFromRepositoryGroup! -        | config repo | -        repo := self getRepositoryFromRepositoryGroup. -        repo cacheAllFileNamesDuring: [ | updateList | -                updateList := self updateListFor: repo. -                "Proceed only if there are updates available at all." -                updateList ifNotEmpty: [ -                        updateList := self refreshUpdateMapFor: repo with: updateList. -                        "Now process each update file. Check if we have all dependencies and if not, -                        load the entire configuration (this is mostly to skip older updates quickly)" -                        updateList do:[:assoc| -                                ProgressNotification signal: '' extra: 'Processing ', assoc value. -                                config := repo versionNamed: assoc value. -                                self updateFromConfig: config. -                                self lastUpdateMap at: repo description put: assoc key. -                        ] displayingProgress: 'Processing configurations'. -                        "We've loaded all the provided update configurations. -                        Use the latest configuration to update all the remaining packages." -                        (self useLatestPackagesFrom: repo) ifTrue: [ -                                config updateFromRepositories. -                                config upgrade]. -                ]]. -        ^ config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository: (in category 'updating') ----- + updateFromRepository: aRepository + +        ^ self basicUpdateFromRepository: aRepository thenDo: [:config | +                "We've loaded all the provided update configurations. Use the latest configuration to update all the remaining packages." +                (self useLatestPackagesFrom: aRepository) ifTrue: [ +                        config updateFromRepositories. +                        config upgrade]]! Item was changed:   ----- Method: MCMcmUpdater>>updateFromRepository:upTo: (in category 'updating') ----- + updateFromRepository: aRepository upTo: versionNumber - updateFromRepository: repository upTo: versionNumber   +        ^ self +                basicUpdateFromRepository: aRepository +                whileUpdatesSatisfy: [:updateVersion | updateVersion <= versionNumber] +                upToUpdate: nil +                thenDo: []! -        | config | -        repository cacheAllFileNamesDuring: [ | updateList | -                updateList := self updateListFor: repository. -                "Proceed only if there are updates available at all." -                updateList ifNotEmpty: [ -                        updateList := self refreshUpdateMapFor: repository with: updateList. -                        "Now process each update file. Check if we have all dependencies and if not, -                        load the entire configuration (this is mostly to skip older updates quickly)" -                        updateList do:[:assoc| -                                assoc key > versionNumber ifTrue: [^config]. -                                ProgressNotification signal: '' extra: 'Processing ', assoc value. -                                config := repository versionNamed: assoc value. -                                self updateFromConfig: config. -                                self lastUpdateMap at: repository description put: assoc key. -                        ] displayingProgress: 'Processing configurations'. -                ]]. -        ^config - ! Item was added: + ----- Method: MCMcmUpdater>>updateFromRepository:upToUpdate: (in category 'updating') ----- + updateFromRepository: aRepository upToUpdate: anIntegerOrNil + +        ^ self +                basicUpdateFromRepository: aRepository +                whileUpdatesSatisfy: [true] +                upToUpdate: anIntegerOrNil +                thenDo: []! -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Fri Apr 16 08:21:54 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 16 Apr 2021 10:21:54 +0200 Subject: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz In-Reply-To: References: <53352cd9abea4ff999373cc0b798f00c@student.hpi.uni-potsdam.de> Message-ID: Yes, but it is the timestamp of initial commit, not the timestamp of addition into trunk (unless you extract that by other means). Since we can move versions from months ago from inbox (or anything else) to trunk, in presence of several branches, you can't really decide... Le ven. 16 avr. 2021 à 10:09, Marcel Taeumel a écrit : > > Hmm... each package version has a timestamp. This means you can sort the versions created between two MCMs. From there you can compute an ordered list of potential build numbers. From that list, you might be able to pick one. :-) Still, unreliable and not worth the effort. > > Best, > Marcel > > Am 15.04.2021 18:25:18 schrieb Vanessa Freudenberg : > > “Interpolating” would be unreliable IMHO. There is a direct correspondence from explicit MCMs to version numbers, but not three other way around. You could say “please build version 20313” which would succeed because there is a config that produces that number, but if you were asking for version 20314 then we wouldn’t know which package to update beyond the version given in the config. > > – Vanessa – > > On Thu, Apr 15, 2021 at 04:08 Marcel Taeumel wrote: >> >> Hi Christoph, >> >> as Vanessa explained, updates up to a specific MCM in the current update map might work. This also would not apply to cross-release/trunk updates in general. But might work most of the time since we rarely update release repositories. >> >> Since we now also have comments in MCMs, a user might actually be able to pick the desired MCM from a list of not-yet-loaded ones. >> >> (Hmm... maybe approximating a list of versions from interpolating the build version between two MCMs might work ...) >> >> Best, >> Marcel >> >> Am 15.04.2021 02:13:34 schrieb Vanessa Freudenberg : >> >> Hi Christoph, >> >> Good idea, but is not quite that simple. The image "version number" does not uniquely identify a specific set of package versions. It's not enough to build a similar image again. >> >> To have somewhat reproducible builds (they're not bit-identical) you need to store the actual list of loaded package versions. The easiest way to do that would be using an MCM. Only when an explicit config map is deployed that indeed is a "fixed point" with a defined set of packages. >> >> MCMcmUpdater normally loads each explicit update map, plus then automatically updates the last map to the latest package versions. That is governed by the useLatestPackagesFrom: method. >> >> The latest config map appears to be >> http://source.squeak.org/trunk/update-mt.485.mcm >> >> A method for reproducible builds could take e.g. 'mt.485' as an argument and should produce an image with version number 20313: >> >> ((MCRepository trunk versionNamed: 'update-mt.485.mcm') dependencies collect: [:dep | dep versionInfo versionNumber]) sum >> >> >> –Vanessa– >> >> >> On Thu, Apr 8, 2021 at 1:37 PM Thiede, Christoph wrote: >>> >>> Please review! :-) >>> >>> >>> A concrete use case I was having in mind for this feature is to allow arbitrary Squeak Trunk version numbers in smalltalkCI, see: https://github.com/hpi-swa/smalltalkCI/pull/506 >>> >>> At the moment, it is WIP - an unpolished prototype only, but the idea is that you could specify something like Squeak64-18242 instead of Squeak64-trunk in the CI/CLI args. >>> >>> >>> Nevertheless, even if the proposal for SCI should get rejected, I think this is a helpful feature because releases are quite rare in Squeak and I find it important to tag certain states in the Trunk evolution. >>> >>> To improve support for the SCI PR, I would also like to backport these changes to 5.3 - there was only a single merge conflict, so if you agree with this proposal, I can send you a changeset for 5.3. Thanks in advance! :-) >>> >>> Best, >>> Christoph >>> ________________________________ >>> Von: Squeak-dev im Auftrag von commits at source.squeak.org >>> Gesendet: Donnerstag, 8. April 2021 22:30:32 >>> An: squeak-dev at lists.squeakfoundation.org >>> Betreff: [squeak-dev] The Inbox: MonticelloConfigurations-ct.166.mcz >>> >>> A new version of MonticelloConfigurations was added to project The Inbox: >>> http://source.squeak.org/inbox/MonticelloConfigurations-ct.166.mcz >>> >>> ==================== Summary ==================== >>> >>> Name: MonticelloConfigurations-ct.166 >>> Author: ct >>> Time: 8 April 2021, 10:30:30.702818 pm >>> UUID: 6d887a86-fe0f-8e4c-a878-e40e8e612918 >>> Ancestors: MonticelloConfigurations-mt.165 >>> >>> Adds support in MCMcmUpdater to install updates up to a specified system version number. This can be helpful when you want to bring an image into an exact state of an alpha version. I.e., a bug report or a tool can refer to Squeak6.0 Alpha #19570. Now it's possible to bring your 5.3 image into this state by evaluating: >>> >>> MCMcmUpdater default doUpdate: true upToUpdate: 19570. >>> >>> Still, it is possible to install all updates or navigate forward to a certain upstream version using the existing protocol: >>> >>> MCMcmUpdater default doUpdate: true. >>> MCMcmUpdater default doUpdate: true upTo: 470. >>> >>> Detailed changelog (anticlimax): >>> >>> - Added 'upToUpdate:' variant of update selectors on MCMcmUpdater. >>> - Refactored existing update selectors to deduplicate the logic for doing a complete update (#doUpdate: etc.) versus installing all updates up to an upstream version (#doUpdate:upTo: etc.). >>> - Added #currentSystemVersion and #totalSystemVersion on MCConfiguration to determine the current resp. eventual system version as implied by the update stream. >>> - Renamed (+ deprecated) #depsSatisfying:version(s)Do:displayingProgress: due to misleading use of singular in the block keyword. >>> - Improved multilingual support for the updater. >>> - Improved documentation of the update protocol. >>> >>> Note that in some situations, a small number of follow-up updates will be installed that go beyond the specified system version number. This is caused by interdependencies between the target version and its postdecessors when a definiton was moved from one package into another one. See sender of MCReorganizationPreloader. >>> >>> =============== Diff against MonticelloConfigurations-mt.165 =============== >>> >>> Item was added: >>> + ----- Method: MCConfiguration class>>ensureOpenTranscript:during: (in category 'preferences') ----- >>> + ensureOpenTranscript: aBoolean during: aBlock >>> + >>> + | previous | >>> + previous := self ensureOpenTranscript. >>> + self ensureOpenTranscript: aBoolean. >>> + ^ aBlock ensure: [ >>> + self ensureOpenTranscript: previous]! >>> >>> Item was added: >>> + ----- Method: MCConfiguration>>currentSystemVersion (in category 'updating') ----- >>> + currentSystemVersion >>> + "Answer the current system version found in my configuration (or the associated working copy)." >>> + >>> + ^ self systemVersionForDeps: (self dependencies >>> + collect: [:dep | >>> + dep isFulfilledByAncestors >>> + ifTrue: [dep versionInfo] >>> + ifFalse: [dep package workingCopy ancestors] ] )! >>> >>> Item was added: >>> + ----- Method: MCConfiguration>>depsSatisfying:upToUpdate:versionsDo:displayingProgress: (in category 'private') ----- >>> + depsSatisfying: selectBlock upToUpdate: anIntegerOrNil versionsDo: versionBlock displayingProgress: progressString >>> + >>> + | count selectedVersions cleanWorkingCopies | >>> + self cacheAllFileNamesDuring: [ >>> + self repositories do: [ :eachRepository | >>> + MCRepositoryGroup default addRepository: eachRepository ]. >>> + >>> + "First, download selected versions" >>> + count := 0. >>> + selectedVersions := OrderedCollection new. >>> + self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | >>> + verName := dep versionInfo name. >>> + self class extraProgressInfo ifTrue: >>> + [ ProgressNotification signal: '' extra: ('Downloading {1}' translated format: {verName}) ]. >>> + repo := self repositories >>> + detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] >>> + ifNone: [ self logError: ('Version {1} not found in any repository' translated format: {verName}). >>> + self logError: 'Aborting' translated. >>> + ^ count ]. >>> + (selectBlock value: dep) ifTrue: [ | version | >>> + version := self versionNamed: verName for: dep from: repo. >>> + version ifNil: [ self logError: ('Could not download version {1} from {2}' translated format: {verName. repo description}). >>> + self logError: 'Aborting' translated. >>> + ^ count ]. >>> + dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" >>> + dep package workingCopy repositoryGroup addRepository: repo. >>> + selectedVersions add: version ] ]. >>> + >>> + "Then, process only those definitions that moved from one package to another, to avoid order dependence" >>> + cleanWorkingCopies := MCWorkingCopy allManagers select: >>> + [ :wc | wc modified not and: >>> + [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. >>> + MCReorganizationPreloader preloadMovesBetween: selectedVersions. >>> + >>> + "Finally, load/merge selected versions" >>> + [:exit | self withProgress: progressString in: selectedVersions do: [ :version | >>> + self logUpdate: version package with: version. >>> + self class extraProgressInfo ifTrue: >>> + [ ProgressNotification signal: '' extra: ('Installing {1}' translated format: {version info name}) ]. >>> + versionBlock value: version. >>> + count := count + 1. >>> + anIntegerOrNil ifNotNil: [ >>> + self currentSystemVersion highestUpdate < anIntegerOrNil ifFalse: exit. >>> + self flag: #optimization. "ct: By customizing the system version computation, we could save redundant version downloads above. However, because of the preloading stage, this might become a bit more sophisticated." ] ]. >>> + ] valueWithExit. >>> + >>> + "Clean up packages made dirty by MCReorganizationPreloader" >>> + cleanWorkingCopies >>> + select: [ :wc | wc modified ] >>> + thenDo: [ :wc | wc checkModified ]. >>> + ]. >>> + ^ count! >>> >>> Item was changed: >>> ----- Method: MCConfiguration>>depsSatisfying:versionDo:displayingProgress: (in category 'private') ----- >>> + depsSatisfying: selectBlock versionDo: versionBlock displayingProgress: progressString >>> + >>> + self deprecated. >>> + ^ self >>> + depsSatisfying: selectBlock >>> + versionsDo: versionBlock >>> + displayingProgress: progressString! >>> - depsSatisfying: selectBlock versionDo: verBlock displayingProgress: progressString >>> - | count selectedVersions cleanWorkingCopies | >>> - self cacheAllFileNamesDuring: [ >>> - self repositories do: [ :eachRepository | >>> - MCRepositoryGroup default addRepository: eachRepository ]. >>> - "First, download selected versions" >>> - count := 0. >>> - selectedVersions := OrderedCollection new. >>> - self withProgress: progressString in: self dependencies do: [ :dep | | verName repo | >>> - verName := dep versionInfo name. >>> - self class extraProgressInfo ifTrue: >>> - [ ProgressNotification signal: '' extra: 'Downloading ' , verName ]. >>> - repo := self repositories >>> - detect: [ :eachRepository | eachRepository includesVersionNamed: verName ] >>> - ifNone: [ self logError: 'Version ' , verName , ' not found in any repository'. >>> - self logError: 'Aborting'. >>> - ^ count ]. >>> - (selectBlock value: dep) ifTrue: [ | version | >>> - version := self versionNamed: verName for: dep from: repo. >>> - version ifNil: [ self logError: 'Could not download version ' , verName , ' from ' , repo description. >>> - self logError: 'Aborting'. >>> - ^ count ]. >>> - dep package workingCopy newRepositoryGroupIfDefault. "fix old working copies" >>> - dep package workingCopy repositoryGroup addRepository: repo. >>> - selectedVersions add: version]]. >>> - "Then, process only those definitions that moved from one package to another, to avoid order dependence" >>> - cleanWorkingCopies := MCWorkingCopy allManagers select: >>> - [ :wc | wc modified not and: >>> - [ selectedVersions anySatisfy: [ :v | wc package = v package ] ] ]. >>> - MCReorganizationPreloader preloadMovesBetween: selectedVersions. >>> - "Finally, load/merge selected versions" >>> - self withProgress: progressString in: selectedVersions do: [ :version | >>> - self logUpdate: version package with: version. >>> - self class extraProgressInfo ifTrue: >>> - [ ProgressNotification signal: '' extra: 'Installing ' , version info name ]. >>> - verBlock value: version. >>> - count := count + 1 ]. >>> - "Clean up packages made dirty by MCReorganizationPreloader" >>> - cleanWorkingCopies >>> - select: [ :wc | wc modified ] >>> - thenDo: [ :wc | wc checkModified ]. >>> - ]. >>> - ^ count! >>> >>> Item was added: >>> + ----- Method: MCConfiguration>>depsSatisfying:versionsDo:displayingProgress: (in category 'private') ----- >>> + depsSatisfying: selectBlock versionsDo: versionBlock displayingProgress: progressString >>> + >>> + ^ self >>> + depsSatisfying: selectBlock >>> + upToUpdate: nil >>> + versionsDo: versionBlock >>> + displayingProgress: progressString! >>> >>> Item was changed: >>> ----- Method: MCConfiguration>>load (in category 'actions') ----- >>> load >>> ^self depsSatisfying: [:dep | dep isCurrent not] >>> + versionsDo: [:ver | ver load] >>> + displayingProgress: 'loading packages' translated! >>> - versionDo: [:ver | ver load] >>> - displayingProgress: 'loading packages' >>> - ! >>> >>> Item was changed: >>> ----- Method: MCConfiguration>>merge (in category 'actions') ----- >>> merge >>> ^self depsSatisfying: [:dep | dep isFulfilledByAncestors not] >>> + versionsDo: [:ver | ver merge] >>> + displayingProgress: 'merging packages' translated! >>> - versionDo: [:ver | ver merge] >>> - displayingProgress: 'merging packages' >>> - ! >>> >>> Item was changed: >>> ----- Method: MCConfiguration>>setSystemVersion (in category 'updating') ----- >>> setSystemVersion >>> - "Set the current system version date to the latest date found in my configuration (or the associated working copy). Also set the highest update number to the sum of version numbers in my configuration." >>> >>> + | newVersion | >>> + newVersion := self currentSystemVersion. >>> - | versionNumbers versionDates | >>> - versionNumbers := self dependencies collect: [:d | >>> - (d versionInfo name copyAfterLast: $.) asInteger]. >>> - versionDates := self dependencies collect: [:d | >>> - d versionInfo date >>> - ifNil: [d package workingCopy ancestors first date]]. >>> SystemVersion current >>> + date: newVersion date; >>> + highestUpdate: newVersion highestUpdate.! >>> - date: versionDates max; >>> - highestUpdate: versionNumbers sum.! >>> >>> Item was added: >>> + ----- Method: MCConfiguration>>systemVersionForDeps: (in category 'updating') ----- >>> + systemVersionForDeps: dependencies >>> + "Answer the system version that will be reached by loading the passed dependencies." >>> + >>> + | versionNumbers versionDates | >>> + versionNumbers := dependencies collect: [:dep | >>> + dep isCollection >>> + ifFalse: [dep name versionNumber] >>> + ifTrue: [(dep collect: [:version | >>> + version name versionNumber]) >>> + ifEmpty: [0] >>> + ifNotEmpty: #max]]. >>> + versionDates := dependencies with: self dependencies collect: [:dep :originalDep | >>> + (dep isCollection ifFalse: [dep date]) >>> + ifNil: [originalDep package workingCopy ancestors >>> + ifEmpty: [nil] >>> + ifNotEmpty: [:ancestors | ancestors first date]]]. >>> + >>> + ^ SystemVersion new >>> + date: ((versionDates copyWithout: nil) >>> + ifEmpty: [nil] >>> + ifNotEmpty: #max); >>> + highestUpdate: versionNumbers sum! >>> >>> Item was added: >>> + ----- Method: MCConfiguration>>totalSystemVersion (in category 'updating') ----- >>> + totalSystemVersion >>> + "Answer the total system version that will be reached by upgrading the receiver." >>> + >>> + ^ self systemVersionForDeps: (self dependencies collect: #versionInfo)! >>> >>> Item was changed: >>> ----- Method: MCConfiguration>>upgrade (in category 'actions') ----- >>> upgrade >>> + >>> + ^ self upgradeUpToUpdate: nil! >>> - ^self depsSatisfying: >>> - [:dep | dep isFulfilledByAncestors not] >>> - versionDo: >>> - [:ver | >>> - (self class upgradeIsMerge and: [ver shouldMerge]) >>> - ifFalse: [ver load] >>> - ifTrue: >>> - [[ver merge] >>> - on: MCNoChangesException >>> - do: [:req| req resume ] >>> - on: MCMergeResolutionRequest >>> - do: [:request | >>> - request merger conflicts isEmpty >>> - ifTrue: [request resume: true] >>> - ifFalse: [request pass]] >>> - on: Deprecation >>> - do: [:req| req resume ]]] >>> - displayingProgress: 'upgrading packages'! >>> >>> Item was added: >>> + ----- Method: MCConfiguration>>upgradeUpToUpdate: (in category 'actions') ----- >>> + upgradeUpToUpdate: anIntegerOrNil >>> + >>> + ^ self >>> + depsSatisfying: [:dep | >>> + dep isFulfilledByAncestors not] >>> + upToUpdate: anIntegerOrNil >>> + versionsDo: [:ver | >>> + (self class upgradeIsMerge and: [ver shouldMerge]) >>> + ifFalse: [ver load] >>> + ifTrue: >>> + [[ver merge] >>> + on: MCNoChangesException >>> + do: [:req | req resume ] >>> + on: MCMergeResolutionRequest >>> + do: [:request | >>> + request merger conflicts isEmpty >>> + ifTrue: [request resume: true] >>> + ifFalse: [request pass]] >>> + on: Deprecation >>> + do: [:req | req resume ]]] >>> + displayingProgress: 'upgrading packages' translated! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>basicDoUpdate:do: (in category 'updating') ----- >>> + basicDoUpdate: interactive do: aBlock >>> + "Update the image by evaluating aBlock. If this is the default updater for the system, update the system version when complete. If interactive, use a modal notifier, otherwise only update the transcript. Flush all caches. If a previous download failed, this is often helpful." >>> + >>> + | config previousUpdateLevel | >>> + previousUpdateLevel := SystemVersion current highestUpdate. >>> + MCFileBasedRepository flushAllCaches. >>> + >>> + MCConfiguration ensureOpenTranscript: interactive during: [ >>> + config := aBlock value. >>> + >>> + config ifNil: [ >>> + interactive ifTrue: [^ self inform: 'Unable to retrieve updates from remote repository.' translated]. >>> + Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. >>> + ^ self ]. >>> + >>> + MCMcmUpdater default == self >>> + ifTrue: [ >>> + config setSystemVersion. >>> + interactive ifTrue: [ >>> + self inform: (self updateMessageFor: previousUpdateLevel)]. >>> + Transcript cr; >>> + show: '========== Update completed: ' translated; >>> + show: previousUpdateLevel; >>> + show: ' -> ' ; >>> + show: SystemVersion current highestUpdate; >>> + show: ' =========='; cr ] >>> + ifFalse: [ >>> + interactive >>> + ifTrue: [ self inform: 'Update completed.' ]. >>> + Transcript cr; show: '========== Update completed. ==========' translated; cr ] ].! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>basicUpdateFromRepositories:do: (in category 'updating') ----- >>> + basicUpdateFromRepositories: repositoryUrls do: repositoryBlock >>> + >>> + | repos config | >>> + MCConfiguration upgradeIsMerge: true. >>> + "The list of repositories to consult in order" >>> + repos := repositoryUrls collect: [:url| >>> + MCRepositoryGroup default repositories >>> + detect: [:repo | repo description = url] >>> + ifNone: [ | repo | >>> + repo := MCHttpRepository location: url. >>> + MCRepositoryGroup default addRepository: repo. >>> + repo]]. >>> + >>> + "The list of updates-author.version.mcm sorted by version" >>> + repos do: [:repo | >>> + config := repositoryBlock value: repo]. >>> + ^ config! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:thenDo: (in category 'updating') ----- >>> + basicUpdateFromRepository: aRepository thenDo: configBlock >>> + >>> + ^ self >>> + basicUpdateFromRepository: aRepository >>> + whileUpdatesSatisfy: [true] >>> + upToUpdate: nil >>> + thenDo: configBlock! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>basicUpdateFromRepository:whileUpdatesSatisfy:upToUpdate:thenDo: (in category 'updating') ----- >>> + basicUpdateFromRepository: aRepository whileUpdatesSatisfy: updateBlock upToUpdate: anIntegerOrNil thenDo: configBlock >>> + >>> + | config | >>> + aRepository cacheAllFileNamesDuring: [ | updateList | >>> + updateList := self updateListFor: aRepository. >>> + "Proceed only if there are updates available at all." >>> + updateList ifNotEmpty: [ >>> + updateList := self refreshUpdateMapFor: aRepository with: updateList. >>> + "Now process each update file. Check if we have all dependencies and if not, load the entire configuration (this is mostly to skip older updates quickly)" >>> + [:exit | updateList >>> + do: [:assoc | >>> + (updateBlock cull: assoc key cull: assoc value) ifFalse: exit. >>> + ProgressNotification signal: '' extra: ('Processing {1}' translated format: {assoc value}). >>> + config := aRepository versionNamed: assoc value. >>> + anIntegerOrNil ifNotNil: [ >>> + config currentSystemVersion highestUpdate <= anIntegerOrNil ifFalse: exit]. >>> + self updateFromConfig: config upToUpdate: anIntegerOrNil. >>> + anIntegerOrNil ifNotNil: [ >>> + config currentSystemVersion highestUpdate < config totalSystemVersion highestUpdate ifTrue: exit]. >>> + self lastUpdateMap at: aRepository description put: assoc key] >>> + displayingProgress: 'Processing configurations' translated] valueWithExit. >>> + configBlock cull: config]]. >>> + ^ config! >>> >>> Item was changed: >>> ----- Method: MCMcmUpdater>>doUpdate: (in category 'updating') ----- >>> doUpdate: interactive >>> + "Update the image by loading all pending updates from the server." >>> - "Update the image by loading all pending updates from the server. If this is >>> - the default updater for the system, update the system version when complete. >>> - If interteractive use a modal notifier, otherwise only update the transcript. >>> - Flush all caches. If a previous download failed this is often helpful" >>> >>> + ^ self basicDoUpdate: interactive do: [ >>> + self updateFromRepository ]! >>> - | config previousUpdateLevel ensureTranscriptSetting | >>> - previousUpdateLevel := SystemVersion current highestUpdate. >>> - MCFileBasedRepository flushAllCaches. >>> - ensureTranscriptSetting := MCConfiguration ensureOpenTranscript. >>> - [ MCConfiguration ensureOpenTranscript: interactive. >>> - config := self updateFromRepository. >>> - config ifNil: [ >>> - interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. >>> - Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. >>> - ^ self ]. >>> - MCMcmUpdater default == self >>> - ifTrue: [ >>> - config setSystemVersion. >>> - interactive ifTrue: [ >>> - self inform: (self updateMessageFor: previousUpdateLevel)]. >>> - Transcript cr; >>> - show: '========== Update completed: ' translated; >>> - show: previousUpdateLevel; >>> - show: ' -> ' ; >>> - show: SystemVersion current highestUpdate; >>> - show: ' =========='; cr ] >>> - ifFalse: [ >>> - interactive >>> - ifTrue: [ self inform: 'Update completed.' ]. >>> - Transcript cr; show: '========== Update completed. ==========' translated; cr ] ] >>> - ensure: [ MCConfiguration ensureOpenTranscript: ensureTranscriptSetting]. >>> - >>> - ! >>> >>> Item was changed: >>> ----- Method: MCMcmUpdater>>doUpdate:upTo: (in category 'updating') ----- >>> doUpdate: interactive upTo: versionNumber >>> + "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." >>> - "Update the image by loading all pending updates from the server. If this is >>> - the default updater for the system, update the system version when complete. >>> - If interteractive use a modal notifier, otherwise only update the transcript. >>> - Flush all caches. If a previous download failed this is often helpful" >>> >>> + ^ self basicDoUpdate: interactive do: [ >>> + self updateFromRepositories: {self repository} upTo: versionNumber ]! >>> - | config previousUpdateLevel | >>> - previousUpdateLevel := SystemVersion current highestUpdate. >>> - MCFileBasedRepository flushAllCaches. >>> - config := self updateFromRepositories: { self repository } upTo: versionNumber. >>> - config ifNil: [ >>> - interactive ifTrue: [ ^self inform: 'Unable to retrieve updates from remote repository.' translated ]. >>> - Transcript cr; show: '========== Unable to retrieve updates from remote repository. ==========' translated; cr. >>> - ^ self ]. >>> - MCMcmUpdater default == self >>> - ifTrue: [ >>> - config setSystemVersion. >>> - interactive ifTrue: [ >>> - self inform: (self updateMessageFor: previousUpdateLevel)]. >>> - Transcript cr; >>> - show: '========== Update completed: ' translated; >>> - show: previousUpdateLevel; >>> - show: ' -> ' ; >>> - show: SystemVersion current highestUpdate; >>> - show: ' =========='; cr ] >>> - ifFalse: [ >>> - interactive >>> - ifTrue: [ self inform: 'Update completed.' ]. >>> - Transcript cr; show: '========== Update completed. ==========' translated; cr ] >>> - ! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>doUpdate:upToUpdate: (in category 'updating') ----- >>> + doUpdate: interactive upToUpdate: anIntegerOrNil >>> + "Update the image by loading all pending updates from the server until the system version has reached at least anInteger. If anInteger is nil, install all available updates." >>> + >>> + ^ self basicDoUpdate: interactive do: [ >>> + self updateFromRepositories: {self repository} upToUpdate: anIntegerOrNil ]! >>> >>> Item was changed: >>> ----- Method: MCMcmUpdater>>doUpdateUpTo: (in category 'updating') ----- >>> doUpdateUpTo: versionNumber >>> + "Update the image by loading all pending updates from the server until update stream with the specified version number has been processed." >>> - "Update the image by loading all pending updates from the server. If this is >>> - the default updater for the system, update the system version when complete. >>> - Flush all caches. If a previous download failed this is often helpful" >>> >>> ^self doUpdate: true upTo: versionNumber >>> ! >>> >>> Item was changed: >>> ----- Method: MCMcmUpdater>>updateFromConfig: (in category 'updating') ----- >>> updateFromConfig: config >>> >>> + ^ self updateFromConfig: config upToUpdate: nil! >>> - "Skip packages that were specifically unloaded" >>> - config dependencies: (config dependencies >>> - reject: [:dep| self class skipPackages includes: dep package name]). >>> - self class updateMissingPackages ifFalse:[ >>> - "Skip packages that are not in the image" >>> - config dependencies: (config dependencies >>> - select: [:dep| dep package hasWorkingCopy])]. >>> - (config dependencies allSatisfy:[:dep| dep isFulfilled]) >>> - ifFalse:[config upgrade]. >>> - ! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>updateFromConfig:upToUpdate: (in category 'updating') ----- >>> + updateFromConfig: config upToUpdate: anIntegerOrNil >>> + >>> + "Skip packages that were specifically unloaded" >>> + config dependencies: (config dependencies >>> + reject: [:dep | self class skipPackages includes: dep package name]). >>> + self class updateMissingPackages ifFalse: [ >>> + "Skip packages that are not in the image" >>> + config dependencies: (config dependencies >>> + select: [:dep | dep package hasWorkingCopy])]. >>> + (config dependencies allSatisfy: [:dep | dep isFulfilled]) >>> + ifFalse: [config upgradeUpToUpdate: anIntegerOrNil].! >>> >>> Item was changed: >>> ----- Method: MCMcmUpdater>>updateFromRepositories:upTo: (in category 'updating') ----- >>> updateFromRepositories: repositoryUrls upTo: versionNumber >>> + " >>> + MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest') upTo: 3 >>> + " >>> - "MCMcmUpdater updateFromRepositories: #( >>> - 'http://squeaksource.com/MCUpdateTest' >>> - )" >>> >>> + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | >>> + self updateFromRepository: repo upTo: versionNumber]! >>> - | repos config | >>> - MCConfiguration upgradeIsMerge: true. >>> - "The list of repositories to consult in order" >>> - repos := repositoryUrls collect:[:url| >>> - MCRepositoryGroup default repositories >>> - detect:[:r| r description = url] >>> - ifNone:[ | r | >>> - r := MCHttpRepository location: url user: '' password: ''. >>> - MCRepositoryGroup default addRepository: r. >>> - r]]. >>> - >>> - "The list of updates-author.version.mcm sorted by version" >>> - repos do:[ :r | config := self updateFromRepository: r upTo: versionNumber]. >>> - ^config! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>updateFromRepositories:upToUpdate: (in category 'updating') ----- >>> + updateFromRepositories: repositoryUrls upToUpdate: anIntegerOrNil >>> + " >>> + MCMcmUpdater default updateFromRepositories: #('http://squeaksource.com/MCUpdateTest') upToUpdate: 2130 >>> + " >>> + >>> + ^ self basicUpdateFromRepositories: repositoryUrls do: [:repo | >>> + self updateFromRepository: repo upToUpdate: anIntegerOrNil ]! >>> >>> Item was changed: >>> ----- Method: MCMcmUpdater>>updateFromRepository (in category 'updating') ----- >>> updateFromRepository >>> >>> + ^ self updateFromRepository: self getRepositoryFromRepositoryGroup! >>> - | config repo | >>> - repo := self getRepositoryFromRepositoryGroup. >>> - repo cacheAllFileNamesDuring: [ | updateList | >>> - updateList := self updateListFor: repo. >>> - "Proceed only if there are updates available at all." >>> - updateList ifNotEmpty: [ >>> - updateList := self refreshUpdateMapFor: repo with: updateList. >>> - "Now process each update file. Check if we have all dependencies and if not, >>> - load the entire configuration (this is mostly to skip older updates quickly)" >>> - updateList do:[:assoc| >>> - ProgressNotification signal: '' extra: 'Processing ', assoc value. >>> - config := repo versionNamed: assoc value. >>> - self updateFromConfig: config. >>> - self lastUpdateMap at: repo description put: assoc key. >>> - ] displayingProgress: 'Processing configurations'. >>> - "We've loaded all the provided update configurations. >>> - Use the latest configuration to update all the remaining packages." >>> - (self useLatestPackagesFrom: repo) ifTrue: [ >>> - config updateFromRepositories. >>> - config upgrade]. >>> - ]]. >>> - ^ config >>> - ! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>updateFromRepository: (in category 'updating') ----- >>> + updateFromRepository: aRepository >>> + >>> + ^ self basicUpdateFromRepository: aRepository thenDo: [:config | >>> + "We've loaded all the provided update configurations. Use the latest configuration to update all the remaining packages." >>> + (self useLatestPackagesFrom: aRepository) ifTrue: [ >>> + config updateFromRepositories. >>> + config upgrade]]! >>> >>> Item was changed: >>> ----- Method: MCMcmUpdater>>updateFromRepository:upTo: (in category 'updating') ----- >>> + updateFromRepository: aRepository upTo: versionNumber >>> - updateFromRepository: repository upTo: versionNumber >>> >>> + ^ self >>> + basicUpdateFromRepository: aRepository >>> + whileUpdatesSatisfy: [:updateVersion | updateVersion <= versionNumber] >>> + upToUpdate: nil >>> + thenDo: []! >>> - | config | >>> - repository cacheAllFileNamesDuring: [ | updateList | >>> - updateList := self updateListFor: repository. >>> - "Proceed only if there are updates available at all." >>> - updateList ifNotEmpty: [ >>> - updateList := self refreshUpdateMapFor: repository with: updateList. >>> - "Now process each update file. Check if we have all dependencies and if not, >>> - load the entire configuration (this is mostly to skip older updates quickly)" >>> - updateList do:[:assoc| >>> - assoc key > versionNumber ifTrue: [^config]. >>> - ProgressNotification signal: '' extra: 'Processing ', assoc value. >>> - config := repository versionNamed: assoc value. >>> - self updateFromConfig: config. >>> - self lastUpdateMap at: repository description put: assoc key. >>> - ] displayingProgress: 'Processing configurations'. >>> - ]]. >>> - ^config >>> - ! >>> >>> Item was added: >>> + ----- Method: MCMcmUpdater>>updateFromRepository:upToUpdate: (in category 'updating') ----- >>> + updateFromRepository: aRepository upToUpdate: anIntegerOrNil >>> + >>> + ^ self >>> + basicUpdateFromRepository: aRepository >>> + whileUpdatesSatisfy: [true] >>> + upToUpdate: anIntegerOrNil >>> + thenDo: []! >>> >>> >>> >> > From marcel.taeumel at hpi.de Fri Apr 16 11:50:24 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 13:50:24 +0200 Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: <1618255943259-0.post@n4.nabble.com> References: <1618255943259-0.post@n4.nabble.com> Message-ID: Hi all! Hehe. "shadows + morphic" got me distracted. ^__^ Hmm... personally, I prefer "owner" over "anOwner" as block variable. That is, I don't care about shadowing the instVar name -- just locally focused readability. That is, I am a fan of accessors and thus rarely (? never ?) bitten by confusing instVar access and tempVar access. :-) For classes with longer methods and extensive instVar access (...Compiler?), shadowing can be an issue for code readability, though. > In a larger context, I would strongly opt for (finally) introducing a > mechanism for linter/compiler annotations in CodeHolders. Most modern > editors and IDEs have it, even Pharo; if Squeak does not want to get left > behind, we should support something like this, too. It could or should be > configurable, of course. How come? While structured information is nice, I am opposed to introducing more things that are prone to errors. :-) What would you expect me to annotate in such a case? Marking intentional shadowing? I wouldn't want to. ;-) Tool-specific configuration/annotation -- yes, linter and compiler are tools -- should not interfere with an artifact's primary representation. For example, it's problematic that there is only a single #inspectorClass or #explorerContents per domain object. That does not scale; it can also obfuscate the object's interface. In a similar manner, if one would start to "enrich" source code with various annotations for all kinds of supported compilers/parsers/linters etc. ... nah.  There are already pragmas, which can be used to annotate methods. Sub-method annotation might be beneficial in not-too-frequent situations ... thus, maybe not worth the effort. Best, Marcel Am 12.04.2021 21:32:34 schrieb Christoph Thiede : Hi Eliot, I fear that changes like this will not be very durable unless tested in any way. At the moment, you won't even notice a new shadow unless you have opened a Transcript by accident when accepting a method. Should we maybe show a message window for shadows instead when compiled interactively, analogously to the warnings about superfluous temps? (In a larger context, I would strongly opt for (finally) introducing a mechanism for linter/compiler annotations in CodeHolders. Most modern editors and IDEs have it, even Pharo; if Squeak does not want to get left behind, we should support something like this, too. It could or should be configurable, of course.) LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal name for a variable that holds Morph instances, right? :) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 16 12:46:38 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 16 Apr 2021 12:46:38 +0000 Subject: [squeak-dev] "Browse revisions" server error for long methods Message-ID: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> Hi all, hi Chris, I think there is an issue with the "Browse revisions" feature. When I invoke it on Context >> #doPrimitive:method:receiver:args:, I reproducibly get the following error: Revisions request failed. Server 'reply' in debugger. 414 Request-URI Too Large And indeed, the original request is a little bit large: url: 'http://source.squeak.org/trunk/' args: {'action'->#('history') . 'mc-definition'->#('%09%00%00%00%07%06%12MCMethodDefinition%03%11%C3%80%00%18%C3%A7doPrimitive%3A%20primitiveIndex%20method%3A%20meth%20receiver%3A%20receiver%20args%3A%20arguments%0D%09%22Simulate%20a%20primitive%20method%20whose%20index%20is%20primitiveIndex.%20%20The%20simulated%20receiver%20and%0D%09%20arguments%20are%20given%20as%20arguments%20to%20this%20message.%20If%20successful%2C%20push%20result%20and%20return%0D%09%20resuming%20context%2C%20else%20%5E%20%7BerrCode%2C%20PrimitiveFailToken%7D.%20Any%20primitive%20which%20provokes%0D%09%20execution%20needs%20to%20be%20intercepted%20and%20simulated%20to%20avoid%20execution%20running%20away.%22%0D%0D%09%7C%20value%20%7C%0D%09%22Judicious%20use%20of%20primitive%2019%20%28a%20null%20primitive%20that%20doesn%27t%20do%20anything%29%20prevents%0D%09%20the%20debugger%20from%20entering%20various%20run-away%20activities%20such%20as%20spawning%20a%20new%0D%09%20process%2C%20etc.%20%20Injudicious%20use%20results%20in%20the%20debugger%20not%20being%20able%20to%20debug%0D%09%20interesting%20code%2C%20such%20as%20the%20debugger%20itself.%20%20Hence%20use%20primitive%2019%20with%20care%20%3A-%29%22%0D%09%22SystemNavigation%20new%20browseAllSelect%3A%20%5B%3Am%7C%20m%20primitive%20%3D%2019%5D%22%0D%09primitiveIndex%20%3D%2019%20ifTrue%3A%20%5B%0D%09%09%5Bself%20notify%3A%20%28%27The%20code%20being%20simulated%20is%20trying%20to%20control%20a%20process%20%28%7B1%7D%29.%20Process%20controlling%20cannot%20be%20simulated.%20If%20you%20proceed%2C%20things%20may%20happen%20outside%20the%20observable%20area%20of%20the%20simulator.%27%20translated%20format%3A%20%7Bmeth%20reference%7D%29%5D%0D%09%09%09ifCurtailed%3A%20%5Bself%20push%3A%20nil%20%22Cheap%20fix%20of%20the%20context%27s%20internal%20state%22%5D%5D.%0D%09%0D%09%28%28primitiveIndex%20between%3A%20201%20and%3A%20222%29%0D%09%20and%3A%20%5B%28self%20objectClass%3A%20receiver%29%20includesBehavior%3A%20BlockClosure%5D%29%20ifTrue%3A%0D%09%09%5B%28primitiveIndex%20%3D%20206%0D%09%09%20%20or%3A%20%5BprimitiveIndex%20%3D%20208%5D%29%20ifTrue%3A%09%09%09%09%09%09%22%5BFull%5DBlockClosure%3E%3EvalueWithArguments%3A%22%0D%09%09%09%5B%5Ereceiver%20simulateValueWithArguments%3A%20arguments%20first%20caller%3A%20self%5D.%0D%09%09%20%28%28primitiveIndex%20between%3A%20201%20and%3A%20209%29%09%09%09%20%22%5BFull%5DBlockClosure%3E%3Evalue%5B%3Avalue%3A...%5D%22%0D%09%09%20%20or%3A%20%5BprimitiveIndex%20between%3A%20221%20and%3A%20222%5D%29%20ifTrue%3A%20%22%5BFull%5DBlockClosure%3E%3EvalueNoContextSwitch%5B%3A%5D%22%0D%09%09%09%5B%5Ereceiver%20simulateValueWithArguments%3A%20arguments%20caller%3A%20self%5D%5D.%0D%0D%09primitiveIndex%20%3D%2083%20ifTrue%3A%20%22afr%209%2F11%2F1998%2019%3A50%22%20%22Object%3E%3Eperform%3A%5Bwith%3A...%5D%22%0D%09%09%5B%7C%20selector%20%7C%0D%09%09selector%20%3A%3D%20arguments%20at%3A%201%20ifAbsent%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20argument%27%5D.%0D%09%09arguments%20size%20-%201%20%3D%20selector%20numArgs%20ifFalse%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20number%20of%20arguments%27%5D.%0D%09%09%5Eself%20send%3A%20selector%20to%3A%20receiver%20with%3A%20arguments%20allButFirst%5D.%0D%09primitiveIndex%20%3D%2084%20ifTrue%3A%20%22afr%209%2F11%2F1998%2019%3A50%20%26%20eem%208%2F18%2F2009%2017%3A04%22%20%22Object%3E%3Eperform%3AwithArguments%3A%22%0D%09%09%5B%7C%20selector%20args%20%7C%0D%09%09arguments%20size%20%3D%202%20ifFalse%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20argument%27%5D.%0D%09%09selector%20%3A%3D%20arguments%20first.%0D%09%09args%20%3A%3D%20arguments%20second.%0D%09%09args%20isArray%20ifFalse%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20argument%27%5D.%0D%09%09args%20size%20%3D%20selector%20numArgs%20ifFalse%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20number%20of%20arguments%27%5D.%0D%09%09%5Eself%20send%3A%20selector%20to%3A%20receiver%20with%3A%20args%5D.%0D%09primitiveIndex%20%3D%20100%20ifTrue%3A%20%22eem%208%2F18%2F2009%2016%3A57%22%20%22Object%3E%3Eperform%3AwithArguments%3AinSuperclass%3A%22%0D%09%09%5B%7C%20rcvr%20selector%20args%20superclass%20%7C%0D%09%09arguments%20size%0D%09%09%09caseOf%3A%20%7B%0D%09%09%09%09%5B3%5D%20-%3E%20%5B%0D%09%09%09%09%09rcvr%20%3A%3D%20receiver.%0D%09%09%09%09%09selector%20%3A%3D%20arguments%20first.%0D%09%09%09%09%09args%20%3A%3D%20arguments%20second.%0D%09%09%09%09%09superclass%20%3A%3D%20arguments%20third%5D.%0D%09%09%09%09%5B4%5D%20-%3E%20%5B%22mirror%20primitive%22%0D%09%09%09%09%09rcvr%20%3A%3D%20arguments%20first.%0D%09%09%09%09%09selector%20%3A%3D%20arguments%20second.%0D%09%09%09%09%09args%20%3A%3D%20arguments%20third.%0D%09%09%09%09%09superclass%20%3A%3D%20arguments%20fourth%5D%20%7D%0D%09%09%09otherwise%3A%20%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20argument%27%5D.%0D%09%09args%20isArray%20ifFalse%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20argument%27%5D.%0D%09%09args%20size%20%3D%20selector%20numArgs%20ifFalse%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20number%20of%20arguments%27%5D.%0D%09%09%28%28self%20objectClass%3A%20rcvr%29%20includesBehavior%3A%20superclass%29%20ifFalse%3A%0D%09%09%09%5B%5E%20self%20class%20primitiveFailTokenFor%3A%20%23%27bad%20argument%27%5D.%0D%09%09%5Eself%20send%3A%20selector%20to%3A%20rcvr%20with%3A%20args%20lookupIn%3A%20superclass%5D.%0D%0D%09%22Mutex%3E%3EprimitiveEnterCriticalSection%0D%09%20Mutex%3E%3EprimitiveTestAndSetOwnershipOfCriticalSection%22%0D%09%28primitiveIndex%20%3D%20186%20or%3A%20%5BprimitiveIndex%20%3D%20187%5D%29%20ifTrue%3A%0D%09%09%5B%7C%20effective%20%7C%0D%09%09%20effective%20%3A%3D%20Processor%20activeProcess%20effectiveProcess.%0D%09%09%20%22active%20%3D%3D%20effective%22%0D%09%09%20value%20%3A%3D%20primitiveIndex%20%3D%20186%0D%09%09%09%09%09ifTrue%3A%20%5Breceiver%20primitiveEnterCriticalSectionOnBehalfOf%3A%20effective%5D%0D%09%09%09%09%09ifFalse%3A%20%5Breceiver%20primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf%3A%20effective%5D.%0D%09%09%20%5E%28self%20isPrimFailToken%3A%20value%29%0D%09%09%09ifTrue%3A%20%5Bvalue%5D%0D%09%09%09ifFalse%3A%20%5Bself%20push%3A%20value%5D%5D.%0D%0D%09primitiveIndex%20%3D%20188%20ifTrue%3A%09%22Object%3E%3EwithArgs%3AexecuteMethod%3A%0D%09%09%09%09%09%09%09%09%09CompiledMethod%20class%3E%3Ereceiver%3AwithArguments%3AexecuteMethod%3A%0D%09%09%09%09%09%09%09%09%09VMMirror%3E%3EifFail%3Aobject%3Awith%3AexecuteMethod%3A%20et%20al%22%0D%09%09%5B%7C%20n%20args%20methodArg%20thisReceiver%20%7C%0D%09%09%20%28%28n%20%3A%3D%20arguments%20size%29%20between%3A%202%20and%3A%204%29%20ifFalse%3A%0D%09%09%09%5B%5Eself%20class%20primitiveFailTokenFor%3A%20%23%27unsupported%20operation%27%5D.%0D%09%09%20%28%28self%20objectClass%3A%20%28args%20%3A%3D%20arguments%20at%3A%20n%20-%201%29%29%20%3D%3D%20Array%0D%09%09%20%20and%3A%20%5B%28self%20objectClass%3A%20%28methodArg%20%3A%3D%20arguments%20at%3A%20n%29%29%20includesBehavior%3A%20CompiledMethod%5D%29%20ifFalse%3A%0D%09%09%09%5B%5Eself%20class%20primitiveFailTokenFor%3A%20%23%27bad%20argument%27%5D.%0D%09%09%20methodArg%20numArgs%20%3D%20args%20size%20ifFalse%3A%0D%09%09%09%5B%5Eself%20class%20primitiveFailTokenFor%3A%20%23%27bad%20number%20of%20arguments%27%5D.%0D%09%09%20thisReceiver%20%3A%3D%20arguments%20at%3A%20n%20-%202%20ifAbsent%3A%20%5Breceiver%5D.%0D%09%09%20methodArg%20primitive%20%3E%200%20ifTrue%3A%0D%09%09%09%5BmethodArg%20isQuick%20ifTrue%3A%0D%09%09%09%09%5B%5Eself%20push%3A%20%28methodArg%20valueWithReceiver%3A%20thisReceiver%20arguments%3A%20args%29%5D.%0D%09%09%09%20%5Eself%20doPrimitive%3A%20methodArg%20primitive%20method%3A%20meth%20receiver%3A%20thisReceiver%20args%3A%20args%5D.%0D%09%09%20%5EContext%0D%09%09%09sender%3A%20self%0D%09%09%09receiver%3A%20thisReceiver%0D%09%09%09method%3A%20methodArg%0D%09%09%09arguments%3A%20args%5D.%0D%0D%09primitiveIndex%20%3D%20118%20ifTrue%3A%20%22%5Breceiver%3A%5DtryPrimitive%3AwithArgs%3A%3B%20avoid%20recursing%20in%20the%20VM%22%0D%09%09%5B%28arguments%20size%20%3D%203%0D%09%09%20%20and%3A%20%5B%28self%20objectClass%3A%20arguments%20second%29%20%3D%3D%20SmallInteger%0D%09%09%20%20and%3A%20%5B%28self%20objectClass%3A%20arguments%20last%29%20%3D%3D%20Array%5D%5D%29%20ifTrue%3A%0D%09%09%09%5B%5Eself%20doPrimitive%3A%20arguments%20second%20method%3A%20meth%20receiver%3A%20arguments%20first%20args%3A%20arguments%20last%5D.%0D%09%09%20%28arguments%20size%20%3D%202%0D%09%09%20and%3A%20%5B%28self%20objectClass%3A%20arguments%20first%29%20%3D%3D%20SmallInteger%0D%09%09%20and%3A%20%5B%28self%20objectClass%3A%20arguments%20last%29%20%3D%3D%20Array%5D%5D%29%20ifFalse%3A%0D%09%09%09%5B%5Eself%20class%20primitiveFailTokenFor%3A%20nil%5D.%0D%09%09%20%5Eself%20doPrimitive%3A%20arguments%20first%20method%3A%20meth%20receiver%3A%20receiver%20args%3A%20arguments%20last%5D.%0D%0D%09value%20%3A%3D%20primitiveIndex%20%3D%20120%20%22FFI%20method%22%0D%09%09%09%09ifTrue%3A%20%5B%28meth%20literalAt%3A%201%29%20tryInvokeWithArguments%3A%20arguments%5D%0D%09%09%09%09ifFalse%3A%0D%09%09%09%09%09%5BprimitiveIndex%20%3D%20117%20%22named%20primitives%22%0D%09%09%09%09%09%09ifTrue%3A%20%5Bself%20tryNamedPrimitiveIn%3A%20meth%20for%3A%20receiver%20withArgs%3A%20arguments%5D%0D%09%09%09%09%09%09ifFalse%3A%20%22should%20use%20self%20receiver%3A%20receiver%20tryPrimitive%3A%20primitiveIndex%20withArgs%3A%20arguments%20but%20this%20is%20only%20in%20later%20VMs%20%28and%20appears%20to%20be%20broken%29%22%0D%09%09%09%09%09%09%09%5Breceiver%20tryPrimitive%3A%20primitiveIndex%20withArgs%3A%20arguments%5D%5D.%0D%0D%09%5E%28self%20isPrimFailToken%3A%20value%29%0D%09%09ifTrue%3A%20%5Bvalue%5D%0D%09%09ifFalse%3A%20%5Bself%20push%3A%20value%5D%06%07private%06%21doPrimitive%3Amethod%3Areceiver%3Aargs%3A%06%07Context%11%12ct%203%2F20%2F2021%2019%3A02')} user: '' passwd: '' Hm ... does the server really need the entire source string? In theory, a hash or method timestamp or just the signature should suffice, shouldn't it? :-) Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Fri Apr 16 12:49:49 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Fri, 16 Apr 2021 07:49:49 -0500 (CDT) Subject: [squeak-dev] "Browse revisions" server error for long methods In-Reply-To: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> References: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> Message-ID: <1618577389573-0.post@n4.nabble.com> Hmm ... Confusingly, the error message still persists when I manually truncate the source in the method definition. On the other hand, the feature works fine for other methods such as String >> #asInteger. Is the request limit just way too low? Could you maybe increase this limitation? Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From marcel.taeumel at hpi.de Fri Apr 16 12:54:19 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 14:54:19 +0200 Subject: [squeak-dev] "Browse revisions" server error for long methods In-Reply-To: <1618577389573-0.post@n4.nabble.com> References: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> <1618577389573-0.post@n4.nabble.com> Message-ID: Hi Christoph, "request URI too large" might be unrelated to the stuff put into the request header (here "mc-definition"). Best, Marcel Am 16.04.2021 14:49:59 schrieb Christoph Thiede : Hmm ... Confusingly, the error message still persists when I manually truncate the source in the method definition. On the other hand, the feature works fine for other methods such as String >> #asInteger. Is the request limit just way too low? Could you maybe increase this limitation? Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Fri Apr 16 13:10:07 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Fri, 16 Apr 2021 08:10:07 -0500 (CDT) Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz In-Reply-To: References: Message-ID: <1618578607101-0.post@n4.nabble.com> Hi Nicolas, I see that you reverted Kernel-ct.1382 (which has been merged into the Trunk earlier via Kernel-mt.1383). Was this a merge error or an intended rollback? Assuming the latter, I would like to discuss this again, please. :-) I already noticed by myself that the control primitive warning occurred a bit too often in situations where you would not expect it (for instance, when stepping through "Object sourceCodeAt: #at:"). Still, do we indeed do not want to get informed about any attempt by the debugged process to execute logic in another process? Also, the simulator is not only used by the debugger but also in miscellaneous non-interactive situations, including MessageTally, some KernelTests, and SimulationStudio where the warning might be even more relevant because the assumption or the contract is that the passed logic will be simulated completely. Would it be a compromise for you to signal a custom EscapeFromSimulationWarning (better name proposals are welcome :-) ) instead and to ignore them in the Debugger? I am looking forward to your reply! :-) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From christoph.thiede at student.hpi.uni-potsdam.de Fri Apr 16 13:16:08 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Fri, 16 Apr 2021 08:16:08 -0500 (CDT) Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz In-Reply-To: <1618578607101-0.post@n4.nabble.com> References: <1618578607101-0.post@n4.nabble.com> Message-ID: <1618578968761-0.post@n4.nabble.com> PS: I also see that you touched the simulation of criticalSection primitives (primitiveIndex = 186 ...) again. Again, was this intended or an incident? :-) (OT: We are really treading on each other's toes in this method ... What can we learn from this? Is it too large and should be split up? Or should we improve our tooling support for resolving merge conflicts?) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From marcel.taeumel at hpi.de Fri Apr 16 13:40:13 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 15:40:13 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz In-Reply-To: <1618578968761-0.post@n4.nabble.com> References: <1618578607101-0.post@n4.nabble.com> <1618578968761-0.post@n4.nabble.com> Message-ID: Hi Christoph, the commit message in Kernel-nice.1386 reads: "[...] Note that Kernel-ct.1383 supersedes Kernel-ct.1382 and removes the annoying warning. [...]" I think the problem was that both ct.1382 and ct.1382 change the same method but do not actually consider each other. With our current tools, sub-method merging is rather tricky and hence the author should take care that this does not happen. :-) Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. Best, Marcel Am 16.04.2021 15:16:18 schrieb Christoph Thiede : PS: I also see that you touched the simulation of criticalSection primitives (primitiveIndex = 186 ...) again. Again, was this intended or an incident? :-) (OT: We are really treading on each other's toes in this method ... What can we learn from this? Is it too large and should be split up? Or should we improve our tooling support for resolving merge conflicts?) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Fri Apr 16 13:51:15 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Fri, 16 Apr 2021 08:51:15 -0500 (CDT) Subject: [squeak-dev] The Trunk: MorphicExtras-mt.292.mcz In-Reply-To: References: Message-ID: <1618581075971-0.post@n4.nabble.com> Thank you, Marcel! :-) To browse all example methods, you can use this snippet: self systemNavigation browseMessageList: [(PackageInfo named: 'MorphicExtras') extensionMethods select: [:m | m category includesSubstring: 'example']] name: 'Objectland examples' Nevertheless, soon, you will also get a visual collection of all the examples, so stay tuned ... :-) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From marcel.taeumel at hpi.de Fri Apr 16 13:56:26 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 15:56:26 +0200 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.292.mcz In-Reply-To: <1618581075971-0.post@n4.nabble.com> References: <1618581075971-0.post@n4.nabble.com> Message-ID: Toothpaste! *scnr*  Am 16.04.2021 15:51:25 schrieb Christoph Thiede : Thank you, Marcel! :-) To browse all example methods, you can use this snippet: self systemNavigation browseMessageList: [(PackageInfo named: 'MorphicExtras') extensionMethods select: [:m | m category includesSubstring: 'example']] name: 'Objectland examples' Nevertheless, soon, you will also get a visual collection of all the examples, so stay tuned ... :-) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Fri Apr 16 15:13:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 15:13:15 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1752.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1752.mcz ==================== Summary ==================== Name: Morphic-mt.1752 Author: mt Time: 16 April 2021, 5:13:09.752509 pm UUID: cea50880-c57e-dc43-abdc-104a41e256e8 Ancestors: Morphic-mt.1751, Morphic-ct.1585, Morphic-ct.1586 Merges fixes and enhancements for TextEditor from Morphic-ct.1585, Morphic-ct.1586. Tweaks the proposed interactive print-it as follows: - Make it a preference, ask for it during code loading - Do not copy the (interactive) text action to avoid spreading object references (depends on Collections-mt.941) - for the print-it text, append an extra space with the original emphasis to support type-in - do not style obvious "store strings" such as strings and numbers =============== Diff against Morphic-mt.1751 =============== Item was changed: Editor subclass: #TextEditor instanceVariableNames: 'model paragraph markBlock pointBlock beginTypeInIndex emphasisHere lastParenLocation otherInterval oldInterval typeAhead history' + classVariableNames: 'AutoEnclose AutoIndent ChangeText EncloseSelection FindText InteractivePrintIt' - classVariableNames: 'AutoEnclose AutoIndent ChangeText EncloseSelection FindText' poolDictionaries: '' category: 'Morphic-Text Support'! TextEditor class instanceVariableNames: 'cmdActions shiftCmdActions yellowButtonMenu shiftedYellowButtonMenu'! !TextEditor commentStamp: '' prior: 0! See comment in Editor. My instances edit Text, this is, they support multiple lines and TextAttributes. They have no specific facilities for editing Smalltalk code. Those are found in SmalltalkEditor.! TextEditor class instanceVariableNames: 'cmdActions shiftCmdActions yellowButtonMenu shiftedYellowButtonMenu'! Item was added: + ----- Method: TextEditor class>>interactivePrintIt (in category 'preferences') ----- + interactivePrintIt + + + ^ InteractivePrintIt ifNil: [ true ]! Item was added: + ----- Method: TextEditor class>>interactivePrintIt: (in category 'preferences') ----- + interactivePrintIt: aBoolean + + InteractivePrintIt := aBoolean.! Item was changed: ----- Method: TextEditor>>afterSelectionInsertAndSelect: (in category 'new selection') ----- + afterSelectionInsertAndSelect: aStringOrText - afterSelectionInsertAndSelect: aString + self insertAndSelect: aStringOrText at: self stopIndex ! - self insertAndSelect: aString at: self stopIndex ! Item was changed: ----- Method: TextEditor>>insertAndSelect:at: (in category 'new selection') ----- + insertAndSelect: aStringOrText at: anInteger - insertAndSelect: aString at: anInteger + | spacer | self closeTypeIn. - self selectInvisiblyFrom: anInteger to: anInteger - 1. self openTypeIn. + spacer := Text string: ' ' attributes: emphasisHere. + self replace: self selectionInterval + with: (aStringOrText isString + ifTrue: [spacer, (Text string: aStringOrText attributes: emphasisHere)] + ifFalse: [spacer, aStringOrText, spacer "Extra spacer for type-in after insertion with current emphasis."]) - with: (Text string: (' ', aString) attributes: emphasisHere) and: []. - self closeTypeIn.! Item was changed: ----- Method: TextEditor>>mouseDown: (in category 'events') ----- mouseDown: evt "Either 1) handle text actions in the paragraph, 2) begin a text drag operation, or 3) modify the caret/selection." | clickPoint b | oldInterval := self selectionInterval. clickPoint := evt cursorPoint. b := paragraph characterBlockAtPoint: clickPoint. (paragraph clickAt: clickPoint for: model controller: self) ifTrue: [ + self flag: #note. "mt: Do not reset the current text selection for successful text actions. Leave markBlock and pointBlock as is. This behavior matches the one in web browsers when clicking on links." - markBlock := b. - pointBlock := b. evt hand releaseKeyboardFocus: morph. evt hand releaseMouseFocus: morph. ^ self ]. (morph dragEnabled and: [self isEventInSelection: evt]) ifTrue: [ evt hand waitForClicksOrDrag: morph event: evt selectors: {#click:. nil. nil. #startDrag:} threshold: HandMorph dragThreshold. morph setProperty: #waitingForTextDrag toValue: true. ^ self]. evt shiftPressed ifFalse: [ self closeTypeIn. markBlock := b. pointBlock := b ] ifTrue: [ self closeTypeIn. self mouseMove: evt ]. self storeSelectionInParagraph! Item was changed: ----- Method: TextEditor>>printIt (in category 'do-its') ----- printIt self evaluateSelectionAndDo: [:result | (model respondsTo: #printIt:result:) ifTrue: [model perform: #printIt:result: with: self selection with: result] + ifFalse: [self afterSelectionInsertAndSelect: (self printItTextFor: result)]]! - ifFalse: [self afterSelectionInsertAndSelect: result printString]]! Item was added: + ----- Method: TextEditor>>printItTextFor: (in category 'do-its') ----- + printItTextFor: anObject + + ^ (self class interactivePrintIt and: [(anObject isString or: [anObject isNumber]) not]) + ifFalse: [anObject printString] + ifTrue: [Text string: anObject printString attribute: (TextInspectIt on: anObject)]! Item was changed: ----- Method: TextEditor>>selection (in category 'accessing-selection') ----- selection "Answer the text in the paragraph that is currently selected." + | result | + result := paragraph text copyFrom: self startIndex to: self stopIndex - 1. + self class interactivePrintIt ifTrue: [ + result removeAttributesThat: [:attr | attr isOblivious]]. + ^ result! - ^paragraph text copyFrom: self startIndex to: self stopIndex - 1 ! Item was changed: + (PackageInfo named: 'Morphic') postscript: 'TextEditor interactivePrintIt: (Project uiManager confirm: ''There is a new preference called "Interactive print-it".\\Do you want to enable it?'' withCRs).'! - (PackageInfo named: 'Morphic') postscript: 'PasteUpMorph allSubInstancesDo: [:m | m isFlap ifTrue: [m morphicLayerNumber: Morph navigatorLayer]]. - TheWorldMainDockingBar updateInstances. - SystemProgressMorph reset. - self currentWorld reorderSubmorphsInLayers.'! From commits at source.squeak.org Fri Apr 16 15:15:19 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 15:15:19 0000 Subject: [squeak-dev] The Trunk: Collections-mt.943.mcz Message-ID: Marcel Taeumel uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-mt.943.mcz ==================== Summary ==================== Name: Collections-mt.943 Author: mt Time: 16 April 2021, 5:15:16.314509 pm UUID: 36386512-337e-2b48-acfd-e21eb731c656 Ancestors: Collections-ul.940 Complements Morphic-mt.1752 =============== Diff against Collections-ul.940 =============== Item was added: + ----- Method: TextAction>>actionColor (in category 'accessing') ----- + actionColor + + ^ Purple ifNil: [Purple := self userInterfaceTheme color ifNil: [Color r: 0.4 g: 0.0 b: 1]]! Item was changed: ----- Method: TextAction>>emphasizeScanner: (in category 'accessing') ----- emphasizeScanner: scanner "Set the emphasis for text display" + + scanner textColor: self actionColor.! - Purple ifNil: [Purple := self userInterfaceTheme color ifNil: [Color r: 0.4 g: 0.0 b: 1]]. - scanner textColor: Purple.! Item was added: + ----- Method: TextAttribute>>isOblivious (in category 'testing') ----- + isOblivious + "Mark text attributes to be removed upon interaction such as copy-and-paste." + + ^ false! Item was added: + TextDoIt subclass: #TextInspectIt + instanceVariableNames: 'target' + classVariableNames: '' + poolDictionaries: '' + category: 'Collections-Text'! Item was added: + ----- Method: TextInspectIt class>>on: (in category 'instance creation') ----- + on: anObject + + ^ self new target: anObject; yourself! Item was added: + ----- Method: TextInspectIt>>actOnClickFor:in:at:editor: (in category 'mouse events') ----- + actOnClickFor: anObject in: aParagraph at: clickPoint editor: editor + "Note: evalString gets evaluated IN THE CONTEXT OF anObject + -- meaning that self and all instVars are accessible" + self target + ifNil: [(Compiler evaluate: evalString for: anObject) inspect] + ifNotNil: [:object | object inspect]. + ^ true ! Item was added: + ----- Method: TextInspectIt>>emphasizeScanner: (in category 'accessing') ----- + emphasizeScanner: scanner + "Set the emphasis for text display" + + scanner textColor: self actionColor.! Item was added: + ----- Method: TextInspectIt>>isOblivious (in category 'testing') ----- + isOblivious + "Avoid spreading object references by copy-and-paste." + + ^ true! Item was added: + ----- Method: TextInspectIt>>target (in category 'accessing') ----- + target + + ^ target! Item was added: + ----- Method: TextInspectIt>>target: (in category 'accessing') ----- + target: anObject + + target := anObject.! From commits at source.squeak.org Fri Apr 16 15:21:16 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 15:21:16 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1585.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1585.mcz ==================== Summary ==================== Name: Morphic-ct.1585 Author: ct Time: 10 November 2019, 4:01:42.092559 pm UUID: 9564d2b2-4af1-044b-96fd-532e60252fd7 Ancestors: Morphic-mt.1584 TextEditor: Don't change the cursor position after a text action has been performed. This keeps a possible selection stable after you, for example, followed a link. =============== Diff against Morphic-mt.1584 =============== Item was changed: ----- Method: TextEditor>>mouseDown: (in category 'events') ----- mouseDown: evt "Either 1) handle text actions in the paragraph, 2) begin a text drag operation, or 3) modify the caret/selection." | clickPoint b | oldInterval := self selectionInterval. clickPoint := evt cursorPoint. b := paragraph characterBlockAtPoint: clickPoint. (paragraph clickAt: clickPoint for: model controller: self) ifTrue: [ - markBlock := b. - pointBlock := b. evt hand releaseKeyboardFocus: morph. evt hand releaseMouseFocus: morph. ^ self ]. (morph dragEnabled and: [self isEventInSelection: evt]) ifTrue: [ evt hand waitForClicksOrDrag: morph event: evt selectors: {#click:. nil. nil. #startDrag:} threshold: HandMorph dragThreshold. morph setProperty: #waitingForTextDrag toValue: true. ^ self]. evt shiftPressed ifFalse: [ self closeTypeIn. markBlock := b. pointBlock := b ] ifTrue: [ self closeTypeIn. self mouseMove: evt ]. self storeSelectionInParagraph! From commits at source.squeak.org Fri Apr 16 15:21:49 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 15:21:49 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.1586.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1586.mcz ==================== Summary ==================== Name: Morphic-ct.1586 Author: ct Time: 10 November 2019, 4:06:17.228559 pm UUID: d752eb23-2116-0945-b043-aff08fed94fd Ancestors: Morphic-mt.1584 Proposal: Style printIt results as a pluggable link that can be clicked to inspect the result. To enable this behavior, this commit also extends #insertAndSelect:at: to allow for inserting both strings and texts. =============== Diff against Morphic-mt.1584 =============== Item was changed: ----- Method: PluggableTextMorph>>printIt (in category 'menu commands') ----- printIt | oldEditor | textMorph editor selectFrom: selectionInterval first to: selectionInterval last; model: model. "For, eg, evaluateSelection" textMorph handleEdit: [(oldEditor := textMorph editor) evaluateSelectionAndDo: [:result | selectionInterval := oldEditor selectionInterval. textMorph installEditorToReplace: oldEditor. + textMorph handleEdit: [ oldEditor afterSelectionInsertAndSelect: + (oldEditor printTextFor: result)]. - textMorph handleEdit: [oldEditor afterSelectionInsertAndSelect: result printString]. selectionInterval := oldEditor selectionInterval. textMorph editor selectFrom: selectionInterval first to: selectionInterval last. self scrollSelectionIntoView]]! Item was changed: ----- Method: TextEditor>>afterSelectionInsertAndSelect: (in category 'new selection') ----- + afterSelectionInsertAndSelect: aStringOrText - afterSelectionInsertAndSelect: aString + self insertAndSelect: aStringOrText at: self stopIndex ! - self insertAndSelect: aString at: self stopIndex ! Item was changed: ----- Method: TextEditor>>insertAndSelect:at: (in category 'new selection') ----- + insertAndSelect: aStringOrText at: anInteger - insertAndSelect: aString at: anInteger + aStringOrText isString ifTrue: [ + ^ self + insertAndSelect: (Text string: aStringOrText attributes: emphasisHere) + at: anInteger]. - self closeTypeIn. + self closeTypeIn. self selectInvisiblyFrom: anInteger to: anInteger - 1. self openTypeIn. self replace: self selectionInterval + with: (Text string: ' ' attributes: emphasisHere), aStringOrText - with: (Text string: (' ', aString) attributes: emphasisHere) and: []. - self closeTypeIn.! Item was changed: ----- Method: TextEditor>>printIt (in category 'do-its') ----- printIt self evaluateSelectionAndDo: [:result | (model respondsTo: #printIt:result:) ifTrue: [model perform: #printIt:result: with: self selection with: result] + ifFalse: [self afterSelectionInsertAndSelect: (self printTextFor: result)]]! - ifFalse: [self afterSelectionInsertAndSelect: result printString]]! Item was added: + ----- Method: TextEditor>>printTextFor: (in category 'do-its') ----- + printTextFor: anObject + + ^ Text + string: anObject printString + attributes: {PluggableTextAttribute evalBlock: [anObject inspect]}! From marcel.taeumel at hpi.de Fri Apr 16 15:27:54 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 17:27:54 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> Message-ID: Hi all! It is now in Trunk. You can opt-out via the preference browser. Still, you will be asked the first time when you update your image. CI scripts will default to "true". Best, Marcel Am 17.11.2019 17:36:11 schrieb Jakob Reschke : Thiede, Christoph schrieb am Fr., 15. Nov. 2019, 09:38: Just another idea (I seem to have too many of them :D): Some kind of UnderlyingObjectAttribute (with a better name, of course) an editor can check the selection before compiling it when inspectIt/exploreIt is pressed? Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor checks for UnderylingObjectAttribute -> none found, so the string is compilaed as usual. Example 2: (Text string: '2 + 3' attributes: (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> Editor finds an UnderylingObjectAttribute -> instead of compiling the selection, the cached result is reused for the inspector. We would not even need to display this Attribute visually if it works reliably. Make sure it is transient in some way because it would be quite annoying if the hidden object were out of date with regards to the text. -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Fri Apr 16 16:35:51 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 16:35:51 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1753.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1753.mcz ==================== Summary ==================== Name: Morphic-mt.1753 Author: mt Time: 16 April 2021, 6:35:45.937811 pm UUID: 716e754a-65bd-6b41-b41b-3b7dd526ffb8 Ancestors: Morphic-mt.1752 Removes dialog interaction from update stream for the sake of CI. =============== Diff against Morphic-mt.1752 =============== Item was changed: + (PackageInfo named: 'Morphic') postscript: 'Transcript showln: ''[NOTICE] There is a new preference called "Interactive print-it". Please check your preference browser to choose the preferred value.'''! - (PackageInfo named: 'Morphic') postscript: 'TextEditor interactivePrintIt: (Project uiManager confirm: ''There is a new preference called "Interactive print-it".\\Do you want to enable it?'' withCRs).'! From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 16 16:39:00 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 16 Apr 2021 16:39:00 +0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> , Message-ID: Hi Marcel, it's great that you have found a solution to this idea! :-) > + ^ (self class interactivePrintIt and: [(anObject isString or: [anObject isNumber]) not]) Is this necessary? I know that an inspector for a literal object like these does not make great sense, but this just feels like an unnecessary heuristic and limitation for me and adds complexity. I would like to be able to open an inspector always. Also consider this snippet where the print-link does not exist for an MCVersionName: :-) MCRepository inbox allFileNames first > CI scripts will default to "true". Unfortunately, no, mine just timed out while preparing the image. Also, my server images for @SqueakSmalltalkBot were interrupted. I'd opt for keeping preamble/postscript content in the update stream strictly non-interactive. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Freitag, 16. April 2021 17:27:54 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz Hi all! It is now in Trunk. You can opt-out via the preference browser. Still, you will be asked the first time when you update your image. CI scripts will default to "true". Best, Marcel Am 17.11.2019 17:36:11 schrieb Jakob Reschke : Thiede, Christoph > schrieb am Fr., 15. Nov. 2019, 09:38: Just another idea (I seem to have too many of them :D): Some kind of UnderlyingObjectAttribute (with a better name, of course) an editor can check the selection before compiling it when inspectIt/exploreIt is pressed? Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor checks for UnderylingObjectAttribute -> none found, so the string is compilaed as usual. Example 2: (Text string: '2 + 3' attributes: (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> Editor finds an UnderylingObjectAttribute -> instead of compiling the selection, the cached result is reused for the inspector. We would not even need to display this Attribute visually if it works reliably. Make sure it is transient in some way because it would be quite annoying if the hidden object were out of date with regards to the text. -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Fri Apr 16 17:34:20 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 16 Apr 2021 19:34:20 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz In-Reply-To: References: <1618578607101-0.post@n4.nabble.com> <1618578968761-0.post@n4.nabble.com> Message-ID: Hi Christoph, Hmm, there must have been some confusion on my side. I've tried to carefully review the remaining contributions in the inbox. To my understanding Kernel-ct.1383 fixes more simulation cases than Kernel-ct.1382. Since - the tests simulating primitives 83, 84 & 100 were failing, - and that a more recent inbox contribution was trying to fix that, I thought that merging this contribution was a good idea. It apparently was fixing two tests out of three after trial. Also, to my experience, generating a warning when we simulate primitiveIndex >= 85 and: [primitiveIndex <= 88] "control primitives"]) is super annoying! It always happens when running some kernel tests and forces me to switch warning off altogether. But switching warning off is not a good solution (and it makes some more tests fail !). Kernel-ct.1383 being more recent, I thought that the removal of warnings was intentional... I saw later that you removed from newProcess... SHould we? My understanding now is that you need this warning in some specific context. Is that it? We can't fix one usage by breaking another. We have to find a solution that fits both purposes. Le ven. 16 avr. 2021 à 15:40, Marcel Taeumel a écrit : > > Hi Christoph, > > the commit message in Kernel-nice.1386 reads: "[...] Note that Kernel-ct.1383 supersedes Kernel-ct.1382 and removes the annoying warning. [...]" > > I think the problem was that both ct.1382 and ct.1382 change the same method but do not actually consider each other. With our current tools, sub-method merging is rather tricky and hence the author should take care that this does not happen. :-) > > Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. > > Best, > Marcel > > Am 16.04.2021 15:16:18 schrieb Christoph Thiede : > > PS: I also see that you touched the simulation of criticalSection primitives > (primitiveIndex = 186 ...) again. Again, was this intended or an incident? > :-) > > (OT: We are really treading on each other's toes in this method ... What can > we learn from this? Is it too large and should be split up? Or should we > improve our tooling support for resolving merge conflicts?) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > From marcel.taeumel at hpi.de Fri Apr 16 17:52:16 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 16 Apr 2021 19:52:16 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> Message-ID: Hi Christoph, I think that this clickable link is a compromise between printString and storeString. For mouse navigation, you can always choose "inspect it" from the context menu on that text selection. ;-) I also found the link color annyoing for simple literals. > Also consider this snippet where the print-link does not exist for an MCVersionName Looks fine. ^__^ I am certain that we will collect more feedback on this feature during the next weeks and months. Let's refine it then. Best, Marcel Am 16.04.2021 18:39:10 schrieb Thiede, Christoph : Hi Marcel, it's great that you have found a solution to this idea! :-) > +        ^ (self class interactivePrintIt and: [(anObject isString or: [anObject isNumber]) not]) Is this necessary? I know that an inspector for a literal object like these does not make great sense, but this just feels like an unnecessary heuristic and limitation for me and adds complexity. I would like to be able to open an inspector always. Also consider this snippet where the print-link does not exist for an MCVersionName: :-) MCRepository inbox allFileNames first > CI scripts will default to "true". Unfortunately, no, mine just timed out while preparing the image. Also, my server images for @SqueakSmalltalkBot were interrupted. I'd opt for keeping preamble/postscript content in the update stream strictly non-interactive. :-) Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Freitag, 16. April 2021 17:27:54 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz   Hi all! It is now in Trunk. You can opt-out via the preference browser. Still, you will be asked the first time when you update your image. CI scripts will default to "true". Best, Marcel Am 17.11.2019 17:36:11 schrieb Jakob Reschke : Thiede, Christoph schrieb am Fr., 15. Nov. 2019, 09:38: Just another idea (I seem to have too many of them :D): Some kind of UnderlyingObjectAttribute (with a better name, of course) an editor can check the selection before compiling it when inspectIt/exploreIt is pressed? Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor checks for UnderylingObjectAttribute -> none found, so the string is compilaed as usual. Example 2: (Text string: '2 + 3' attributes: (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> Editor finds an UnderylingObjectAttribute -> instead of compiling the selection, the cached result is reused for the inspector. We would not even need to display this Attribute visually if it works reliably. Make sure it is transient in some way because it would be quite annoying if the hidden object were out of date with regards to the text. -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Fri Apr 16 18:35:35 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 16 Apr 2021 20:35:35 +0200 Subject: [squeak-dev] the semantics of SyntaxErrorNotification resume: Message-ID: Hi all, I see some new tests failing - testResumeEarlySyntaxError - testResumeLateSyntaxError This is entirely my fault because of the "fix" of exception handling. Indeed, I have not rearmed the exception stack in resume: action, and I think I should have done so. However, I see that SyntaxErrorNotification>>resume: launch a new compilation entirely. This sounds un-necessary to me because we already have ReparseAfterSourceEditing for that purpose... (again I'm the original author of that, Christoph only improved it) IMO, the purpose is not really to resume: but rather to retry compilation using newSource. We (I ?) have used resume: only because notify:at: does signal a SyntaxErrorNotification, then immediately retries if the exception resumes. (notification := SyntaxErrorNotification cue: (cue copy source: (source contents asText copyReplaceFrom: location to: location - 1 with: messageText); yourself) doitFlag: doitFlag errorMessage: string location: location) signal. notification tryNewSourceIfAvailable But if the handler does retryWithNewSource: newSource instead of resume: newSource, then we just have to let retryWithNewSource perform a self resignalAs: ReparseAfterSourceEditing new. I think that it's the right solution, rather than bending the semantics of resume: (the argument of resume: is normally the value that should be returned to the sender of signal...). So if you see some changes of SyntaxErrorNotification in trunk, you'll know a bit more about it (I'm not sure whether I can redact a commit message with that level of explanation). Nicolas From commits at source.squeak.org Fri Apr 16 19:42:45 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 19:42:45 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1389.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1389.mcz ==================== Summary ==================== Name: Kernel-nice.1389 Author: nice Time: 16 April 2021, 9:42:34.176501 pm UUID: 895e77fd-ce0e-484f-ad8a-00564ca98639 Ancestors: Kernel-nice.1388 Fix missing reactivation of handlers upon resume; It is the responsibility of handling actions to rearm the handlers that have been disabled during the search of active handler. =============== Diff against Kernel-nice.1388 =============== Item was changed: ----- Method: Exception>>resume: (in category 'handling') ----- resume: resumptionValue "Return resumptionValue as the value of the signal message." self isResumable ifFalse: [IllegalResumeAttempt signal]. + self reactivateHandlers. self resumeUnchecked: resumptionValue! From nicolas.cellier.aka.nice at gmail.com Fri Apr 16 19:52:17 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 16 Apr 2021 21:52:17 +0200 Subject: [squeak-dev] the semantics of SyntaxErrorNotification resume: In-Reply-To: References: Message-ID: Le ven. 16 avr. 2021 à 20:35, Nicolas Cellier a écrit : > > Hi all, > I see some new tests failing > - testResumeEarlySyntaxError > - testResumeLateSyntaxError > > This is entirely my fault because of the "fix" of exception handling. > Indeed, I have not rearmed the exception stack in resume: action, and > I think I should have done so. > > However, I see that SyntaxErrorNotification>>resume: launch a new > compilation entirely. > This sounds un-necessary to me because we already have > ReparseAfterSourceEditing for that purpose... > (again I'm the original author of that, Christoph only improved it) > > IMO, the purpose is not really to resume: but rather to retry > compilation using newSource. > We (I ?) have used resume: only because notify:at: does signal a > SyntaxErrorNotification, then immediately retries if the exception > resumes. > > (notification := SyntaxErrorNotification > cue: (cue copy > source: (source contents asText > copyReplaceFrom: location > to: location - 1 > with: messageText); > yourself) > doitFlag: doitFlag > errorMessage: string > location: location) signal. > notification tryNewSourceIfAvailable > > But if the handler does retryWithNewSource: newSource instead of > resume: newSource, then we just have to let retryWithNewSource perform > a self resignalAs: ReparseAfterSourceEditing new. > > I think that it's the right solution, rather than bending the > semantics of resume: (the argument of resume: is normally the value > that should be returned to the sender of signal...). > > So if you see some changes of SyntaxErrorNotification in trunk, you'll > know a bit more about it > (I'm not sure whether I can redact a commit message with that level of > explanation). > > Nicolas On the other hand, I cannot entirely remove tryNewSourceIfAvailable, because it is still the resolution path for SyntaxError window... So I have two alternatives: resignalAs: or resume: (with reactivateHandlers fix). retryWithNewSource: source "Retry the compilation with new source code. Assume that there is already a handler of ReparseAfterSourceEditing on the sender stack. All I have to do then, is to resignal myself as such and let the existing handler do its business." ^ self resignalAs: (ReparseAfterSourceEditing new withNewSource: source) Or: retryWithNewSource: source "Retry the compilation with new source code. Assume: - that the signallerContext will tryNewSourceIfAvailable - and the presence of a handler of ReparseAfterSourceEditing on the sender stack" newSource := source. ^ self resume: self defaultResumeValue I'm still in favour of naming it #retryWithNewSource: rather than resume: because super resume: has another semantic than we shall better not bend. From commits at source.squeak.org Fri Apr 16 20:19:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 20:19:40 0000 Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz Message-ID: Nicolas Cellier uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-nice.457.mcz ==================== Summary ==================== Name: Compiler-nice.457 Author: nice Time: 16 April 2021, 10:19:30.223501 pm UUID: e2ce8f47-9ed2-0d46-aca1-1dd90ebed4b4 Ancestors: Compiler-nice.456 Rename resume: source -> retryWithNewSource: source. The purpose of such exception handling is indeed to retry the compilation with new source. The purpose of resume: anObject is to return anObject to the context that sent signal, that's a slightly different semantic. It happens that if we resume after setting newSource, the signaller (Parser>>notify:at:) will effectively then tryNewSourceIfAvailable. So effectively, resuming will end up in retrying (if there is a handler of ReparseAfterSourceEditing up the sender stack, but the Parser normally puts one). But, even if this is HOW we implement the #retryWithNewSource:, this is not WHAT we wish to ask to the SyntaxErrorNotification. in other words, we shouldn't let the implementation leak in the semantics, otherwise we put the burden of understanding the implementation on the shoulders of programmers, when they could just have trusted the semantics of pseudo natural language offered by keywords. While at it, remove the accessors of newSource. They are not used and may be considered private. This will reduce the unecessary polymorphism. =============== Diff against Compiler-nice.456 =============== Item was removed: - ----- Method: SyntaxErrorNotification>>newSource (in category 'accessing') ----- - newSource - ^newSource! Item was removed: - ----- Method: SyntaxErrorNotification>>newSource: (in category 'accessing') ----- - newSource: aTextOrString - newSource := aTextOrString! Item was removed: - ----- Method: SyntaxErrorNotification>>resume: (in category 'accessing') ----- - resume: source - - self reparse: source notifying: nil ifFail: nil. - ^ super resume: self defaultResumeValue! Item was added: + ----- Method: SyntaxErrorNotification>>retryWithNewSource: (in category 'handling') ----- + retryWithNewSource: source + "Retry the compilation with new source code. + Assume + - that the signallerContext will tryNewSourceIfAvailable + - the presence of a handler of ReparseAfterSourceEditing on the sender stack" + + newSource := source. + ^ self resume! From nicolas.cellier.aka.nice at gmail.com Fri Apr 16 20:21:03 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 16 Apr 2021 22:21:03 +0200 Subject: [squeak-dev] the semantics of SyntaxErrorNotification resume: In-Reply-To: References: Message-ID: Le ven. 16 avr. 2021 à 21:52, Nicolas Cellier a écrit : > > Le ven. 16 avr. 2021 à 20:35, Nicolas Cellier > a écrit : > > > > Hi all, > > I see some new tests failing > > - testResumeEarlySyntaxError > > - testResumeLateSyntaxError > > > > This is entirely my fault because of the "fix" of exception handling. > > Indeed, I have not rearmed the exception stack in resume: action, and > > I think I should have done so. > > > > However, I see that SyntaxErrorNotification>>resume: launch a new > > compilation entirely. > > This sounds un-necessary to me because we already have > > ReparseAfterSourceEditing for that purpose... > > (again I'm the original author of that, Christoph only improved it) > > > > IMO, the purpose is not really to resume: but rather to retry > > compilation using newSource. > > We (I ?) have used resume: only because notify:at: does signal a > > SyntaxErrorNotification, then immediately retries if the exception > > resumes. > > > > (notification := SyntaxErrorNotification > > cue: (cue copy > > source: (source contents asText > > copyReplaceFrom: location > > to: location - 1 > > with: messageText); > > yourself) > > doitFlag: doitFlag > > errorMessage: string > > location: location) signal. > > notification tryNewSourceIfAvailable > > > > But if the handler does retryWithNewSource: newSource instead of > > resume: newSource, then we just have to let retryWithNewSource perform > > a self resignalAs: ReparseAfterSourceEditing new. > > > > I think that it's the right solution, rather than bending the > > semantics of resume: (the argument of resume: is normally the value > > that should be returned to the sender of signal...). > > > > So if you see some changes of SyntaxErrorNotification in trunk, you'll > > know a bit more about it > > (I'm not sure whether I can redact a commit message with that level of > > explanation). > > > > Nicolas > > On the other hand, I cannot entirely remove tryNewSourceIfAvailable, > because it is still the resolution path for SyntaxError window... > So I have two alternatives: resignalAs: or resume: (with > reactivateHandlers fix). > > retryWithNewSource: source > "Retry the compilation with new source code. > Assume that there is already a handler of > ReparseAfterSourceEditing on the sender stack. > All I have to do then, is to resignal myself as such and let the > existing handler do its business." > > ^ self resignalAs: (ReparseAfterSourceEditing new withNewSource: source) > > Or: > > retryWithNewSource: source > "Retry the compilation with new source code. > Assume: > - that the signallerContext will tryNewSourceIfAvailable > - and the presence of a handler of ReparseAfterSourceEditing on > the sender stack" > > newSource := source. > ^ self resume: self defaultResumeValue > > I'm still in favour of naming it #retryWithNewSource: rather than > resume: because super resume: has another semantic than we shall > better not bend. I opted for the second solution. I hope that the commit message explains the reason for renaming sufficiently clearly. From commits at source.squeak.org Fri Apr 16 20:35:13 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 20:35:13 0000 Subject: [squeak-dev] The Trunk: Tools-nice.1041.mcz Message-ID: Nicolas Cellier uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-nice.1041.mcz ==================== Summary ==================== Name: Tools-nice.1041 Author: nice Time: 16 April 2021, 10:35:02.178501 pm UUID: 748a435f-3013-754a-a132-23d62251d01d Ancestors: Tools-nice.1040 Fixup copy/paste slip in stackTopTranslated =============== Diff against Tools-nice.1040 =============== Item was changed: ----- Method: ContextInspector>>stackTopTranslated (in category 'private') ----- stackTopTranslated "Alas translation is slow enough that we notice the slow down in trying to step in the debugger..." (CurrentLocale ~= Locale current + or: [CachedStackTopLabel isNil]) ifTrue: - or: [CachedTempVarsLabel isNil]) ifTrue: [CurrentLocale := Locale current. CachedStackTopLabel := 'stack top' translated]. ^CachedStackTopLabel! From commits at source.squeak.org Fri Apr 16 20:39:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 20:39:37 0000 Subject: [squeak-dev] The Trunk: Tests-nice.454.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.454.mcz ==================== Summary ==================== Name: Tests-nice.454 Author: nice Time: 16 April 2021, 10:39:27.763501 pm UUID: a798edc1-1f4c-dc40-a835-38af2973efb5 Ancestors: Tests-nice.453 Use SyntaxErrorNotification>>retryWithNewSource: rather than resume: This better document the intention (rather than the implementation). Note that resume: will no longer tryNewSourceIfAvailable, it will just act as super, that is return its argument to the sender of signal. =============== Diff against Tests-nice.453 =============== Item was changed: ----- Method: CompilerSyntaxErrorNotifyingTest>>testResumeEarlySyntaxError (in category 'tests') ----- testResumeEarlySyntaxError | result | result := [Compiler evaluate: ''''''''] on: SyntaxErrorNotification + do: [:ex | ex retryWithNewSource: '''''''''']. - do: [:ex | ex resume: '''''''''']. self assert: '''' equals: result! Item was changed: ----- Method: CompilerSyntaxErrorNotifyingTest>>testResumeLateSyntaxError (in category 'tests') ----- testResumeLateSyntaxError | result | result := [Compiler evaluate: '6*:7'] on: SyntaxErrorNotification + do: [:ex | ex retryWithNewSource: '6*7']. - do: [:ex | ex resume: '6*7']. self assert: 42 equals: result! From commits at source.squeak.org Fri Apr 16 21:03:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 16 Apr 2021 21:03:26 0000 Subject: [squeak-dev] The Trunk: ToolsTests-nice.103.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolsTests to project The Trunk: http://source.squeak.org/trunk/ToolsTests-nice.103.mcz ==================== Summary ==================== Name: ToolsTests-nice.103 Author: nice Time: 16 April 2021, 11:03:17.401501 pm UUID: 02b5002e-2e71-524a-812b-cb320a93288c Ancestors: ToolsTests-mt.102 WeakSetInspectorTest>>testSymbolTableM6812 times out. Be more generous (at the cost of more time spent in tests...). Ideally we should seek an acceleration of the test, fast tests are good tests. =============== Diff against ToolsTests-mt.102 =============== Item was changed: ----- Method: WeakSetInspectorTest>>testSymbolTableM6812 (in category 'tests') ----- testSymbolTableM6812 "This test is related to http://bugs.squeak.org/view.php?id=6812. Check whether field selection and garbage collection are somehow interfering." | getRandomSymbol symbols priorContents currentContents currentIndex | + self object removeAll. getRandomSymbol := [ | token | token := (1 to: 10) collect: [:ea | ($a to: $z) atRandom] as: String. (Symbol lookup: token) ifNil: [token asSymbol] ifNotNil: [nil]]. symbols := OrderedCollection new. 10 timesRepeat: [ getRandomSymbol value ifNotNil: [:symbol | symbols add: symbol]]. self object addAll: symbols. Smalltalk garbageCollect. self assert: symbols size equals: self object size. self assert: symbols notEmpty. 1 to: symbols size do: [:round | currentIndex := 1. symbols removeLast. [(currentIndex := currentIndex + 1) <= self inspector fieldList size] whileTrue: [ self inspector selectionIndex: currentIndex. self assert: priorContents ~= (currentContents := self inspector contents). priorContents := currentContents. Smalltalk garbageCollect. "Removes symbol from weak set" self simulateStepping. "Removes field from weak-set inspector"]]. self assert: symbols isEmpty. self assert: self object isEmpty.! From nicolas.cellier.aka.nice at gmail.com Fri Apr 16 21:37:37 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 16 Apr 2021 23:37:37 +0200 Subject: [squeak-dev] stepping over non local return in a protected block Message-ID: When debugging things like this: [^2] ensure: [Transcript cr; show: 'done']. if we step into the protected block [^2], then step over ^2, we incorrectly get a BlockCannotReturn. In deeper stacks, I saw some weirder behaviour (when debugging test03EventHandler I put a halt into m on: #mouseDown send: #value: to:[:evt| self halt. evt redButtonPressed ifTrue:[m color: Color red]. evt yellowButtonPressed ifTrue:[m color: Color yellow]. evt blueButtonPressed ifTrue:[m color: Color blue]]. and stepped over such a [^...] ensure: - result is very hard to understand/trace) I'm pretty sure this has been thoroughly investigated and discussed during the last year or so (I remember of some infinite debugger thread and some hard work of Christoph). After the integration of many fixes in exception handling, process termination, unwinding, and simulation machinery, thanks to Jaromir, Marcel, Christoph, ... (apologies to whoever I forgot), maybe it's time to revisit this problem. Christoph, if you still have brain cells unburnt by this problem ;) From nicolas.cellier.aka.nice at gmail.com Fri Apr 16 22:12:05 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 17 Apr 2021 00:12:05 +0200 Subject: [squeak-dev] I've reached my limits Message-ID: I often recommend using the debugger in order to acquire a better understanding of code. A priori, I think that no bug can resist a thorough analysis/best efforts. A posteriori, it seems that I've reached my limits with the debugging of test03EventHandler. If you find where the blue button down event is filtered/catched without prior knowledge of Morphic event handling, by just stepping, then either you are lucky, or your analytical capabilities are tremendous (you can probably focus on 77 symbols simultaneously rather than the average of 7)! For me, that's not the right angle of attack! All I acquired is an increased reluctance to start a deeper learning of Morphic, more questioning about whether I'm becoming too old, and the conviction that things are maybe getting too complex (more than strictly necessary?). Look at the full stack (which BTW is not the full stack -- and more not shown --). I let the test03EventHandler fix to people with prior knowledge, not only because I was distracted by debugger bugs... Nicolas --- The full stack --- MorphicEventTests(Object)>>halt [] in MorphicEventTests>>test03EventHandler EventHandler>>send:to:withEvent:fromMorph: EventHandler>>mouseDown:fromMorph: Morph>>mouseDown: Morph>>handleMouseDown: MouseButtonEvent>>sentTo: Morph>>handleEvent: MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: Morph>>processEvent:using: Morph>>processEvent: [] in MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf: Array(SequenceableCollection)>>do: PasteUpMorph(Morph)>>submorphsDo: MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: PasteUpMorph(Morph)>>processEvent:using: [] in PasteUpMorph>>processEvent:using: [] in ActiveWorldVariable class(DynamicVariable class)>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveWorldVariable class(DynamicVariable class)>>value:during: [] in ActiveWorldVariable class>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveWorldVariable class>>value:during: PasteUpMorph>>becomeActiveDuring: PasteUpMorph>>processEvent:using: PasteUpMorph(Morph)>>processEvent: HaloMorph(SimpleHaloMorph)>>mouseDown: HaloMorph>>mouseDown: HaloMorph(Morph)>>handleMouseDown: MouseButtonEvent>>sentTo: HaloMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: HaloMorph(Morph)>>processEvent:using: MorphicEventDispatcher>>doProcessingForFocusEvent:with: MorphicEventDispatcher>>dispatchFocusEventFully:with: MorphicEventDispatcher>>dispatchFocusEventAllOver:with: HaloMorph(SimpleHaloMorph)>>processFocusEvent:using: HaloMorph(Morph)>>processFocusEvent: [] in [] in [] in HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: [] in ActiveEventVariable class(DynamicVariable class)>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveEventVariable class(DynamicVariable class)>>value:during: [] in ActiveEventVariable class>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveEventVariable class>>value:during: MouseButtonEvent(MorphicEvent)>>becomeActiveDuring: [] in [] in HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: [] in ActiveHandVariable class(DynamicVariable class)>>value:during: -- and more not shown -- From leves at caesar.elte.hu Fri Apr 16 23:17:28 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Sat, 17 Apr 2021 01:17:28 +0200 (CEST) Subject: [squeak-dev] "Browse revisions" server error for long methods In-Reply-To: <1618577389573-0.post@n4.nabble.com> References: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> <1618577389573-0.post@n4.nabble.com> Message-ID: The problem is that the service is implemented as a GET request instead of a POST or PUT request, so data can only be encoded in the URL. Like most web servers, nginx has an upper limit on the length of the URLs accepted (though it's implicit in case of nginx). And even though the accepted maximum length could be increased, there would still be cases where the error occurs. The right solution is to implement this as a POST or a PUT service. Levente On Fri, 16 Apr 2021, Christoph Thiede wrote: > Hmm ... Confusingly, the error message still persists when I manually > truncate the source in the method definition. On the other hand, the feature > works fine for other methods such as String >> #asInteger. Is the request > limit just way too low? Could you maybe increase this limitation? > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html From commits at source.squeak.org Sat Apr 17 02:14:18 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 17 Apr 2021 02:14:18 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-eem.293.mcz Message-ID: Eliot Miranda uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-eem.293.mcz ==================== Summary ==================== Name: MorphicExtras-eem.293 Author: eem Time: 16 April 2021, 7:14:15.621938 pm UUID: 27489c5b-4cc5-4581-905d-881e877c32d6 Ancestors: MorphicExtras-mt.292 Add frame buffering to the CameraInterface (i.e. if possible the CameraPlugin copies data directly into a pinned bitmap instead of into an internal buffer which is then copied into the bitmap in getFrameForCamera:into:. Update the camera:framesDo:while: utility to use buffering and/or interrupt notification if possible. =============== Diff against MorphicExtras-mt.292 =============== Item was added: + ----- Method: CameraInterface class>>bufferedInterruptDrivenVideoTest: (in category 'test') ----- + bufferedInterruptDrivenVideoTest: camNum + "A quick test of video input. Displays video on the screen until the mouse is pressed. + Answer nil if the interrupt-driven interface is unavailable." + "self bufferedInterruptDrivenVideoTest: 1" + "self bufferedInterruptDrivenVideoTest: 2" + "[self bufferedInterruptDrivenVideoTest: 2] fork. + self bufferedInterruptDrivenVideoTest: 1" + + | semaphore height frameExtent frameBuffer | + height := 16. + 1 to: camNum - 1 do: + [:camIndex| "N.B. the extent of an unopened camera is 0 at 0" + height := height + (self frameExtent: camIndex) y + 16]. + (self cameraIsOpen: camNum) ifFalse: + [(self openCamera: camNum width: 352 height: 288) ifNil: + [self inform: 'no camera'. + ^nil]]. + frameExtent := self frameExtent: camNum. + frameBuffer := Form extent: frameExtent depth: 32. + frameBuffer bits pin. + self camera: camNum setFrameBuffer: frameBuffer bits. + + semaphore := Semaphore new. + [self camera: camNum setSemaphore: (Smalltalk registerExternalObject: semaphore)] + on: Error + do: [:err| + Smalltalk unregisterExternalObject: semaphore. + self inform: 'interrupt-driven camera interface unavailable: ', err messageText. + ^nil]. + [| n startTime frameCount msecs fps | + [semaphore wait. + startTime ifNil: + [frameCount := 0. + frameExtent := self frameExtent: camNum. + "N.B. the actual frame size may not be determined until delivery of the first frame. + So resize the form if necessary." + frameExtent ~= frameBuffer extent ifTrue: + [frameBuffer := Form extent: frameExtent depth: 32 bits: frameBuffer bits]. + startTime := Time millisecondClockValue]. + Sensor anyButtonPressed] whileFalse: + [n := self getFrameForCamera: camNum into: frameBuffer bits. + n > 0 ifTrue: + [frameCount := frameCount + 1. + frameBuffer displayAt: 16 @ height]]. + msecs := Time millisecondClockValue - startTime. + fps := (frameCount * 1000) // msecs. + ^(self cameraName: camNum), ': ', frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'] + ensure: + [self closeCamera: camNum. + Smalltalk unregisterExternalObject: semaphore. + Sensor waitNoButton]! Item was changed: ----- Method: CameraInterface class>>camera:framesDo:while: (in category 'utilities') ----- camera: cameraNum framesDo: aBlock while: whileBlock + "Evaluate aBlock every time a frame becomes available. Answer a tuple of frames per second + and the number of 16ms delays per second if polling is used, plus indications of which schemes + were used. Be destructive; use only one bitmap, overwriting its contents with each successive frame. + Use the buffered interface if possible. It is the sender's responsibility to open and close the camera." + | form bitmap schemes delay start duration frameCount delayCount semaphore | - "Evaluate aBlock every time a frame becomes available. Answer a tuple of frames per second and number of 16ms delays per second. - Be destructive; use only one bitmap, overwriting its contents with each successive frame. - It is the sender's responsibility to open and close the camera." - | form bitmap delay start duration frameCount delayCount | form := Form extent: (self frameExtent: cameraNum) depth: 32. bitmap := form bits. + bitmap pin. + schemes := Array new writeStream. + [self camera: cameraNum setFrameBuffer: bitmap. + schemes nextPut: 'buffered'] + on: Error + do: [:err| + bitmap unpin. + schemes nextPut: 'copied']. + semaphore := Semaphore new. + [self camera: cameraNum setSemaphore: (Smalltalk registerExternalObject: semaphore). + schemes nextPut: 'interrupt driven'] + on: Error + do: [:err| + Smalltalk unregisterExternalObject: semaphore. + semaphore := nil. + schemes nextPut: 'polling']. delay := Delay forMilliseconds: (1000 / 60) asInteger. "60 fps is fast" + start := Time utcMicrosecondClock. frameCount := delayCount := 0. + [semaphore ifNotNil: + [semaphore wait]. + [(self getFrameForCamera: cameraNum into: bitmap) <= 0] whileTrue: - [[(self camera: cameraNum getParam: 1) <= 0] whileTrue: [delay wait. delayCount := delayCount + 1]. - self getFrameForCamera: cameraNum into: bitmap. frameCount := frameCount + 1. aBlock value: form. whileBlock value] whileTrue. ^{ frameCount * 1.0e6 / (duration := Time utcMicrosecondClock - start). + delayCount * 1.0e6 / duration }, + schemes contents - delayCount * 1.0e6 / duration } "| cameraNum | self openCamera: (cameraNum := 1) width: 640 height: 480. self waitForCameraStart: cameraNum. [self camera: cameraNum framesDo: [:bitmap| bitmap display] while: [Sensor noButtonPressed]] ensure: [self closeCamera: cameraNum]"! Item was added: + ----- Method: CameraInterface class>>camera:setFrameBuffer: (in category 'camera ops') ----- + camera: cameraNum setFrameBuffer: frameBuffer + "Set a pinned non-pointer object as the frame buffer for the camera. + Fail if cameraNum does not reference an open camera, or if the buffer is not large enough." + + ^self primitiveFailed! Item was added: + ----- Method: CameraInterface class>>camera:setFrameBufferA:B: (in category 'camera ops') ----- + camera: cameraNum setFrameBufferA: frameBufferA B: frameBufferBOrNil + "Set a pair of pinned non-pointer objects as the frame buffers for the camera. + If both are non-nil the plugin will fill them alternating between first frameBufferA and second frameBufferBOrNil. + Fail if frameBufferBOrNil is not nil and a different size from frameBufferA. + Fail if cameraNum does not reference an open camera, or if the buffers are not large enough." + + ^self primitiveFailed! Item was changed: ----- Method: CameraInterface class>>interruptDrivenVideoTest: (in category 'test') ----- interruptDrivenVideoTest: camNum "A quick test of video input. Displays video on the screen until the mouse is pressed. Answer nil if the interrupt-driven interface is unavailable." "self interruptDrivenVideoTest: 1" "self interruptDrivenVideoTest: 2" "[self interruptDrivenVideoTest: 2] fork. self interruptDrivenVideoTest: 1" | semaphore height frameExtent | height := 16. 1 to: camNum - 1 do: + [:camIndex| "N.B. the extent of an unopened camera is 0 at 0" - [:camIndex| "N.B. the of an unopened camera is 0 at 0" height := height + (self frameExtent: camIndex) y + 16]. (self cameraIsOpen: camNum) ifFalse: [(self openCamera: camNum width: 352 height: 288) ifNil: [self inform: 'no camera'. ^nil]]. semaphore := Semaphore new. [self camera: camNum setSemaphore: (Smalltalk registerExternalObject: semaphore)] on: Error do: [:err| Smalltalk unregisterExternalObject: semaphore. self inform: 'interrupt-driven camera interface unavailable: ', err messageText. ^nil]. [| f n startTime frameCount msecs fps | [semaphore wait. "N.B. the frame extent may not be known until the delivery of the first frame. So we have to delay initialization." startTime ifNil: [(frameExtent := self frameExtent: camNum) x = 0 ifTrue: [self inform: 'no camera'. ^nil]. f := Form extent: (self frameExtent: camNum) depth: 32. frameCount := 0. startTime := Time millisecondClockValue]. Sensor anyButtonPressed] whileFalse: [n := self getFrameForCamera: camNum into: f bits. n > 0 ifTrue: [frameCount := frameCount + 1. f displayAt: 16 @ height]]. msecs := Time millisecondClockValue - startTime. fps := (frameCount * 1000) // msecs. ^(self cameraName: camNum), ': ', frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'] ensure: [self closeCamera: camNum. Smalltalk unregisterExternalObject: semaphore. Sensor waitNoButton]! Item was changed: ----- Method: CameraInterface class>>videoTest: (in category 'test') ----- videoTest: camNum "A quick test of video input. Displays video on the screen until the mouse is pressed." "self videoTest: 1" "self videoTest: 2" | frameExtent f n startTime frameCount msecs fps | + (self cameraIsOpen: camNum) ifFalse: + [(self openCamera: camNum width: 320 height: 240) ifNil: + [self inform: 'no camera'. + ^nil]]. - (self openCamera: camNum width: 320 height: 240) ifNil: [^ self inform: 'no camera']. self waitForCameraStart: camNum. (frameExtent := self frameExtent: camNum) x = 0 ifTrue: [^ self inform: 'no camera']. f := Form extent: (self frameExtent: camNum) depth: 32. frameCount := 0. startTime := nil. [Sensor anyButtonPressed] whileFalse: [n := self getFrameForCamera: camNum into: f bits. n > 0 ifTrue: [startTime ifNil: [startTime := Time millisecondClockValue]. frameCount := frameCount + 1. f display]]. Sensor waitNoButton. msecs := Time millisecondClockValue - startTime. self closeCamera: camNum. fps := frameCount * 1000 // msecs. + ^(self cameraName: camNum), ': ', frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'! - ^frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'! From vanessa at codefrau.net Sat Apr 17 03:10:29 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Fri, 16 Apr 2021 20:10:29 -0700 Subject: [squeak-dev] "Browse revisions" server error for long methods In-Reply-To: References: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> <1618577389573-0.post@n4.nabble.com> Message-ID: The argument to the server call is serializing the whole definition: serializeForRequest: aMCDefinition ^ ((ReferenceStream on: (RWBinaryOrTextStream on: ByteArray new)) nextPut: aMCDefinition ; yourself) contents asString encodeForHTTP So either, as Levente suggests, it needs to be POSTed which allows larger data, or something smaller needs to be posted to the server, like MCDefinition>>description. Either way, it sounds like both server and client need to be touched for this. –Vanessa– On Fri, Apr 16, 2021 at 4:17 PM Levente Uzonyi wrote: > The problem is that the service is implemented as a GET request instead > of a POST or PUT request, so data can only be encoded in the URL. > Like most web servers, nginx has an upper limit on the length of the URLs > accepted (though it's implicit in case of nginx). > And even though the accepted maximum length could be increased, there > would still be cases where the error occurs. > The right solution is to implement this as a POST or a PUT service. > > > Levente > > On Fri, 16 Apr 2021, Christoph Thiede wrote: > > > Hmm ... Confusingly, the error message still persists when I manually > > truncate the source in the method definition. On the other hand, the > feature > > works fine for other methods such as String >> #asInteger. Is the request > > limit just way too low? Could you maybe increase this limitation? > > > > Best, > > Christoph > > > > > > > > ----- > > Carpe Squeak! > > -- > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From m at jaromir.net Sat Apr 17 08:57:54 2021 From: m at jaromir.net (Jaromir Matas) Date: Sat, 17 Apr 2021 03:57:54 -0500 (CDT) Subject: [squeak-dev] stepping over non local return in a protected block In-Reply-To: References: Message-ID: <1618649874366-0.post@n4.nabble.com> Hi Nicolas, Nicolas Cellier wrote > When debugging things like this: > > [^2] ensure: [Transcript cr; show: 'done']. > > if we step into the protected block [^2], then step over ^2, we > incorrectly get a BlockCannotReturn. Hmm, that's the bug that plagued #terminate and caused unwind errors... I didn't fully realize then; I simply avoided it by eliminating the simulation code from #terminate :) This behavior happens when the VM calls #aboutToReturn:through: and the Debugger executes #stepOver it (or over #return:through: or #resume:through:) - sorry if I'm stating the obvious; unfortunately I have negligible knowledge of the Debugger. I'm really looking forward to seeing a solution! Thanks, best, ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From francisco.garau at gmail.com Sat Apr 17 09:47:57 2021 From: francisco.garau at gmail.com (Francisco Garau) Date: Sat, 17 Apr 2021 10:47:57 +0100 Subject: [squeak-dev] playing with syntax alternatives Message-ID: Hello -- I want to do some experimentation with alternative syntax for Smalltalk. My main motivation is trying to unify the block and method syntax. I see a block as an in-lined method with an empty selector. This syntax helps to visualize that an object is basically a closure over its instance variables. To make this work, I would also need to make Blocks understand the message #: (which would be equivalent to the current #value:). Some examples will be more clear than I can describe. Currently: succ := [:n | n + 1]. (succ value: 3) = 4. addTo := [:a :b | a + b]. (addTo value: 3 value: 4) = 7. Proposal: [succ: n | n + 1]. (succ :3) = 4. [add: a to: b | a + b]. (add :3 to : 4) = 7. Class declaration syntax: [Point << Object | | x y | [hash | ^x hash + y hash]. [extent: aPoint | ^Rectangle origin: self extent: aPoint]. [distance: aPoint | | dx dy | dx := aPoint x - x. dy := aPoint y - y. ^((dx * dx) + (dy * dy)) sqrt]. ]. I am reaching out for ideas or direction on how to do such experiments. I would rather avoid touching the current compiler. Maybe defining this alternative syntax that compiles to regular Smalltalk. Nowadays PEG parsers are very trendy. Is there one available for any of the Squeak/Smalltalk flavours? Thanks, Francisco -------------- next part -------------- An HTML attachment was scrubbed... URL: From Marcel.Taeumel at hpi.de Sat Apr 17 11:43:08 2021 From: Marcel.Taeumel at hpi.de (Taeumel, Marcel) Date: Sat, 17 Apr 2021 11:43:08 +0000 Subject: [squeak-dev] I've reached my limits In-Reply-To: References: Message-ID: My bad. I will take a look at it. Maybe I also find a way to improve documentation and code. I will keep you posted. Marcel ________________________________ From: Squeak-dev on behalf of Nicolas Cellier Sent: Saturday, April 17, 2021 12:12:05 AM To: The general-purpose Squeak developers list Subject: [squeak-dev] I've reached my limits I often recommend using the debugger in order to acquire a better understanding of code. A priori, I think that no bug can resist a thorough analysis/best efforts. A posteriori, it seems that I've reached my limits with the debugging of test03EventHandler. If you find where the blue button down event is filtered/catched without prior knowledge of Morphic event handling, by just stepping, then either you are lucky, or your analytical capabilities are tremendous (you can probably focus on 77 symbols simultaneously rather than the average of 7)! For me, that's not the right angle of attack! All I acquired is an increased reluctance to start a deeper learning of Morphic, more questioning about whether I'm becoming too old, and the conviction that things are maybe getting too complex (more than strictly necessary?). Look at the full stack (which BTW is not the full stack -- and more not shown --). I let the test03EventHandler fix to people with prior knowledge, not only because I was distracted by debugger bugs... Nicolas --- The full stack --- MorphicEventTests(Object)>>halt [] in MorphicEventTests>>test03EventHandler EventHandler>>send:to:withEvent:fromMorph: EventHandler>>mouseDown:fromMorph: Morph>>mouseDown: Morph>>handleMouseDown: MouseButtonEvent>>sentTo: Morph>>handleEvent: MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: Morph>>processEvent:using: Morph>>processEvent: [] in MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf: Array(SequenceableCollection)>>do: PasteUpMorph(Morph)>>submorphsDo: MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: PasteUpMorph(Morph)>>processEvent:using: [] in PasteUpMorph>>processEvent:using: [] in ActiveWorldVariable class(DynamicVariable class)>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveWorldVariable class(DynamicVariable class)>>value:during: [] in ActiveWorldVariable class>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveWorldVariable class>>value:during: PasteUpMorph>>becomeActiveDuring: PasteUpMorph>>processEvent:using: PasteUpMorph(Morph)>>processEvent: HaloMorph(SimpleHaloMorph)>>mouseDown: HaloMorph>>mouseDown: HaloMorph(Morph)>>handleMouseDown: MouseButtonEvent>>sentTo: HaloMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: HaloMorph(Morph)>>processEvent:using: MorphicEventDispatcher>>doProcessingForFocusEvent:with: MorphicEventDispatcher>>dispatchFocusEventFully:with: MorphicEventDispatcher>>dispatchFocusEventAllOver:with: HaloMorph(SimpleHaloMorph)>>processFocusEvent:using: HaloMorph(Morph)>>processFocusEvent: [] in [] in [] in HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: [] in ActiveEventVariable class(DynamicVariable class)>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveEventVariable class(DynamicVariable class)>>value:during: [] in ActiveEventVariable class>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveEventVariable class>>value:during: MouseButtonEvent(MorphicEvent)>>becomeActiveDuring: [] in [] in HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: [] in ActiveHandVariable class(DynamicVariable class)>>value:during: -- and more not shown -- -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Sat Apr 17 12:04:16 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 17 Apr 2021 12:04:16 0000 Subject: [squeak-dev] The Trunk: MorphicTests-mt.77.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-mt.77.mcz ==================== Summary ==================== Name: MorphicTests-mt.77 Author: mt Time: 17 April 2021, 2:04:15.737481 pm UUID: 3bd12899-bf8f-c84c-9f58-61da5c7b8224 Ancestors: MorphicTests-nice.76 Quick fix for #test03EventHandler. Note that we might want to extract that "reset pattern", which I employed in several test cases already, into TestCase for all tests to use. Also note that I will start an extra discussion about whether the blue button should be exclusive for the halo or whether morphs should be able to override this. =============== Diff against MorphicTests-nice.76 =============== Item was changed: TestCase subclass: #UserInputEventTests + instanceVariableNames: 'hand world reset' - instanceVariableNames: 'hand world' classVariableNames: '' poolDictionaries: '' category: 'MorphicTests-Events'! Item was changed: ----- Method: UserInputEventTests>>setUp (in category 'running') ----- setUp super setUp. world := (PasteUpMorph newWorldForProject: nil) extent: 300 at 200; yourself. hand := HandMorphForEventTests new. world removeHand: world firstHand; "the default hand" + addHand: hand. + + reset := { + [:enable | [Morph haloForAll: enable]] + value: Morph haloForAll + }. + Morph haloForAll: false.! - addHand: hand.! Item was changed: ----- Method: UserInputEventTests>>tearDown (in category 'running') ----- tearDown hand showHardwareCursor: true. "Nasty side-effect" + reset do: #value. super tearDown.! From commits at source.squeak.org Sat Apr 17 12:33:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 17 Apr 2021 12:33:26 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1754.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1754.mcz ==================== Summary ==================== Name: Morphic-mt.1754 Author: mt Time: 17 April 2021, 2:33:21.323481 pm UUID: 5fa87166-5835-1545-910d-74cd9d19c630 Ancestors: Morphic-mt.1753 For event filters, dispatch #ignore through the event's current hand as a way to inform that hand such as in test for logging, which helps debugging and understanding the flow of events. =============== Diff against Morphic-mt.1753 =============== Item was added: + ----- Method: HandMorph>>ignoreEvent: (in category 'events-filtering') ----- + ignoreEvent: anEvent + "Double dispatch from MorphicEvent >> #ignore: to let custom hands tweak this behavior such as logging it." + + anEvent wasIgnored: true.! Item was changed: ----- Method: MorphicEvent>>ignore (in category 'dispatching') ----- ignore + source ignoreEvent: self.! - self wasIgnored: true.! Item was changed: ----- Method: ScrollPane>>filterEvent:for: (in category 'event filtering') ----- filterEvent: aKeyboardEvent for: morphOrNil "See #initialize. This filter should be installed as keyboard event filter during the capture phase." + (aKeyboardEvent isKeystroke + and: [self scrollByKeyboard: aKeyboardEvent]) + ifTrue: [aKeyboardEvent ignore]. - aKeyboardEvent isKeystroke - ifFalse: [^ aKeyboardEvent]. + ^ aKeyboardEvent! - ^ aKeyboardEvent - wasIgnored: (self scrollByKeyboard: aKeyboardEvent); - yourself! From commits at source.squeak.org Sat Apr 17 12:34:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 17 Apr 2021 12:34:46 0000 Subject: [squeak-dev] The Trunk: MorphicTests-mt.78.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-mt.78.mcz ==================== Summary ==================== Name: MorphicTests-mt.78 Author: mt Time: 17 April 2021, 2:34:45.066481 pm UUID: 6b91789b-fdd8-e84c-a604-20d387270a86 Ancestors: MorphicTests-mt.77 Tweak test-specific hand to log ignored events to support debugging failing tests. Complements Morphic-mt.1754 =============== Diff against MorphicTests-mt.77 =============== Item was changed: HandMorph subclass: #HandMorphForEventTests + instanceVariableNames: 'eventsDuringCapture eventsDuringBubble eventsRejected eventsFiltered eventsIgnored isHandling' - instanceVariableNames: 'eventsDuringCapture eventsDuringBubble eventsRejected eventsFiltered isHandling' classVariableNames: '' poolDictionaries: '' category: 'MorphicTests-Events'! Item was added: + ----- Method: HandMorphForEventTests>>eventsIgnored (in category 'accessing') ----- + eventsIgnored + ^ eventsIgnored ifNil: [eventsIgnored := OrderedCollection new]! Item was added: + ----- Method: HandMorphForEventTests>>ignoreEvent: (in category 'event filtering') ----- + ignoreEvent: anEvent + "Log ignored event to support debugging." + + super ignoreEvent: anEvent. + self eventsIgnored add: anEvent copy -> (thisContext stackOfSize: 5).! Item was changed: ----- Method: MorphicEventTests>>test03EventHandler (in category 'tests') ----- test03EventHandler | m | m := Morph new. m extent: 20 at 20; topLeft: 0 at 0. m wantsHaloFromClick: false. m wantsYellowButtonMenu: false. m wantsMetaMenu: false. + m on: #mouseDown send: #value: to: [:evt| - m on: #mouseDown send: #value: to:[:evt| evt redButtonPressed ifTrue:[m color: Color red]. evt yellowButtonPressed ifTrue:[m color: Color yellow]. evt blueButtonPressed ifTrue:[m color: Color blue]]. + m color: Color blue. m openInWorld: world. hand handleEvent: (self redMouseDownAt: m center). self assert: Color red equals: m color. hand handleEvent: (self yellowMouseDownAt: m center). self assert: Color yellow equals: m color. hand handleEvent: (self blueMouseDownAt: m center). self assert: Color blue equals: m color.! From marcel.taeumel at hpi.de Sat Apr 17 12:51:22 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sat, 17 Apr 2021 14:51:22 +0200 Subject: [squeak-dev] I've reached my limits In-Reply-To: References: Message-ID: Hi Nicolas, I fixed this bug in MorphicTests-mt.77 by disabling "Morph haloForAll". Well, I think that event handling in Morphic has a conceptual complexity that is comparable to other (non-Smalltalk) UI frameworks. Events travel through the hierarchy of morphs, starting in the world. Only one morph can be the actual handler. Event filters might intercept this, do something different, and tell the mechanism to further ignore the event. In this test03EventHandler, the question was why that event did not reach its destination (here: that block in the test method). Of course, "self halt" does not work when a destination is not reached. Why might an event not reach the desired handler (morph): a) the target handler omits to reply to #handlesMouseDown: (etc.) b) another (maybe sibling) morph is on top of it c) the morph is not even in the hand's world d) an event filter intervenes and marks the event as "ignored" The cases a), b), and c) can easily be checked through the debugger. The world and the entire morph hierarchy is easily accessible. Bounds can be checked against the event's position. This leaves case d), which is quite tricky to debug. Well, one can try to figure out, which implementor of #filterEvent:for: is the culprit. There are only 13 in the current Trunk. This path might lead to success. :-) But I think we can do better. That's why I made it possible to log event-ignoring coming from arbitrary event filters in the hand (morph) we use in the event tests. The log includes short stacks to figure out the actual event filter. Here is an example for this bug: While I did immediately recalled that "blue button fails" means "halo got the event" because I did something to the halo dispatcher in the last weeks, this is typically unclear for the average programmer, who is jumping between domains (and classes/packages) in the entire image. SO! By inspecting the "eventsIgnored" through the debugger, one can easily see both "mouseDown blue" and "PasteUpMorph >> tryInvokeHalo:" as the culprit. That's why disabling the halo during this test solves the issue. Best, Marcel Am 17.04.2021 13:43:08 schrieb Taeumel, Marcel : My bad. I will take a look at it. Maybe I also find a way to improve documentation and code. I will keep you posted. Marcel From: Squeak-dev on behalf of Nicolas Cellier Sent: Saturday, April 17, 2021 12:12:05 AM To: The general-purpose Squeak developers list Subject: [squeak-dev] I've reached my limits   I often recommend using the debugger in order to acquire a better understanding of code. A priori, I think that no bug can resist a thorough analysis/best efforts. A posteriori, it seems that I've reached my limits with the debugging of test03EventHandler. If you find where the blue button down event is filtered/catched without prior knowledge of Morphic event handling, by just stepping, then either you are lucky, or your analytical capabilities are tremendous (you can probably focus on 77 symbols simultaneously rather than the average of 7)! For me, that's not the right angle of attack! All I acquired is an increased reluctance to start a deeper learning of Morphic, more questioning about whether I'm becoming too old, and the conviction that things are maybe getting too complex (more than strictly necessary?). Look at the full stack (which BTW is not the full stack -- and more not shown --). I let the test03EventHandler fix to people with prior knowledge, not only because I was distracted by debugger bugs... Nicolas --- The full stack --- MorphicEventTests(Object)>>halt [] in MorphicEventTests>>test03EventHandler EventHandler>>send:to:withEvent:fromMorph: EventHandler>>mouseDown:fromMorph: Morph>>mouseDown: Morph>>handleMouseDown: MouseButtonEvent>>sentTo: Morph>>handleEvent: MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: Morph>>processEvent:using: Morph>>processEvent: [] in MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf: Array(SequenceableCollection)>>do: PasteUpMorph(Morph)>>submorphsDo: MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf:  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: PasteUpMorph(Morph)>>processEvent:using: [] in PasteUpMorph>>processEvent:using: [] in ActiveWorldVariable class(DynamicVariable class)>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveWorldVariable class(DynamicVariable class)>>value:during: [] in ActiveWorldVariable class>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveWorldVariable class>>value:during: PasteUpMorph>>becomeActiveDuring: PasteUpMorph>>processEvent:using: PasteUpMorph(Morph)>>processEvent: HaloMorph(SimpleHaloMorph)>>mouseDown: HaloMorph>>mouseDown: HaloMorph(Morph)>>handleMouseDown: MouseButtonEvent>>sentTo: HaloMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: [] in MorphicEventDispatcher>>dispatchMouseDown:with: FullBlockClosure(BlockClosure)>>ensure: MorphicEventDispatcher>>dispatchMouseDown:with: MorphicEventDispatcher>>dispatchEvent:with: HaloMorph(Morph)>>processEvent:using: MorphicEventDispatcher>>doProcessingForFocusEvent:with: MorphicEventDispatcher>>dispatchFocusEventFully:with: MorphicEventDispatcher>>dispatchFocusEventAllOver:with: HaloMorph(SimpleHaloMorph)>>processFocusEvent:using: HaloMorph(Morph)>>processFocusEvent: [] in [] in [] in HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: [] in ActiveEventVariable class(DynamicVariable class)>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveEventVariable class(DynamicVariable class)>>value:during: [] in ActiveEventVariable class>>value:during: FullBlockClosure(BlockClosure)>>ensure: ActiveEventVariable class>>value:during: MouseButtonEvent(MorphicEvent)>>becomeActiveDuring: [] in [] in HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: [] in ActiveHandVariable class(DynamicVariable class)>>value:during: -- and more not shown -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 71703 bytes Desc: not available URL: From commits at source.squeak.org Sat Apr 17 12:52:00 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 17 Apr 2021 12:52:00 0000 Subject: [squeak-dev] The Inbox: MorphicExtras-ct.294.mcz Message-ID: A new version of MorphicExtras was added to project The Inbox: http://source.squeak.org/inbox/MorphicExtras-ct.294.mcz ==================== Summary ==================== Name: MorphicExtras-ct.294 Author: ct Time: 17 April 2021, 2:51:54.531043 pm UUID: c53b8fad-931b-0042-9e5b-70308fa24666 Ancestors: MorphicExtras-eem.293 Make proper use of DisplayScreen >>#restoreAfter: in SketchMorph examples. =============== Diff against MorphicExtras-eem.293 =============== Item was changed: ----- Method: SketchMorph class>>extraExampleCook (in category '*MorphicExtras-examples') ----- extraExampleCook "SketchMorph extraExampleCook openInWorld" ^ (self withForm: Form extraCook) + addMouseUpActionWith: 'Display restoreAfter: [Form toothpaste: 30]'; - addMouseUpActionWith: 'Form toothpaste: 30'; balloonText: 'Click me and then drag the cursor over the screen'; yourself! Item was changed: ----- Method: SketchMorph class>>extraExampleWizard (in category '*MorphicExtras-examples') ----- extraExampleWizard "SketchMorph extraExampleWizard openInWorld" ^ (self withForm: Form extraWizard) addMouseUpActionWith: + (MessageSend receiver: Display selector: #restoreAfter: argument: [Pen new web]); - (MessageSend receiver: Pen new selector: #web); balloonText: 'Click me and then drag the cursor over the screen\(Trust me, I won''t turn you into a toad!!)' withCRs; yourself! From marcel.taeumel at hpi.de Sat Apr 17 13:02:48 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sat, 17 Apr 2021 15:02:48 +0200 Subject: [squeak-dev] Discussion | Exclusivity of the blue button for Morphic halo Message-ID: Hi all! Any morph can choose to show its halo on any event by calling #addHalo(:). The system-wide "Morph haloForAll" preference enables halo invocation through the blue-button click -- for any morph without it knowing. For Etoys, this is part of the basic user interface, for Squeak, it is an important programming (and debugging) tool to inspect graphical elements. As a consequence, morphs that want to handle the blue-click on their own will be (and feel) overlooked. Their handler routine will not be called. On the bright side, even misbehaving morphs can always be clicked on and inspected -- and fixed. Here is the question: What is your take on the interference between "Morph haloForAll" and a morph's own desire to handle blue-click events? Have a nice weekend! Best, Marcel -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Sat Apr 17 13:04:27 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sat, 17 Apr 2021 15:04:27 +0200 Subject: [squeak-dev] "Browse revisions" server error for long methods In-Reply-To: References: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> <1618577389573-0.post@n4.nabble.com> Message-ID: +1 for using POST (if it is easier to implement... Chris?) Best, Marcel Am 17.04.2021 05:11:17 schrieb Vanessa Freudenberg : The argument to the server call is serializing the whole definition: serializeForRequest: aMCDefinition ^ ((ReferenceStream on: (RWBinaryOrTextStream on: ByteArray new)) nextPut: aMCDefinition ; yourself) contents asString encodeForHTTP So either, as Levente suggests, it needs to be POSTed which allows larger data, or something smaller needs to be posted to the server, like MCDefinition>>description. Either way, it sounds like both server and client need to be touched for this. –Vanessa– On Fri, Apr 16, 2021 at 4:17 PM Levente Uzonyi wrote: The problem is that the service is implemented as a GET request instead of a POST or PUT request, so data can only be encoded in the URL. Like most web servers, nginx has an upper limit on the length of the URLs accepted (though it's implicit in case of nginx). And even though the accepted maximum length could be increased, there would still be cases where the error occurs. The right solution is to implement this as a POST or a PUT service. Levente On Fri, 16 Apr 2021, Christoph Thiede wrote: > Hmm ... Confusingly, the error message still persists when I manually > truncate the source in the method definition. On the other hand, the feature > works fine for other methods such as String >> #asInteger. Is the request > limit just way too low? Could you maybe increase this limitation? > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html [http://forum.world.st/Squeak-Dev-f45488.html] -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Sat Apr 17 14:39:00 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 17 Apr 2021 16:39:00 +0200 Subject: [squeak-dev] I've reached my limits In-Reply-To: References: Message-ID: Hi Marcel, thanks for the explanations. The sole purpose of halt was indeed to check at which depth the handler would be activated. This gave me a clue about the possibility or not to detect interception by just stepping (how deep at worse would I have to step into). Another alternative that I did not try out would have been to step in two debuggers in parallel, one with the red or yellow event, the other with blue... Le sam. 17 avr. 2021 à 14:51, Marcel Taeumel a écrit : > Hi Nicolas, > > I fixed this bug in MorphicTests-mt.77 by disabling "Morph haloForAll". > > Well, I think that event handling in Morphic has a conceptual complexity > that is comparable to other (non-Smalltalk) UI frameworks. Events travel > through the hierarchy of morphs, starting in the world. Only one morph can > be the actual handler. Event filters might intercept this, do something > different, and tell the mechanism to further ignore the event. > > In this test03EventHandler, the question was why that event did not reach > its destination (here: that block in the test method). Of course, "self > halt" does not work when a destination is not reached. > > Why might an event not reach the desired handler (morph): > a) the target handler omits to reply to #handlesMouseDown: (etc.) > b) another (maybe sibling) morph is on top of it > c) the morph is not even in the hand's world > d) an event filter intervenes and marks the event as "ignored" > > The cases a), b), and c) can easily be checked through the debugger. The > world and the entire morph hierarchy is easily accessible. Bounds can be > checked against the event's position. > > This leaves case d), which is quite tricky to debug. Well, one can try to > figure out, which implementor of #filterEvent:for: is the culprit. There > are only 13 in the current Trunk. This path might lead to success. :-) > > But I think we can do better. That's why I made it possible to log > event-ignoring coming from arbitrary event filters in the hand (morph) we > use in the event tests. The log includes short stacks to figure out the > actual event filter. Here is an example for this bug: > > > > While I did immediately recalled that "blue button fails" means "halo got > the event" because I did something to the halo dispatcher in the last > weeks, this is typically unclear for the average programmer, who is jumping > between domains (and classes/packages) in the entire image. SO! By > inspecting the "eventsIgnored" through the debugger, one can easily see > both "mouseDown blue" and "PasteUpMorph >> tryInvokeHalo:" as the culprit. > > That's why disabling the halo during this test solves the issue. > > Best, > Marcel > > Am 17.04.2021 13:43:08 schrieb Taeumel, Marcel : > My bad. I will take a look at it. Maybe I also find a way to improve > documentation and code. I will keep you posted. > > Marcel > ------------------------------ > *From:* Squeak-dev on > behalf of Nicolas Cellier > *Sent:* Saturday, April 17, 2021 12:12:05 AM > *To:* The general-purpose Squeak developers list < > squeak-dev at lists.squeakfoundation.org> > *Subject:* [squeak-dev] I've reached my limits > > I often recommend using the debugger in order to acquire a better > understanding of code. > A priori, I think that no bug can resist a thorough analysis/best efforts. > > A posteriori, it seems that I've reached my limits with the debugging > of test03EventHandler. > If you find where the blue button down event is filtered/catched > without prior knowledge of Morphic event handling, by just stepping, > then either you are lucky, or your analytical capabilities are > tremendous (you can probably focus on 77 symbols simultaneously rather > than the average of 7)! > For me, that's not the right angle of attack! > > All I acquired is an increased reluctance to start a deeper learning > of Morphic, more questioning about whether I'm becoming too old, and > the conviction that things are maybe getting too complex (more than > strictly necessary?). > > Look at the full stack (which BTW is not the full stack -- and more > not shown --). > > I let the test03EventHandler fix to people with prior knowledge, not > only because I was distracted by debugger bugs... > > Nicolas > > --- The full stack --- > MorphicEventTests(Object)>>halt > [] in MorphicEventTests>>test03EventHandler > EventHandler>>send:to:withEvent:fromMorph: > EventHandler>>mouseDown:fromMorph: > Morph>>mouseDown: > Morph>>handleMouseDown: > MouseButtonEvent>>sentTo: > Morph>>handleEvent: > MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: > [] in MorphicEventDispatcher>>dispatchMouseDown:with: > FullBlockClosure(BlockClosure)>>ensure: > MorphicEventDispatcher>>dispatchMouseDown:with: > MorphicEventDispatcher>>dispatchEvent:with: > Morph>>processEvent:using: > Morph>>processEvent: > [] in MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf: > Array(SequenceableCollection)>>do: > PasteUpMorph(Morph)>>submorphsDo: > MorphicEventDispatcher>>dispatchEvent:toSubmorphsOf: > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: > [] in MorphicEventDispatcher>>dispatchMouseDown:with: > FullBlockClosure(BlockClosure)>>ensure: > MorphicEventDispatcher>>dispatchMouseDown:with: > MorphicEventDispatcher>>dispatchEvent:with: > PasteUpMorph(Morph)>>processEvent:using: > [] in PasteUpMorph>>processEvent:using: > [] in ActiveWorldVariable class(DynamicVariable class)>>value:during: > FullBlockClosure(BlockClosure)>>ensure: > ActiveWorldVariable class(DynamicVariable class)>>value:during: > [] in ActiveWorldVariable class>>value:during: > FullBlockClosure(BlockClosure)>>ensure: > ActiveWorldVariable class>>value:during: > PasteUpMorph>>becomeActiveDuring: > PasteUpMorph>>processEvent:using: > PasteUpMorph(Morph)>>processEvent: > HaloMorph(SimpleHaloMorph)>>mouseDown: > HaloMorph>>mouseDown: > HaloMorph(Morph)>>handleMouseDown: > MouseButtonEvent>>sentTo: > HaloMorph(Morph)>>handleEvent: > MorphicEventDispatcher>>dispatchEvent:withHandler:withMorph: > [] in MorphicEventDispatcher>>dispatchMouseDown:with: > FullBlockClosure(BlockClosure)>>ensure: > MorphicEventDispatcher>>dispatchMouseDown:with: > MorphicEventDispatcher>>dispatchEvent:with: > HaloMorph(Morph)>>processEvent:using: > MorphicEventDispatcher>>doProcessingForFocusEvent:with: > MorphicEventDispatcher>>dispatchFocusEventFully:with: > MorphicEventDispatcher>>dispatchFocusEventAllOver:with: > HaloMorph(SimpleHaloMorph)>>processFocusEvent:using: > HaloMorph(Morph)>>processFocusEvent: > [] in [] in [] in > HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: > [] in ActiveEventVariable class(DynamicVariable class)>>value:during: > FullBlockClosure(BlockClosure)>>ensure: > ActiveEventVariable class(DynamicVariable class)>>value:during: > [] in ActiveEventVariable class>>value:during: > FullBlockClosure(BlockClosure)>>ensure: > ActiveEventVariable class>>value:during: > MouseButtonEvent(MorphicEvent)>>becomeActiveDuring: > [] in [] in HandMorphForEventTests(HandMorph)>>sendFocusEvent:to:clear: > [] in ActiveHandVariable class(DynamicVariable class)>>value:during: > -- and more not shown -- > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 71703 bytes Desc: not available URL: From commits at source.squeak.org Sat Apr 17 17:09:38 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 17 Apr 2021 17:09:38 0000 Subject: [squeak-dev] The Inbox: MorphicExtras-ct.295.mcz Message-ID: A new version of MorphicExtras was added to project The Inbox: http://source.squeak.org/inbox/MorphicExtras-ct.295.mcz ==================== Summary ==================== Name: MorphicExtras-ct.295 Author: ct Time: 17 April 2021, 7:09:30.182932 pm UUID: e1a46d30-9232-aa4e-a316-9aad80fa0978 Ancestors: MorphicExtras-eem.293 PianoKeyboardMorph: Don't play a sound when a menu is invoked. =============== Diff against MorphicExtras-eem.293 =============== Item was changed: ----- Method: PianoKeyboardMorph>>mouseDownPitch:event:noteMorph: (in category 'simple keyboard') ----- mouseDownPitch: midiKey event: event noteMorph: noteMorph | pitch | + event redButtonPressed ifFalse: [^ self]. event hand hasSubmorphs ifTrue: [^ self "no response if drag something over me"]. event hand mouseFocus ifNil: ["If dragged into me, then establish focus so I'll see moves" event hand newMouseFocus: noteMorph event: event]. noteMorph color: playingKeyColor. pitch := AbstractSound pitchForMIDIKey: midiKey + 23. soundPlaying ifNotNil: [soundPlaying stopGracefully]. soundPlaying := soundPrototype soundForPitch: pitch dur: 100.0 loudness: 0.3. SoundPlayer resumePlaying: soundPlaying quickStart: true. ! From christoph.thiede at student.hpi.uni-potsdam.de Sat Apr 17 17:25:23 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Sat, 17 Apr 2021 12:25:23 -0500 (CDT) Subject: [squeak-dev] The Inbox: Tools-ct.959.mcz In-Reply-To: <5101007b-7b32-f7f2-7963-da776b982719@gmail.com> References: <1584971006315-0.post@n4.nabble.com> <4e8e180c-48e5-d703-2797-5310e35c090f@gmail.com> <66aadeabcca04da9b98e008f92d4f315@student.hpi.uni-potsdam.de> <1605889979781-0.post@n4.nabble.com> <5101007b-7b32-f7f2-7963-da776b982719@gmail.com> Message-ID: <1618680323673-0.post@n4.nabble.com> Hi Subbu, hi all, apparently, Nabble has mixed up two different threads here, but I hope I will keep track of the original conversation. I think indeed a button bar in the change sorter could be something useful. Nevertheless, I believe this would be a bigger change than my original proposal and personally, I would not find some time for it soon. Thus I would like to propose to merge this patch as-is for the moment, provided that you agree with the idea in general. A small menu item should not harm, should it? :-) For me, this menu item has been very useful in recent times, it just makes the dual sorter easier to access. As soon as anyone other finds some time for adding a button bar, we can integrate it there, of course. (Apart from that, I would rather dislike using the grip you also proposed because IMHO, it would increase the overall visual complexity of our tools, but that's only a personal opinion. :-)) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From christoph.thiede at student.hpi.uni-potsdam.de Sat Apr 17 17:34:06 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Sat, 17 Apr 2021 12:34:06 -0500 (CDT) Subject: [squeak-dev] The Inbox: Morphic-ct.1659.mcz In-Reply-To: References: <7dc6df4f2c9f4b758d0309d48b8bc9a1@student.hpi.uni-potsdam.de> Message-ID: <1618680846148-0.post@n4.nabble.com> Hi Marcel, > > isn't this situation comparable to the items in the docking bar? > > Those look like a menu already. System window buttons do not. I think that this might be a somewhat subjective question. The changeset name in the docking bar does not really look like a menu to me. :-) To my humble self, this rule sounds pretty consistent: An action will only be invoked as soon as you release the hand above a button. Nevertheless, some items are displayed directly whereas others are organized within a menu structure. In every case, I would like it to get rid of the redundant click for choosing a menu item. I have tested this feature for the last 10 months in my image and found it very convenient. :-) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From christoph.thiede at student.hpi.uni-potsdam.de Sat Apr 17 19:31:33 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Sat, 17 Apr 2021 14:31:33 -0500 (CDT) Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: References: <1618255943259-0.post@n4.nabble.com> Message-ID: <1618687893179-0.post@n4.nabble.com> Hi Marcel, > That is, I don't care about shadowing the instVar name -- just locally > focused readability. That is, I am a fan of accessors and thus rarely (? > never ?) bitten by confusing instVar access and tempVar access. :-) For > classes with longer methods and extensive instVar access (...Compiler?), > shadowing can be an issue for code readability, though. That is an interesting insight. Personally, I have stumbled upon unintended shadows a number of times, which is probably related to my way of dealing with tempvars - usually, I do not declare any of them manually but have them added by the compiler when accepting the method. With this approach, it can happen quickly that you miss a tempvar declaration because a variable with the same name already exists. Analogously sometimes, I remove all declarations after refactoring a method when I am unsure whether all tempvars are still in use - and in this situation, I would be irritated if no tempvar declaration is generated because a prior author of the method (most likely a stupid former self) has shadowed an instvar. But as it depends on the individual coding style, as you write, do you think we should provide a toggle/preference to decriminalize instvar shadows? *** > > linter/compiler annotations ... > How come? Well, there might be a lot of opinions on this issue and probably I did not express my perspective in the right way. Please give me a second chance. :-) Just to make sure what we are talking about - when I said annotations, I meant something like this: That is, visual highlight + additional information that is shown upon interaction (hover or click). Are we talking about the same kind of annotations? :-) Such annotations could be used for different things: Compiler warnings (undeclared/undefined/unused temp, shadowed variable, deprecated syntax such as underscore assignments), syntax errors (if we manage to make the Compiler more robust), linter warnings (for example SwaLint), spelling errors, etc. At the moment, we communicate all this information in several different ways: Some (syntax errors) are displayed via Shout, which is nice but lacks proper self-explanation ("Why is this all red? What is wrong with this?") (and also requires us to maintain two separate parsers); others (compiler warnings) are shown only when a method is accepted, so here we have a chance to shorten feedback loops and make the compilation experience more live; even others are shown in the Transcript only, which only a few people will notice at all; and some others will just not be shown unless you use another tool such as the SwaLint UI to see these messages. A common solution that we can see in many modern tools is interactive (sometimes expandable/explorable) annotations that are fed by multiple sources. A good example (maybe even the gold standard?) might be the language server API in Visual Studio Code. I think the popularity of this concept is just based on its usefulness: You do not need to check multiple tools but can union all their outputs in a single view (sink), combined with the ability to filter different sources individually. > While structured information is nice, I am opposed to introducing more > things that are prone to errors. :-) What kind of errors do you mean exactly? If robustness is a thing, I would not give up the entire concept instead of using a few #ifError's. :-) > yes, linter and compiler are tools Hmm ... when I work with the source code pane of a CodeHolder, I actually have the impression to work with the compiler itself, at least I can't name any other tool that would be more close to writing code. See interactive compilation. The compiler is a necessary step in the pipeline of making the entered code executable. > Tool-specific configuration/annotation [...] should not interfere with an > artifact's primary representation. [...] That does not scale; it can also > obfuscate the object's interface. I think I see your point, too many annotations could be distracting. But I am confident that we could overcome this problem by adding a simple but powerful filter mechanism. And very of course, these annotations should be configurable using preferences. Besides, at the moment, there would be only two or three kinds of annotation sources at all, so this might also be a problem for the not-so-near future. :-) > For example, it's problematic that there is only a single #inspectorClass > or #explorerContents per domain object. > various annotations for all kinds of supported compilers/parsers/linters > etc. ... nah. Yeah, we could add another indirection for dispatching access to such tools. But I do not see how this would restrict our abilities to filter this (hypothetical) mass of tools? Also, in the case of compilers, we already have #compilerClass. In the context of a CodeHolder, you would need to decide on one of many compilers anyway ... > There are already pragmas, which can be used to annotate methods. That confuses me. :-) This is a completely different kind of annotations, isn't it? Pragmas are used to store additional, intrinsic information attached to the source code, hover annotations are used to display derived information from different tools - they are transient but not a part of the primary object itself. My proposal was *not* to insert any durable artifacts/comments into the source code while analyzing it. And perhaps one last, more general thought: I think I don't have to emphasize that I'm a big fan of the Squeak tools like most people who will read this. :-) Nevertheless, I have to admit that many other (I call them "modern") editors/IDEs are based on architectures that appear to be more flexible, more scalable, more composed than our CodeHolder and our Browser are. I'm thinking about Visual Studio and Visual Studio Code when making this statement. They provide great opportunities for third-party tools to integrate potentially useful enhancements into the existing IDEs. I don't like to say it, but my impression is that their approach would be more suitable than our tooling which has grown over time when you try to customize the entire development system for a specific domain. Think of exciting additions such as Babylonian programming or also Fabio's new CallTargetBrowser. It's a pity that you still need to subclass from the main tool class (Browser) in all these situations to install such small but useful extensions. VS Code, on the other hand, has a more extensible design and provides lots of APIs that make the development of a small utility more simple. That being said, I don't want to say that the Squeak/Smalltalk approach of designing tools is wrong and should be abandoned - the opposite is true, the liveness and self-description of Squeak are still unmatched! But I think that we need to make more efforts to modularize the Squeak tools and provide more extension points. The new InspectorField API might be a good step in this direction, but we need much more of these APIs. It would be a shame if developers preferred a system like VS Code over Squeak/Smalltalk because it's easier to extend - in particular in the light that Squeak is frequently used for research and experiments. That's why I said in my previous message, "If Squeak does not want to get left behind, we should support something like this [annotations]". :-) Well, I am glad that you survived this massive wall of text and I'm looking forward to your thoughts. :-) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From commits at source.squeak.org Sat Apr 17 20:06:30 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 17 Apr 2021 20:06:30 0000 Subject: [squeak-dev] The Inbox: ST80-ct.269.mcz Message-ID: A new version of ST80 was added to project The Inbox: http://source.squeak.org/inbox/ST80-ct.269.mcz ==================== Summary ==================== Name: ST80-ct.269 Author: ct Time: 17 April 2021, 10:06:28.149652 pm UUID: 2f319f7f-9553-0d47-94ea-f3398af6f4b4 Ancestors: ST80-mt.268 Reuse new Arc >> #computeVertices: to display arcs. Complements ST80-ct.240. Also added an extension point for modifying the granularity of arcs, #numberOfVertices. Sorry for the confusion, this patch has somehow went down in my changes file. :-) Benchmarks: Use anArc from Arc example and do: [anArc displayOn: Display] bench. Before: 726 microseconds per run. After: 650 microseconds per run. =============== Diff against ST80-mt.268 =============== Item was changed: Path subclass: #Arc + instanceVariableNames: 'quadrant radius center numberOfVertices' - instanceVariableNames: 'quadrant radius center' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !Arc commentStamp: '' prior: 0! Arcs are an unusual implementation of splines due to Ted Kaehler. Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner. Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern). By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines. Voila.! Item was changed: ----- Method: Arc>>computeVertices: (in category 'displaying') ----- computeVertices: size | dAngle dSin dCos point | dAngle := (90 / (size - 1)) degreesToRadians. dSin := dAngle sin. dCos := dAngle cos. point := (1 to: quadrant) inject: 0 @ radius into: [:p :i | p leftRotated]. ^ (OrderedCollection new: size) add: (center + point) rounded; + addAll: ((2 to: size) collect: [:i | - addAll: ((1 to: size - 1) collect: [:i | point := point * dCos + (point * dSin) leftRotated. (center + point) rounded]); yourself! Item was changed: ----- Method: Arc>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') ----- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm + | line | - | nSegments line angle sin cos xn yn | - nSegments := 12.0. line := Line new. line form: self form. + (self computeVertices: self numberOfVertices) overlappingPairsDo: [:start :dest | + line + beginPoint: start; + endPoint: dest; + displayOn: aDisplayMedium - angle := (90.0 / nSegments) degreesToRadians. - sin := angle sin. - cos := angle cos. - quadrant = 1 - ifTrue: - [xn := radius asFloat. - yn := 0.0]. - quadrant = 2 - ifTrue: - [xn := 0.0. - yn := 0.0 - radius asFloat]. - quadrant = 3 - ifTrue: - [xn := 0.0 - radius asFloat. - yn := 0.0]. - quadrant = 4 - ifTrue: - [xn := 0.0. - yn := radius asFloat]. - nSegments asInteger - timesRepeat: - [ | xn1 yn1 | - xn1 := xn * cos + (yn * sin). - yn1 := yn * cos - (xn * sin). - line beginPoint: center + (xn asInteger @ yn asInteger). - line endPoint: center + (xn1 asInteger @ yn1 asInteger). - line - displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger + fillColor: aForm]! - fillColor: aForm. - xn := xn1. - yn := yn1]! Item was added: + ----- Method: Arc>>numberOfVertices (in category 'accessing') ----- + numberOfVertices + + ^ numberOfVertices ifNil: [12]! Item was added: + ----- Method: Arc>>numberOfVertices: (in category 'accessing') ----- + numberOfVertices: anInteger + + numberOfVertices := anInteger.! From vanessa at codefrau.net Sat Apr 17 23:20:17 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sat, 17 Apr 2021 16:20:17 -0700 Subject: [squeak-dev] "Browse revisions" server error for long methods In-Reply-To: References: <191c8a93fb6049a6b179da416dcc8eb7@student.hpi.uni-potsdam.de> <1618577389573-0.post@n4.nabble.com> Message-ID: Well, class + selector + author initials / time stamp should be enough to identify the method on the server. Sending the whole source code with it seems unnecessary. –Vanessa – On Sat, Apr 17, 2021 at 06:04 Marcel Taeumel wrote: > +1 for using POST (if it is easier to implement... Chris?) > > Best, > Marcel > > Am 17.04.2021 05:11:17 schrieb Vanessa Freudenberg : > The argument to the server call is serializing the whole definition: > > serializeForRequest: aMCDefinition > ^ ((ReferenceStream on: (RWBinaryOrTextStream on: ByteArray new)) nextPut: > aMCDefinition ; yourself) contents asString encodeForHTTP > > So either, as Levente suggests, it needs to be POSTed which allows larger > data, or something smaller needs to be posted to the server, like > MCDefinition>>description. Either way, it sounds like both server and > client need to be touched for this. > > –Vanessa– > > On Fri, Apr 16, 2021 at 4:17 PM Levente Uzonyi > wrote: > >> The problem is that the service is implemented as a GET request instead >> of a POST or PUT request, so data can only be encoded in the URL. >> Like most web servers, nginx has an upper limit on the length of the URLs >> accepted (though it's implicit in case of nginx). >> And even though the accepted maximum length could be increased, there >> would still be cases where the error occurs. >> The right solution is to implement this as a POST or a PUT service. >> >> >> Levente >> >> On Fri, 16 Apr 2021, Christoph Thiede wrote: >> >> > Hmm ... Confusingly, the error message still persists when I manually >> > truncate the source in the method definition. On the other hand, the >> feature >> > works fine for other methods such as String >> #asInteger. Is the >> request >> > limit just way too low? Could you maybe increase this limitation? >> > >> > Best, >> > Christoph >> > >> > >> > >> > ----- >> > Carpe Squeak! >> > -- >> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Sun Apr 18 03:39:18 2021 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sat, 17 Apr 2021 20:39:18 -0700 Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: <1618255943259-0.post@n4.nabble.com> References: <1618255943259-0.post@n4.nabble.com> Message-ID: <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> Hi Christoph, > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: > > Hi Eliot, > > I fear that changes like this will not be very durable unless tested in any > way. At the moment, you won't even notice a new shadow unless you have > opened a Transcript by accident when accepting a method. Should we maybe > show a message window for shadows instead when compiled interactively, > analogously to the warnings about superfluous temps? I’m removing shadows, not adding new ones. In all cars I saw eleven ing s from the compiler in the update stream and replaced shadowed temp cars by renamed temp vars. So my changes have no semantic effect and only remove the warning. > > (In a larger context, I would strongly opt for (finally) introducing a > mechanism for linter/compiler annotations in CodeHolders. Most modern > editors and IDEs have it, even Pharo; if Squeak does not want to get left > behind, we should support something like this, too. It could or should be > configurable, of course.) > > LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal name > for a variable that holds Morph instances, right? :) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > From kksubbu.ml at gmail.com Sun Apr 18 11:35:54 2021 From: kksubbu.ml at gmail.com (K K Subbu) Date: Sun, 18 Apr 2021 17:05:54 +0530 Subject: [squeak-dev] The Inbox: Tools-ct.959.mcz In-Reply-To: <1618680323673-0.post@n4.nabble.com> References: <1584971006315-0.post@n4.nabble.com> <4e8e180c-48e5-d703-2797-5310e35c090f@gmail.com> <66aadeabcca04da9b98e008f92d4f315@student.hpi.uni-potsdam.de> <1605889979781-0.post@n4.nabble.com> <5101007b-7b32-f7f2-7963-da776b982719@gmail.com> <1618680323673-0.post@n4.nabble.com> Message-ID: On 17/04/21 10:55 pm, Christoph Thiede wrote: > Thus I would like to propose to merge this patch as-is for the moment, > provided that you agree with the idea in general. A small menu item should > not harm, should it? :-) For me, this menu item has been very useful in > recent times, it just makes the dual sorter easier to access. As soon as > anyone other finds some time for adding a button bar, we can integrate it > there, of course. Chris, I have no objections to the patch being merged. Having a change sorter flip between single/dual is a useful feature indeed. Useful enough to deserve direct visibility instead of being hidden in a menu two levels down. But that can wait for the next batch of improvements. Thank you for the efforts .. Subbu From marcel.taeumel at hpi.de Sun Apr 18 12:44:32 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sun, 18 Apr 2021 14:44:32 +0200 Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> Message-ID: Hi Christoph, hi Eliot, it might be that the likelihood of shadowing increases with the use of cull'ed block invocations, which we have been supporting more and more in the last years: self owner ifNotNil: [:owner | "..."]. self submorphs ifNotEmpty: [:submorphs | "..."]. As alternative names, one could drop their actual "role" and just use their kinds (as generic as desired): self owner ifNotNil: [:morph | "..."]. self submorphs ifNotEmpty: [:morphs | "..."]. self submorphs ifNotEmpty: [:objects | "..."]. In the past, I happened to mistakenly have used the wrong role, shadowing the right one: self allOwnersDo: [:owner | "..."]. self allOwnersDo: [:morph | "..."]. Yet, we do have misleading protocol on what to actually call "owner." Just the morph that has me directly in its submorphs? That might be another topic. :-) *** To avoid shadowing, I find myself using (a) abbreviations, (b) kind/class, or (c) count-prefix "a" or "some". Or a combination of those. Unfortunately, omitting the domain-specific role in a name might impair readability. I just noticed that I am finde with "aMorph" as a method argument, yet I would never use "a" in a block argument. :-D Strange. Best, Marcel Am 18.04.2021 05:39:33 schrieb Eliot Miranda : Hi Christoph, > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: > > Hi Eliot, > > I fear that changes like this will not be very durable unless tested in any > way. At the moment, you won't even notice a new shadow unless you have > opened a Transcript by accident when accepting a method. Should we maybe > show a message window for shadows instead when compiled interactively, > analogously to the warnings about superfluous temps? I’m removing shadows, not adding new ones. In all cars I saw eleven ing s from the compiler in the update stream and replaced shadowed temp cars by renamed temp vars. So my changes have no semantic effect and only remove the warning. > > (In a larger context, I would strongly opt for (finally) introducing a > mechanism for linter/compiler annotations in CodeHolders. Most modern > editors and IDEs have it, even Pharo; if Squeak does not want to get left > behind, we should support something like this, too. It could or should be > configurable, of course.) > > LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal name > for a variable that holds Morph instances, right? :) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Sun Apr 18 12:48:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 18 Apr 2021 12:48:37 0000 Subject: [squeak-dev] The Trunk: ST80-ct.269.mcz Message-ID: Marcel Taeumel uploaded a new version of ST80 to project The Trunk: http://source.squeak.org/trunk/ST80-ct.269.mcz ==================== Summary ==================== Name: ST80-ct.269 Author: ct Time: 17 April 2021, 10:06:28.149652 pm UUID: 2f319f7f-9553-0d47-94ea-f3398af6f4b4 Ancestors: ST80-mt.268 Reuse new Arc >> #computeVertices: to display arcs. Complements ST80-ct.240. Also added an extension point for modifying the granularity of arcs, #numberOfVertices. Sorry for the confusion, this patch has somehow went down in my changes file. :-) Benchmarks: Use anArc from Arc example and do: [anArc displayOn: Display] bench. Before: 726 microseconds per run. After: 650 microseconds per run. =============== Diff against ST80-mt.268 =============== Item was changed: Path subclass: #Arc + instanceVariableNames: 'quadrant radius center numberOfVertices' - instanceVariableNames: 'quadrant radius center' classVariableNames: '' poolDictionaries: '' category: 'ST80-Paths'! !Arc commentStamp: '' prior: 0! Arcs are an unusual implementation of splines due to Ted Kaehler. Imagine two lines that meet at a corner. Now imagine two moving points; one moves from the corner to the end on one line, the other moves from the end of the other line in to the corner. Now imagine a series of lines drawn between those moving points at each step along the way (they form a sort of spider web pattern). By connecting segments of the intersecting lines, a smooth curve is achieved that is tangent to both of the original lines. Voila.! Item was changed: ----- Method: Arc>>computeVertices: (in category 'displaying') ----- computeVertices: size | dAngle dSin dCos point | dAngle := (90 / (size - 1)) degreesToRadians. dSin := dAngle sin. dCos := dAngle cos. point := (1 to: quadrant) inject: 0 @ radius into: [:p :i | p leftRotated]. ^ (OrderedCollection new: size) add: (center + point) rounded; + addAll: ((2 to: size) collect: [:i | - addAll: ((1 to: size - 1) collect: [:i | point := point * dCos + (point * dSin) leftRotated. (center + point) rounded]); yourself! Item was changed: ----- Method: Arc>>displayOn:at:clippingBox:rule:fillColor: (in category 'displaying') ----- displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm + | line | - | nSegments line angle sin cos xn yn | - nSegments := 12.0. line := Line new. line form: self form. + (self computeVertices: self numberOfVertices) overlappingPairsDo: [:start :dest | + line + beginPoint: start; + endPoint: dest; + displayOn: aDisplayMedium - angle := (90.0 / nSegments) degreesToRadians. - sin := angle sin. - cos := angle cos. - quadrant = 1 - ifTrue: - [xn := radius asFloat. - yn := 0.0]. - quadrant = 2 - ifTrue: - [xn := 0.0. - yn := 0.0 - radius asFloat]. - quadrant = 3 - ifTrue: - [xn := 0.0 - radius asFloat. - yn := 0.0]. - quadrant = 4 - ifTrue: - [xn := 0.0. - yn := radius asFloat]. - nSegments asInteger - timesRepeat: - [ | xn1 yn1 | - xn1 := xn * cos + (yn * sin). - yn1 := yn * cos - (xn * sin). - line beginPoint: center + (xn asInteger @ yn asInteger). - line endPoint: center + (xn1 asInteger @ yn1 asInteger). - line - displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger + fillColor: aForm]! - fillColor: aForm. - xn := xn1. - yn := yn1]! Item was added: + ----- Method: Arc>>numberOfVertices (in category 'accessing') ----- + numberOfVertices + + ^ numberOfVertices ifNil: [12]! Item was added: + ----- Method: Arc>>numberOfVertices: (in category 'accessing') ----- + numberOfVertices: anInteger + + numberOfVertices := anInteger.! From commits at source.squeak.org Sun Apr 18 16:43:55 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 18 Apr 2021 16:43:55 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1042.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1042.mcz ==================== Summary ==================== Name: Tools-mt.1042 Author: mt Time: 18 April 2021, 6:43:53.338254 pm UUID: 3fd43581-c48b-154a-9dfa-7d666d9d5076 Ancestors: Tools-nice.1041 In change records, make info about removal more robust and extensible. =============== Diff against Tools-nice.1041 =============== Item was changed: ----- Method: ChangeSorter>>browseVersions (in category 'message list') ----- browseVersions "Create and schedule a changelist browser on the versions of the selected message." | class selector method category pair sourcePointer | (selector := self selectedMessageName) ifNil: [^ self]. class := self selectedClassOrMetaClass. (class includesSelector: selector) ifTrue: [method := class compiledMethodAt: selector. category := class whichCategoryIncludesSelector: selector. sourcePointer := nil] ifFalse: [pair := myChangeSet methodInfoFromRemoval: {class name. selector}. pair ifNil: [^ nil]. sourcePointer := pair first. method := CompiledMethod toReturnSelfTrailerBytes: (CompiledMethodTrailer new sourcePointer: sourcePointer). + category := pair second]. - category := pair last]. VersionsBrowser browseVersionsOf: method class: self selectedClass meta: class isMeta category: category selector: selector lostMethodPointer: sourcePointer. ! Item was changed: ----- Method: StandardToolSet class>>browseVersionsOf:selector: (in category 'browsing') ----- browseVersionsOf: class selector: selector "Open and answer a browser on versions of the method. If the method doesn't exist try and find version from the current change set. If not found there, answer nil." | methodOrNil methodCategory | methodOrNil := class compiledMethodAt: selector ifAbsent: []. methodOrNil ifNil: [(ChangeSet current methodInfoFromRemoval: {class name. selector}) ifNil: [^nil] ifNotNil: [:pair| methodOrNil := CompiledMethod toReturnSelfTrailerBytes: (CompiledMethodTrailer new sourcePointer: pair first). + methodCategory := pair second]]. - methodCategory := pair last]]. ^VersionsBrowser browseVersionsOf: methodOrNil class: class theNonMetaClass meta: class isMeta category: (methodCategory ifNil: [class organization categoryOfElement: selector]) selector: selector! From commits at source.squeak.org Sun Apr 18 16:49:09 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 18 Apr 2021 16:49:09 0000 Subject: [squeak-dev] The Trunk: System-mt.1228.mcz Message-ID: Marcel Taeumel uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-mt.1228.mcz ==================== Summary ==================== Name: System-mt.1228 Author: mt Time: 18 April 2021, 6:49:05.736254 pm UUID: 513db764-6353-204e-9724-18519504a7b5 Ancestors: System-ul.1227 Adds queries to enumerate actual domain objects for changed classes or methods. Adds change stamps for class changes and method removal. Note that I followed the not-so-good practice of using "Utilities changeStamp" to assure a single kind of timestamp (to sort later). In the future, we should change all this to DateAndTime and deprecate TimeStamp. =============== Diff against System-ul.1227 =============== Item was changed: ----- Method: ChangeSet>>changedClasses (in category 'class changes') ----- changedClasses - "Answer an OrderedCollection of changed or edited classes. - Does not include removed classes. Sort alphabetically by name." + ^ Array streamContents: [:stream | + self changedClassesDo: [:class | + stream nextPut: class]]! - "Much faster to sort names first, then convert back to classes. Because metaclasses reconstruct their name at every comparison in the sorted collection. - 8/91 sw chgd to filter out non-existent classes (triggered by problems with class-renames" - - ^ self changedClassNames - collect: [:className | Smalltalk classNamed: className] - thenSelect: [:aClass | aClass notNil]! Item was added: + ----- Method: ChangeSet>>changedClassesDo: (in category 'class changes') ----- + changedClassesDo: block + "Answer an OrderedCollection of changed or edited classes. + Does not include removed classes. Sort alphabetically by name." + + "Much faster to sort names first, then convert back to classes. Because metaclasses reconstruct their name at every comparison in the sorted collection. + 8/91 sw chgd to filter out non-existent classes (triggered by problems with class-renames" + + self flag: #environmentsMissing. + self changedClassNames do: [:className | | record class changeTypes dateAndTime category | + record := changeRecords at: className. + class := (Smalltalk classNamed: className) ifNil: [ + PseudoClass new + name: className; + definition: record priorDefinition; + yourself]. + changeTypes := record allChangeTypes. + dateAndTime := [TimeStamp fromMethodTimeStamp: record timeStamp] + ifError: [TimeStamp epoch]. + category := [class category] ifError: ['unknown']. + block + cull: class + cull: changeTypes + cull: dateAndTime + cull: category].! Item was added: + ----- Method: ChangeSet>>changedMethods (in category 'method changes') ----- + changedMethods + + ^ Array streamContents: [:stream | + self changedMethodsDo: [:class | + stream nextPut: class]]! Item was added: + ----- Method: ChangeSet>>changedMethodsDo: (in category 'method changes') ----- + changedMethodsDo: block + + self flag: #environmentsMissing. + changeRecords keysAndValuesDo: [:className :classRecord | + (Smalltalk classNamed: className) ifNotNil: [:class | + classRecord methodChanges keysAndValuesDo: [:selector :methodRecord | + | method category sourcePointer dateAndTime | + (class includesSelector: selector) + ifTrue: [ + method := class compiledMethodAt: selector. + category := class organization categoryOfElement: selector. + sourcePointer := method sourcePointer. + dateAndTime := method timeStamp] + ifFalse: [ "Method was removed. Try to reconstruct information." + methodRecord methodInfoFromRemoval ifNotNil: [:spec | + sourcePointer := spec first. + category := spec second. + method := CompiledMethod toReturnSelfTrailerBytes: + (CompiledMethodTrailer new sourcePointer: sourcePointer). + method methodClass: class; selector: selector. + dateAndTime := spec size > 2 ifTrue: [spec third]]]. + method ifNotNil: [ + dateAndTime := [TimeStamp fromMethodTimeStamp: dateAndTime] + ifError: [TimeStamp epoch]. + block + cull: method + cull: methodRecord changeType + cull: dateAndTime + cull: category]]]].! Item was added: + ----- Method: ChangeSet>>classChanges (in category 'accessing') ----- + classChanges + + ^ changeRecords keys select: + [:className | (changeRecords at: className) allChangeTypes notEmpty]! Item was changed: ----- Method: ChangeSet>>event: (in category 'change logging') ----- event: anEvent "Hook for SystemChangeNotifier" anEvent itemKind = SystemChangeNotifier classKind ifTrue: [ anEvent isRemoved ifTrue: [self noteRemovalOf: anEvent item]. anEvent isAdded ifTrue: [self addClass: anEvent item]. anEvent isModified ifTrue: [anEvent anyChanges ifTrue: [self changeClass: anEvent item from: anEvent oldItem]]. anEvent isCommented ifTrue: [self commentClass: anEvent item]. anEvent isRenamed ifTrue: [self renameClass: anEvent item from: anEvent oldName to: anEvent newName]. anEvent isReorganized ifTrue: [self reorganizeClass: anEvent item]. anEvent isRecategorized ifTrue: [self changeClass: anEvent item from: anEvent item]. ]. anEvent itemKind = SystemChangeNotifier methodKind ifTrue: [ anEvent isAdded ifTrue: [self noteNewMethod: anEvent item forClass: anEvent itemClass selector: anEvent itemSelector priorMethod: nil]. anEvent isModified ifTrue: [self noteNewMethod: anEvent item forClass: anEvent itemClass selector: anEvent itemSelector priorMethod: anEvent oldItem]. anEvent isRemoved + ifTrue: [self removeSelector: anEvent itemSelector class: anEvent itemClass priorMethod: anEvent item lastMethodInfo: {anEvent item sourcePointer. anEvent itemProtocol. Utilities changeStamp}]. - ifTrue: [self removeSelector: anEvent itemSelector class: anEvent itemClass priorMethod: anEvent item lastMethodInfo: {anEvent item sourcePointer. anEvent itemProtocol}]. anEvent isRecategorized ifTrue: [self reorganizeClass: anEvent itemClass]. ].! Item was changed: Object subclass: #ClassChangeRecord + instanceVariableNames: 'inForce revertable changeTypes thisDefinition priorDefinition thisName priorName thisOrganization priorOrganization thisComment priorComment thisMD priorMD methodChanges timeStamp' - instanceVariableNames: 'inForce revertable changeTypes thisDefinition priorDefinition thisName priorName thisOrganization priorOrganization thisComment priorComment thisMD priorMD methodChanges' classVariableNames: '' poolDictionaries: '' category: 'System-Changes'! !ClassChangeRecord commentStamp: 'fbs 9/6/2013 17:32' prior: 0! A ClassChangeRecorder keeps track of most substantive changes permissible in a project, isolated or not. Structure: inForce a boolean Tells whether these changes are in effect. true for all changeSets in and above the current project. It should be sufficient only to record this for the changeSet as a whole, but this redundancy could help in error recovery. classIsLocal a boolean True if and only if this class is defined in this layer of the project structure. changeTypes an identitySet Summarizes which changes have been made in this class. Values include #comment, #reorganize, #rename, and the four more summarized below. thisName a string Retains the class name for this layer. priorName a string Preserves the prior name. thisComment a text Retains the class comment for this layer. priorComment a text Preserves the prior comment. thisOrganization a classOrganizer Retains the class organization for this layer. priorOrganization a classOrganizer Preserves the prior organization. thisMD a methodDictionary Used to prepare changes for nearly atomic invocation of this layer (see below). priorMD a methodDictionary Preserves the state of an altered class as it exists in the next outer layer of the project structure. methodChanges a dictionary of classChangeRecords Retains all the method changes for this layer. Four of the possible changeTypes are maintained in a mutually exclusive set, analogously to MethodChangeRecords. Here is a simple summary of the relationship between these four changeType symbols and the recording of prior state | prior == nil | prior not nil --------- |---------------------------- |-------------------- add | add | change --------- |---------------------------- |-------------------- remove | addedThenRemoved | remove A classChangeRecorder is notified of changes by the method noteMethodChange: . ClassChangeRecorders are designed to invoke a set of changes relative to the definition of a class in an prior layer. It is important that both invocation and revocation of these changes take place in a nearly atomic fashion so that interdependent changes will be adopted as a whole, and so that only one flush of the method cache should be necessary. A further reason for revocation to be simple is that it may be requested as an attempt to recover from an error in a project that is failing.! Item was changed: ----- Method: ClassChangeRecord>>noteChangeType:fromClass: (in category 'all changes') ----- noteChangeType: changeSymbol fromClass: class + timeStamp := Utilities changeStamp. (changeSymbol = #new or: [changeSymbol = #add]) ifTrue: [changeTypes add: #add. changeTypes remove: #change ifAbsent: []. revertable := false. ^ self]. changeSymbol = #change ifTrue: [(changeTypes includes: #add) ifTrue: [^ self]. ^ changeTypes add: changeSymbol]. changeSymbol == #addedThenRemoved ifTrue: [^ self]. "An entire class was added but then removed" changeSymbol = #comment ifTrue: [^ changeTypes add: changeSymbol]. changeSymbol = #reorganize ifTrue: [^ changeTypes add: changeSymbol]. changeSymbol = #rename ifTrue: [^ changeTypes add: changeSymbol]. (changeSymbol beginsWith: 'oldName: ') ifTrue: ["Must only be used when assimilating other changeSets" (changeTypes includes: #add) ifTrue: [^ self]. priorName := changeSymbol copyFrom: 'oldName: ' size + 1 to: changeSymbol size. ^ changeTypes add: #rename]. changeSymbol = #remove ifTrue: [(changeTypes includes: #add) ifTrue: [changeTypes add: #addedThenRemoved] ifFalse: [changeTypes add: #remove]. ^ changeTypes removeAllFoundIn: #(add change comment reorganize)]. self error: 'Unrecognized changeType'! Item was added: + ----- Method: ClassChangeRecord>>timeStamp (in category 'accessing') ----- + timeStamp + + ^ timeStamp! From commits at source.squeak.org Sun Apr 18 17:00:48 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 18 Apr 2021 17:00:48 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1755.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1755.mcz ==================== Summary ==================== Name: Morphic-mt.1755 Author: mt Time: 18 April 2021, 7:00:43.878254 pm UUID: e5705780-2988-a54e-b6c7-21b4194fcd5c Ancestors: Morphic-mt.1754, Morphic-ct.1659 Fix our two menu-invocating buttons to act on mouse-down and actually look like menus: (1) menu button in system window and (2) change-set button in world-main-docking-bar. Merges Morphic-ct.1659. Thanks Christoph (ct) for pointing out this issue about menu invocation through buttons. See http://forum.world.st/The-Inbox-Morphic-ct-1659-mcz-tp5116728.html By example, this commit also adds a menu to the change-set button in the docking bar. This menu lists the latest method and class changes. To make this work, the following things got addressed: - Fixes DockingBarUpdatingItemMorph, which missed several changes from DockingBarItemMorph. (Interesting specialization challenge...) - Let menus #rubberBandCells to allow for changing menu item's widths. - Adds query about latest changes to #listChangesOn:. (Feel free to improve this. Maybe add preference for number of elements?) Complements (and depends on) System-mt.1228 and Tools-mt.1042. =============== Diff against Morphic-mt.1754 =============== Item was changed: ----- Method: DockingBarMorph>>addUpdatingItem: (in category 'construction') ----- addUpdatingItem: aBlock | item | item := DockingBarUpdatingItemMorph new. aBlock value: item. + item subMenu ifNotNil: [:menu | + "Docking bar and protruding menu should appear visually merged." + menu morphicLayerNumber: self morphicLayerNumber + 1]. self addMorphBack: item! Item was changed: ----- Method: DockingBarMorph>>ensureSelectedItem: (in category 'events') ----- ensureSelectedItem: evt self selectedItem ifNil: [ self selectItem: ( self submorphs + detect: [ :each | each isMenuItemMorph ] - detect: [ :each | each isKindOf: DockingBarItemMorph ] ifNone: [ ^self ]) event: evt ]! Item was changed: ----- Method: DockingBarMorph>>filterEvent:for: (in category 'events-processing') ----- filterEvent: aKeyboardEvent for: anObject "Provide keyboard shortcuts." | index itemToSelect | aKeyboardEvent controlKeyPressed ifFalse: [^ aKeyboardEvent]. aKeyboardEvent isKeystroke ifFalse: [^ aKeyboardEvent]. "Search field." aKeyboardEvent keyCharacter = $0 ifTrue: [ self searchBarMorph ifNotNil: [ :morph | morph model activate: aKeyboardEvent in: morph ]. ^ aKeyboardEvent ignore "hit!!"]. "Select menu items." (aKeyboardEvent keyValue between: $1 asciiValue and: $9 asciiValue) ifFalse: [^ aKeyboardEvent]. index := aKeyboardEvent keyValue - $1 asciiValue + 1. itemToSelect := (self submorphs select: [ :each | + each isMenuItemMorph ]) - each isKindOf: DockingBarItemMorph ]) at: index ifAbsent: [^ aKeyboardEvent]. self activate: aKeyboardEvent. self selectItem: itemToSelect event: aKeyboardEvent. ^ aKeyboardEvent ignore "hit!!"! Item was changed: ----- Method: DockingBarMorph>>moveSelectionDown:event: (in category 'control') ----- moveSelectionDown: direction event: evt "Move the current selection up or down by one, presumably under keyboard control. direction = +/-1" | index | index := (submorphs indexOf: selectedItem ifAbsent: [1-direction]) + direction. submorphs do: "Ensure finite" [:unused | | m | m := submorphs atWrap: index. + (m isMenuItemMorph and: [m isEnabled]) ifTrue: - ((m isKindOf: DockingBarItemMorph) and: [m isEnabled]) ifTrue: [^ self selectItem: m event: evt]. "Keep looking for an enabled item" index := index + direction sign]. ^ self selectItem: nil event: evt! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>adjacentTo (in category 'selecting') ----- + adjacentTo + + | roundedCornersOffset verticalOffset | + roundedCornersOffset := MenuMorph roundedMenuCorners + ifTrue: [Morph preferredCornerRadius negated] + ifFalse: [0]. + verticalOffset := 2. + + owner isFloating + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToTop + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToLeft + ifTrue: [^ {self bounds topRight + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToBottom + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToRight + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset negated)}]. + ^ {self bounds bottomLeft + (roundedCornersOffset @ 5)}! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createSubmenu (in category 'private') ----- + createSubmenu + + ^DockingBarMenuMorph new! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createUpdatingSubmenu (in category 'private') ----- + createUpdatingSubmenu + + ^DockingBarUpdatingMenuMorph new! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'world') ----- - ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'as yet unclassified') ----- decorateOwner "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawIconOn: (in category 'drawing') ----- + drawIconOn: aCanvas + + | pos | + self hasIcon ifTrue: [ + | iconForm | + iconForm := self iconForm. + + pos := (contents + ifEmpty: [self left + (self width - iconForm width // 2)] + ifNotEmpty: [self left]) + @ (self top + (self height - iconForm height // 2)). + + aCanvas + translucentImage: iconForm + at: pos].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawLabelOn: (in category 'drawing') ----- + drawLabelOn: aCanvas + + | stringBounds | + self contents ifEmpty: [^ self]. + + stringBounds := bounds. + + self hasIcon ifTrue: [ + stringBounds := stringBounds left: stringBounds left + self iconForm width + 2 ]. + + "Vertical centering." + stringBounds := stringBounds top: stringBounds top + stringBounds bottom - self fontToUse height // 2. + "Horizontal centering." + stringBounds := stringBounds left: stringBounds left + (stringBounds width - (self fontToUse widthOfString: contents) // 2) abs. + + aCanvas + drawString: contents + in: stringBounds + font: self fontToUse + color: self colorToUse.! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawSubMenuMarkerOn: (in category 'drawing') ----- + drawSubMenuMarkerOn: aCanvas + "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseDown: (in category 'events') ----- + mouseDown: evt + "Handle a mouse down event. Menu items get activated when the mouse is over them." + + (evt shiftPressed and:[self wantsKeyboardFocusOnShiftClick]) ifTrue: [ ^super mouseDown: evt ]. "enable label editing" + isSelected + ifTrue: [ + owner selectItem: nil event: evt. ] + ifFalse: [ + owner activate: evt. "Redirect to menu for valid transitions" + owner selectItem: self event: evt. ] + ! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'events') ----- - ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'as yet unclassified') ----- mouseEnter: evt "Do not hover docking bar items directory. Mouse-down required. But if you already see a submenu, support hovering." owner selectedItem ifNotNil: [owner selectItem: self event: evt]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseUp: (in category 'events') ----- + mouseUp: evt + "Handle a mouse up event. Menu items get activated when the mouse is over them. Do nothing if we're not in a 'valid menu transition', meaning that the current hand focus must be aimed at the owning menu." + + evt hand mouseFocus == owner ifFalse: [ ^self ]. + self contentString ifNotNil: [ + self contents: self contentString withMarkers: true inverse: true. + self refreshWorld. + (Delay forMilliseconds: 200) wait ].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>select: (in category 'selecting') ----- + select: evt + + super select: evt. + subMenu ifNotNil: [ + evt hand newKeyboardFocus: subMenu ]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>wantsKeyboardFocusOnShiftClick (in category 'events') ----- + wantsKeyboardFocusOnShiftClick + "set this preference to false to prevent user editing of docking bar menu items" + ^Preferences valueOfPreference: #allowMenubarItemEditing ifAbsent: [false]! Item was added: + ----- Method: DockingBarUpdatingMenuMorph>>morphicLayerNumber: (in category 'update') ----- + morphicLayerNumber: n + + super morphicLayerNumber: n. + ! Item was changed: ----- Method: MenuMorph>>initialize (in category 'initialization') ----- initialize super initialize. self setDefaultParameters. self changeTableLayout. self listDirection: #topToBottom. self hResizing: #shrinkWrap. self vResizing: #shrinkWrap. + self rubberBandCells: true. self disableLayout: true. self morphicLayerNumber: self class menuLayer. defaultTarget := nil. selectedItem := nil. stayUp := false. popUpOwner := nil.! Item was changed: ----- Method: SystemWindow>>createMenuBox (in category 'initialization') ----- createMenuBox ^ (self createBox: self class menuBoxImage) actionSelector: #offerWindowMenu; + setBalloonText: 'window menu' translated; + actWhen: #buttonDown; + yourself! - setBalloonText: 'window menu' translated! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'right side') ----- browseChanges ChangeSorter open.! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'right side') ----- browseChangesLabel "The project name is the same as the current change set." ^ Project current name! Item was added: + ----- Method: TheWorldMainDockingBar>>changesMenuOn: (in category 'submenu - changes') ----- + changesMenuOn: aDockingBar + + aDockingBar addUpdatingItem: [:item | + item + help: 'Browse this project''s changes' translated; + wordingProvider: self + wordingSelector: #browseChangesLabel; + subMenuUpdater: self + selector: #listChangesOn:].! Item was changed: ----- Method: TheWorldMainDockingBar>>fillDockingBar: (in category 'construction') ----- fillDockingBar: aDockingBar "Private - fill the given docking bar" self menusOn: aDockingBar. aDockingBar addSpacer. + self changesMenuOn: aDockingBar. - self projectNameOn: aDockingBar. aDockingBar addSpacer. self rightSideOn: aDockingBar. aDockingBar setProperty: #mainDockingBarTimeStamp toValue: self class timeStamp.! Item was added: + ----- Method: TheWorldMainDockingBar>>listChangesOn: (in category 'submenu - changes') ----- + listChangesOn: menu + + | latestMethodChanges latestClassChanges| + latestMethodChanges := (Array streamContents: [:s | + ChangeSet current changedMethodsDo: [:method :changeType :dateAndTime :category | + s nextPut: { dateAndTime. method. changeType. category }]]) + sorted: [:a :b | a first >= b first]. + + 1 to: (10 min: latestMethodChanges size) do: [:index | | spec method | + spec := latestMethodChanges at: index. + method := spec second. + menu addItem: [:item | + item + contents: ('{1} {2} \{{3}\} \{{4}\}' format: {method methodClass. method selector. spec fourth. method methodClass category}) ; + target: ToolSet; + balloonText: spec third asString; + icon: ((#(remove addedThenRemoved) includes: spec third) ifTrue: [MenuIcons smallDeleteIcon] ifFalse: [ + spec third = #add ifTrue: [MenuIcons smallNewIcon] ifFalse: [MenuIcons blankIcon]]); + selector: (method isInstalled ifTrue: [#browseMethod:] ifFalse: [#browseMethodVersion:]); + arguments: {method}]]. + + latestClassChanges := (Array streamContents: [:s | + ChangeSet current changedClassesDo: [:class :changeTypes :dateAndTime :category | + "We are not interested in classes whose method's did only change." + changeTypes ifNotEmpty: [s nextPut: { dateAndTime. class. changeTypes. category }]]]) + sorted: [:a :b | a first >= b first]. + + latestClassChanges ifNotEmpty: [menu addLine]. + 1 to: (10 min: latestClassChanges size) do: [:index | | spec class | + spec := latestClassChanges at: index. + class := spec second. + menu addItem: [:item | + item + contents: ('{1} \{{2}\}' format: {class name. spec fourth }) ; + target: ToolSet; + balloonText: (spec third sorted joinSeparatedBy: Character space); + icon: ((spec third includesAnyOf: #(remove addedThenRemoved)) + ifTrue: [MenuIcons smallDeleteIcon] + ifFalse: [ + (spec third includes: #add) + ifTrue: [MenuIcons smallNewIcon] + ifFalse: [MenuIcons blankIcon]]); + selector: ((spec third includes: #remove) ifTrue: [#inspect:] ifFalse: [#browseClass:]); + arguments: {class}]]. + + menu addLine; addItem: [:item | + item + contents: 'Browse current change set...' translated; + target: self; + selector: #browseChanges].! Item was removed: - ----- Method: TheWorldMainDockingBar>>projectNameOn: (in category 'right side') ----- - projectNameOn: aDockingBar - - aDockingBar addUpdatingItem: [:item | - item - help: 'Browse this project''s changes'; - target: self; - selector: #browseChanges; - wordingProvider: self - wordingSelector: #browseChangesLabel].! Item was changed: + (PackageInfo named: 'Morphic') postscript: 'TheWorldMainDockingBar updateInstances.'! - (PackageInfo named: 'Morphic') postscript: 'Transcript showln: ''[NOTICE] There is a new preference called "Interactive print-it". Please check your preference browser to choose the preferred value.'''! From marcel.taeumel at hpi.de Sun Apr 18 17:05:24 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sun, 18 Apr 2021 19:05:24 +0200 Subject: [squeak-dev] The Trunk: Morphic-mt.1755.mcz In-Reply-To: References: Message-ID: Am 18.04.2021 19:01:02 schrieb commits at source.squeak.org : Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1755.mcz ==================== Summary ==================== Name: Morphic-mt.1755 Author: mt Time: 18 April 2021, 7:00:43.878254 pm UUID: e5705780-2988-a54e-b6c7-21b4194fcd5c Ancestors: Morphic-mt.1754, Morphic-ct.1659 Fix our two menu-invocating buttons to act on mouse-down and actually look like menus: (1) menu button in system window and (2) change-set button in world-main-docking-bar. Merges Morphic-ct.1659. Thanks Christoph (ct) for pointing out this issue about menu invocation through buttons. See http://forum.world.st/The-Inbox-Morphic-ct-1659-mcz-tp5116728.html By example, this commit also adds a menu to the change-set button in the docking bar. This menu lists the latest method and class changes. To make this work, the following things got addressed: - Fixes DockingBarUpdatingItemMorph, which missed several changes from DockingBarItemMorph. (Interesting specialization challenge...) - Let menus #rubberBandCells to allow for changing menu item's widths. - Adds query about latest changes to #listChangesOn:. (Feel free to improve this. Maybe add preference for number of elements?) Complements (and depends on) System-mt.1228 and Tools-mt.1042. =============== Diff against Morphic-mt.1754 =============== Item was changed: ----- Method: DockingBarMorph>>addUpdatingItem: (in category 'construction') ----- addUpdatingItem: aBlock | item | item := DockingBarUpdatingItemMorph new. aBlock value: item. + item subMenu ifNotNil: [:menu | + "Docking bar and protruding menu should appear visually merged." + menu morphicLayerNumber: self morphicLayerNumber + 1]. self addMorphBack: item! Item was changed: ----- Method: DockingBarMorph>>ensureSelectedItem: (in category 'events') ----- ensureSelectedItem: evt self selectedItem ifNil: [ self selectItem: ( self submorphs + detect: [ :each | each isMenuItemMorph ] - detect: [ :each | each isKindOf: DockingBarItemMorph ] ifNone: [ ^self ]) event: evt ]! Item was changed: ----- Method: DockingBarMorph>>filterEvent:for: (in category 'events-processing') ----- filterEvent: aKeyboardEvent for: anObject "Provide keyboard shortcuts." | index itemToSelect | aKeyboardEvent controlKeyPressed ifFalse: [^ aKeyboardEvent]. aKeyboardEvent isKeystroke ifFalse: [^ aKeyboardEvent]. "Search field." aKeyboardEvent keyCharacter = $0 ifTrue: [ self searchBarMorph ifNotNil: [ :morph | morph model activate: aKeyboardEvent in: morph ]. ^ aKeyboardEvent ignore "hit!!"]. "Select menu items." (aKeyboardEvent keyValue between: $1 asciiValue and: $9 asciiValue) ifFalse: [^ aKeyboardEvent]. index := aKeyboardEvent keyValue - $1 asciiValue + 1. itemToSelect := (self submorphs select: [ :each | + each isMenuItemMorph ]) - each isKindOf: DockingBarItemMorph ]) at: index ifAbsent: [^ aKeyboardEvent]. self activate: aKeyboardEvent. self selectItem: itemToSelect event: aKeyboardEvent. ^ aKeyboardEvent ignore "hit!!"! Item was changed: ----- Method: DockingBarMorph>>moveSelectionDown:event: (in category 'control') ----- moveSelectionDown: direction event: evt "Move the current selection up or down by one, presumably under keyboard control. direction = +/-1" | index | index := (submorphs indexOf: selectedItem ifAbsent: [1-direction]) + direction. submorphs do: "Ensure finite" [:unused | | m | m := submorphs atWrap: index. + (m isMenuItemMorph and: [m isEnabled]) ifTrue: - ((m isKindOf: DockingBarItemMorph) and: [m isEnabled]) ifTrue: [^ self selectItem: m event: evt]. "Keep looking for an enabled item" index := index + direction sign]. ^ self selectItem: nil event: evt! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>adjacentTo (in category 'selecting') ----- + adjacentTo + + | roundedCornersOffset verticalOffset | + roundedCornersOffset := MenuMorph roundedMenuCorners + ifTrue: [Morph preferredCornerRadius negated] + ifFalse: [0]. + verticalOffset := 2. + + owner isFloating + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToTop + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToLeft + ifTrue: [^ {self bounds topRight + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToBottom + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToRight + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset negated)}]. + ^ {self bounds bottomLeft + (roundedCornersOffset @ 5)}! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createSubmenu (in category 'private') ----- + createSubmenu + + ^DockingBarMenuMorph new! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createUpdatingSubmenu (in category 'private') ----- + createUpdatingSubmenu + + ^DockingBarUpdatingMenuMorph new! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'world') ----- - ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'as yet unclassified') ----- decorateOwner "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawIconOn: (in category 'drawing') ----- + drawIconOn: aCanvas + + | pos | + self hasIcon ifTrue: [ + | iconForm | + iconForm := self iconForm. + + pos := (contents + ifEmpty: [self left + (self width - iconForm width // 2)] + ifNotEmpty: [self left]) + @ (self top + (self height - iconForm height // 2)). + + aCanvas + translucentImage: iconForm + at: pos].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawLabelOn: (in category 'drawing') ----- + drawLabelOn: aCanvas + + | stringBounds | + self contents ifEmpty: [^ self]. + + stringBounds := bounds. + + self hasIcon ifTrue: [ + stringBounds := stringBounds left: stringBounds left + self iconForm width + 2 ]. + + "Vertical centering." + stringBounds := stringBounds top: stringBounds top + stringBounds bottom - self fontToUse height // 2. + "Horizontal centering." + stringBounds := stringBounds left: stringBounds left + (stringBounds width - (self fontToUse widthOfString: contents) // 2) abs. + + aCanvas + drawString: contents + in: stringBounds + font: self fontToUse + color: self colorToUse.! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawSubMenuMarkerOn: (in category 'drawing') ----- + drawSubMenuMarkerOn: aCanvas + "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseDown: (in category 'events') ----- + mouseDown: evt + "Handle a mouse down event. Menu items get activated when the mouse is over them." + + (evt shiftPressed and:[self wantsKeyboardFocusOnShiftClick]) ifTrue: [ ^super mouseDown: evt ]. "enable label editing" + isSelected + ifTrue: [ + owner selectItem: nil event: evt. ] + ifFalse: [ + owner activate: evt. "Redirect to menu for valid transitions" + owner selectItem: self event: evt. ] + ! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'events') ----- - ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'as yet unclassified') ----- mouseEnter: evt "Do not hover docking bar items directory. Mouse-down required. But if you already see a submenu, support hovering." owner selectedItem ifNotNil: [owner selectItem: self event: evt]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseUp: (in category 'events') ----- + mouseUp: evt + "Handle a mouse up event. Menu items get activated when the mouse is over them. Do nothing if we're not in a 'valid menu transition', meaning that the current hand focus must be aimed at the owning menu." + + evt hand mouseFocus == owner ifFalse: [ ^self ]. + self contentString ifNotNil: [ + self contents: self contentString withMarkers: true inverse: true. + self refreshWorld. + (Delay forMilliseconds: 200) wait ].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>select: (in category 'selecting') ----- + select: evt + + super select: evt. + subMenu ifNotNil: [ + evt hand newKeyboardFocus: subMenu ]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>wantsKeyboardFocusOnShiftClick (in category 'events') ----- + wantsKeyboardFocusOnShiftClick + "set this preference to false to prevent user editing of docking bar menu items" + ^Preferences valueOfPreference: #allowMenubarItemEditing ifAbsent: [false]! Item was added: + ----- Method: DockingBarUpdatingMenuMorph>>morphicLayerNumber: (in category 'update') ----- + morphicLayerNumber: n + + super morphicLayerNumber: n. + ! Item was changed: ----- Method: MenuMorph>>initialize (in category 'initialization') ----- initialize super initialize. self setDefaultParameters. self changeTableLayout. self listDirection: #topToBottom. self hResizing: #shrinkWrap. self vResizing: #shrinkWrap. + self rubberBandCells: true. self disableLayout: true. self morphicLayerNumber: self class menuLayer. defaultTarget := nil. selectedItem := nil. stayUp := false. popUpOwner := nil.! Item was changed: ----- Method: SystemWindow>>createMenuBox (in category 'initialization') ----- createMenuBox ^ (self createBox: self class menuBoxImage) actionSelector: #offerWindowMenu; + setBalloonText: 'window menu' translated; + actWhen: #buttonDown; + yourself! - setBalloonText: 'window menu' translated! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'right side') ----- browseChanges ChangeSorter open.! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'right side') ----- browseChangesLabel "The project name is the same as the current change set." ^ Project current name! Item was added: + ----- Method: TheWorldMainDockingBar>>changesMenuOn: (in category 'submenu - changes') ----- + changesMenuOn: aDockingBar + + aDockingBar addUpdatingItem: [:item | + item + help: 'Browse this project''s changes' translated; + wordingProvider: self + wordingSelector: #browseChangesLabel; + subMenuUpdater: self + selector: #listChangesOn:].! Item was changed: ----- Method: TheWorldMainDockingBar>>fillDockingBar: (in category 'construction') ----- fillDockingBar: aDockingBar "Private - fill the given docking bar" self menusOn: aDockingBar. aDockingBar addSpacer. + self changesMenuOn: aDockingBar. - self projectNameOn: aDockingBar. aDockingBar addSpacer. self rightSideOn: aDockingBar. aDockingBar setProperty: #mainDockingBarTimeStamp toValue: self class timeStamp.! Item was added: + ----- Method: TheWorldMainDockingBar>>listChangesOn: (in category 'submenu - changes') ----- + listChangesOn: menu + + | latestMethodChanges latestClassChanges| + latestMethodChanges := (Array streamContents: [:s | + ChangeSet current changedMethodsDo: [:method :changeType :dateAndTime :category | + s nextPut: { dateAndTime. method. changeType. category }]]) + sorted: [:a :b | a first >= b first]. + + 1 to: (10 min: latestMethodChanges size) do: [:index | | spec method | + spec := latestMethodChanges at: index. + method := spec second. + menu addItem: [:item | + item + contents: ('{1} {2} \{{3}\} \{{4}\}' format: {method methodClass. method selector. spec fourth. method methodClass category}) ; + target: ToolSet; + balloonText: spec third asString; + icon: ((#(remove addedThenRemoved) includes: spec third) ifTrue: [MenuIcons smallDeleteIcon] ifFalse: [ + spec third = #add ifTrue: [MenuIcons smallNewIcon] ifFalse: [MenuIcons blankIcon]]); + selector: (method isInstalled ifTrue: [#browseMethod:] ifFalse: [#browseMethodVersion:]); + arguments: {method}]]. + + latestClassChanges := (Array streamContents: [:s | + ChangeSet current changedClassesDo: [:class :changeTypes :dateAndTime :category | + "We are not interested in classes whose method's did only change." + changeTypes ifNotEmpty: [s nextPut: { dateAndTime. class. changeTypes. category }]]]) + sorted: [:a :b | a first >= b first]. + + latestClassChanges ifNotEmpty: [menu addLine]. + 1 to: (10 min: latestClassChanges size) do: [:index | | spec class | + spec := latestClassChanges at: index. + class := spec second. + menu addItem: [:item | + item + contents: ('{1} \{{2}\}' format: {class name. spec fourth }) ; + target: ToolSet; + balloonText: (spec third sorted joinSeparatedBy: Character space); + icon: ((spec third includesAnyOf: #(remove addedThenRemoved)) + ifTrue: [MenuIcons smallDeleteIcon] + ifFalse: [ + (spec third includes: #add) + ifTrue: [MenuIcons smallNewIcon] + ifFalse: [MenuIcons blankIcon]]); + selector: ((spec third includes: #remove) ifTrue: [#inspect:] ifFalse: [#browseClass:]); + arguments: {class}]]. + + menu addLine; addItem: [:item | + item + contents: 'Browse current change set...' translated; + target: self; + selector: #browseChanges].! Item was removed: - ----- Method: TheWorldMainDockingBar>>projectNameOn: (in category 'right side') ----- - projectNameOn: aDockingBar - - aDockingBar addUpdatingItem: [:item | - item - help: 'Browse this project''s changes'; - target: self; - selector: #browseChanges; - wordingProvider: self - wordingSelector: #browseChangesLabel].! Item was changed: + (PackageInfo named: 'Morphic') postscript: 'TheWorldMainDockingBar updateInstances.'! - (PackageInfo named: 'Morphic') postscript: 'Transcript showln: ''[NOTICE] There is a new preference called "Interactive print-it". Please check your preference browser to choose the preferred value.'''! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 160977 bytes Desc: not available URL: From marcel.taeumel at hpi.de Sun Apr 18 17:20:47 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sun, 18 Apr 2021 19:20:47 +0200 Subject: [squeak-dev] playing with syntax alternatives In-Reply-To: References: Message-ID: Hi Francisco, have you checked out Ohm/S yet? https://github.com/hpi-swa/Ohm-S [https://github.com/hpi-swa/Ohm-S] Best, Marcel Am 17.04.2021 11:48:19 schrieb Francisco Garau : Hello -- I want to do some experimentation with alternative syntax for Smalltalk. My main motivation is trying to unify the block and method syntax. I see a block as an in-lined method with an empty selector. This syntax helps to visualize that an object is basically a closure over its instance variables. To make this work, I would also need to make Blocks understand the message #: (which would be equivalent to the current #value:). Some examples will be more clear than I can describe. Currently: succ := [:n | n + 1]. (succ value: 3) = 4. addTo := [:a :b | a + b]. (addTo value: 3 value: 4) = 7. Proposal: [succ: n | n + 1]. (succ :3) = 4.  [add: a to: b | a + b]. (add :3 to : 4) = 7.  Class declaration syntax: [Point << Object | | x y | [hash | ^x hash + y hash]. [extent: aPoint | ^Rectangle origin: self extent: aPoint]. [distance: aPoint | | dx dy | dx := aPoint x - x. dy := aPoint y - y. ^((dx * dx) + (dy * dy)) sqrt].  ]. I am reaching out for ideas or direction on how to do such experiments. I would rather avoid touching the current  compiler. Maybe defining this alternative syntax that compiles to regular Smalltalk. Nowadays PEG parsers are very trendy. Is there one available for any of the Squeak/Smalltalk flavours? Thanks, Francisco -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Sun Apr 18 19:47:55 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sun, 18 Apr 2021 21:47:55 +0200 Subject: [squeak-dev] deprecation policy Message-ID: Hi all, 60Deprecated refers to WindowColorSpec But WindowColorSpec was in 51Deprecated which is no more in the update map. So we must clarify a bit... Deprecated(n) cannot refer to Deprecated(n-1), otherwise we can never remove the deprecated packages... I suggest we move WindoColorSpec from 51Deprecated to 60Deprecated and emit a new version for each of these... Thoughts? Nicolas From marcel.taeumel at hpi.de Mon Apr 19 07:22:06 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 09:22:06 +0200 Subject: [squeak-dev] deprecation policy In-Reply-To: References: Message-ID: Hi Nicolas, nice catch! I messed this up on March 4, 2020 when cleaning up the Etoys stuff: http://forum.world.st/The-Trunk-EToys-mt-382-mcz-td5112849.html [http://forum.world.st/The-Trunk-EToys-mt-382-mcz-td5112849.html] http://forum.world.st/The-Trunk-60Deprecated-mt-69-mcz-td5112851.html [http://forum.world.st/The-Trunk-60Deprecated-mt-69-mcz-td5112851.html] > Deprecated(n) cannot refer to Deprecated(n-1), otherwise we can never > remove the deprecated packages... Exactly. > I suggest we move WindoColorSpec from 51Deprecated to 60Deprecated and > emit a new version for each of these... Agreed. But just in the Trunk repo. Not the older release repos (squeak53, squeak52, squeak51, ...). Best, Marcel Am 18.04.2021 21:48:16 schrieb Nicolas Cellier : Hi all, 60Deprecated refers to WindowColorSpec But WindowColorSpec was in 51Deprecated which is no more in the update map. So we must clarify a bit... Deprecated(n) cannot refer to Deprecated(n-1), otherwise we can never remove the deprecated packages... I suggest we move WindoColorSpec from 51Deprecated to 60Deprecated and emit a new version for each of these... Thoughts? Nicolas -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 19 07:54:44 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 09:54:44 +0200 Subject: [squeak-dev] stepping over non local return in a protected block In-Reply-To: <1618649874366-0.post@n4.nabble.com> References: <1618649874366-0.post@n4.nabble.com> Message-ID: Hmm... at least you get a debugger. In Squeak 5.3, you are not able to put a "self halt" into that event handler in test03EventHandler. ^__^ Yet, I noticed that when stepping over that "^ self dispatchEvent:..." in #dispatchMouseDown:with:, a second debugger appears. That's a bug. The expected behavior would be that the same debugger shows the "halt." I think. Best, Marcel Am 17.04.2021 10:58:06 schrieb Jaromir Matas : Hi Nicolas, Nicolas Cellier wrote > When debugging things like this: > > [^2] ensure: [Transcript cr; show: 'done']. > > if we step into the protected block [^2], then step over ^2, we > incorrectly get a BlockCannotReturn. Hmm, that's the bug that plagued #terminate and caused unwind errors... I didn't fully realize then; I simply avoided it by eliminating the simulation code from #terminate :) This behavior happens when the VM calls #aboutToReturn:through: and the Debugger executes #stepOver it (or over #return:through: or #resume:through:) - sorry if I'm stating the obvious; unfortunately I have negligible knowledge of the Debugger. I'm really looking forward to seeing a solution! Thanks, best, ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 326399 bytes Desc: not available URL: From commits at source.squeak.org Mon Apr 19 08:04:21 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 19 Apr 2021 08:04:21 0000 Subject: [squeak-dev] The Trunk: MorphicTests-mt.79.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-mt.79.mcz ==================== Summary ==================== Name: MorphicTests-mt.79 Author: mt Time: 19 April 2021, 10:04:21.810053 am UUID: 7bae0322-f841-224f-ac06-f4e370992115 Ancestors: MorphicTests-mt.78 Update test03EventHandler to be more realistic. Avoid triggering the mouse-focus-event-disptach path. =============== Diff against MorphicTests-mt.78 =============== Item was changed: ----- Method: MorphicEventTests>>test03EventHandler (in category 'tests') ----- test03EventHandler + "Test a morph's event handler, which is configured via #on:send:to:. Note that the handler only reacts on #mouseDown but we do send a #mouseUp to reset the mouse focus to ensure the same event-dispatching flow for all three mouse buttons." | m | m := Morph new. m extent: 20 at 20; topLeft: 0 at 0. m wantsHaloFromClick: false. m wantsYellowButtonMenu: false. m wantsMetaMenu: false. m on: #mouseDown send: #value: to: [:evt| evt redButtonPressed ifTrue:[m color: Color red]. evt yellowButtonPressed ifTrue:[m color: Color yellow]. evt blueButtonPressed ifTrue:[m color: Color blue]]. m color: Color blue. m openInWorld: world. + self assert: hand mouseFocus isNil. hand handleEvent: (self redMouseDownAt: m center). + hand handleEvent: (self redMouseUpAt: m center). self assert: Color red equals: m color. + self assert: hand mouseFocus isNil. hand handleEvent: (self yellowMouseDownAt: m center). + hand handleEvent: (self yellowMouseUpAt: m center). self assert: Color yellow equals: m color. + + self assert: hand mouseFocus isNil. - hand handleEvent: (self blueMouseDownAt: m center). + hand handleEvent: (self blueMouseUpAt: m center). self assert: Color blue equals: m color.! Item was added: + ----- Method: UserInputEventTests>>blueMouseUpAt: (in category 'support') ----- + blueMouseUpAt: point + + ^ MouseButtonEvent new + setType: #mouseUp + position: point + which: 2r001 "blue changed" + buttons: 2r000 "nothing pressed" + hand: hand + stamp: Time millisecondClockValue! Item was added: + ----- Method: UserInputEventTests>>yellowMouseUpAt: (in category 'support') ----- + yellowMouseUpAt: point + + ^ MouseButtonEvent new + setType: #mouseUp + position: point + which: 2r010 "yellow changed" + buttons: 2r000 "nothing pressed" + hand: hand + stamp: Time millisecondClockValue! From tonyg at leastfixedpoint.com Mon Apr 19 08:36:39 2021 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Mon, 19 Apr 2021 10:36:39 +0200 Subject: [squeak-dev] Shadowing Considered Useful (was Re: Shadows (was: The Trunk: Morphic-eem.1742.mcz)) In-Reply-To: References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> Message-ID: <3fed21b2-4956-d6ee-0fb6-16f6fb90e851@leastfixedpoint.com> Hi all, Slight tangent - I wanted to show a place where I actively want to be able to shadow variables lexically. I am working with an Actor DSL that expands to use of a "well-known" local variable called "thisTurn". Here's an example of the kind of expanded code I want to be able to have: thisTurn spawn: [:thisTurn | "NB. thisTurn here is in a different Actor's context to the thisTurn that had #spawn: sent to it!" thisTurn assert: (Presence new userName: 'me'). thisTurn assert: (Observe new label: #Presence; observer: (thisTurn ref onAsserted: [:thisTurn :p :handle | "Similarly, thisTurn here is the turn active at the time an asserted event matching the given label is processed, not the time that the Observe assertion is made." "..."]; onRetracted: [:thisTurn :handle | "..."]))] The idea is that thisTurn should represent the ambiently-active-and-current Turn at the time each little fragment of code runs. I could use a DynamicVariable, but it seems a bit of a shame to use such a big hammer to (poorly?) simulate what lexical scope gives for free. TL;DR: To this old functional programmer, shadowing within a method isn't an error, but is instead useful. Now that we have had proper lexical closures for quite a few years, could we consider lifting the restriction on shadowing? I'm aware there would likely be social obstacles to doing so; would there also be technical obstacles? Cheers, Tony On 4/18/21 2:44 PM, Marcel Taeumel wrote: > Hi Christoph, hi Eliot, > > it might be that the likelihood of shadowing increases with the use of > cull'ed block invocations, which we have been supporting more and more > in the last years: > > self owner ifNotNil: [:owner | "..."]. > self submorphs ifNotEmpty: [:submorphs | "..."]. > > As alternative names, one could drop their actual "role" and just use > their kinds (as generic as desired): > > self owner ifNotNil: [:morph | "..."]. > self submorphs ifNotEmpty: [:morphs | "..."]. > self submorphs ifNotEmpty: [:objects | "..."]. > > In the past, I happened to mistakenly have used the wrong role, > shadowing the right one: > > self allOwnersDo: [:owner | "..."]. > self allOwnersDo: [:morph | "..."]. > > Yet, we do have misleading protocol on what to actually call "owner." > Just the morph that has me directly in its submorphs? That might be > another topic. :-) > > *** > > To avoid shadowing, I find myself using (a) abbreviations, (b) > kind/class, or (c) count-prefix "a" or "some". Or a combination of > those. Unfortunately, omitting the domain-specific role in a name might > impair readability. > > I just noticed that I am finde with "aMorph" as a method argument, yet I > would never use "a" in a block argument. :-D Strange. > > Best, > Marcel > >> Am 18.04.2021 05:39:33 schrieb Eliot Miranda : >> >> Hi Christoph, >> >> >> > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: >> > >> > Hi Eliot, >> > >> > I fear that changes like this will not be very durable unless tested >> in any >> > way. At the moment, you won't even notice a new shadow unless you have >> > opened a Transcript by accident when accepting a method. Should we maybe >> > show a message window for shadows instead when compiled interactively, >> > analogously to the warnings about superfluous temps? >> >> I’m removing shadows, not adding new ones. In all cars I saw eleven >> ing s from the compiler in the update stream and replaced shadowed >> temp cars by renamed temp vars. So my changes have no semantic effect >> and only remove the warning. >> >> > >> > (In a larger context, I would strongly opt for (finally) introducing a >> > mechanism for linter/compiler annotations in CodeHolders. Most modern >> > editors and IDEs have it, even Pharo; if Squeak does not want to get >> left >> > behind, we should support something like this, too. It could or >> should be >> > configurable, of course.) >> > >> > LBNL, if I understand Chris correctly, "anOwner" might be a >> suboptimal name >> > for a variable that holds Morph instances, right? :) >> > >> > Best, >> > Christoph >> > >> > >> > >> > ----- >> > Carpe Squeak! >> > -- >> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >> > >> > > From marcel.taeumel at hpi.de Mon Apr 19 08:47:08 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 10:47:08 +0200 Subject: [squeak-dev] Shadowing Considered Useful (was Re: Shadows (was: The Trunk: Morphic-eem.1742.mcz)) In-Reply-To: <3fed21b2-4956-d6ee-0fb6-16f6fb90e851@leastfixedpoint.com> References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> <3fed21b2-4956-d6ee-0fb6-16f6fb90e851@leastfixedpoint.com> Message-ID: Hi Tony, thanks for this example. :-) > I could use a DynamicVariable, but it seems a bit of a shame to use such > a big hammer to (poorly?) simulate what lexical scope gives for free. Hmm.... I wonder if that would be actually a "big hammer" or just an indication that you favor larger pieces of code (i.e. long methods) over short ones. In modules composed of many short(-ish) methods, I tend to focus on object messaging and higher-level control flow. There, I do not think about lexical scoping as an important design element. In Vivide, I use DynamicVariable to scope relevant domain objects (i.e. active vivide, active profile, active organization, active script, ...). :-) (I noticed that Newspeak puts a stronger focus on lexical scoping than Squeak/Smalltalk does.) Best, Marcel Am 19.04.2021 10:36:53 schrieb Tony Garnock-Jones : Hi all, Slight tangent - I wanted to show a place where I actively want to be able to shadow variables lexically. I am working with an Actor DSL that expands to use of a "well-known" local variable called "thisTurn". Here's an example of the kind of expanded code I want to be able to have: thisTurn spawn: [:thisTurn | "NB. thisTurn here is in a different Actor's context to the thisTurn that had #spawn: sent to it!" thisTurn assert: (Presence new userName: 'me'). thisTurn assert: (Observe new label: #Presence; observer: (thisTurn ref onAsserted: [:thisTurn :p :handle | "Similarly, thisTurn here is the turn active at the time an asserted event matching the given label is processed, not the time that the Observe assertion is made." "..."]; onRetracted: [:thisTurn :handle | "..."]))] The idea is that thisTurn should represent the ambiently-active-and-current Turn at the time each little fragment of code runs. I could use a DynamicVariable, but it seems a bit of a shame to use such a big hammer to (poorly?) simulate what lexical scope gives for free. TL;DR: To this old functional programmer, shadowing within a method isn't an error, but is instead useful. Now that we have had proper lexical closures for quite a few years, could we consider lifting the restriction on shadowing? I'm aware there would likely be social obstacles to doing so; would there also be technical obstacles? Cheers, Tony On 4/18/21 2:44 PM, Marcel Taeumel wrote: > Hi Christoph, hi Eliot, > > it might be that the likelihood of shadowing increases with the use of > cull'ed block invocations, which we have been supporting more and more > in the last years: > > self owner ifNotNil: [:owner | "..."]. > self submorphs ifNotEmpty: [:submorphs | "..."]. > > As alternative names, one could drop their actual "role" and just use > their kinds (as generic as desired): > > self owner ifNotNil: [:morph | "..."]. > self submorphs ifNotEmpty: [:morphs | "..."]. > self submorphs ifNotEmpty: [:objects | "..."]. > > In the past, I happened to mistakenly have used the wrong role, > shadowing the right one: > > self allOwnersDo: [:owner | "..."]. > self allOwnersDo: [:morph | "..."]. > > Yet, we do have misleading protocol on what to actually call "owner." > Just the morph that has me directly in its submorphs? That might be > another topic. :-) > > *** > > To avoid shadowing, I find myself using (a) abbreviations, (b) > kind/class, or (c) count-prefix "a" or "some". Or a combination of > those. Unfortunately, omitting the domain-specific role in a name might > impair readability. > > I just noticed that I am finde with "aMorph" as a method argument, yet I > would never use "a" in a block argument. :-D Strange. > > Best, > Marcel > >> Am 18.04.2021 05:39:33 schrieb Eliot Miranda : >> >> Hi Christoph, >> >> >> > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: >> > >> > Hi Eliot, >> > >> > I fear that changes like this will not be very durable unless tested >> in any >> > way. At the moment, you won't even notice a new shadow unless you have >> > opened a Transcript by accident when accepting a method. Should we maybe >> > show a message window for shadows instead when compiled interactively, >> > analogously to the warnings about superfluous temps? >> >> I’m removing shadows, not adding new ones. In all cars I saw eleven >> ing s from the compiler in the update stream and replaced shadowed >> temp cars by renamed temp vars. So my changes have no semantic effect >> and only remove the warning. >> >> > >> > (In a larger context, I would strongly opt for (finally) introducing a >> > mechanism for linter/compiler annotations in CodeHolders. Most modern >> > editors and IDEs have it, even Pharo; if Squeak does not want to get >> left >> > behind, we should support something like this, too. It could or >> should be >> > configurable, of course.) >> > >> > LBNL, if I understand Chris correctly, "anOwner" might be a >> suboptimal name >> > for a variable that holds Morph instances, right? :) >> > >> > Best, >> > Christoph >> > >> > >> > >> > ----- >> > Carpe Squeak! >> > -- >> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >> > >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From tonyg at leastfixedpoint.com Mon Apr 19 08:54:21 2021 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Mon, 19 Apr 2021 10:54:21 +0200 Subject: [squeak-dev] Shadowing Considered Useful (was Re: Shadows (was: The Trunk: Morphic-eem.1742.mcz)) In-Reply-To: References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> <3fed21b2-4956-d6ee-0fb6-16f6fb90e851@leastfixedpoint.com> Message-ID: <8c4ee580-2a3a-160e-270d-25a452e1d144@leastfixedpoint.com> On 4/19/21 10:47 AM, Marcel Taeumel wrote: > Hmm.... I wonder if that would be actually a "big hammer" or just an > indication that you favor larger pieces of code (i.e. long methods) over > short ones. In modules composed of many short(-ish) methods, I tend to > focus on object messaging and higher-level control flow. There, I do not > think about lexical scoping as an important design element. Yeah. Note that this code is the output of a code generator that avoids the need for most user-visible explicit references to thisTurn. User code would be shorter and simpler, something like spawn: [ assert: (Presence new userName: 'me'). assert: (Observe new label: #Presence; observer: ( onAsserted: [:p :handle | ...]; onRetracted: [:handle | ...]))] And it's still an open (research) question as to whether Smalltalk is well-suited to this style of programming at all. Overuse of blocks (especially blocks as state, i.e. callbacks!) makes for poor integration with tooling and bad interactions with edits to methods. In a parallel track I'm trying to figure out a way of avoiding blocks and using methods more (that is, trying to find a different way of expressing my DSL that fits better with Smalltalk as-is). I'd still want to hide thisTurn where possible though, just like thisContext is hidden. > In Vivide, I use DynamicVariable to scope relevant domain objects (i.e. > active vivide, active profile, active organization, active script, ...). :-) Ah! Thanks, I'll check that out, see if I can take inspiration from it! Regards, Tony From marcel.taeumel at hpi.de Mon Apr 19 09:32:53 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 11:32:53 +0200 Subject: [squeak-dev] Idioms | How to send messages in Context? Message-ID: Hi all! Take a look at this: When would a context use #send:to:with: and when just directly send it? self send: #cannotReturn: to: self with: {value}. self cannotReturn: value. self send: #cannotReturn:to: to: self with: {value. self}. self cannotReturn: value to: self. There are other examples. See: Context >> #jump:if: Context >> #return:from: Best, Marcel -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 151341 bytes Desc: not available URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 09:57:27 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 09:57:27 +0000 Subject: [squeak-dev] Idioms | How to send messages in Context? In-Reply-To: References: Message-ID: Hi Marcel, #cannotReturn: is put onto the stack of the process being executed/simulated. #send:to:with: is part of the simulation protocol. Analogously, #resume:through: will appear on the executed process stack whereas #return:from: is used by the simulator as stated in the comment. :-) I think these methods are already arranged in two different protocols, which are "controlling" for the execution perspective and "instruction decoding" for the simulation perspective. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 19. April 2021 11:32:53 An: squeak-dev Betreff: [squeak-dev] Idioms | How to send messages in Context? Hi all! Take a look at this: [cid:f1a64b9d-78f4-4480-bacf-75cff8b29d45] When would a context use #send:to:with: and when just directly send it? self send: #cannotReturn: to: self with: {value}. self cannotReturn: value. self send: #cannotReturn:to: to: self with: {value. self}. self cannotReturn: value to: self. There are other examples. See: Context >> #jump:if: Context >> #return:from: Best, Marcel -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 151341 bytes Desc: image.png URL: From marcel.taeumel at hpi.de Mon Apr 19 10:46:44 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 12:46:44 +0200 Subject: [squeak-dev] Idioms | How to send messages in Context? In-Reply-To: References: Message-ID: Hi Christoph, makes sense. Thank you! Best, Marcel Am 19.04.2021 11:57:39 schrieb Thiede, Christoph : Hi Marcel, #cannotReturn: is put onto the stack of the process being executed/simulated. #send:to:with: is part of the simulation protocol. Analogously, #resume:through: will appear on the executed process stack whereas #return:from: is used by the simulator as stated in the comment. :-) I think these methods are already arranged in two different protocols, which are "controlling" for the execution perspective and "instruction decoding" for the simulation perspective. Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 19. April 2021 11:32:53 An: squeak-dev Betreff: [squeak-dev] Idioms | How to send messages in Context?   Hi all! Take a look at this: When would a context use #send:to:with: and when just directly send it? self send: #cannotReturn: to: self with: {value}. self cannotReturn: value. self send: #cannotReturn:to: to: self with: {value. self}. self cannotReturn: value to: self. There are other examples. See: Context >> #jump:if: Context >> #return:from: Best, Marcel -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 151341 bytes Desc: not available URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 10:50:11 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 10:50:11 +0000 Subject: [squeak-dev] stepping over non local return in a protected block In-Reply-To: References: <1618649874366-0.post@n4.nabble.com>, Message-ID: Hi all, thanks for reporting. I think that we see two overlapping effects here: First, #runUntilErrorOrReturnFrom: (which is called eventually by Debugger >> #stepOver) does not support Context >> #aboutToReturn:through: correctly, still. I'd like to refer to this thread again: http://forum.world.st/BUG-REGRESSION-while-debugging-Generator-gt-gt-nextPut-td5108125.html#a5127567 But the fact that the guard contexts are not removed again should not lead to a cannot return situation. Instead, I would rather have expected that the UI process would be terminated. But somehow, the termination in BlockClosure >> #newProcess fails. I observed that primitive 88 in Process >> #suspend fails so the execution continues right from the bottom context of the process. I'm not sure why primitiveSuspend fails here. Might this be related to the changes in termination logic? Jaromir? :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 19. April 2021 09:54:44 An: squeak-dev Betreff: Re: [squeak-dev] stepping over non local return in a protected block Hmm... at least you get a debugger. In Squeak 5.3, you are not able to put a "self halt" into that event handler in test03EventHandler. ^__^ Yet, I noticed that when stepping over that "^ self dispatchEvent:..." in #dispatchMouseDown:with:, a second debugger appears. That's a bug. The expected behavior would be that the same debugger shows the "halt." I think. [cid:a5ced8c3-367c-42c8-ba0d-8b1cf7ba75b8] Best, Marcel Am 17.04.2021 10:58:06 schrieb Jaromir Matas : Hi Nicolas, Nicolas Cellier wrote > When debugging things like this: > > [^2] ensure: [Transcript cr; show: 'done']. > > if we step into the protected block [^2], then step over ^2, we > incorrectly get a BlockCannotReturn. Hmm, that's the bug that plagued #terminate and caused unwind errors... I didn't fully realize then; I simply avoided it by eliminating the simulation code from #terminate :) This behavior happens when the VM calls #aboutToReturn:through: and the Debugger executes #stepOver it (or over #return:through: or #resume:through:) - sorry if I'm stating the obvious; unfortunately I have negligible knowledge of the Debugger. I'm really looking forward to seeing a solution! Thanks, best, ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 326399 bytes Desc: image.png URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 10:57:53 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 10:57:53 +0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1755.mcz In-Reply-To: References: , Message-ID: <36794c9e20014cccbeb4fa6d349c2187@student.hpi.uni-potsdam.de> Hi Marcel, interesting concept, I will try out the usability the next time! Some first thoughts: * I very often used this button to open a change sorter window. (The new menu is not bad, but of course, it only offers a subset of all functionalities of a change sorter). Can we maybe move the "Browse" item to the top of the menu? * Also, we might want to add a link to the DualChangeSorter there. I use that tool very often and I think this would be a way to access it even faster. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Sonntag, 18. April 2021 19:05 Uhr An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Morphic-mt.1755.mcz [cid:94efd291-fc7a-4b8c-af47-720794ff5704] Am 18.04.2021 19:01:02 schrieb commits at source.squeak.org : Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1755.mcz ==================== Summary ==================== Name: Morphic-mt.1755 Author: mt Time: 18 April 2021, 7:00:43.878254 pm UUID: e5705780-2988-a54e-b6c7-21b4194fcd5c Ancestors: Morphic-mt.1754, Morphic-ct.1659 Fix our two menu-invocating buttons to act on mouse-down and actually look like menus: (1) menu button in system window and (2) change-set button in world-main-docking-bar. Merges Morphic-ct.1659. Thanks Christoph (ct) for pointing out this issue about menu invocation through buttons. See http://forum.world.st/The-Inbox-Morphic-ct-1659-mcz-tp5116728.html By example, this commit also adds a menu to the change-set button in the docking bar. This menu lists the latest method and class changes. To make this work, the following things got addressed: - Fixes DockingBarUpdatingItemMorph, which missed several changes from DockingBarItemMorph. (Interesting specialization challenge...) - Let menus #rubberBandCells to allow for changing menu item's widths. - Adds query about latest changes to #listChangesOn:. (Feel free to improve this. Maybe add preference for number of elements?) Complements (and depends on) System-mt.1228 and Tools-mt.1042. =============== Diff against Morphic-mt.1754 =============== Item was changed: ----- Method: DockingBarMorph>>addUpdatingItem: (in category 'construction') ----- addUpdatingItem: aBlock | item | item := DockingBarUpdatingItemMorph new. aBlock value: item. + item subMenu ifNotNil: [:menu | + "Docking bar and protruding menu should appear visually merged." + menu morphicLayerNumber: self morphicLayerNumber + 1]. self addMorphBack: item! Item was changed: ----- Method: DockingBarMorph>>ensureSelectedItem: (in category 'events') ----- ensureSelectedItem: evt self selectedItem ifNil: [ self selectItem: ( self submorphs + detect: [ :each | each isMenuItemMorph ] - detect: [ :each | each isKindOf: DockingBarItemMorph ] ifNone: [ ^self ]) event: evt ]! Item was changed: ----- Method: DockingBarMorph>>filterEvent:for: (in category 'events-processing') ----- filterEvent: aKeyboardEvent for: anObject "Provide keyboard shortcuts." | index itemToSelect | aKeyboardEvent controlKeyPressed ifFalse: [^ aKeyboardEvent]. aKeyboardEvent isKeystroke ifFalse: [^ aKeyboardEvent]. "Search field." aKeyboardEvent keyCharacter = $0 ifTrue: [ self searchBarMorph ifNotNil: [ :morph | morph model activate: aKeyboardEvent in: morph ]. ^ aKeyboardEvent ignore "hit!!"]. "Select menu items." (aKeyboardEvent keyValue between: $1 asciiValue and: $9 asciiValue) ifFalse: [^ aKeyboardEvent]. index := aKeyboardEvent keyValue - $1 asciiValue + 1. itemToSelect := (self submorphs select: [ :each | + each isMenuItemMorph ]) - each isKindOf: DockingBarItemMorph ]) at: index ifAbsent: [^ aKeyboardEvent]. self activate: aKeyboardEvent. self selectItem: itemToSelect event: aKeyboardEvent. ^ aKeyboardEvent ignore "hit!!"! Item was changed: ----- Method: DockingBarMorph>>moveSelectionDown:event: (in category 'control') ----- moveSelectionDown: direction event: evt "Move the current selection up or down by one, presumably under keyboard control. direction = +/-1" | index | index := (submorphs indexOf: selectedItem ifAbsent: [1-direction]) + direction. submorphs do: "Ensure finite" [:unused | | m | m := submorphs atWrap: index. + (m isMenuItemMorph and: [m isEnabled]) ifTrue: - ((m isKindOf: DockingBarItemMorph) and: [m isEnabled]) ifTrue: [^ self selectItem: m event: evt]. "Keep looking for an enabled item" index := index + direction sign]. ^ self selectItem: nil event: evt! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>adjacentTo (in category 'selecting') ----- + adjacentTo + + | roundedCornersOffset verticalOffset | + roundedCornersOffset := MenuMorph roundedMenuCorners + ifTrue: [Morph preferredCornerRadius negated] + ifFalse: [0]. + verticalOffset := 2. + + owner isFloating + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToTop + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToLeft + ifTrue: [^ {self bounds topRight + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToBottom + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToRight + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset negated)}]. + ^ {self bounds bottomLeft + (roundedCornersOffset @ 5)}! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createSubmenu (in category 'private') ----- + createSubmenu + + ^DockingBarMenuMorph new! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createUpdatingSubmenu (in category 'private') ----- + createUpdatingSubmenu + + ^DockingBarUpdatingMenuMorph new! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'world') ----- - ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'as yet unclassified') ----- decorateOwner "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawIconOn: (in category 'drawing') ----- + drawIconOn: aCanvas + + | pos | + self hasIcon ifTrue: [ + | iconForm | + iconForm := self iconForm. + + pos := (contents + ifEmpty: [self left + (self width - iconForm width // 2)] + ifNotEmpty: [self left]) + @ (self top + (self height - iconForm height // 2)). + + aCanvas + translucentImage: iconForm + at: pos].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawLabelOn: (in category 'drawing') ----- + drawLabelOn: aCanvas + + | stringBounds | + self contents ifEmpty: [^ self]. + + stringBounds := bounds. + + self hasIcon ifTrue: [ + stringBounds := stringBounds left: stringBounds left + self iconForm width + 2 ]. + + "Vertical centering." + stringBounds := stringBounds top: stringBounds top + stringBounds bottom - self fontToUse height // 2. + "Horizontal centering." + stringBounds := stringBounds left: stringBounds left + (stringBounds width - (self fontToUse widthOfString: contents) // 2) abs. + + aCanvas + drawString: contents + in: stringBounds + font: self fontToUse + color: self colorToUse.! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawSubMenuMarkerOn: (in category 'drawing') ----- + drawSubMenuMarkerOn: aCanvas + "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseDown: (in category 'events') ----- + mouseDown: evt + "Handle a mouse down event. Menu items get activated when the mouse is over them." + + (evt shiftPressed and:[self wantsKeyboardFocusOnShiftClick]) ifTrue: [ ^super mouseDown: evt ]. "enable label editing" + isSelected + ifTrue: [ + owner selectItem: nil event: evt. ] + ifFalse: [ + owner activate: evt. "Redirect to menu for valid transitions" + owner selectItem: self event: evt. ] + ! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'events') ----- - ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'as yet unclassified') ----- mouseEnter: evt "Do not hover docking bar items directory. Mouse-down required. But if you already see a submenu, support hovering." owner selectedItem ifNotNil: [owner selectItem: self event: evt]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseUp: (in category 'events') ----- + mouseUp: evt + "Handle a mouse up event. Menu items get activated when the mouse is over them. Do nothing if we're not in a 'valid menu transition', meaning that the current hand focus must be aimed at the owning menu." + + evt hand mouseFocus == owner ifFalse: [ ^self ]. + self contentString ifNotNil: [ + self contents: self contentString withMarkers: true inverse: true. + self refreshWorld. + (Delay forMilliseconds: 200) wait ].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>select: (in category 'selecting') ----- + select: evt + + super select: evt. + subMenu ifNotNil: [ + evt hand newKeyboardFocus: subMenu ]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>wantsKeyboardFocusOnShiftClick (in category 'events') ----- + wantsKeyboardFocusOnShiftClick + "set this preference to false to prevent user editing of docking bar menu items" + ^Preferences valueOfPreference: #allowMenubarItemEditing ifAbsent: [false]! Item was added: + ----- Method: DockingBarUpdatingMenuMorph>>morphicLayerNumber: (in category 'update') ----- + morphicLayerNumber: n + + super morphicLayerNumber: n. + ! Item was changed: ----- Method: MenuMorph>>initialize (in category 'initialization') ----- initialize super initialize. self setDefaultParameters. self changeTableLayout. self listDirection: #topToBottom. self hResizing: #shrinkWrap. self vResizing: #shrinkWrap. + self rubberBandCells: true. self disableLayout: true. self morphicLayerNumber: self class menuLayer. defaultTarget := nil. selectedItem := nil. stayUp := false. popUpOwner := nil.! Item was changed: ----- Method: SystemWindow>>createMenuBox (in category 'initialization') ----- createMenuBox ^ (self createBox: self class menuBoxImage) actionSelector: #offerWindowMenu; + setBalloonText: 'window menu' translated; + actWhen: #buttonDown; + yourself! - setBalloonText: 'window menu' translated! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'right side') ----- browseChanges ChangeSorter open.! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'right side') ----- browseChangesLabel "The project name is the same as the current change set." ^ Project current name! Item was added: + ----- Method: TheWorldMainDockingBar>>changesMenuOn: (in category 'submenu - changes') ----- + changesMenuOn: aDockingBar + + aDockingBar addUpdatingItem: [:item | + item + help: 'Browse this project''s changes' translated; + wordingProvider: self + wordingSelector: #browseChangesLabel; + subMenuUpdater: self + selector: #listChangesOn:].! Item was changed: ----- Method: TheWorldMainDockingBar>>fillDockingBar: (in category 'construction') ----- fillDockingBar: aDockingBar "Private - fill the given docking bar" self menusOn: aDockingBar. aDockingBar addSpacer. + self changesMenuOn: aDockingBar. - self projectNameOn: aDockingBar. aDockingBar addSpacer. self rightSideOn: aDockingBar. aDockingBar setProperty: #mainDockingBarTimeStamp toValue: self class timeStamp.! Item was added: + ----- Method: TheWorldMainDockingBar>>listChangesOn: (in category 'submenu - changes') ----- + listChangesOn: menu + + | latestMethodChanges latestClassChanges| + latestMethodChanges := (Array streamContents: [:s | + ChangeSet current changedMethodsDo: [:method :changeType :dateAndTime :category | + s nextPut: { dateAndTime. method. changeType. category }]]) + sorted: [:a :b | a first >= b first]. + + 1 to: (10 min: latestMethodChanges size) do: [:index | | spec method | + spec := latestMethodChanges at: index. + method := spec second. + menu addItem: [:item | + item + contents: ('{1} {2} \{{3}\} \{{4}\}' format: {method methodClass. method selector. spec fourth. method methodClass category}) ; + target: ToolSet; + balloonText: spec third asString; + icon: ((#(remove addedThenRemoved) includes: spec third) ifTrue: [MenuIcons smallDeleteIcon] ifFalse: [ + spec third = #add ifTrue: [MenuIcons smallNewIcon] ifFalse: [MenuIcons blankIcon]]); + selector: (method isInstalled ifTrue: [#browseMethod:] ifFalse: [#browseMethodVersion:]); + arguments: {method}]]. + + latestClassChanges := (Array streamContents: [:s | + ChangeSet current changedClassesDo: [:class :changeTypes :dateAndTime :category | + "We are not interested in classes whose method's did only change." + changeTypes ifNotEmpty: [s nextPut: { dateAndTime. class. changeTypes. category }]]]) + sorted: [:a :b | a first >= b first]. + + latestClassChanges ifNotEmpty: [menu addLine]. + 1 to: (10 min: latestClassChanges size) do: [:index | | spec class | + spec := latestClassChanges at: index. + class := spec second. + menu addItem: [:item | + item + contents: ('{1} \{{2}\}' format: {class name. spec fourth }) ; + target: ToolSet; + balloonText: (spec third sorted joinSeparatedBy: Character space); + icon: ((spec third includesAnyOf: #(remove addedThenRemoved)) + ifTrue: [MenuIcons smallDeleteIcon] + ifFalse: [ + (spec third includes: #add) + ifTrue: [MenuIcons smallNewIcon] + ifFalse: [MenuIcons blankIcon]]); + selector: ((spec third includes: #remove) ifTrue: [#inspect:] ifFalse: [#browseClass:]); + arguments: {class}]]. + + menu addLine; addItem: [:item | + item + contents: 'Browse current change set...' translated; + target: self; + selector: #browseChanges].! Item was removed: - ----- Method: TheWorldMainDockingBar>>projectNameOn: (in category 'right side') ----- - projectNameOn: aDockingBar - - aDockingBar addUpdatingItem: [:item | - item - help: 'Browse this project''s changes'; - target: self; - selector: #browseChanges; - wordingProvider: self - wordingSelector: #browseChangesLabel].! Item was changed: + (PackageInfo named: 'Morphic') postscript: 'TheWorldMainDockingBar updateInstances.'! - (PackageInfo named: 'Morphic') postscript: 'Transcript showln: ''[NOTICE] There is a new preference called "Interactive print-it". Please check your preference browser to choose the preferred value.'''! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 160977 bytes Desc: image.png URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 11:10:54 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 11:10:54 +0000 Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz In-Reply-To: References: Message-ID: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de> Hi Nicolas, the renaming is a breaking change. We should make sure to document such changes in the changelog for the next release. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Freitag, 16. April 2021 22:19:40 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Compiler-nice.457.mcz Nicolas Cellier uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-nice.457.mcz ==================== Summary ==================== Name: Compiler-nice.457 Author: nice Time: 16 April 2021, 10:19:30.223501 pm UUID: e2ce8f47-9ed2-0d46-aca1-1dd90ebed4b4 Ancestors: Compiler-nice.456 Rename resume: source -> retryWithNewSource: source. The purpose of such exception handling is indeed to retry the compilation with new source. The purpose of resume: anObject is to return anObject to the context that sent signal, that's a slightly different semantic. It happens that if we resume after setting newSource, the signaller (Parser>>notify:at:) will effectively then tryNewSourceIfAvailable. So effectively, resuming will end up in retrying (if there is a handler of ReparseAfterSourceEditing up the sender stack, but the Parser normally puts one). But, even if this is HOW we implement the #retryWithNewSource:, this is not WHAT we wish to ask to the SyntaxErrorNotification. in other words, we shouldn't let the implementation leak in the semantics, otherwise we put the burden of understanding the implementation on the shoulders of programmers, when they could just have trusted the semantics of pseudo natural language offered by keywords. While at it, remove the accessors of newSource. They are not used and may be considered private. This will reduce the unecessary polymorphism. =============== Diff against Compiler-nice.456 =============== Item was removed: - ----- Method: SyntaxErrorNotification>>newSource (in category 'accessing') ----- - newSource - ^newSource! Item was removed: - ----- Method: SyntaxErrorNotification>>newSource: (in category 'accessing') ----- - newSource: aTextOrString - newSource := aTextOrString! Item was removed: - ----- Method: SyntaxErrorNotification>>resume: (in category 'accessing') ----- - resume: source - - self reparse: source notifying: nil ifFail: nil. - ^ super resume: self defaultResumeValue! Item was added: + ----- Method: SyntaxErrorNotification>>retryWithNewSource: (in category 'handling') ----- + retryWithNewSource: source + "Retry the compilation with new source code. + Assume + - that the signallerContext will tryNewSourceIfAvailable + - the presence of a handler of ReparseAfterSourceEditing on the sender stack" + + newSource := source. + ^ self resume! -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 11:21:44 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 11:21:44 +0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> , Message-ID: <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> Hi Marcel, I still stumble upon this edge case for some print-it results that do not support click-to-inspect. Why do we need this exception? :-) > > Also consider this snippet where the print-link does not exist for an MCVersionName > > Looks fine. I don't think it looks fine, why do you think so? :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Freitag, 16. April 2021 19:52:16 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz Hi Christoph, I think that this clickable link is a compromise between printString and storeString. For mouse navigation, you can always choose "inspect it" from the context menu on that text selection. ;-) I also found the link color annyoing for simple literals. > Also consider this snippet where the print-link does not exist for an MCVersionName Looks fine. ^__^ I am certain that we will collect more feedback on this feature during the next weeks and months. Let's refine it then. Best, Marcel Am 16.04.2021 18:39:10 schrieb Thiede, Christoph : Hi Marcel, it's great that you have found a solution to this idea! :-) > + ^ (self class interactivePrintIt and: [(anObject isString or: [anObject isNumber]) not]) Is this necessary? I know that an inspector for a literal object like these does not make great sense, but this just feels like an unnecessary heuristic and limitation for me and adds complexity. I would like to be able to open an inspector always. Also consider this snippet where the print-link does not exist for an MCVersionName: :-) MCRepository inbox allFileNames first > CI scripts will default to "true". Unfortunately, no, mine just timed out while preparing the image. Also, my server images for @SqueakSmalltalkBot were interrupted. I'd opt for keeping preamble/postscript content in the update stream strictly non-interactive. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Freitag, 16. April 2021 17:27:54 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz Hi all! It is now in Trunk. You can opt-out via the preference browser. Still, you will be asked the first time when you update your image. CI scripts will default to "true". Best, Marcel Am 17.11.2019 17:36:11 schrieb Jakob Reschke : Thiede, Christoph > schrieb am Fr., 15. Nov. 2019, 09:38: Just another idea (I seem to have too many of them :D): Some kind of UnderlyingObjectAttribute (with a better name, of course) an editor can check the selection before compiling it when inspectIt/exploreIt is pressed? Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor checks for UnderylingObjectAttribute -> none found, so the string is compilaed as usual. Example 2: (Text string: '2 + 3' attributes: (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> Editor finds an UnderylingObjectAttribute -> instead of compiling the selection, the cached result is reused for the inspector. We would not even need to display this Attribute visually if it works reliably. Make sure it is transient in some way because it would be quite annoying if the hidden object were out of date with regards to the text. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 11:32:19 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 11:32:19 +0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz In-Reply-To: References: <1618578607101-0.post@n4.nabble.com> <1618578968761-0.post@n4.nabble.com> , Message-ID: Hi Nicolas, in general, I use to submit one inbox version per proposal/fix/change. They all branch from the main Trunk line so I consider each of them something that you would call a Pull Request in the GitHub world. This also means that no inbox proposal is to be considered deprecated only because I upload a newer version. When I indeed intend to replace the former version, I usually add a notice "replaces version Package-ct.xxx" to the message of the new version. :-) I think our special problem in this case was that it is not a straightforward task to merge multiple changes of a single method with our tooling. I see the problem with annoying warnings, which is why I proposed to create a new subclass for these warnings! Then we could easily ignore these warnings when they are raised inside of the debugger. For other use cases such as automated tests or SimulationStudio, however, we would still see them. > I saw later that you removed from newProcess... SHould we? I think we should. Either a simulator client is interested to be informed about attempts of the code to escape from simulation, or it isn't. In every case, creating a process is an absolutely boring event with regard to that interest, but all actions such as resuming, terminating, or signaling a process could be of interest. > Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. I'll put that onto my list, but I've myself lost track of the changes regarding primitive 186 et al. I'm not the author of these changes ... Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Freitag, 16. April 2021 19:34:20 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Kernel-nice.1386.mcz Hi Christoph, Hmm, there must have been some confusion on my side. I've tried to carefully review the remaining contributions in the inbox. To my understanding Kernel-ct.1383 fixes more simulation cases than Kernel-ct.1382. Since - the tests simulating primitives 83, 84 & 100 were failing, - and that a more recent inbox contribution was trying to fix that, I thought that merging this contribution was a good idea. It apparently was fixing two tests out of three after trial. Also, to my experience, generating a warning when we simulate primitiveIndex >= 85 and: [primitiveIndex <= 88] "control primitives"]) is super annoying! It always happens when running some kernel tests and forces me to switch warning off altogether. But switching warning off is not a good solution (and it makes some more tests fail !). Kernel-ct.1383 being more recent, I thought that the removal of warnings was intentional... I saw later that you removed from newProcess... SHould we? My understanding now is that you need this warning in some specific context. Is that it? We can't fix one usage by breaking another. We have to find a solution that fits both purposes. Le ven. 16 avr. 2021 à 15:40, Marcel Taeumel a écrit : > > Hi Christoph, > > the commit message in Kernel-nice.1386 reads: "[...] Note that Kernel-ct.1383 supersedes Kernel-ct.1382 and removes the annoying warning. [...]" > > I think the problem was that both ct.1382 and ct.1382 change the same method but do not actually consider each other. With our current tools, sub-method merging is rather tricky and hence the author should take care that this does not happen. :-) > > Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. > > Best, > Marcel > > Am 16.04.2021 15:16:18 schrieb Christoph Thiede : > > PS: I also see that you touched the simulation of criticalSection primitives > (primitiveIndex = 186 ...) again. Again, was this intended or an incident? > :-) > > (OT: We are really treading on each other's toes in this method ... What can > we learn from this? Is it too large and should be split up? Or should we > improve our tooling support for resolving merge conflicts?) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Mon Apr 19 12:29:34 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 19 Apr 2021 14:29:34 +0200 Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz In-Reply-To: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de> References: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, given that resume: was a recent addition, i don't think that we must care too much. https://source.squeak.org/trunk/Compiler-ct.405.diff Maybe we released Squeak 5.3 since? In this case, it MUST at least be in the release notes indeed. Le lun. 19 avr. 2021 à 13:11, Thiede, Christoph a écrit : > > Hi Nicolas, > > > the renaming is a breaking change. We should make sure to document such changes in the changelog for the next release. > > > Best, > Christoph > ________________________________ > Von: Squeak-dev im Auftrag von commits at source.squeak.org > Gesendet: Freitag, 16. April 2021 22:19:40 > An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org > Betreff: [squeak-dev] The Trunk: Compiler-nice.457.mcz > > Nicolas Cellier uploaded a new version of Compiler to project The Trunk: > http://source.squeak.org/trunk/Compiler-nice.457.mcz > > ==================== Summary ==================== > > Name: Compiler-nice.457 > Author: nice > Time: 16 April 2021, 10:19:30.223501 pm > UUID: e2ce8f47-9ed2-0d46-aca1-1dd90ebed4b4 > Ancestors: Compiler-nice.456 > > Rename resume: source -> retryWithNewSource: source. > > The purpose of such exception handling is indeed to retry the compilation with new source. > > The purpose of resume: anObject is to return anObject to the context that sent signal, that's a slightly different semantic. > > It happens that if we resume after setting newSource, the signaller (Parser>>notify:at:) will effectively then tryNewSourceIfAvailable. > So effectively, resuming will end up in retrying (if there is a handler of ReparseAfterSourceEditing up the sender stack, but the Parser normally puts one). > > But, even if this is HOW we implement the #retryWithNewSource:, > this is not WHAT we wish to ask to the SyntaxErrorNotification. > in other words, we shouldn't let the implementation leak in the semantics, otherwise we put the burden of understanding the implementation on the shoulders of programmers, when they could just have trusted the semantics of pseudo natural language offered by keywords. > > While at it, remove the accessors of newSource. > They are not used and may be considered private. > This will reduce the unecessary polymorphism. > > =============== Diff against Compiler-nice.456 =============== > > Item was removed: > - ----- Method: SyntaxErrorNotification>>newSource (in category 'accessing') ----- > - newSource > - ^newSource! > > Item was removed: > - ----- Method: SyntaxErrorNotification>>newSource: (in category 'accessing') ----- > - newSource: aTextOrString > - newSource := aTextOrString! > > Item was removed: > - ----- Method: SyntaxErrorNotification>>resume: (in category 'accessing') ----- > - resume: source > - > - self reparse: source notifying: nil ifFail: nil. > - ^ super resume: self defaultResumeValue! > > Item was added: > + ----- Method: SyntaxErrorNotification>>retryWithNewSource: (in category 'handling') ----- > + retryWithNewSource: source > + "Retry the compilation with new source code. > + Assume > + - that the signallerContext will tryNewSourceIfAvailable > + - the presence of a handler of ReparseAfterSourceEditing on the sender stack" > + > + newSource := source. > + ^ self resume! > > > From m at jaromir.net Mon Apr 19 13:08:55 2021 From: m at jaromir.net (Jaromir Matas) Date: Mon, 19 Apr 2021 08:08:55 -0500 (CDT) Subject: [squeak-dev] stepping over non local return in a protected block In-Reply-To: References: <1618649874366-0.post@n4.nabble.com> Message-ID: <1618837735369-0.post@n4.nabble.com> Hi Christoph, Christoph Thiede wrote > But the fact that the guard contexts are not removed again should not lead > to a cannot return situation. Instead, I would rather have expected that > the UI process would be terminated. But somehow, the termination in > BlockClosure >> #newProcess fails. I observed that primitive 88 in Process > >> #suspend fails so the execution continues right from the bottom context > of the process. I'm not sure why primitiveSuspend fails here. Might this > be related to the changes in termination logic? Jaromir? :-) In my opinion the problem is that when the Debugger invokes #stepOver over a non-local return, it invokes #evaluate:onBehalfOf: down the chain of sends to execute the non-local return and that's where the problem lies: #evaluate:onBehalfOf: incorrectly executes the non-local return on the wrong stack - the debugger process uses its own stack to have #evaluate:onBehalfOf: executed the non-local return ([^2]) which fails to find its home context which is indeed on a different stack (original process's stack). The cannot return is just a consequence of the failure to find the home context... At least this is my working hypothesis :) Compared to #evaluate:onBehalfOf:, the #runUntilErrorOrReturnFrom: method itself jumps right into the debugged process's stack - which results in flawless execution of the non-local return! It finds it's home context and jumps into it and continues execution. I, however, haven't explored the behavior of the combination of #evaluate:onBehalfOf: and #runUntilErrorOrReturnFrom: :o As I said my Debugger knowledge is still negligible, unfortunately. Prior to your change from active to genuine process the `[^2] ensure: []` example caused the infinite debugger loop... after that it only causes the cannot return error. So I guess it's unlikely the change in #terminate somehow affected the bug's behavior; the bug was there before and behaves similarly. The change in #teminate only eliminated the use #evaluate:onBehalfOf: in the termination procedure... I'm looking at it from a different angle now, I'll keep you posted... Thanks, best, ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 13:09:34 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 13:09:34 +0000 Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz In-Reply-To: References: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de>, Message-ID: Hi Nicolas, Squeak 5.3 has Compiler-eem.416 and "resume: source". So this is worth a mention in the release note. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Montag, 19. April 2021 14:29:34 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Compiler-nice.457.mcz Hi Christoph, given that resume: was a recent addition, i don't think that we must care too much. https://source.squeak.org/trunk/Compiler-ct.405.diff Maybe we released Squeak 5.3 since? In this case, it MUST at least be in the release notes indeed. Le lun. 19 avr. 2021 à 13:11, Thiede, Christoph a écrit : > > Hi Nicolas, > > > the renaming is a breaking change. We should make sure to document such changes in the changelog for the next release. > > > Best, > Christoph > ________________________________ > Von: Squeak-dev im Auftrag von commits at source.squeak.org > Gesendet: Freitag, 16. April 2021 22:19:40 > An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org > Betreff: [squeak-dev] The Trunk: Compiler-nice.457.mcz > > Nicolas Cellier uploaded a new version of Compiler to project The Trunk: > http://source.squeak.org/trunk/Compiler-nice.457.mcz > > ==================== Summary ==================== > > Name: Compiler-nice.457 > Author: nice > Time: 16 April 2021, 10:19:30.223501 pm > UUID: e2ce8f47-9ed2-0d46-aca1-1dd90ebed4b4 > Ancestors: Compiler-nice.456 > > Rename resume: source -> retryWithNewSource: source. > > The purpose of such exception handling is indeed to retry the compilation with new source. > > The purpose of resume: anObject is to return anObject to the context that sent signal, that's a slightly different semantic. > > It happens that if we resume after setting newSource, the signaller (Parser>>notify:at:) will effectively then tryNewSourceIfAvailable. > So effectively, resuming will end up in retrying (if there is a handler of ReparseAfterSourceEditing up the sender stack, but the Parser normally puts one). > > But, even if this is HOW we implement the #retryWithNewSource:, > this is not WHAT we wish to ask to the SyntaxErrorNotification. > in other words, we shouldn't let the implementation leak in the semantics, otherwise we put the burden of understanding the implementation on the shoulders of programmers, when they could just have trusted the semantics of pseudo natural language offered by keywords. > > While at it, remove the accessors of newSource. > They are not used and may be considered private. > This will reduce the unecessary polymorphism. > > =============== Diff against Compiler-nice.456 =============== > > Item was removed: > - ----- Method: SyntaxErrorNotification>>newSource (in category 'accessing') ----- > - newSource > - ^newSource! > > Item was removed: > - ----- Method: SyntaxErrorNotification>>newSource: (in category 'accessing') ----- > - newSource: aTextOrString > - newSource := aTextOrString! > > Item was removed: > - ----- Method: SyntaxErrorNotification>>resume: (in category 'accessing') ----- > - resume: source > - > - self reparse: source notifying: nil ifFail: nil. > - ^ super resume: self defaultResumeValue! > > Item was added: > + ----- Method: SyntaxErrorNotification>>retryWithNewSource: (in category 'handling') ----- > + retryWithNewSource: source > + "Retry the compilation with new source code. > + Assume > + - that the signallerContext will tryNewSourceIfAvailable > + - the presence of a handler of ReparseAfterSourceEditing on the sender stack" > + > + newSource := source. > + ^ self resume! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Mon Apr 19 14:04:28 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 19 Apr 2021 16:04:28 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz In-Reply-To: References: <1618578607101-0.post@n4.nabble.com> <1618578968761-0.post@n4.nabble.com> Message-ID: Hi Christoph, Le lun. 19 avr. 2021 à 13:32, Thiede, Christoph a écrit : > > Hi Nicolas, > > > in general, I use to submit one inbox version per proposal/fix/change. They all branch from the main Trunk line so I consider each of them something that you would call a Pull Request in the GitHub world. This also means that no inbox proposal is to be considered deprecated only because I upload a newer version. When I indeed intend to replace the former version, I usually add a notice "replaces version Package-ct.xxx" to the message of the new version. :-) > > I think our special problem in this case was that it is not a straightforward task to merge multiple changes of a single method with our tooling. > Yes, changing several times the same method is necessarily a conflict for our tools. IMO it's a good thing, because it will require human attention for resolution. Merging based on line editions is not the right solution IMO. If both editions modify the temps, they will conflict anyway. Even if methods are atomic pieces, two modifications of the same method are not necessarily exclusive. It happens that we updated a comment in one branch, or renamed a message, inst var or class in the other, etc... But here, I failed to identify this situation. I might have been biased by the desire to see the warnings go ;) > > I see the problem with annoying warnings, which is why I proposed to create a new subclass for these warnings! Then we could easily ignore these warnings when they are raised inside of the debugger. For other use cases such as automated tests or SimulationStudio, however, we would still see them. > Yes, this could work. I also wondered if we could disable warnings at specific send sites on user request (instead of disabling all the Warnings). A good way to exercise new super powers for the Sorcerer's Apprentices ;) > > > I saw later that you removed from newProcess... SHould we? > > > I think we should. Either a simulator client is interested to be informed about attempts of the code to escape from simulation, or it isn't. In every case, creating a process is an absolutely boring event with regard to that interest, but all actions such as resuming, terminating, or signaling a process could be of interest. > > > Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. > > I'll put that onto my list, but I've myself lost track of the changes regarding primitive 186 et al. I'm not the author of these changes ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Nicolas Cellier > Gesendet: Freitag, 16. April 2021 19:34:20 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Trunk: Kernel-nice.1386.mcz > > Hi Christoph, > Hmm, there must have been some confusion on my side. > I've tried to carefully review the remaining contributions in the inbox. > To my understanding Kernel-ct.1383 fixes more simulation cases than > Kernel-ct.1382. > Since > - the tests simulating primitives 83, 84 & 100 were failing, > - and that a more recent inbox contribution was trying to fix that, > I thought that merging this contribution was a good idea. > It apparently was fixing two tests out of three after trial. > > Also, to my experience, generating a warning when we simulate > primitiveIndex >= 85 and: [primitiveIndex <= 88] "control primitives"]) > is super annoying! It always happens when running some kernel tests > and forces me to switch warning off altogether. > But switching warning off is not a good solution (and it makes some > more tests fail !). > Kernel-ct.1383 being more recent, I thought that the removal of > warnings was intentional... > > I saw later that you removed from newProcess... SHould we? > > My understanding now is that you need this warning in some specific > context. Is that it? > We can't fix one usage by breaking another. We have to find a solution > that fits both purposes. > > Le ven. 16 avr. 2021 à 15:40, Marcel Taeumel a écrit : > > > > Hi Christoph, > > > > the commit message in Kernel-nice.1386 reads: "[...] Note that Kernel-ct.1383 supersedes Kernel-ct.1382 and removes the annoying warning. [...]" > > > > I think the problem was that both ct.1382 and ct.1382 change the same method but do not actually consider each other. With our current tools, sub-method merging is rather tricky and hence the author should take care that this does not happen. :-) > > > > Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. > > > > Best, > > Marcel > > > > Am 16.04.2021 15:16:18 schrieb Christoph Thiede : > > > > PS: I also see that you touched the simulation of criticalSection primitives > > (primitiveIndex = 186 ...) again. Again, was this intended or an incident? > > :-) > > > > (OT: We are really treading on each other's toes in this method ... What can > > we learn from this? Is it too large and should be split up? Or should we > > improve our tooling support for resolving merge conflicts?) > > > > Best, > > Christoph > > > > > > > > ----- > > Carpe Squeak! > > -- > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > > > > > From commits at source.squeak.org Mon Apr 19 14:25:10 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 19 Apr 2021 14:25:10 0000 Subject: [squeak-dev] The Trunk: System-mt.1229.mcz Message-ID: Marcel Taeumel uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-mt.1229.mcz ==================== Summary ==================== Name: System-mt.1229 Author: mt Time: 19 April 2021, 4:25:07.545053 pm UUID: e30af833-38ea-524f-b023-4657894a7d92 Ancestors: System-mt.1228 Fixes #changeStampPerSe and use it to remove interruptions from the update stream (again). =============== Diff against System-mt.1228 =============== Item was changed: ----- Method: ChangeSet>>event: (in category 'change logging') ----- event: anEvent "Hook for SystemChangeNotifier" anEvent itemKind = SystemChangeNotifier classKind ifTrue: [ anEvent isRemoved ifTrue: [self noteRemovalOf: anEvent item]. anEvent isAdded ifTrue: [self addClass: anEvent item]. anEvent isModified ifTrue: [anEvent anyChanges ifTrue: [self changeClass: anEvent item from: anEvent oldItem]]. anEvent isCommented ifTrue: [self commentClass: anEvent item]. anEvent isRenamed ifTrue: [self renameClass: anEvent item from: anEvent oldName to: anEvent newName]. anEvent isReorganized ifTrue: [self reorganizeClass: anEvent item]. anEvent isRecategorized ifTrue: [self changeClass: anEvent item from: anEvent item]. ]. anEvent itemKind = SystemChangeNotifier methodKind ifTrue: [ anEvent isAdded ifTrue: [self noteNewMethod: anEvent item forClass: anEvent itemClass selector: anEvent itemSelector priorMethod: nil]. anEvent isModified ifTrue: [self noteNewMethod: anEvent item forClass: anEvent itemClass selector: anEvent itemSelector priorMethod: anEvent oldItem]. anEvent isRemoved + ifTrue: [self removeSelector: anEvent itemSelector class: anEvent itemClass priorMethod: anEvent item lastMethodInfo: {anEvent item sourcePointer. anEvent itemProtocol. Utilities changeStampPerSe}]. - ifTrue: [self removeSelector: anEvent itemSelector class: anEvent itemClass priorMethod: anEvent item lastMethodInfo: {anEvent item sourcePointer. anEvent itemProtocol. Utilities changeStamp}]. anEvent isRecategorized ifTrue: [self reorganizeClass: anEvent itemClass]. ].! Item was changed: ----- Method: ClassChangeRecord>>noteChangeType:fromClass: (in category 'all changes') ----- noteChangeType: changeSymbol fromClass: class + timeStamp := Utilities changeStampPerSe. - timeStamp := Utilities changeStamp. (changeSymbol = #new or: [changeSymbol = #add]) ifTrue: [changeTypes add: #add. changeTypes remove: #change ifAbsent: []. revertable := false. ^ self]. changeSymbol = #change ifTrue: [(changeTypes includes: #add) ifTrue: [^ self]. ^ changeTypes add: changeSymbol]. changeSymbol == #addedThenRemoved ifTrue: [^ self]. "An entire class was added but then removed" changeSymbol = #comment ifTrue: [^ changeTypes add: changeSymbol]. changeSymbol = #reorganize ifTrue: [^ changeTypes add: changeSymbol]. changeSymbol = #rename ifTrue: [^ changeTypes add: changeSymbol]. (changeSymbol beginsWith: 'oldName: ') ifTrue: ["Must only be used when assimilating other changeSets" (changeTypes includes: #add) ifTrue: [^ self]. priorName := changeSymbol copyFrom: 'oldName: ' size + 1 to: changeSymbol size. ^ changeTypes add: #rename]. changeSymbol = #remove ifTrue: [(changeTypes includes: #add) ifTrue: [changeTypes add: #addedThenRemoved] ifFalse: [changeTypes add: #remove]. ^ changeTypes removeAllFoundIn: #(add change comment reorganize)]. self error: 'Unrecognized changeType'! Item was changed: ----- Method: Utilities class>>changeStampPerSe (in category 'identification') ----- changeStampPerSe "Answer a string to be pasted into source code to mark who changed it and when." ^String streamContents: [ : stream | + stream nextPutAll: (self authorInitialsPerSe isEmptyOrNil - self authorInitialsPerSe isEmptyOrNil ifTrue: [ '�' ] + ifFalse: [ self authorInitialsPerSe ]). - ifFalse: [ self authorInitialsPerSe ]. stream space ; nextPutAll: Date today mmddyyyy ; space. + stream nextPutAll: ((String streamContents: - (String streamContents: [ : s | Time now print24: true on: s ]) copyFrom: 1 + to: 5) ]! - to: 5 ]! From nicolas.cellier.aka.nice at gmail.com Mon Apr 19 14:29:04 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 19 Apr 2021 16:29:04 +0200 Subject: [squeak-dev] status of inbox Kernel-ct.1363 In-Reply-To: References: Message-ID: I see only a minor problem with this version: it breaks testRunSimulatedContextAtEachStep. This test did profit by polymorphism of asContext to use a Context instead of a Block(Closure). But Context does no understand asContextWithSender: Maybe more a problem of the test itself than of the proposed change. Le jeu. 15 avr. 2021 à 11:52, Nicolas Cellier a écrit : > > I mean authorship... > > Le jeu. 15 avr. 2021 à 11:50, Nicolas Cellier a écrit : >> >> With the merge commit that would make 3 commits for a single method. My plan is to cherry pick the change on top of trunk with proper comment. With our tools, ownership is preserved anyway :) >> >> Le jeu. 15 avr. 2021 à 11:05, Marcel Taeumel a écrit : >>> >>> Hi Nicolas, >>> >>> ct.1363 depends on ct.1362, the latter being easier to review. Maybe Christoph (ct) can point us to the "request" he mentioned in the message in 1363. Yet, it looks like Eliot (indirectly) approved this already: http://forum.world.st/The-Inbox-Kernel-ct-1362-mcz-tp5124354.html ..? Or at least he planned to look at this. >>> >>> (Let's hope that the words "branch commit" do not hide more dependencies. Not sure what it means here.) >>> >>> Best, >>> Marcel >>> >>> Am 15.04.2021 10:48:09 schrieb Nicolas Cellier : >>> >>> Hi all, >>> again a good and difficult to analyze contribution. >>> We mostly send runSimulated:contextAtEachStep: to thisContext, except >>> in one case in base image: >>> >>> MessageTally tallySends: [3.14159 printString] >>> >>> This is effectively broken in trunk, and repaired after applying Kernel-ct.1363. >>> Before I merge this, additional advice is welcome, this is a tough >>> subject, breaking the Debugger would be the last thing we want to do. >>> >>> From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 14:54:22 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 14:54:22 +0000 Subject: [squeak-dev] status of inbox Kernel-ct.1363 In-Reply-To: References: , Message-ID: <7905ceab27c94e079b6c147ae2e035fd@student.hpi.uni-potsdam.de> Hi all, sorry for the late reply, this must somehow have escaped my attention. Yes, Kernel-ct.1363 depends on Kernel-ct.1362 and (hopefully?) improves the understandability of the method. Eliot has requested this in the thread of Kernel-ct.1362. > it breaks testRunSimulatedContextAtEachStep. True. Blocks should indeed be supported I think. Then we need indeed "current := aBlock asContext. current privSender: self." instead of #asContextWithSender:. Shall add a third version to do this or does the merger want to do this? :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Montag, 19. April 2021 16:29:04 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] status of inbox Kernel-ct.1363 I see only a minor problem with this version: it breaks testRunSimulatedContextAtEachStep. This test did profit by polymorphism of asContext to use a Context instead of a Block(Closure). But Context does no understand asContextWithSender: Maybe more a problem of the test itself than of the proposed change. Le jeu. 15 avr. 2021 à 11:52, Nicolas Cellier a écrit : > > I mean authorship... > > Le jeu. 15 avr. 2021 à 11:50, Nicolas Cellier a écrit : >> >> With the merge commit that would make 3 commits for a single method. My plan is to cherry pick the change on top of trunk with proper comment. With our tools, ownership is preserved anyway :) >> >> Le jeu. 15 avr. 2021 à 11:05, Marcel Taeumel a écrit : >>> >>> Hi Nicolas, >>> >>> ct.1363 depends on ct.1362, the latter being easier to review. Maybe Christoph (ct) can point us to the "request" he mentioned in the message in 1363. Yet, it looks like Eliot (indirectly) approved this already: http://forum.world.st/The-Inbox-Kernel-ct-1362-mcz-tp5124354.html ..? Or at least he planned to look at this. >>> >>> (Let's hope that the words "branch commit" do not hide more dependencies. Not sure what it means here.) >>> >>> Best, >>> Marcel >>> >>> Am 15.04.2021 10:48:09 schrieb Nicolas Cellier : >>> >>> Hi all, >>> again a good and difficult to analyze contribution. >>> We mostly send runSimulated:contextAtEachStep: to thisContext, except >>> in one case in base image: >>> >>> MessageTally tallySends: [3.14159 printString] >>> >>> This is effectively broken in trunk, and repaired after applying Kernel-ct.1363. >>> Before I merge this, additional advice is welcome, this is a tough >>> subject, breaking the Debugger would be the last thing we want to do. >>> >>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From m at jaromir.net Mon Apr 19 14:58:32 2021 From: m at jaromir.net (Jaromir Matas) Date: Mon, 19 Apr 2021 09:58:32 -0500 (CDT) Subject: [squeak-dev] status of inbox Kernel-ct.1363 In-Reply-To: References: Message-ID: <1618844312411-0.post@n4.nabble.com> Nicolas Cellier wrote > I see only a minor problem with this version: > > it breaks testRunSimulatedContextAtEachStep. > This test did profit by polymorphism of asContext to use a Context > instead of a Block(Closure). > But Context does no understand asContextWithSender: Hi, how about adding Context >> asContextWithSender: aContext ^self privSender: aContext It would complement the `Context >> asContext` nicely :) ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From marcel.taeumel at hpi.de Mon Apr 19 14:58:44 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 16:58:44 +0200 Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz In-Reply-To: References: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de> <,> Message-ID: > So this is worth a mention in the release note. Done. https://github.com/squeak-smalltalk/squeak-app/blob/squeak-trunk/release-notes/6.0 [https://github.com/squeak-smalltalk/squeak-app/blob/squeak-trunk/release-notes/6.0] Best, Marcel Am 19.04.2021 15:09:43 schrieb Thiede, Christoph : Hi Nicolas, Squeak 5.3 has Compiler-eem.416 and "resume: source". So this is worth a mention in the release note. Best, Christoph Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Montag, 19. April 2021 14:29:34 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Compiler-nice.457.mcz   Hi Christoph, given that resume: was a recent addition, i don't think that we must care too much. https://source.squeak.org/trunk/Compiler-ct.405.diff [https://source.squeak.org/trunk/Compiler-ct.405.diff] Maybe we released Squeak 5.3 since? In this case, it MUST at least be in the release notes indeed. Le lun. 19 avr. 2021 à 13:11, Thiede, Christoph a écrit : > > Hi Nicolas, > > > the renaming is a breaking change. We should make sure to document such changes in the changelog for the next release. > > > Best, > Christoph > ________________________________ > Von: Squeak-dev im Auftrag von commits at source.squeak.org > Gesendet: Freitag, 16. April 2021 22:19:40 > An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org > Betreff: [squeak-dev] The Trunk: Compiler-nice.457.mcz > > Nicolas Cellier uploaded a new version of Compiler to project The Trunk: > http://source.squeak.org/trunk/Compiler-nice.457.mcz [http://source.squeak.org/trunk/Compiler-nice.457.mcz] > > ==================== Summary ==================== > > Name: Compiler-nice.457 > Author: nice > Time: 16 April 2021, 10:19:30.223501 pm > UUID: e2ce8f47-9ed2-0d46-aca1-1dd90ebed4b4 > Ancestors: Compiler-nice.456 > > Rename resume: source -> retryWithNewSource: source. > > The purpose of such exception handling is indeed to retry the compilation with new source. > > The purpose of resume: anObject is to return anObject to the context that sent signal, that's a slightly different semantic. > > It happens that if we resume after setting newSource, the signaller (Parser>>notify:at:) will effectively then tryNewSourceIfAvailable. > So effectively, resuming will end up in retrying (if there is a handler of ReparseAfterSourceEditing up the sender stack, but the Parser normally puts one). > > But, even if this is HOW we implement the #retryWithNewSource:, > this is not WHAT we wish to ask to the SyntaxErrorNotification. > in other words, we shouldn't let the implementation leak in the semantics, otherwise we put the burden of understanding the implementation on the shoulders of programmers, when they could just have trusted the semantics of pseudo natural language offered by keywords. > > While at it, remove the accessors of newSource. > They are not used and may be considered private. > This will reduce the unecessary polymorphism. > > =============== Diff against Compiler-nice.456 =============== > > Item was removed: > - ----- Method: SyntaxErrorNotification>>newSource (in category 'accessing') ----- > - newSource > -        ^newSource! > > Item was removed: > - ----- Method: SyntaxErrorNotification>>newSource: (in category 'accessing') ----- > - newSource: aTextOrString > -        newSource := aTextOrString! > > Item was removed: > - ----- Method: SyntaxErrorNotification>>resume: (in category 'accessing') ----- > - resume: source > - > -        self reparse: source notifying: nil ifFail: nil. > -        ^ super resume: self defaultResumeValue! > > Item was added: > + ----- Method: SyntaxErrorNotification>>retryWithNewSource: (in category 'handling') ----- > + retryWithNewSource: source > +        "Retry the compilation with new source code. > +        Assume > +        - that the signallerContext will tryNewSourceIfAvailable > +        - the presence of a handler of ReparseAfterSourceEditing on the sender stack" > + > +        newSource := source. > +        ^ self resume! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 19 15:06:10 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 17:06:10 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, hi all. I think that we should not highlight the following kinds of Objects to reserve this feature for really interesting structures that are worth inspecting without an extra evaluate. The kinds to ignore are: ByteString ByteSymbol Number Boolean UndefinedObject So, we can use both (1) visuals and (2) interactivity to let the more complex objects say: "Hey, I have interesting structure! Did you mix up print-it with inspect-it? No worries, just click on me." This effect will not be if any stoopid literal gets this treatment. :-) Best, Marcel Am 19.04.2021 13:21:53 schrieb Thiede, Christoph : Hi Marcel, I still stumble upon this edge case for some print-it results that do not support click-to-inspect. Why do we need this exception? :-) > > Also consider this snippet where the print-link does not exist for an MCVersionName >  > Looks fine. I don't think it looks fine, why do you think so? :-) Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Freitag, 16. April 2021 19:52:16 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz   Hi Christoph, I think that this clickable link is a compromise between printString and storeString. For mouse navigation, you can always choose "inspect it" from the context menu on that text selection. ;-) I also found the link color annyoing for simple literals. > Also consider this snippet where the print-link does not exist for an MCVersionName Looks fine. ^__^ I am certain that we will collect more feedback on this feature during the next weeks and months. Let's refine it then. Best, Marcel Am 16.04.2021 18:39:10 schrieb Thiede, Christoph : Hi Marcel, it's great that you have found a solution to this idea! :-) > +        ^ (self class interactivePrintIt and: [(anObject isString or: [anObject isNumber]) not]) Is this necessary? I know that an inspector for a literal object like these does not make great sense, but this just feels like an unnecessary heuristic and limitation for me and adds complexity. I would like to be able to open an inspector always. Also consider this snippet where the print-link does not exist for an MCVersionName: :-) MCRepository inbox allFileNames first > CI scripts will default to "true". Unfortunately, no, mine just timed out while preparing the image. Also, my server images for @SqueakSmalltalkBot were interrupted. I'd opt for keeping preamble/postscript content in the update stream strictly non-interactive. :-) Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Freitag, 16. April 2021 17:27:54 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz   Hi all! It is now in Trunk. You can opt-out via the preference browser. Still, you will be asked the first time when you update your image. CI scripts will default to "true". Best, Marcel Am 17.11.2019 17:36:11 schrieb Jakob Reschke : Thiede, Christoph schrieb am Fr., 15. Nov. 2019, 09:38: Just another idea (I seem to have too many of them :D): Some kind of UnderlyingObjectAttribute (with a better name, of course) an editor can check the selection before compiling it when inspectIt/exploreIt is pressed? Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor checks for UnderylingObjectAttribute -> none found, so the string is compilaed as usual. Example 2: (Text string: '2 + 3' attributes: (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> Editor finds an UnderylingObjectAttribute -> instead of compiling the selection, the cached result is reused for the inspector. We would not even need to display this Attribute visually if it works reliably. Make sure it is transient in some way because it would be quite annoying if the hidden object were out of date with regards to the text. -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 19 15:47:53 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 19 Apr 2021 15:47:53 0000 Subject: [squeak-dev] The Inbox: Kernel-mt.1390.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-mt.1390.mcz ==================== Summary ==================== Name: Kernel-mt.1390 Author: mt Time: 19 April 2021, 5:47:51.865053 pm UUID: c36ac126-16de-3d41-be90-6b7fd46bc0c7 Ancestors: Kernel-nice.1389 Proposal. Better support for hot code updates by restarting from a denoted (i.e. domain-specific) context (or active method). For example, this could be used to better update the McmUpdater as soon as a code change in itself is detected. Two options: either mark the restart context with an on:do: handler or process a query to look up that context such as by package name. =============== Diff against Kernel-nice.1389 =============== Item was added: + Notification subclass: #RestartContextRequest + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'Kernel-Exceptions'! Item was added: + ----- Method: RestartContextRequest class>>fromContextSuchThat: (in category 'as yet unclassified') ----- + fromContextSuchThat: block + "Use this to restart from an arbitrary context on the stack." + + | context | + context := thisContext sender. + [context notNil] whileTrue: [ + (block value: context) ifTrue: [ + ^ self new restartFrom: context]. + context := context sender]. + self error: 'No context found!!'.! Item was added: + ----- Method: RestartContextRequest>>restartFrom: (in category 'as yet unclassified') ----- + restartFrom: aContext + + | process actualContext unwindError | + aContext ifNil: [^ self error: 'No context to restart!!']. + + process := Processor activeProcess. + + [actualContext := process popTo: aContext. + unwindError := actualContext ~= aContext. + unwindError + ifTrue: [process resume] + ifFalse: [process restartTop; stepToSendOrReturn; resume] + ] fork. + + process suspend.! Item was added: + ----- Method: RestartContextRequest>>restartFromHere (in category 'as yet unclassified') ----- + restartFromHere + "Use this to restart from an exception handler." + self restartFrom: handlerContext.! From marcel.taeumel at hpi.de Mon Apr 19 15:50:02 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 19 Apr 2021 17:50:02 +0200 Subject: [squeak-dev] The Inbox: Kernel-mt.1390.mcz In-Reply-To: References: Message-ID: Here are the two options in an exapmle: Am 19.04.2021 17:48:03 schrieb commits at source.squeak.org : A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-mt.1390.mcz ==================== Summary ==================== Name: Kernel-mt.1390 Author: mt Time: 19 April 2021, 5:47:51.865053 pm UUID: c36ac126-16de-3d41-be90-6b7fd46bc0c7 Ancestors: Kernel-nice.1389 Proposal. Better support for hot code updates by restarting from a denoted (i.e. domain-specific) context (or active method). For example, this could be used to better update the McmUpdater as soon as a code change in itself is detected. Two options: either mark the restart context with an on:do: handler or process a query to look up that context such as by package name. =============== Diff against Kernel-nice.1389 =============== Item was added: + Notification subclass: #RestartContextRequest + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'Kernel-Exceptions'! Item was added: + ----- Method: RestartContextRequest class>>fromContextSuchThat: (in category 'as yet unclassified') ----- + fromContextSuchThat: block + "Use this to restart from an arbitrary context on the stack." + + | context | + context := thisContext sender. + [context notNil] whileTrue: [ + (block value: context) ifTrue: [ + ^ self new restartFrom: context]. + context := context sender]. + self error: 'No context found!!'.! Item was added: + ----- Method: RestartContextRequest>>restartFrom: (in category 'as yet unclassified') ----- + restartFrom: aContext + + | process actualContext unwindError | + aContext ifNil: [^ self error: 'No context to restart!!']. + + process := Processor activeProcess. + + [actualContext := process popTo: aContext. + unwindError := actualContext ~= aContext. + unwindError + ifTrue: [process resume] + ifFalse: [process restartTop; stepToSendOrReturn; resume] + ] fork. + + process suspend.! Item was added: + ----- Method: RestartContextRequest>>restartFromHere (in category 'as yet unclassified') ----- + restartFromHere + "Use this to restart from an exception handler." + self restartFrom: handlerContext.! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 158062 bytes Desc: not available URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 15:56:52 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 15:56:52 +0000 Subject: [squeak-dev] stepping over non local return in a protected block In-Reply-To: <1618837735369-0.post@n4.nabble.com> References: <1618649874366-0.post@n4.nabble.com> , <1618837735369-0.post@n4.nabble.com> Message-ID: <010384c17c884a5481a0eed900b1281e@student.hpi.uni-potsdam.de> Thanks Jaromir, this exception makes very much sense. So to fix this bug, we "only" need to fix #runUntilErrorOrReturnFrom: for stack-manipulating code. I'll need to clean up my inbox a bit to find out whether there have been any recent posts on this issue ... :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Jaromir Matas Gesendet: Montag, 19. April 2021 15:08:55 An: squeak-dev at lists.squeakfoundation.org Betreff: Re: [squeak-dev] stepping over non local return in a protected block Hi Christoph, Christoph Thiede wrote > But the fact that the guard contexts are not removed again should not lead > to a cannot return situation. Instead, I would rather have expected that > the UI process would be terminated. But somehow, the termination in > BlockClosure >> #newProcess fails. I observed that primitive 88 in Process > >> #suspend fails so the execution continues right from the bottom context > of the process. I'm not sure why primitiveSuspend fails here. Might this > be related to the changes in termination logic? Jaromir? :-) In my opinion the problem is that when the Debugger invokes #stepOver over a non-local return, it invokes #evaluate:onBehalfOf: down the chain of sends to execute the non-local return and that's where the problem lies: #evaluate:onBehalfOf: incorrectly executes the non-local return on the wrong stack - the debugger process uses its own stack to have #evaluate:onBehalfOf: executed the non-local return ([^2]) which fails to find its home context which is indeed on a different stack (original process's stack). The cannot return is just a consequence of the failure to find the home context... At least this is my working hypothesis :) Compared to #evaluate:onBehalfOf:, the #runUntilErrorOrReturnFrom: method itself jumps right into the debugged process's stack - which results in flawless execution of the non-local return! It finds it's home context and jumps into it and continues execution. I, however, haven't explored the behavior of the combination of #evaluate:onBehalfOf: and #runUntilErrorOrReturnFrom: :o As I said my Debugger knowledge is still negligible, unfortunately. Prior to your change from active to genuine process the `[^2] ensure: []` example caused the infinite debugger loop... after that it only causes the cannot return error. So I guess it's unlikely the change in #terminate somehow affected the bug's behavior; the bug was there before and behaves similarly. The change in #teminate only eliminated the use #evaluate:onBehalfOf: in the termination procedure... I'm looking at it from a different angle now, I'll keep you posted... Thanks, best, ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From kksubbu.ml at gmail.com Mon Apr 19 16:23:22 2021 From: kksubbu.ml at gmail.com (K K Subbu) Date: Mon, 19 Apr 2021 21:53:22 +0530 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> Message-ID: All, How about: Object>>isInspectable ^true ByteString>>isInspectable ^false Number>>isInspectable ^false ... so inspectors can skip unitary objects? Just a thought .. Subbu On 19/04/21 8:36 pm, Marcel Taeumel wrote: > Hi Christoph, hi all. > > I think that we should not highlight the following kinds of Objects to > reserve this feature for really interesting structures that are worth > inspecting without an extra evaluate. The kinds to ignore are: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > So, we can use both (1) visuals and (2) interactivity to let the more > complex objects say: "Hey, I have interesting structure! Did you mix up > print-it with inspect-it? No worries, just click on me." > > This effect will not be if any stoopid literal gets this treatment. :-) > > Best, > Marcel >> >> Am 19.04.2021 13:21:53 schrieb Thiede, Christoph >> : >> >> Hi Marcel, >> >> >> I still stumble upon this edge case for some print-it results that do >> not support click-to-inspect. Why do we need this exception? :-) >> >> >> > > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> > >> > Looks fine. >> >> I don't think it looks fine, why do you think so? :-) >> >> Best, >> Christoph >> ------------------------------------------------------------------------ >> *Von:* Squeak-dev im >> Auftrag von Taeumel, Marcel >> *Gesendet:* Freitag, 16. April 2021 19:52:16 >> *An:* squeak-dev >> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >> Hi Christoph, >> >> I think that this clickable link is a compromise between printString >> and storeString. For mouse navigation, you can always choose "inspect >> it" from the context menu on that text selection. ;-) I also found the >> link color annyoing for simple literals. >> >> > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> >> Looks fine. ^__^ I am certain that we will collect more feedback on >> this feature during the next weeks and months. Let's refine it then. >> >> Best, >> Marcel >>> >>> Am 16.04.2021 18:39:10 schrieb Thiede, Christoph >>> : >>> >>> Hi Marcel, it's great that you have found a solution to this idea! :-) >>> >>> >>> > +        ^ (self class interactivePrintIt and: [(anObject isString >>> or: [anObject isNumber]) not]) >>> >>> >>> Is this necessary? I know that an inspector for a literal object like >>> these does not make great sense, but this just feels like an >>> unnecessary heuristic and limitation for me and adds complexity. I >>> would like to be able to open an inspector always. Also consider this >>> snippet where the print-link does not exist for an MCVersionName: :-) >>> >>> MCRepository inbox allFileNames first >>> >>> >>> > CI scripts will default to "true". >>> >>> >>> Unfortunately, no, mine just timed out while preparing the image. >>> Also, my server images for @SqueakSmalltalkBot were interrupted. I'd >>> opt for keeping preamble/postscript content in the update stream >>> strictly non-interactive. :-) >>> >>> >>> Best, >>> >>> Christoph >>> >>> >>> ------------------------------------------------------------------------ >>> *Von:* Squeak-dev im >>> Auftrag von Taeumel, Marcel >>> *Gesendet:* Freitag, 16. April 2021 17:27:54 >>> *An:* squeak-dev >>> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >>> Hi all! >>> >>> It is now in Trunk. You can opt-out via the preference browser. >>> Still, you will be asked the first time when you update your image. >>> CI scripts will default to "true". >>> >>> Best, >>> Marcel >>>> >>>> Am 17.11.2019 17:36:11 schrieb Jakob Reschke : >>>> >>>> Thiede, Christoph >>> > schrieb am >>>> Fr., 15. Nov. 2019, 09:38: >>>> >>>> >>>> Just another idea (I seem to have too many of them :D): Some >>>> kind of UnderlyingObjectAttribute (with a better name, of >>>> course) an editor can check the selection before compiling it >>>> when inspectIt/exploreIt is pressed? >>>> >>>> >>>> Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor >>>> checks for UnderylingObjectAttribute -> none found, so the >>>> string is compilaed as usual. >>>> >>>> Example 2: (Text string: '2 + 3' attributes: >>>> (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> >>>> Editor finds an UnderylingObjectAttribute -> instead of >>>> compiling the selection, the cached result is reused for >>>> the inspector. >>>> >>>> We would not even need to display this Attribute visually if it >>>> works reliably. >>>> >>>> >>>> Make sure it is transient in some way because it would be quite >>>> annoying if the hidden object were out of date with regards to the text. > > From commits at source.squeak.org Mon Apr 19 16:38:08 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 19 Apr 2021 16:38:08 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1390.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1390.mcz ==================== Summary ==================== Name: Kernel-nice.1390 Author: nice Time: 19 April 2021, 6:37:54.360183 pm UUID: 3ba56195-f0d4-454c-b3f7-d07e1eadcad7 Ancestors: Kernel-nice.1389 Fixes regression in Context >> #runSimulated:contextAtEachStep: when the message is sent to something else than thisContext. This happens when tallying sends (see MessageTally class >> #tallySendsTo:inBlock:showTree: ) This commit integrates the change poposed in: https://source.squeak.org/treated/Kernel-ct.1363.diff which was a commented version of: https://source.squeak.org/treated/Kernel-ct.1362.diff Thanks Christoph for the fix! Also implement #asContextWithSender: in Context so that testRunSimulatedContextAtEachStep continues to work. Thanks Jaromir for the suggestion. =============== Diff against Kernel-nice.1389 =============== Item was added: + ----- Method: Context>>asContextWithSender: (in category 'closure support') ----- + asContextWithSender: aContext + self privSender: aContext. + ^ self! Item was changed: ----- Method: Context>>runSimulated:contextAtEachStep: (in category 'system simulation') ----- runSimulated: aBlock contextAtEachStep: anotherBlock "Simulate the execution of the argument, aBlock, until it ends or is curtailed. If any exception is signaled during the execution, simulate it being handled on the present caller stack. Evaluate anotherBlock with the current context prior to each instruction executed. Answer the simulated value of aBlock." | current resume ensure | resume := false. + "Affect the context stack of the receiver during the simulation of aBlock." + current := aBlock asContextWithSender: self. + "Insert outer context denoting the end of the simulation." + ensure := (ensure := current) insertSender: (Context contextEnsure: + [resume := true. + ensure privSender: thisContext home sender]). - current := aBlock asContext. - ensure := current insertSender: (Context contextEnsure: [resume := true]). - ensure sender ifNil: [ensure privSender: self]. "For backward compatibility, do not fail if aBlock is dead." (anotherBlock numArgs = 0 ifTrue: ["optimized" [resume]] ifFalse: ["stop execution on time, don't expose simulation details to caller" [current == ensure or: ["Context >> #resume:" current size >= 2 and: [(current at: 2) == ensure]]] ]) whileFalse: [anotherBlock cull: current. current := current step]. + "Continue with the execution in the previous context." ^ current jump! From tim at rowledge.org Mon Apr 19 16:50:29 2021 From: tim at rowledge.org (tim Rowledge) Date: Mon, 19 Apr 2021 09:50:29 -0700 Subject: [squeak-dev] Idioms | How to send messages in Context? In-Reply-To: References: Message-ID: >> >> #cannotReturn: is put onto the stack of the process being executed/simulated. #send:to:with: is part of the simulation protocol. Analogously, #resume:through: will appear on the executed process stack whereas #return:from: is used by the simulator as stated in the comment. :-) I It might be worth considering the names of these methods in order to make that very clear. Perhaps something like #simSend:to:with: ? tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Klingon Code Warrior:- 4) "This machine is a piece of GAGH! I need dual G5 processors if I am to do battle with this code!" From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:08:07 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:08:07 +0000 Subject: [squeak-dev] Idioms | How to send messages in Context? In-Reply-To: References: , Message-ID: <04198977a82947df85eb68e579c75a5b@student.hpi.uni-potsdam.de> > It might be worth considering the names of these methods in order to make that very clear. Perhaps something like #simSend:to:with: ? Yeah, I already thought about something like this. But this would be a greater refactoring, I guess. Another not-so-serious argument is that I have started using the "sim" prefix for extension methods on Context from SimulationStudio. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von tim Rowledge Gesendet: Montag, 19. April 2021 18:50:29 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Idioms | How to send messages in Context? >> >> #cannotReturn: is put onto the stack of the process being executed/simulated. #send:to:with: is part of the simulation protocol. Analogously, #resume:through: will appear on the executed process stack whereas #return:from: is used by the simulator as stated in the comment. :-) I It might be worth considering the names of these methods in order to make that very clear. Perhaps something like #simSend:to:with: ? tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Klingon Code Warrior:- 4) "This machine is a piece of GAGH! I need dual G5 processors if I am to do battle with this code!" -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 19 17:11:04 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 19 Apr 2021 17:11:04 0000 Subject: [squeak-dev] The Trunk: ToolsTests-nice.104.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolsTests to project The Trunk: http://source.squeak.org/trunk/ToolsTests-nice.104.mcz ==================== Summary ==================== Name: ToolsTests-nice.104 Author: nice Time: 19 April 2021, 7:10:52.441183 pm UUID: 1ddda785-3f79-1643-bdc5-bf74b3123646 Ancestors: ToolsTests-nice.103 Fix the somehow fragile testSelectedMessageName. Serious tests would require some form of well controlled mocks, but is it really worth? =============== Diff against ToolsTests-nice.103 =============== Item was changed: ----- Method: DependencyBrowserTest>>testSelectedMessageName (in category 'tests - message list') ----- testSelectedMessageName "Warning!! When Collections' dependencies change, this test may start to fail!!" self assert: browser selectedMessageName isNil. browser packageListIndex: (browser packageList indexOf: #Collections). self assert: browser selectedMessageName isNil. browser packageDepsIndex: (browser packageDeps indexOf: #Compiler). self assert: browser selectedMessageName isNil. browser classDepsIndex: (browser classDeps indexOf: #Scanner). self assert: browser selectedMessageName isNil. browser classListIndex: (browser classList indexOf: #Symbol). + self assert: browser selectedMessageName == #isMessageSelector. - self assert: browser selectedMessageName == #storeOn:. browser messageListIndex: 1. + self assert: browser selectedMessageName == #isMessageSelector. - self assert: browser selectedMessageName == #storeOn:. browser messageListIndex: 0. self assert: browser selectedMessageName isNil.! From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:29:06 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:29:06 +0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> , Message-ID: <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Hi Marcel, hi all, I keeping considering this type check as something bad and unexpected. :-) First, as I have mentioned earlier, subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example. Second, even a string can be non-trivial, for instance, "String value: 1234", where I only will see a question mark unless I inspect the result. Yes, in the second example, I could also trouble the Compiler again for a new inspect-it, but I just don't see why we should restrict these useful links for certain types of results. Also, in all situations where you do some experiments concerning identity, an inspector would be very helpful to track individual instances. Re-evaluating the expression would not be a solution here. To summarize, I just would not say that any object in Squeak can have a boring structure. It's just the other way around, these clickable results are a great way to make the inspector more visible in the system. PS: We should also consider making the new links available for print-its in the search bar. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von K K Subbu Gesendet: Montag, 19. April 2021 18:23:22 An: squeak-dev at lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz All, How about: Object>>isInspectable ^true ByteString>>isInspectable ^false Number>>isInspectable ^false ... so inspectors can skip unitary objects? Just a thought .. Subbu On 19/04/21 8:36 pm, Marcel Taeumel wrote: > Hi Christoph, hi all. > > I think that we should not highlight the following kinds of Objects to > reserve this feature for really interesting structures that are worth > inspecting without an extra evaluate. The kinds to ignore are: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > So, we can use both (1) visuals and (2) interactivity to let the more > complex objects say: "Hey, I have interesting structure! Did you mix up > print-it with inspect-it? No worries, just click on me." > > This effect will not be if any stoopid literal gets this treatment. :-) > > Best, > Marcel >> >> Am 19.04.2021 13:21:53 schrieb Thiede, Christoph >> : >> >> Hi Marcel, >> >> >> I still stumble upon this edge case for some print-it results that do >> not support click-to-inspect. Why do we need this exception? :-) >> >> >> > > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> > >> > Looks fine. >> >> I don't think it looks fine, why do you think so? :-) >> >> Best, >> Christoph >> ------------------------------------------------------------------------ >> *Von:* Squeak-dev im >> Auftrag von Taeumel, Marcel >> *Gesendet:* Freitag, 16. April 2021 19:52:16 >> *An:* squeak-dev >> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >> Hi Christoph, >> >> I think that this clickable link is a compromise between printString >> and storeString. For mouse navigation, you can always choose "inspect >> it" from the context menu on that text selection. ;-) I also found the >> link color annyoing for simple literals. >> >> > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> >> Looks fine. ^__^ I am certain that we will collect more feedback on >> this feature during the next weeks and months. Let's refine it then. >> >> Best, >> Marcel >>> >>> Am 16.04.2021 18:39:10 schrieb Thiede, Christoph >>> : >>> >>> Hi Marcel, it's great that you have found a solution to this idea! :-) >>> >>> >>> > + ^ (self class interactivePrintIt and: [(anObject isString >>> or: [anObject isNumber]) not]) >>> >>> >>> Is this necessary? I know that an inspector for a literal object like >>> these does not make great sense, but this just feels like an >>> unnecessary heuristic and limitation for me and adds complexity. I >>> would like to be able to open an inspector always. Also consider this >>> snippet where the print-link does not exist for an MCVersionName: :-) >>> >>> MCRepository inbox allFileNames first >>> >>> >>> > CI scripts will default to "true". >>> >>> >>> Unfortunately, no, mine just timed out while preparing the image. >>> Also, my server images for @SqueakSmalltalkBot were interrupted. I'd >>> opt for keeping preamble/postscript content in the update stream >>> strictly non-interactive. :-) >>> >>> >>> Best, >>> >>> Christoph >>> >>> >>> ------------------------------------------------------------------------ >>> *Von:* Squeak-dev im >>> Auftrag von Taeumel, Marcel >>> *Gesendet:* Freitag, 16. April 2021 17:27:54 >>> *An:* squeak-dev >>> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >>> Hi all! >>> >>> It is now in Trunk. You can opt-out via the preference browser. >>> Still, you will be asked the first time when you update your image. >>> CI scripts will default to "true". >>> >>> Best, >>> Marcel >>>> >>>> Am 17.11.2019 17:36:11 schrieb Jakob Reschke : >>>> >>>> Thiede, Christoph >>> > schrieb am >>>> Fr., 15. Nov. 2019, 09:38: >>>> >>>> >>>> Just another idea (I seem to have too many of them :D): Some >>>> kind of UnderlyingObjectAttribute (with a better name, of >>>> course) an editor can check the selection before compiling it >>>> when inspectIt/exploreIt is pressed? >>>> >>>> >>>> Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor >>>> checks for UnderylingObjectAttribute -> none found, so the >>>> string is compilaed as usual. >>>> >>>> Example 2: (Text string: '2 + 3' attributes: >>>> (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> >>>> Editor finds an UnderylingObjectAttribute -> instead of >>>> compiling the selection, the cached result is reused for >>>> the inspector. >>>> >>>> We would not even need to display this Attribute visually if it >>>> works reliably. >>>> >>>> >>>> Make sure it is transient in some way because it would be quite >>>> annoying if the hidden object were out of date with regards to the text. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:30:13 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:30:13 +0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1390.mcz In-Reply-To: References: Message-ID: Great, thank both of you! :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Montag, 19. April 2021 18:38:08 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Kernel-nice.1390.mcz Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1390.mcz ==================== Summary ==================== Name: Kernel-nice.1390 Author: nice Time: 19 April 2021, 6:37:54.360183 pm UUID: 3ba56195-f0d4-454c-b3f7-d07e1eadcad7 Ancestors: Kernel-nice.1389 Fixes regression in Context >> #runSimulated:contextAtEachStep: when the message is sent to something else than thisContext. This happens when tallying sends (see MessageTally class >> #tallySendsTo:inBlock:showTree: ) This commit integrates the change poposed in: https://source.squeak.org/treated/Kernel-ct.1363.diff which was a commented version of: https://source.squeak.org/treated/Kernel-ct.1362.diff Thanks Christoph for the fix! Also implement #asContextWithSender: in Context so that testRunSimulatedContextAtEachStep continues to work. Thanks Jaromir for the suggestion. =============== Diff against Kernel-nice.1389 =============== Item was added: + ----- Method: Context>>asContextWithSender: (in category 'closure support') ----- + asContextWithSender: aContext + self privSender: aContext. + ^ self! Item was changed: ----- Method: Context>>runSimulated:contextAtEachStep: (in category 'system simulation') ----- runSimulated: aBlock contextAtEachStep: anotherBlock "Simulate the execution of the argument, aBlock, until it ends or is curtailed. If any exception is signaled during the execution, simulate it being handled on the present caller stack. Evaluate anotherBlock with the current context prior to each instruction executed. Answer the simulated value of aBlock." | current resume ensure | resume := false. + "Affect the context stack of the receiver during the simulation of aBlock." + current := aBlock asContextWithSender: self. + "Insert outer context denoting the end of the simulation." + ensure := (ensure := current) insertSender: (Context contextEnsure: + [resume := true. + ensure privSender: thisContext home sender]). - current := aBlock asContext. - ensure := current insertSender: (Context contextEnsure: [resume := true]). - ensure sender ifNil: [ensure privSender: self]. "For backward compatibility, do not fail if aBlock is dead." (anotherBlock numArgs = 0 ifTrue: ["optimized" [resume]] ifFalse: ["stop execution on time, don't expose simulation details to caller" [current == ensure or: ["Context >> #resume:" current size >= 2 and: [(current at: 2) == ensure]]] ]) whileFalse: [anotherBlock cull: current. current := current step]. + "Continue with the execution in the previous context." ^ current jump! -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:36:06 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:36:06 +0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1386.mcz In-Reply-To: References: <1618578607101-0.post@n4.nabble.com> <1618578968761-0.post@n4.nabble.com> , Message-ID: <5c6fa64b87f04f4b8f6d2332255d5859@student.hpi.uni-potsdam.de> Hi Nicolas, > Yes, this could work. Great! It's on my list. :-) > Yes, changing several times the same method is necessarily a conflict for our tools. > IMO it's a good thing, because it will require human attention for resolution. > Merging based on line editions is not the right solution IMO. > If both editions modify the temps, they will conflict anyway. Agreed. Still, I think it would be nice if you could just accept your manual resolution of a conflicting method right into a merge browser. By accepting the entire merge then, your manually resolved method should be installed into the image. How would you think about that? > I also wondered if we could disable warnings at specific send sites on user request (instead of disabling all the Warnings). Ah, something like "ignore deprecation warnings for sends from specific method/class/package"? This could be worth a thought. But I do not yet have a real use case for this. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Montag, 19. April 2021 16:04:28 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Kernel-nice.1386.mcz Hi Christoph, Le lun. 19 avr. 2021 à 13:32, Thiede, Christoph a écrit : > > Hi Nicolas, > > > in general, I use to submit one inbox version per proposal/fix/change. They all branch from the main Trunk line so I consider each of them something that you would call a Pull Request in the GitHub world. This also means that no inbox proposal is to be considered deprecated only because I upload a newer version. When I indeed intend to replace the former version, I usually add a notice "replaces version Package-ct.xxx" to the message of the new version. :-) > > I think our special problem in this case was that it is not a straightforward task to merge multiple changes of a single method with our tooling. > Yes, changing several times the same method is necessarily a conflict for our tools. IMO it's a good thing, because it will require human attention for resolution. Merging based on line editions is not the right solution IMO. If both editions modify the temps, they will conflict anyway. Even if methods are atomic pieces, two modifications of the same method are not necessarily exclusive. It happens that we updated a comment in one branch, or renamed a message, inst var or class in the other, etc... But here, I failed to identify this situation. I might have been biased by the desire to see the warnings go ;) > > I see the problem with annoying warnings, which is why I proposed to create a new subclass for these warnings! Then we could easily ignore these warnings when they are raised inside of the debugger. For other use cases such as automated tests or SimulationStudio, however, we would still see them. > Yes, this could work. I also wondered if we could disable warnings at specific send sites on user request (instead of disabling all the Warnings). A good way to exercise new super powers for the Sorcerer's Apprentices ;) > > > I saw later that you removed from newProcess... SHould we? > > > I think we should. Either a simulator client is interested to be informed about attempts of the code to escape from simulation, or it isn't. In every case, creating a process is an absolutely boring event with regard to that interest, but all actions such as resuming, terminating, or signaling a process could be of interest. > > > Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. > > I'll put that onto my list, but I've myself lost track of the changes regarding primitive 186 et al. I'm not the author of these changes ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Nicolas Cellier > Gesendet: Freitag, 16. April 2021 19:34:20 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Trunk: Kernel-nice.1386.mcz > > Hi Christoph, > Hmm, there must have been some confusion on my side. > I've tried to carefully review the remaining contributions in the inbox. > To my understanding Kernel-ct.1383 fixes more simulation cases than > Kernel-ct.1382. > Since > - the tests simulating primitives 83, 84 & 100 were failing, > - and that a more recent inbox contribution was trying to fix that, > I thought that merging this contribution was a good idea. > It apparently was fixing two tests out of three after trial. > > Also, to my experience, generating a warning when we simulate > primitiveIndex >= 85 and: [primitiveIndex <= 88] "control primitives"]) > is super annoying! It always happens when running some kernel tests > and forces me to switch warning off altogether. > But switching warning off is not a good solution (and it makes some > more tests fail !). > Kernel-ct.1383 being more recent, I thought that the removal of > warnings was intentional... > > I saw later that you removed from newProcess... SHould we? > > My understanding now is that you need this warning in some specific > context. Is that it? > We can't fix one usage by breaking another. We have to find a solution > that fits both purposes. > > Le ven. 16 avr. 2021 à 15:40, Marcel Taeumel a écrit : > > > > Hi Christoph, > > > > the commit message in Kernel-nice.1386 reads: "[...] Note that Kernel-ct.1383 supersedes Kernel-ct.1382 and removes the annoying warning. [...]" > > > > I think the problem was that both ct.1382 and ct.1382 change the same method but do not actually consider each other. With our current tools, sub-method merging is rather tricky and hence the author should take care that this does not happen. :-) > > > > Please review the current state of Context >> #doPrimitive:method:receiver:args: and upload the missing lines again into the inbox if necessary. > > > > Best, > > Marcel > > > > Am 16.04.2021 15:16:18 schrieb Christoph Thiede : > > > > PS: I also see that you touched the simulation of criticalSection primitives > > (primitiveIndex = 186 ...) again. Again, was this intended or an incident? > > :-) > > > > (OT: We are really treading on each other's toes in this method ... What can > > we learn from this? Is it too large and should be split up? Or should we > > improve our tooling support for resolving merge conflicts?) > > > > Best, > > Christoph > > > > > > > > ----- > > Carpe Squeak! > > -- > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Das.Linux at gmx.de Mon Apr 19 17:40:43 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 19 Apr 2021 19:40:43 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph > On 19. Apr 2021, at 19:29, Thiede, Christoph wrote: > > Hi Marcel, hi all, > > I keeping considering this type check as something bad and unexpected. :-) Note that in this instance, 'isInspectable' is actually a plain behavior check, not a type check at all. It's not "isMorph" or something. While "is*" is often used/misused/abused as type check, this kind here is actually not one of these : Best regards -Tobias > > First, as I have mentioned earlier, subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example. Second, even a string can be non-trivial, for instance, "String value: 1234", where I only will see a question mark unless I inspect the result. Yes, in the second example, I could also trouble the Compiler again for a new inspect-it, but I just don't see why we should restrict these useful links for certain types of results. Also, in all situations where you do some experiments concerning identity, an inspector would be very helpful to track individual instances. Re-evaluating the expression would not be a solution here. > > To summarize, I just would not say that any object in Squeak can have a boring structure. It's just the other way around, these clickable results are a great way to make the inspector more visible in the system. > > PS: We should also consider making the new links available for print-its in the search bar. > > Best, > Christoph > Von: Squeak-dev im Auftrag von K K Subbu > Gesendet: Montag, 19. April 2021 18:23:22 > An: squeak-dev at lists.squeakfoundation.org > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > All, > > How about: > > Object>>isInspectable ^true > ByteString>>isInspectable ^false > Number>>isInspectable ^false > ... > > so inspectors can skip unitary objects? > > Just a thought .. Subbu > > On 19/04/21 8:36 pm, Marcel Taeumel wrote: > > Hi Christoph, hi all. > > > > I think that we should not highlight the following kinds of Objects to > > reserve this feature for really interesting structures that are worth > > inspecting without an extra evaluate. The kinds to ignore are: > > > > ByteString > > ByteSymbol > > Number > > Boolean > > UndefinedObject > > > > So, we can use both (1) visuals and (2) interactivity to let the more > > complex objects say: "Hey, I have interesting structure! Did you mix up > > print-it with inspect-it? No worries, just click on me." > > > > This effect will not be if any stoopid literal gets this treatment. :-) > > > > Best, > > Marcel > >> > >> Am 19.04.2021 13:21:53 schrieb Thiede, Christoph > >> : > >> > >> Hi Marcel, > >> > >> > >> I still stumble upon this edge case for some print-it results that do > >> not support click-to-inspect. Why do we need this exception? :-) > >> > >> > >> > > Also consider this snippet where the print-link does not exist for > >> an MCVersionName > >> > > >> > Looks fine. > >> > >> I don't think it looks fine, why do you think so? :-) > >> > >> Best, > >> Christoph > >> ------------------------------------------------------------------------ > >> *Von:* Squeak-dev im > >> Auftrag von Taeumel, Marcel > >> *Gesendet:* Freitag, 16. April 2021 19:52:16 > >> *An:* squeak-dev > >> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > >> Hi Christoph, > >> > >> I think that this clickable link is a compromise between printString > >> and storeString. For mouse navigation, you can always choose "inspect > >> it" from the context menu on that text selection. ;-) I also found the > >> link color annyoing for simple literals. > >> > >> > Also consider this snippet where the print-link does not exist for > >> an MCVersionName > >> > >> Looks fine. ^__^ I am certain that we will collect more feedback on > >> this feature during the next weeks and months. Let's refine it then. > >> > >> Best, > >> Marcel > >>> > >>> Am 16.04.2021 18:39:10 schrieb Thiede, Christoph > >>> : > >>> > >>> Hi Marcel, it's great that you have found a solution to this idea! :-) > >>> > >>> > >>> > + ^ (self class interactivePrintIt and: [(anObject isString > >>> or: [anObject isNumber]) not]) > >>> > >>> > >>> Is this necessary? I know that an inspector for a literal object like > >>> these does not make great sense, but this just feels like an > >>> unnecessary heuristic and limitation for me and adds complexity. I > >>> would like to be able to open an inspector always. Also consider this > >>> snippet where the print-link does not exist for an MCVersionName: :-) > >>> > >>> MCRepository inbox allFileNames first > >>> > >>> > >>> > CI scripts will default to "true". > >>> > >>> > >>> Unfortunately, no, mine just timed out while preparing the image. > >>> Also, my server images for @SqueakSmalltalkBot were interrupted. I'd > >>> opt for keeping preamble/postscript content in the update stream > >>> strictly non-interactive. :-) > >>> > >>> > >>> Best, > >>> > >>> Christoph > >>> > >>> > >>> ------------------------------------------------------------------------ > >>> *Von:* Squeak-dev im > >>> Auftrag von Taeumel, Marcel > >>> *Gesendet:* Freitag, 16. April 2021 17:27:54 > >>> *An:* squeak-dev > >>> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > >>> Hi all! > >>> > >>> It is now in Trunk. You can opt-out via the preference browser. > >>> Still, you will be asked the first time when you update your image. > >>> CI scripts will default to "true". > >>> > >>> Best, > >>> Marcel > >>>> > >>>> Am 17.11.2019 17:36:11 schrieb Jakob Reschke : > >>>> > >>>> Thiede, Christoph >>>> > schrieb am > >>>> Fr., 15. Nov. 2019, 09:38: > >>>> > >>>> > >>>> Just another idea (I seem to have too many of them :D): Some > >>>> kind of UnderlyingObjectAttribute (with a better name, of > >>>> course) an editor can check the selection before compiling it > >>>> when inspectIt/exploreIt is pressed? > >>>> > >>>> > >>>> Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor > >>>> checks for UnderylingObjectAttribute -> none found, so the > >>>> string is compilaed as usual. > >>>> > >>>> Example 2: (Text string: '2 + 3' attributes: > >>>> (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> > >>>> Editor finds an UnderylingObjectAttribute -> instead of > >>>> compiling the selection, the cached result is reused for > >>>> the inspector. > >>>> > >>>> We would not even need to display this Attribute visually if it > >>>> works reliably. > >>>> > >>>> > >>>> Make sure it is transient in some way because it would be quite > >>>> annoying if the hidden object were out of date with regards to the text. > > > > From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:42:58 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:42:58 +0000 Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com>, Message-ID: <4b820f30aa3d467e8b1e8db6a22765de@student.hpi.uni-potsdam.de> Hi Eliot, hi Marcel, > I’m removing shadows, not adding new ones. I do not doubt this. I only wanted to point to the fact that your refactoring is completely free of safety. If someone else says, "Hey, these names are too long, let's shorten them", then the shadows might be introduced again and no one will notice. A change in tooling could prevent this problem; otherwise, automated tests would do, too. Just a notice. :-) > I just noticed that I am finde with "aMorph" as a method argument, yet I would never use "a" in a block argument. :-D Strange. +1. I also use roles as names (but I do not really like it - these are not really explaining names). Abbreviations are counter-intuitive, too. Another option is "ea", but this only good for very small methods, if at all. I use "some" analogously to "a" for method parameters that should be collections. Maybe "the" might be a better pattern for naming block args? :-) > self owner ifNotNil: [:theOwner | "..."]. > self submorphs ifNotEmpty: [:theSubmorphs | "..."]. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Sonntag, 18. April 2021 14:44:32 An: squeak-dev Betreff: Re: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) Hi Christoph, hi Eliot, it might be that the likelihood of shadowing increases with the use of cull'ed block invocations, which we have been supporting more and more in the last years: self owner ifNotNil: [:owner | "..."]. self submorphs ifNotEmpty: [:submorphs | "..."]. As alternative names, one could drop their actual "role" and just use their kinds (as generic as desired): self owner ifNotNil: [:morph | "..."]. self submorphs ifNotEmpty: [:morphs | "..."]. self submorphs ifNotEmpty: [:objects | "..."]. In the past, I happened to mistakenly have used the wrong role, shadowing the right one: self allOwnersDo: [:owner | "..."]. self allOwnersDo: [:morph | "..."]. Yet, we do have misleading protocol on what to actually call "owner." Just the morph that has me directly in its submorphs? That might be another topic. :-) *** To avoid shadowing, I find myself using (a) abbreviations, (b) kind/class, or (c) count-prefix "a" or "some". Or a combination of those. Unfortunately, omitting the domain-specific role in a name might impair readability. I just noticed that I am finde with "aMorph" as a method argument, yet I would never use "a" in a block argument. :-D Strange. Best, Marcel Am 18.04.2021 05:39:33 schrieb Eliot Miranda : Hi Christoph, > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: > > Hi Eliot, > > I fear that changes like this will not be very durable unless tested in any > way. At the moment, you won't even notice a new shadow unless you have > opened a Transcript by accident when accepting a method. Should we maybe > show a message window for shadows instead when compiled interactively, > analogously to the warnings about superfluous temps? I’m removing shadows, not adding new ones. In all cars I saw eleven ing s from the compiler in the update stream and replaced shadowed temp cars by renamed temp vars. So my changes have no semantic effect and only remove the warning. > > (In a larger context, I would strongly opt for (finally) introducing a > mechanism for linter/compiler annotations in CodeHolders. Most modern > editors and IDEs have it, even Pharo; if Squeak does not want to get left > behind, we should support something like this, too. It could or should be > configurable, of course.) > > LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal name > for a variable that holds Morph instances, right? :) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:44:07 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:44:07 +0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de>, Message-ID: <353609d15e534f0f8dc167687a8d1a05@student.hpi.uni-potsdam.de> Hi Tobias, yes, I know. Then let's correct my formulation into: "this functionality check is something bad and unexpected". :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Tobias Pape Gesendet: Montag, 19. April 2021 19:40:43 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz Hi Christoph > On 19. Apr 2021, at 19:29, Thiede, Christoph wrote: > > Hi Marcel, hi all, > > I keeping considering this type check as something bad and unexpected. :-) Note that in this instance, 'isInspectable' is actually a plain behavior check, not a type check at all. It's not "isMorph" or something. While "is*" is often used/misused/abused as type check, this kind here is actually not one of these : Best regards -Tobias > > First, as I have mentioned earlier, subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example. Second, even a string can be non-trivial, for instance, "String value: 1234", where I only will see a question mark unless I inspect the result. Yes, in the second example, I could also trouble the Compiler again for a new inspect-it, but I just don't see why we should restrict these useful links for certain types of results. Also, in all situations where you do some experiments concerning identity, an inspector would be very helpful to track individual instances. Re-evaluating the expression would not be a solution here. > > To summarize, I just would not say that any object in Squeak can have a boring structure. It's just the other way around, these clickable results are a great way to make the inspector more visible in the system. > > PS: We should also consider making the new links available for print-its in the search bar. > > Best, > Christoph > Von: Squeak-dev im Auftrag von K K Subbu > Gesendet: Montag, 19. April 2021 18:23:22 > An: squeak-dev at lists.squeakfoundation.org > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > All, > > How about: > > Object>>isInspectable ^true > ByteString>>isInspectable ^false > Number>>isInspectable ^false > ... > > so inspectors can skip unitary objects? > > Just a thought .. Subbu > > On 19/04/21 8:36 pm, Marcel Taeumel wrote: > > Hi Christoph, hi all. > > > > I think that we should not highlight the following kinds of Objects to > > reserve this feature for really interesting structures that are worth > > inspecting without an extra evaluate. The kinds to ignore are: > > > > ByteString > > ByteSymbol > > Number > > Boolean > > UndefinedObject > > > > So, we can use both (1) visuals and (2) interactivity to let the more > > complex objects say: "Hey, I have interesting structure! Did you mix up > > print-it with inspect-it? No worries, just click on me." > > > > This effect will not be if any stoopid literal gets this treatment. :-) > > > > Best, > > Marcel > >> > >> Am 19.04.2021 13:21:53 schrieb Thiede, Christoph > >> : > >> > >> Hi Marcel, > >> > >> > >> I still stumble upon this edge case for some print-it results that do > >> not support click-to-inspect. Why do we need this exception? :-) > >> > >> > >> > > Also consider this snippet where the print-link does not exist for > >> an MCVersionName > >> > > >> > Looks fine. > >> > >> I don't think it looks fine, why do you think so? :-) > >> > >> Best, > >> Christoph > >> ------------------------------------------------------------------------ > >> *Von:* Squeak-dev im > >> Auftrag von Taeumel, Marcel > >> *Gesendet:* Freitag, 16. April 2021 19:52:16 > >> *An:* squeak-dev > >> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > >> Hi Christoph, > >> > >> I think that this clickable link is a compromise between printString > >> and storeString. For mouse navigation, you can always choose "inspect > >> it" from the context menu on that text selection. ;-) I also found the > >> link color annyoing for simple literals. > >> > >> > Also consider this snippet where the print-link does not exist for > >> an MCVersionName > >> > >> Looks fine. ^__^ I am certain that we will collect more feedback on > >> this feature during the next weeks and months. Let's refine it then. > >> > >> Best, > >> Marcel > >>> > >>> Am 16.04.2021 18:39:10 schrieb Thiede, Christoph > >>> : > >>> > >>> Hi Marcel, it's great that you have found a solution to this idea! :-) > >>> > >>> > >>> > + ^ (self class interactivePrintIt and: [(anObject isString > >>> or: [anObject isNumber]) not]) > >>> > >>> > >>> Is this necessary? I know that an inspector for a literal object like > >>> these does not make great sense, but this just feels like an > >>> unnecessary heuristic and limitation for me and adds complexity. I > >>> would like to be able to open an inspector always. Also consider this > >>> snippet where the print-link does not exist for an MCVersionName: :-) > >>> > >>> MCRepository inbox allFileNames first > >>> > >>> > >>> > CI scripts will default to "true". > >>> > >>> > >>> Unfortunately, no, mine just timed out while preparing the image. > >>> Also, my server images for @SqueakSmalltalkBot were interrupted. I'd > >>> opt for keeping preamble/postscript content in the update stream > >>> strictly non-interactive. :-) > >>> > >>> > >>> Best, > >>> > >>> Christoph > >>> > >>> > >>> ------------------------------------------------------------------------ > >>> *Von:* Squeak-dev im > >>> Auftrag von Taeumel, Marcel > >>> *Gesendet:* Freitag, 16. April 2021 17:27:54 > >>> *An:* squeak-dev > >>> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > >>> Hi all! > >>> > >>> It is now in Trunk. You can opt-out via the preference browser. > >>> Still, you will be asked the first time when you update your image. > >>> CI scripts will default to "true". > >>> > >>> Best, > >>> Marcel > >>>> > >>>> Am 17.11.2019 17:36:11 schrieb Jakob Reschke : > >>>> > >>>> Thiede, Christoph >>>> > schrieb am > >>>> Fr., 15. Nov. 2019, 09:38: > >>>> > >>>> > >>>> Just another idea (I seem to have too many of them :D): Some > >>>> kind of UnderlyingObjectAttribute (with a better name, of > >>>> course) an editor can check the selection before compiling it > >>>> when inspectIt/exploreIt is pressed? > >>>> > >>>> > >>>> Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor > >>>> checks for UnderylingObjectAttribute -> none found, so the > >>>> string is compilaed as usual. > >>>> > >>>> Example 2: (Text string: '2 + 3' attributes: > >>>> (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> > >>>> Editor finds an UnderylingObjectAttribute -> instead of > >>>> compiling the selection, the cached result is reused for > >>>> the inspector. > >>>> > >>>> We would not even need to display this Attribute visually if it > >>>> works reliably. > >>>> > >>>> > >>>> Make sure it is transient in some way because it would be quite > >>>> annoying if the hidden object were out of date with regards to the text. > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Mon Apr 19 17:46:40 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 19 Apr 2021 19:46:40 +0200 Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: <4b820f30aa3d467e8b1e8db6a22765de@student.hpi.uni-potsdam.de> References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> <4b820f30aa3d467e8b1e8db6a22765de@student.hpi.uni-potsdam.de> Message-ID: In this particular case, I would suggest myOwner, mySubmorphs. Am Mo., 19. Apr. 2021 um 19:43 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > Hi Eliot, hi Marcel, > > > > I’m removing shadows, not adding new ones. > > > I do not doubt this. I only wanted to point to the fact that your > refactoring is completely free of safety. If someone else says, "Hey, these > names are too long, let's shorten them", then the shadows might be > introduced again and no one will notice. A change in tooling could prevent > this problem; otherwise, automated tests would do, too. Just a notice. :-) > > > > I just noticed that I am finde with "aMorph" as a method argument, yet > I would never use "a" in a block argument. :-D Strange. > > +1. I also use roles as names (but I do not really like it - these are not > really explaining names). Abbreviations are counter-intuitive, too. Another > option is "ea", but this only good for very small methods, if at all. I use > "some" analogously to "a" for method parameters that should be collections. > Maybe "the" might be a better pattern for naming block args? :-) > > > self owner ifNotNil: [:theOwner | "..."]. > > self submorphs ifNotEmpty: [:theSubmorphs | "..."]. > > Best, > Christoph > > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Taeumel, Marcel > *Gesendet:* Sonntag, 18. April 2021 14:44:32 > *An:* squeak-dev > *Betreff:* Re: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) > > Hi Christoph, hi Eliot, > > it might be that the likelihood of shadowing increases with the use of > cull'ed block invocations, which we have been supporting more and more in > the last years: > > self owner ifNotNil: [:owner | "..."]. > self submorphs ifNotEmpty: [:submorphs | "..."]. > > As alternative names, one could drop their actual "role" and just use > their kinds (as generic as desired): > > self owner ifNotNil: [:morph | "..."]. > self submorphs ifNotEmpty: [:morphs | "..."]. > self submorphs ifNotEmpty: [:objects | "..."]. > > In the past, I happened to mistakenly have used the wrong role, shadowing > the right one: > > self allOwnersDo: [:owner | "..."]. > self allOwnersDo: [:morph | "..."]. > > Yet, we do have misleading protocol on what to actually call "owner." Just > the morph that has me directly in its submorphs? That might be another > topic. :-) > > *** > > To avoid shadowing, I find myself using (a) abbreviations, (b) kind/class, > or (c) count-prefix "a" or "some". Or a combination of those. > Unfortunately, omitting the domain-specific role in a name might impair > readability. > > I just noticed that I am finde with "aMorph" as a method argument, yet I > would never use "a" in a block argument. :-D Strange. > > Best, > Marcel > > Am 18.04.2021 05:39:33 schrieb Eliot Miranda : > Hi Christoph, > > > > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: > > > > Hi Eliot, > > > > I fear that changes like this will not be very durable unless tested in > any > > way. At the moment, you won't even notice a new shadow unless you have > > opened a Transcript by accident when accepting a method. Should we maybe > > show a message window for shadows instead when compiled interactively, > > analogously to the warnings about superfluous temps? > > I’m removing shadows, not adding new ones. In all cars I saw eleven ing s > from the compiler in the update stream and replaced shadowed temp cars by > renamed temp vars. So my changes have no semantic effect and only remove > the warning. > > > > > (In a larger context, I would strongly opt for (finally) introducing a > > mechanism for linter/compiler annotations in CodeHolders. Most modern > > editors and IDEs have it, even Pharo; if Squeak does not want to get left > > behind, we should support something like this, too. It could or should be > > configurable, of course.) > > > > LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal > name > > for a variable that holds Morph instances, right? :) > > > > Best, > > Christoph > > > > > > > > ----- > > Carpe Squeak! > > -- > > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:47:50 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:47:50 +0000 Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> <4b820f30aa3d467e8b1e8db6a22765de@student.hpi.uni-potsdam.de>, Message-ID: Also possible. :-) Whereas personally, I associate the "my" prefix with demo and example code but not production. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Jakob Reschke Gesendet: Montag, 19. April 2021 19:46:40 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In this particular case, I would suggest myOwner, mySubmorphs. Am Mo., 19. Apr. 2021 um 19:43 Uhr schrieb Thiede, Christoph >: Hi Eliot, hi Marcel, > I’m removing shadows, not adding new ones. I do not doubt this. I only wanted to point to the fact that your refactoring is completely free of safety. If someone else says, "Hey, these names are too long, let's shorten them", then the shadows might be introduced again and no one will notice. A change in tooling could prevent this problem; otherwise, automated tests would do, too. Just a notice. :-) > I just noticed that I am finde with "aMorph" as a method argument, yet I would never use "a" in a block argument. :-D Strange. +1. I also use roles as names (but I do not really like it - these are not really explaining names). Abbreviations are counter-intuitive, too. Another option is "ea", but this only good for very small methods, if at all. I use "some" analogously to "a" for method parameters that should be collections. Maybe "the" might be a better pattern for naming block args? :-) > self owner ifNotNil: [:theOwner | "..."]. > self submorphs ifNotEmpty: [:theSubmorphs | "..."]. Best, Christoph ________________________________ Von: Squeak-dev > im Auftrag von Taeumel, Marcel Gesendet: Sonntag, 18. April 2021 14:44:32 An: squeak-dev Betreff: Re: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) Hi Christoph, hi Eliot, it might be that the likelihood of shadowing increases with the use of cull'ed block invocations, which we have been supporting more and more in the last years: self owner ifNotNil: [:owner | "..."]. self submorphs ifNotEmpty: [:submorphs | "..."]. As alternative names, one could drop their actual "role" and just use their kinds (as generic as desired): self owner ifNotNil: [:morph | "..."]. self submorphs ifNotEmpty: [:morphs | "..."]. self submorphs ifNotEmpty: [:objects | "..."]. In the past, I happened to mistakenly have used the wrong role, shadowing the right one: self allOwnersDo: [:owner | "..."]. self allOwnersDo: [:morph | "..."]. Yet, we do have misleading protocol on what to actually call "owner." Just the morph that has me directly in its submorphs? That might be another topic. :-) *** To avoid shadowing, I find myself using (a) abbreviations, (b) kind/class, or (c) count-prefix "a" or "some". Or a combination of those. Unfortunately, omitting the domain-specific role in a name might impair readability. I just noticed that I am finde with "aMorph" as a method argument, yet I would never use "a" in a block argument. :-D Strange. Best, Marcel Am 18.04.2021 05:39:33 schrieb Eliot Miranda >: Hi Christoph, > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: > > Hi Eliot, > > I fear that changes like this will not be very durable unless tested in any > way. At the moment, you won't even notice a new shadow unless you have > opened a Transcript by accident when accepting a method. Should we maybe > show a message window for shadows instead when compiled interactively, > analogously to the warnings about superfluous temps? I’m removing shadows, not adding new ones. In all cars I saw eleven ing s from the compiler in the update stream and replaced shadowed temp cars by renamed temp vars. So my changes have no semantic effect and only remove the warning. > > (In a larger context, I would strongly opt for (finally) introducing a > mechanism for linter/compiler annotations in CodeHolders. Most modern > editors and IDEs have it, even Pharo; if Squeak does not want to get left > behind, we should support something like this, too. It could or should be > configurable, of course.) > > LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal name > for a variable that holds Morph instances, right? :) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 19 17:53:13 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 19 Apr 2021 17:53:13 +0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1751.mcz In-Reply-To: References: <33e41b5ded384590816403a6340c0ce0@student.hpi.uni-potsdam.de>, Message-ID: <8261ba7128424789a0a31946c97b2311@student.hpi.uni-potsdam.de> Hi Marcel, here are some example selectors: #doButtonAction, #performAction, #value ... While these all are non-recommended selector names, they can occur indeed (and a have indeed a project that forwards clicks from one button to another so the selector is #doButtonAction), and this is why I think that "debug button action" should be more robust against them. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Mittwoch, 14. April 2021 13:03:41 An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Morphic-mt.1751.mcz Hi Christoph, > In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. Can you give me 1 example? :-) Since we begin directly with calling the target ... how should anything interfere? Are you thinking about MethodWrappers? Best, Marcel Am 14.04.2021 12:25:22 schrieb Thiede, Christoph : Thank you for improving this! I already had a similar hack in my image for some time, but your solution is cleaner, of course. When putting further efforts into this construction site, I would like to kindly ask you again to take a look at System-ct.1149. :-) In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. > I refrained from adding the debug/browse interface for button actions to Morph. I don't really see the problem here, Morph includes a lot of functionalities that are only used by certain subclasses. Anyway, could this be worth a trait, TMorphWithAction, or something similar? On the other hand, one morph might support multiple actions, so a generic solution would have its advantages ... Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 14. April 2021 11:19:46 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-mt.1751.mcz Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1751.mcz ==================== Summary ==================== Name: Morphic-mt.1751 Author: mt Time: 14 April 2021, 11:19:35.123489 am UUID: 8fa68c8f-44ca-4d4a-a9e7-f69619be782e Ancestors: Morphic-mt.1750 Slightly improve browsing and debugging of so-called "button actions" by also supporting #perform:orSendTo:, which yields #effectiveActionTarget and #effectiveActionSelector. (Note that this design is still to be improved. I refrained from adding the debug/browse interface for button actions to Morph. A next step might be to take a look at all implementors of #doButtonAction. Maybe this will generate some ideas.) =============== Diff against Morphic-mt.1750 =============== Item was removed: - ----- Method: MenuItemMorph>>browseAllImplementorsOfRealSelector (in category 'browse') ----- - browseAllImplementorsOfRealSelector - SystemNavigation default browseAllImplementorsOf: self realSelector localTo: target class! Item was changed: ----- Method: MenuItemMorph>>browseImplementationOfActionSelector (in category 'browse') ----- browseImplementationOfActionSelector | method | + method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. - method := target class lookupSelector: selector. ToolSet browse: method methodClass selector: method selector.! Item was changed: ----- Method: MenuItemMorph>>debugAction (in category 'browse') ----- debugAction (Process forBlock: [self doButtonAction] + runUntil: [:context | context selector = self effectiveActionSelector]) - runUntil: [:context | context selector = self selector]) debugWithTitle: ('Debug menu action "{1}" in model "{2}"' format: {self contents. self target printString}).! Item was added: + ----- Method: MenuItemMorph>>effectiveActionSelector (in category 'browse') ----- + effectiveActionSelector + + ^ self selector = #perform:orSendTo: + ifTrue: [self arguments first] + ifFalse: [self selector]! Item was added: + ----- Method: MenuItemMorph>>effectiveActionTarget (in category 'browse') ----- + effectiveActionTarget + + ^ (self selector = #perform:orSendTo: + and: [(self target respondsTo: self effectiveActionSelector) not]) + ifTrue: [self arguments second] + ifFalse: [self target]! Item was removed: - ----- Method: MenuItemMorph>>realSelector (in category 'browse') ----- - realSelector - selector == #perform:orSendTo: ifTrue: [^arguments first]. - ^selector! Item was changed: ----- Method: Morph>>doButtonAction (in category 'button') ----- doButtonAction + "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. It is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programmatically from user scripts."! - "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing. Note that there are several ways -- too many ways -- for morphs to have button-like actions. This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism. Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts"! Item was changed: ----- Method: PluggableButtonMorph>>browseImplementationOfActionSelector (in category 'debug menu') ----- browseImplementationOfActionSelector | method | + self updateArguments. + method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. - method := model class lookupSelector: actionSelector. ToolSet browse: method methodClass selector: method selector.! Item was changed: ----- Method: PluggableButtonMorph>>debugAction (in category 'debug menu') ----- debugAction + self updateArguments. + (Process + forBlock: [self doButtonAction] + runUntil: [:context | context selector = self effectiveActionSelector]) - forBlock: [self performAction] - runUntil: [:context | context selector = self actionSelector]) debugWithTitle: ('Debug button action "{1}" in model "{2}"' format: {self label. self target printString}).! Item was added: + ----- Method: PluggableButtonMorph>>doButtonAction (in category 'button') ----- + doButtonAction + + ^ self performAction! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionSelector (in category 'debug menu') ----- + effectiveActionSelector + + ^ self actionSelector = #perform:orSendTo: + ifTrue: [arguments first] + ifFalse: [self actionSelector]! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionTarget (in category 'debug menu') ----- + effectiveActionTarget + + ^ (self actionSelector = #perform:orSendTo: + and: [(self target respondsTo: self effectiveActionSelector) not]) + ifTrue: [arguments second] + ifFalse: [self target]! Item was changed: + ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout-properties') ----- hResizing: aSymbol "We adapt our minimum extent according to our resize behavior." self hResizing == aSymbol ifTrue: [^ self]. super hResizing: aSymbol. self updateMinimumExtent.! Item was changed: + ----- Method: PluggableButtonMorph>>performAction (in category 'event handling') ----- - ----- Method: PluggableButtonMorph>>performAction (in category 'accessing') ----- performAction "Inform the model that this button has been pressed. Sent by the controller when this button is pressed. If the button's actionSelector takes any arguments, they are obtained dynamically by sending the argumentSelector to the argumentsProvider" askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]]. actionSelector ifNotNil: [actionSelector numArgs = 0 ifTrue: [model perform: actionSelector] ifFalse: + [self updateArguments. - [argumentsProvider ifNotNil: - [arguments := argumentsProvider perform: argumentsSelector]. model perform: actionSelector withArguments: arguments]]! Item was added: + ----- Method: PluggableButtonMorph>>updateArguments (in category 'updating') ----- + updateArguments + + argumentsProvider ifNil: [^ self]. + argumentsSelector ifNil: [^ self]. + arguments := argumentsProvider perform: argumentsSelector.! Item was changed: + ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout-properties') ----- vResizing: aSymbol "We adapt our minimum extent according to our resize behavior." self vResizing == aSymbol ifTrue: [^ self]. super vResizing: aSymbol. self updateMinimumExtent.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From Das.Linux at gmx.de Mon Apr 19 17:56:57 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 19 Apr 2021 19:56:57 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: <353609d15e534f0f8dc167687a8d1a05@student.hpi.uni-potsdam.de> References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> <353609d15e534f0f8dc167687a8d1a05@student.hpi.uni-potsdam.de> Message-ID: > On 19. Apr 2021, at 19:44, Thiede, Christoph wrote: > > Hi Tobias, > > yes, I know. Then let's correct my formulation into: "this functionality check is something bad and unexpected". :-) Ok, I don't really understand your reasoning… -t > > Best, > Christoph > Von: Squeak-dev im Auftrag von Tobias Pape > Gesendet: Montag, 19. April 2021 19:40:43 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > Hi Christoph > > > > On 19. Apr 2021, at 19:29, Thiede, Christoph wrote: > > > > Hi Marcel, hi all, > > > > I keeping considering this type check as something bad and unexpected. :-) > > Note that in this instance, 'isInspectable' is actually a plain behavior check, not a type check at all. > It's not "isMorph" or something. While "is*" is often used/misused/abused as type check, this kind here is actually not one of these : > > Best regards > -Tobias > > > > > First, as I have mentioned earlier, subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example. Second, even a string can be non-trivial, for instance, "String value: 1234", where I only will see a question mark unless I inspect the result. Yes, in the second example, I could also trouble the Compiler again for a new inspect-it, but I just don't see why we should restrict these useful links for certain types of results. Also, in all situations where you do some experiments concerning identity, an inspector would be very helpful to track individual instances. Re-evaluating the expression would not be a solution here. > > > > To summarize, I just would not say that any object in Squeak can have a boring structure. It's just the other way around, these clickable results are a great way to make the inspector more visible in the system. > > > > PS: We should also consider making the new links available for print-its in the search bar. > > > > Best, > > Christoph > > Von: Squeak-dev im Auftrag von K K Subbu > > Gesendet: Montag, 19. April 2021 18:23:22 > > An: squeak-dev at lists.squeakfoundation.org > > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > > > All, > > > > How about: > > > > Object>>isInspectable ^true > > ByteString>>isInspectable ^false > > Number>>isInspectable ^false > > ... > > > > so inspectors can skip unitary objects? > > > > Just a thought .. Subbu > > > > On 19/04/21 8:36 pm, Marcel Taeumel wrote: > > > Hi Christoph, hi all. > > > > > > I think that we should not highlight the following kinds of Objects to > > > reserve this feature for really interesting structures that are worth > > > inspecting without an extra evaluate. The kinds to ignore are: > > > > > > ByteString > > > ByteSymbol > > > Number > > > Boolean > > > UndefinedObject > > > > > > So, we can use both (1) visuals and (2) interactivity to let the more > > > complex objects say: "Hey, I have interesting structure! Did you mix up > > > print-it with inspect-it? No worries, just click on me." > > > > > > This effect will not be if any stoopid literal gets this treatment. :-) > > > > > > Best, > > > Marcel > > >> > > >> Am 19.04.2021 13:21:53 schrieb Thiede, Christoph > > >> : > > >> > > >> Hi Marcel, > > >> > > >> > > >> I still stumble upon this edge case for some print-it results that do > > >> not support click-to-inspect. Why do we need this exception? :-) > > >> > > >> > > >> > > Also consider this snippet where the print-link does not exist for > > >> an MCVersionName > > >> > > > >> > Looks fine. > > >> > > >> I don't think it looks fine, why do you think so? :-) > > >> > > >> Best, > > >> Christoph > > >> ------------------------------------------------------------------------ > > >> *Von:* Squeak-dev im > > >> Auftrag von Taeumel, Marcel > > >> *Gesendet:* Freitag, 16. April 2021 19:52:16 > > >> *An:* squeak-dev > > >> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > >> Hi Christoph, > > >> > > >> I think that this clickable link is a compromise between printString > > >> and storeString. For mouse navigation, you can always choose "inspect > > >> it" from the context menu on that text selection. ;-) I also found the > > >> link color annyoing for simple literals. > > >> > > >> > Also consider this snippet where the print-link does not exist for > > >> an MCVersionName > > >> > > >> Looks fine. ^__^ I am certain that we will collect more feedback on > > >> this feature during the next weeks and months. Let's refine it then. > > >> > > >> Best, > > >> Marcel > > >>> > > >>> Am 16.04.2021 18:39:10 schrieb Thiede, Christoph > > >>> : > > >>> > > >>> Hi Marcel, it's great that you have found a solution to this idea! :-) > > >>> > > >>> > > >>> > + ^ (self class interactivePrintIt and: [(anObject isString > > >>> or: [anObject isNumber]) not]) > > >>> > > >>> > > >>> Is this necessary? I know that an inspector for a literal object like > > >>> these does not make great sense, but this just feels like an > > >>> unnecessary heuristic and limitation for me and adds complexity. I > > >>> would like to be able to open an inspector always. Also consider this > > >>> snippet where the print-link does not exist for an MCVersionName: :-) > > >>> > > >>> MCRepository inbox allFileNames first > > >>> > > >>> > > >>> > CI scripts will default to "true". > > >>> > > >>> > > >>> Unfortunately, no, mine just timed out while preparing the image. > > >>> Also, my server images for @SqueakSmalltalkBot were interrupted. I'd > > >>> opt for keeping preamble/postscript content in the update stream > > >>> strictly non-interactive. :-) > > >>> > > >>> > > >>> Best, > > >>> > > >>> Christoph > > >>> > > >>> > > >>> ------------------------------------------------------------------------ > > >>> *Von:* Squeak-dev im > > >>> Auftrag von Taeumel, Marcel > > >>> *Gesendet:* Freitag, 16. April 2021 17:27:54 > > >>> *An:* squeak-dev > > >>> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > >>> Hi all! > > >>> > > >>> It is now in Trunk. You can opt-out via the preference browser. > > >>> Still, you will be asked the first time when you update your image. > > >>> CI scripts will default to "true". > > >>> > > >>> Best, > > >>> Marcel > > >>>> > > >>>> Am 17.11.2019 17:36:11 schrieb Jakob Reschke : > > >>>> > > >>>> Thiede, Christoph > >>>> > schrieb am > > >>>> Fr., 15. Nov. 2019, 09:38: > > >>>> > > >>>> > > >>>> Just another idea (I seem to have too many of them :D): Some > > >>>> kind of UnderlyingObjectAttribute (with a better name, of > > >>>> course) an editor can check the selection before compiling it > > >>>> when inspectIt/exploreIt is pressed? > > >>>> > > >>>> > > >>>> Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor > > >>>> checks for UnderylingObjectAttribute -> none found, so the > > >>>> string is compilaed as usual. > > >>>> > > >>>> Example 2: (Text string: '2 + 3' attributes: > > >>>> (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> > > >>>> Editor finds an UnderylingObjectAttribute -> instead of > > >>>> compiling the selection, the cached result is reused for > > >>>> the inspector. > > >>>> > > >>>> We would not even need to display this Attribute visually if it > > >>>> works reliably. > > >>>> > > >>>> > > >>>> Make sure it is transient in some way because it would be quite > > >>>> annoying if the hidden object were out of date with regards to the text. > > > > > > From jakres+squeak at gmail.com Mon Apr 19 18:10:55 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 19 Apr 2021 20:10:55 +0200 Subject: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) In-Reply-To: References: <1618255943259-0.post@n4.nabble.com> <4291349C-52B2-44A8-A6C9-BC525205C676@gmail.com> <4b820f30aa3d467e8b1e8db6a22765de@student.hpi.uni-potsdam.de> Message-ID: No great difference there: if your demo or example code were an instance, myThing might also have been the result of `self thing`. ;-) Am Mo., 19. Apr. 2021 um 19:47 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > Also possible. :-) Whereas personally, I associate the "my" prefix with > demo and example code but not production. :-) > > Best, > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Jakob Reschke > *Gesendet:* Montag, 19. April 2021 19:46:40 > *An:* The general-purpose Squeak developers list > *Betreff:* Re: [squeak-dev] Shadows (was: The Trunk: Morphic-eem.1742.mcz) > > In this particular case, I would suggest myOwner, mySubmorphs. > > Am Mo., 19. Apr. 2021 um 19:43 Uhr schrieb Thiede, Christoph < > Christoph.Thiede at student.hpi.uni-potsdam.de>: > >> Hi Eliot, hi Marcel, >> >> >> > I’m removing shadows, not adding new ones. >> >> >> I do not doubt this. I only wanted to point to the fact that your >> refactoring is completely free of safety. If someone else says, "Hey, these >> names are too long, let's shorten them", then the shadows might be >> introduced again and no one will notice. A change in tooling could prevent >> this problem; otherwise, automated tests would do, too. Just a notice. :-) >> >> >> > I just noticed that I am finde with "aMorph" as a method argument, yet >> I would never use "a" in a block argument. :-D Strange. >> >> +1. I also use roles as names (but I do not really like it - these are >> not really explaining names). Abbreviations are counter-intuitive, too. >> Another option is "ea", but this only good for very small methods, if at >> all. I use "some" analogously to "a" for method parameters that should be >> collections. Maybe "the" might be a better pattern for naming block args? >> :-) >> >> > self owner ifNotNil: [:theOwner | "..."]. >> > self submorphs ifNotEmpty: [:theSubmorphs | "..."]. >> >> Best, >> Christoph >> >> ------------------------------ >> *Von:* Squeak-dev im >> Auftrag von Taeumel, Marcel >> *Gesendet:* Sonntag, 18. April 2021 14:44:32 >> *An:* squeak-dev >> *Betreff:* Re: [squeak-dev] Shadows (was: The Trunk: >> Morphic-eem.1742.mcz) >> >> Hi Christoph, hi Eliot, >> >> it might be that the likelihood of shadowing increases with the use of >> cull'ed block invocations, which we have been supporting more and more in >> the last years: >> >> self owner ifNotNil: [:owner | "..."]. >> self submorphs ifNotEmpty: [:submorphs | "..."]. >> >> As alternative names, one could drop their actual "role" and just use >> their kinds (as generic as desired): >> >> self owner ifNotNil: [:morph | "..."]. >> self submorphs ifNotEmpty: [:morphs | "..."]. >> self submorphs ifNotEmpty: [:objects | "..."]. >> >> In the past, I happened to mistakenly have used the wrong role, shadowing >> the right one: >> >> self allOwnersDo: [:owner | "..."]. >> self allOwnersDo: [:morph | "..."]. >> >> Yet, we do have misleading protocol on what to actually call "owner." >> Just the morph that has me directly in its submorphs? That might be another >> topic. :-) >> >> *** >> >> To avoid shadowing, I find myself using (a) abbreviations, (b) >> kind/class, or (c) count-prefix "a" or "some". Or a combination of those. >> Unfortunately, omitting the domain-specific role in a name might impair >> readability. >> >> I just noticed that I am finde with "aMorph" as a method argument, yet I >> would never use "a" in a block argument. :-D Strange. >> >> Best, >> Marcel >> >> Am 18.04.2021 05:39:33 schrieb Eliot Miranda : >> Hi Christoph, >> >> >> > On Apr 12, 2021, at 12:32 PM, Christoph Thiede wrote: >> > >> > Hi Eliot, >> > >> > I fear that changes like this will not be very durable unless tested in >> any >> > way. At the moment, you won't even notice a new shadow unless you have >> > opened a Transcript by accident when accepting a method. Should we maybe >> > show a message window for shadows instead when compiled interactively, >> > analogously to the warnings about superfluous temps? >> >> I’m removing shadows, not adding new ones. In all cars I saw eleven ing s >> from the compiler in the update stream and replaced shadowed temp cars by >> renamed temp vars. So my changes have no semantic effect and only remove >> the warning. >> >> > >> > (In a larger context, I would strongly opt for (finally) introducing a >> > mechanism for linter/compiler annotations in CodeHolders. Most modern >> > editors and IDEs have it, even Pharo; if Squeak does not want to get >> left >> > behind, we should support something like this, too. It could or should >> be >> > configurable, of course.) >> > >> > LBNL, if I understand Chris correctly, "anOwner" might be a suboptimal >> name >> > for a variable that holds Morph instances, right? :) >> > >> > Best, >> > Christoph >> > >> > >> > >> > ----- >> > Carpe Squeak! >> > -- >> > Sent from: http://forum.world.st/Squeak-Dev-f45488.html >> > >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Mon Apr 19 19:11:55 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 19 Apr 2021 21:11:55 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1389.mcz In-Reply-To: References: Message-ID: Hi Nicolas, Is there a particular reason why the handlers should not be reactivated in resumeUnchecked:? I used resumeUnchecked: in a test case, which got broken. In this particular case I don't remember the necessity for resumeUnchecked: and could make the test green again by changing to plain resume:. Kind regards, Jakob Am Fr., 16. Apr. 2021 um 21:42 Uhr schrieb : > Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > http://source.squeak.org/trunk/Kernel-nice.1389.mcz > > ==================== Summary ==================== > > Name: Kernel-nice.1389 > Author: nice > Time: 16 April 2021, 9:42:34.176501 pm > UUID: 895e77fd-ce0e-484f-ad8a-00564ca98639 > Ancestors: Kernel-nice.1388 > > Fix missing reactivation of handlers upon resume; > > It is the responsibility of handling actions to rearm the handlers that > have been disabled during the search of active handler. > > =============== Diff against Kernel-nice.1388 =============== > > Item was changed: > ----- Method: Exception>>resume: (in category 'handling') ----- > resume: resumptionValue > "Return resumptionValue as the value of the signal message." > > self isResumable ifFalse: [IllegalResumeAttempt signal]. > + self reactivateHandlers. > self resumeUnchecked: resumptionValue! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 19 19:18:14 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 19 Apr 2021 19:18:14 0000 Subject: [squeak-dev] The Trunk: Tests-nice.455.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.455.mcz ==================== Summary ==================== Name: Tests-nice.455 Author: nice Time: 19 April 2021, 9:18:01.955183 pm UUID: 94f23508-c48c-0d47-8588-b2367071c298 Ancestors: Tests-nice.454 Two unrelated changes: 1) Kernel does not depend on Multilingual anymore (really?) Aknowledge this little victory before the dependecy come back. Alas, Kernel now depend on Morphic due to MouseEvent so the test still fails. Either EventSensor shouldn't be in Kernel, or MouseEvent should not be in Morphic (or both?)... 2) workaround source range test in presence of FullBlockClosure My understanding is that full block bytecodes are not hosted in their home method. As a consequence, full block also have their own PC. So a simple PC map is not elaborate enough to test the selection inside the block. By now, just skip the test of selection inside the full block closure. If some good soul wants to revise the test and make it thorough again, welcome! =============== Diff against Tests-nice.454 =============== Item was changed: ----- Method: ClosureCompilerTest>>supportTestSourceRangeAccessForInjectInto:source: (in category 'tests') ----- supportTestSourceRangeAccessForInjectInto: method source: source "Test debugger source range selection for inject:into:" ^self supportTestSourceRangeAccessForInjectInto: method source: source + selectionSequence: (method encoderClass supportsFullBlocks + ifTrue: ["Full blocks are searated from home method, with their own PC" + #( ':= thisValue' + 'do: [:each | nextValue := binaryBlock value: nextValue value: each]' + '^nextValue')] + ifFalse: [#( ':= thisValue' + 'do: [:each | nextValue := binaryBlock value: nextValue value: each]' + 'value: nextValue value: each' + ':= binaryBlock value: nextValue value: each' + 'nextValue := binaryBlock value: nextValue value: each' + 'value: nextValue value: each' + ':= binaryBlock value: nextValue value: each' + 'nextValue := binaryBlock value: nextValue value: each' + '^nextValue')]).! - selectionSequence: #( ':= thisValue' - 'do: [:each | nextValue := binaryBlock value: nextValue value: each]' - 'value: nextValue value: each' - ':= binaryBlock value: nextValue value: each' - 'nextValue := binaryBlock value: nextValue value: each' - 'value: nextValue value: each' - ':= binaryBlock value: nextValue value: each' - 'nextValue := binaryBlock value: nextValue value: each' - '^nextValue')! Item was changed: ----- Method: ClosureCompilerTest>>supportTestSourceRangeAccessForInjectInto:source:selectionSequence: (in category 'tests') ----- supportTestSourceRangeAccessForInjectInto: method source: source selectionSequence: selections "Test debugger source range selection for inject:into:" | evaluationCount sourceMap debugTokenSequence debugCount | DebuggerMethodMap voidMapCache. evaluationCount := 0. + sourceMap := method debuggerMap abstractSourceMapForMethod: method. - sourceMap := method debuggerMap abstractSourceMap. debugTokenSequence := selections collect: [:string| Scanner new scanTokens: string]. debugCount := 0. thisContext runSimulated: [(1 to: 2) withArgs: { 0. [:sum :each| evaluationCount := evaluationCount + 1. sum + each]} executeMethod: method] contextAtEachStep: [:ctxt| | range debugTokens | (ctxt method == method and: ["Exclude the send of #blockCopy: or #closureCopy:copiedValues: and braceWith:with: to create the block, and the #new: and #at:'s for the indirect temp vector. This for compilation without closure bytecodes. (Note that at:put:'s correspond to stores)" (ctxt willSend and: [(#(closureCopy:copiedValues: blockCopy: new: at: braceWith:with:) includes: ctxt selectorToSendOrSelf) not]) "Exclude the store of the argument into the home context (for BlueBook blocks) and the store of an indirection vector into an initial temp" or: [(ctxt willStore and: [(ctxt isBlock and: [ctxt pc = ctxt startpc]) not and: [(ctxt isBlock not and: [(method usesClosureBytecodes and: [ctxt abstractPC = 2])]) not]]) or: [ctxt willReturn]]]) ifTrue: [debugTokens := debugTokenSequence at: (debugCount := debugCount + 1) ifAbsent: [#(bogusToken)]. self assert: (sourceMap includesKey: ctxt abstractPC). range := sourceMap at: ctxt abstractPC ifAbsent: [(1 to: 0)]. self assert: (Scanner new scanTokens: (source copyFrom: range first to: range last)) = debugTokens]]. self assert: evaluationCount = 2! Item was changed: ----- Method: PackageDependencyTest>>testKernel (in category 'tests') ----- testKernel self testPackage: #Kernel dependsExactlyOn: #( #'Chronology-Core' Collections Compiler Environments Files - Multilingual System #'ToolBuilder-Kernel' ).! From nicolas.cellier.aka.nice at gmail.com Mon Apr 19 19:42:35 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 19 Apr 2021 21:42:35 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1389.mcz In-Reply-To: References: Message-ID: Hi Jakob, good question. I started from the case of defaultAction handling: exception resumeUnchecked: exception defaultAction. We want the handler reactivated before resuming, in order to handle a new Exception in the defaultAction itself. Hence: exception reactivateHandlers; resumeUnchecked: exception defaultAction. Reactivating in resumeUnchecked: would thus mean reactivating too late, or reactivating twice. I thus considered that resumeUnchecked: was sort of private; or rather let's say low level API. Using a lower level API also goes with endorsing more responsibility, like taking care to reactivateHandlers oneself. This is not ideal, because it puts more burden on programmer shoulders. We now have to decide at each send site whether we should reactivateHandlers or not. Also, I have not documented these contracts until now which is not a good thing either. I wanted to see how things will settle, documenting moving targets is not ideal either. Also, my 1st intention was to push to inbox. I committed to trunk accidentally! Fortunately, consequences have not been catastrophic so far. I had tested several variants before pushing, but still, this kind of change is scary ;) We still have to polish a bit. Marcel suggested to better document the reverse operation (deactivateHandler). We could more generally try and replace mysterious tempAt:put: with proper methods... Consider this as work in progress. Suggestions are welcome. Le lun. 19 avr. 2021 à 21:12, Jakob Reschke a écrit : > > Hi Nicolas, > > Is there a particular reason why the handlers should not be reactivated in resumeUnchecked:? > > I used resumeUnchecked: in a test case, which got broken. In this particular case I don't remember the necessity for resumeUnchecked: and could make the test green again by changing to plain resume:. > > Kind regards, > Jakob > > Am Fr., 16. Apr. 2021 um 21:42 Uhr schrieb : >> >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: >> http://source.squeak.org/trunk/Kernel-nice.1389.mcz >> >> ==================== Summary ==================== >> >> Name: Kernel-nice.1389 >> Author: nice >> Time: 16 April 2021, 9:42:34.176501 pm >> UUID: 895e77fd-ce0e-484f-ad8a-00564ca98639 >> Ancestors: Kernel-nice.1388 >> >> Fix missing reactivation of handlers upon resume; >> >> It is the responsibility of handling actions to rearm the handlers that have been disabled during the search of active handler. >> >> =============== Diff against Kernel-nice.1388 =============== >> >> Item was changed: >> ----- Method: Exception>>resume: (in category 'handling') ----- >> resume: resumptionValue >> "Return resumptionValue as the value of the signal message." >> >> self isResumable ifFalse: [IllegalResumeAttempt signal]. >> + self reactivateHandlers. >> self resumeUnchecked: resumptionValue! >> >> > From jakres+squeak at gmail.com Mon Apr 19 20:37:11 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 19 Apr 2021 22:37:11 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Hi Nicolas, I seem to have a Heisenbug now because of this: In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. But if I replace in MCMethodDefinition this: actualClass ^ self actualClassIn: Environment current by this: actualClass Environment current. ^ self actualClassIn: Environment current Then the test is suddenly green again. I suppose that is not acceptable. ;-) It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. Kind regards, Jakob Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > http://source.squeak.org/trunk/Kernel-nice.1384.mcz > > ==================== Summary ==================== > > Name: Kernel-nice.1384 > Author: nice > Time: 11 April 2021, 7:33:23.487481 pm > UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > Ancestors: Kernel-mt.1383 > > Another attempt at fixing #testHandlerFromAction. Unlike previous > attempts, this one preserves the expectations of #testHandlerReentrancy. > > The solution is to de-activate the handlers as we backtrack the stack, but > to reactivate them before performing final exception handling actions (like > resuming, resignalling or performing defaultAction). Indeed, those handlers > must be able to handle a secondary exception raised in the course of this > action. > > =============== Diff against Kernel-mt.1383 =============== > > Item was changed: > ----- Method: Context>>handleSignal: (in category 'private-exceptions') > ----- > handleSignal: exception > "Sent to handler (on:do:) contexts only. If my exception class > (first arg) handles exception > and the handler is active then execute my handle block (second > arg), otherwise forward > this message to the next handler context. If none left, execute > exception's defaultAction > (see nil>>handleSignal:)." > > | handlerActive val | > "If the context has been returned from the handlerActive temp var > may not be accessible." > handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > (((self tempAt: 1) handles: exception) and: [handlerActive]) > ifFalse: > + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > + ^self nextHandlerContext handleSignal: exception]. > - [^self nextHandlerContext handleSignal: exception]. > > exception privHandlerContext: self contextTag. > self tempAt: 3 put: false. "disable self while executing handle > block" > val := [(self tempAt: 2) cull: exception] > + ifCurtailed: [self tempAt: 3 put: true]. > - ensure: [self tempAt: 3 put: true]. > self return: val "return from self if not otherwise directed in > handle block" > ! > > Item was added: > + ----- Method: Context>>reactivateHandlers (in category > 'private-exceptions') ----- > + reactivateHandlers > + "Private - sent to exception handler context only (on:do:). > + Reactivate all the handlers into the chain" > + > + self tempAt: 3 put: true. "this is temporary handlerActive in > #on:do:" > + self nextHandlerContext reactivateHandlers! > > Item was added: > + ----- Method: Exception>>reactivateHandlers (in category 'priv > handling') ----- > + reactivateHandlers > + "reactivate all the exception handlers in the context chain" > + self canSearchForSignalerContext > + ifTrue: [signalContext nextHandlerContext > reactivateHandlers]! > > Item was changed: > ----- Method: Exception>>resignalAs: (in category 'handling') ----- > resignalAs: replacementException > "Signal an alternative exception in place of the receiver." > > + self reactivateHandlers. > self resumeUnchecked: replacementException signal! > > Item was changed: > ----- Method: UndefinedObject>>handleSignal: (in category 'bottom > context') ----- > handleSignal: exception > + "When no more handler (on:do:) context left in sender chain this > gets called. Return from signal with default action. > + Before doing that, reactivate the handlers so that they can catch > eventual secondary exceptions raised by defaultAction." > - "When no more handler (on:do:) context left in sender chain this > gets called. Return from signal with default action." > > + ^ exception reactivateHandlers; resumeUnchecked: exception > defaultAction! > - ^ exception resumeUnchecked: exception defaultAction! > > Item was added: > + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom > context') ----- > + reactivateHandlers > + "nothing to do for bottom context" > + > + ^ self! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Mon Apr 19 22:02:29 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Tue, 20 Apr 2021 00:02:29 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Looks like this does no longer work as before: SquotImageStoreTest>> suppressProgressDisplayDuring: aBlock ... aBlock on: ProgressInitiationException do: [:e | ... e rearmHandlerDuring: [[e sendNotificationsTo: [:min :max :current | "silence"]] on: ProgressNotification do: [:notification | notification resume]] ... rearmHandlerDuring: does reactivate this current handler, but not handlers further up the stack. So e sendNotificationsTo: will evaluate the block in the package loader that eventually unloads the method in the test case while all handlers that are between the ProgressInitiationException signal context and this ProgressInitiationException handler context on the stack are deactivated, including the one that sets the correct Environment (and also the source file caching, by the way). Find the annotated stack below for a little more visualization. Previously, the handler contexts that did not fit the raised Exception were not deactivated. Is the ProgressInitiationException redirection concept broken in general now? Note that the ZeroDivide in ProgressInitiationException>>testWith is now no longer caught. --- The redacted stack of my failing test with some ---annotations---> [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The block under 'Installing ', pkgName displayProgressFrom: ... ProgressInitiationException>>sendNotificationsTo: [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: FullBlockClosure(BlockClosure)>>on:do: [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: [] in Context>>rearmHandlerDuring: FullBlockClosure(BlockClosure)>>ensure: ---reactivated #1---> Context>>rearmHandlerDuring: ProgressInitiationException(Exception)>>rearmHandlerDuring: [] in SquotImageStoreTest>>suppressProgressDisplayDuring: [] in Context>>handleSignal: FullBlockClosure(BlockClosure)>>ifCurtailed: Context>>handleSignal: <--- #1 sender: SquotImageStoreTest>>suppressProgressDisplayDuring: ... Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles class>>cacheDuring: Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad ---triggers stack walk---> ProgressInitiationException(Exception)>>signal ProgressInitiationException>>display:at:from:to:during: ... ByteString(String)>>displayProgressFrom:to:during: [] in [] in [] in [] in MCPackageLoader>>basicLoad ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: [] in [] in [] in MCPackageLoader>>basicLoad ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: CurrentReadOnlySourceFiles class>>cacheDuring: ... MCPackageLoader>>basicLoad ... MCPackageLoader>>loadWithNameLike: [] in SquotPackageShadow>>squotMaterializeWith: ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: Environment>>beCurrentDuring: SquotPackageShadow>>squotMaterializeWith: ... SquotImageStoreTest>>testApplyPatch SquotImageStoreTest(TestCase)>>performTest [] in SquotImageStoreTest>>performTest ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: SquotImageStoreTest>>suppressProgressDisplayDuring: ... Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke : > > Hi Nicolas, > > I seem to have a Heisenbug now because of this: > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > But if I replace in MCMethodDefinition this: > > actualClass > ^ self actualClassIn: Environment current > > by this: > > actualClass > Environment current. > ^ self actualClassIn: Environment current > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > Kind regards, > Jakob > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : >> >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz >> >> ==================== Summary ==================== >> >> Name: Kernel-nice.1384 >> Author: nice >> Time: 11 April 2021, 7:33:23.487481 pm >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 >> Ancestors: Kernel-mt.1383 >> >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. >> >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. >> >> =============== Diff against Kernel-mt.1383 =============== >> >> Item was changed: >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- >> handleSignal: exception >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception >> and the handler is active then execute my handle block (second arg), otherwise forward >> this message to the next handler context. If none left, execute exception's defaultAction >> (see nil>>handleSignal:)." >> >> | handlerActive val | >> "If the context has been returned from the handlerActive temp var may not be accessible." >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. >> + ^self nextHandlerContext handleSignal: exception]. >> - [^self nextHandlerContext handleSignal: exception]. >> >> exception privHandlerContext: self contextTag. >> self tempAt: 3 put: false. "disable self while executing handle block" >> val := [(self tempAt: 2) cull: exception] >> + ifCurtailed: [self tempAt: 3 put: true]. >> - ensure: [self tempAt: 3 put: true]. >> self return: val "return from self if not otherwise directed in handle block" >> ! >> >> Item was added: >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- >> + reactivateHandlers >> + "Private - sent to exception handler context only (on:do:). >> + Reactivate all the handlers into the chain" >> + >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" >> + self nextHandlerContext reactivateHandlers! >> >> Item was added: >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- >> + reactivateHandlers >> + "reactivate all the exception handlers in the context chain" >> + self canSearchForSignalerContext >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! >> >> Item was changed: >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- >> resignalAs: replacementException >> "Signal an alternative exception in place of the receiver." >> >> + self reactivateHandlers. >> self resumeUnchecked: replacementException signal! >> >> Item was changed: >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- >> handleSignal: exception >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." >> >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! >> - ^ exception resumeUnchecked: exception defaultAction! >> >> Item was added: >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- >> + reactivateHandlers >> + "nothing to do for bottom context" >> + >> + ^ self! >> >> From jakres+squeak at gmail.com Mon Apr 19 22:08:30 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Tue, 20 Apr 2021 00:08:30 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Oh by the way, this was helpful to inspect the stack in the incorrect state: MCMethodDefinition>> actualClass (thisContext sender selector == #unload) ifTrue: [thisContext copyStack inspect]. ^ self actualClassIn: Environment current In the Inspector: | context | context := self nextHandlerContext. Array streamContents: [:str | [context notNil] whileTrue: [str nextPut: context. context := context nextHandlerContext]]. | context | context := self. Array streamContents: [:str | [context notNil] whileTrue: [str nextPut: context. context := context sender]]. Am Di., 20. Apr. 2021 um 00:02 Uhr schrieb Jakob Reschke : > > Looks like this does no longer work as before: > > SquotImageStoreTest>> > suppressProgressDisplayDuring: aBlock > ... > aBlock > on: ProgressInitiationException do: [:e | > ... > e rearmHandlerDuring: > [[e sendNotificationsTo: [:min :max :current | "silence"]] > on: ProgressNotification do: [:notification | > notification resume]] > ... > > rearmHandlerDuring: does reactivate this current handler, but not > handlers further up the stack. > So e sendNotificationsTo: will evaluate the block in the package > loader that eventually unloads the method in the test case while all > handlers that are between the ProgressInitiationException signal > context and this ProgressInitiationException handler context on the > stack are deactivated, including the one that sets the correct > Environment (and also the source file caching, by the way). Find the > annotated stack below for a little more visualization. > > Previously, the handler contexts that did not fit the raised Exception > were not deactivated. Is the ProgressInitiationException redirection > concept broken in general now? Note that the ZeroDivide in > ProgressInitiationException>>testWith is now no longer caught. > > --- The redacted stack of my failing test with some ---annotations---> > [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The > block under 'Installing ', pkgName displayProgressFrom: ... > ProgressInitiationException>>sendNotificationsTo: > [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > FullBlockClosure(BlockClosure)>>on:do: > [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > [] in Context>>rearmHandlerDuring: > FullBlockClosure(BlockClosure)>>ensure: > ---reactivated #1---> Context>>rearmHandlerDuring: > ProgressInitiationException(Exception)>>rearmHandlerDuring: > [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > [] in Context>>handleSignal: > FullBlockClosure(BlockClosure)>>ifCurtailed: > Context>>handleSignal: <--- #1 sender: > SquotImageStoreTest>>suppressProgressDisplayDuring: > ... > Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: > Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles > class>>cacheDuring: > Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad > ---triggers stack walk---> ProgressInitiationException(Exception)>>signal > ProgressInitiationException>>display:at:from:to:during: > ... > ByteString(String)>>displayProgressFrom:to:during: > [] in [] in [] in [] in MCPackageLoader>>basicLoad > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > [] in [] in [] in MCPackageLoader>>basicLoad > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > CurrentReadOnlySourceFiles class>>cacheDuring: > ... > MCPackageLoader>>basicLoad > ... > MCPackageLoader>>loadWithNameLike: > [] in SquotPackageShadow>>squotMaterializeWith: > ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: > Environment>>beCurrentDuring: > SquotPackageShadow>>squotMaterializeWith: > ... > SquotImageStoreTest>>testApplyPatch > SquotImageStoreTest(TestCase)>>performTest > [] in SquotImageStoreTest>>performTest > ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: > SquotImageStoreTest>>suppressProgressDisplayDuring: > ... > > Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke > : > > > > Hi Nicolas, > > > > I seem to have a Heisenbug now because of this: > > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > > > But if I replace in MCMethodDefinition this: > > > > actualClass > > ^ self actualClassIn: Environment current > > > > by this: > > > > actualClass > > Environment current. > > ^ self actualClassIn: Environment current > > > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > > > Kind regards, > > Jakob > > > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > >> > >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz > >> > >> ==================== Summary ==================== > >> > >> Name: Kernel-nice.1384 > >> Author: nice > >> Time: 11 April 2021, 7:33:23.487481 pm > >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > >> Ancestors: Kernel-mt.1383 > >> > >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. > >> > >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. > >> > >> =============== Diff against Kernel-mt.1383 =============== > >> > >> Item was changed: > >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > >> handleSignal: exception > >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > >> and the handler is active then execute my handle block (second arg), otherwise forward > >> this message to the next handler context. If none left, execute exception's defaultAction > >> (see nil>>handleSignal:)." > >> > >> | handlerActive val | > >> "If the context has been returned from the handlerActive temp var may not be accessible." > >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > >> + ^self nextHandlerContext handleSignal: exception]. > >> - [^self nextHandlerContext handleSignal: exception]. > >> > >> exception privHandlerContext: self contextTag. > >> self tempAt: 3 put: false. "disable self while executing handle block" > >> val := [(self tempAt: 2) cull: exception] > >> + ifCurtailed: [self tempAt: 3 put: true]. > >> - ensure: [self tempAt: 3 put: true]. > >> self return: val "return from self if not otherwise directed in handle block" > >> ! > >> > >> Item was added: > >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > >> + reactivateHandlers > >> + "Private - sent to exception handler context only (on:do:). > >> + Reactivate all the handlers into the chain" > >> + > >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > >> + self nextHandlerContext reactivateHandlers! > >> > >> Item was added: > >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- > >> + reactivateHandlers > >> + "reactivate all the exception handlers in the context chain" > >> + self canSearchForSignalerContext > >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! > >> > >> Item was changed: > >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- > >> resignalAs: replacementException > >> "Signal an alternative exception in place of the receiver." > >> > >> + self reactivateHandlers. > >> self resumeUnchecked: replacementException signal! > >> > >> Item was changed: > >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- > >> handleSignal: exception > >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. > >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." > >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." > >> > >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! > >> - ^ exception resumeUnchecked: exception defaultAction! > >> > >> Item was added: > >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- > >> + reactivateHandlers > >> + "nothing to do for bottom context" > >> + > >> + ^ self! > >> > >> From marcel.taeumel at hpi.de Tue Apr 20 06:49:17 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 20 Apr 2021 08:49:17 +0200 Subject: [squeak-dev] The Trunk: Tests-nice.455.mcz In-Reply-To: References: Message-ID: Hi Nicolas. > Alas, Kernel now depend on Morphic due to MouseEvent so the test still fails. > Either EventSensor shouldn't be in Kernel, or MouseEvent should not be in Morphic (or both?)... Yes, it is not really specific to Morphic to have (and want to have) objects for user-input events. Considering the realm of "headless" scenarios, EventSensor might not fit into Kernel either. Anyway, "MouseEvent numButtons" is a good abstraction! We should keep it. Best, Marcel Am 19.04.2021 21:18:22 schrieb commits at source.squeak.org : Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.455.mcz ==================== Summary ==================== Name: Tests-nice.455 Author: nice Time: 19 April 2021, 9:18:01.955183 pm UUID: 94f23508-c48c-0d47-8588-b2367071c298 Ancestors: Tests-nice.454 Two unrelated changes: 1) Kernel does not depend on Multilingual anymore (really?) Aknowledge this little victory before the dependecy come back. Alas, Kernel now depend on Morphic due to MouseEvent so the test still fails. Either EventSensor shouldn't be in Kernel, or MouseEvent should not be in Morphic (or both?)... 2) workaround source range test in presence of FullBlockClosure My understanding is that full block bytecodes are not hosted in their home method. As a consequence, full block also have their own PC. So a simple PC map is not elaborate enough to test the selection inside the block. By now, just skip the test of selection inside the full block closure. If some good soul wants to revise the test and make it thorough again, welcome! =============== Diff against Tests-nice.454 =============== Item was changed: ----- Method: ClosureCompilerTest>>supportTestSourceRangeAccessForInjectInto:source: (in category 'tests') ----- supportTestSourceRangeAccessForInjectInto: method source: source "Test debugger source range selection for inject:into:" ^self supportTestSourceRangeAccessForInjectInto: method source: source + selectionSequence: (method encoderClass supportsFullBlocks + ifTrue: ["Full blocks are searated from home method, with their own PC" + #( ':= thisValue' + 'do: [:each | nextValue := binaryBlock value: nextValue value: each]' + '^nextValue')] + ifFalse: [#( ':= thisValue' + 'do: [:each | nextValue := binaryBlock value: nextValue value: each]' + 'value: nextValue value: each' + ':= binaryBlock value: nextValue value: each' + 'nextValue := binaryBlock value: nextValue value: each' + 'value: nextValue value: each' + ':= binaryBlock value: nextValue value: each' + 'nextValue := binaryBlock value: nextValue value: each' + '^nextValue')]).! - selectionSequence: #( ':= thisValue' - 'do: [:each | nextValue := binaryBlock value: nextValue value: each]' - 'value: nextValue value: each' - ':= binaryBlock value: nextValue value: each' - 'nextValue := binaryBlock value: nextValue value: each' - 'value: nextValue value: each' - ':= binaryBlock value: nextValue value: each' - 'nextValue := binaryBlock value: nextValue value: each' - '^nextValue')! Item was changed: ----- Method: ClosureCompilerTest>>supportTestSourceRangeAccessForInjectInto:source:selectionSequence: (in category 'tests') ----- supportTestSourceRangeAccessForInjectInto: method source: source selectionSequence: selections "Test debugger source range selection for inject:into:" | evaluationCount sourceMap debugTokenSequence debugCount | DebuggerMethodMap voidMapCache. evaluationCount := 0. + sourceMap := method debuggerMap abstractSourceMapForMethod: method. - sourceMap := method debuggerMap abstractSourceMap. debugTokenSequence := selections collect: [:string| Scanner new scanTokens: string]. debugCount := 0. thisContext runSimulated: [(1 to: 2) withArgs: { 0. [:sum :each| evaluationCount := evaluationCount + 1. sum + each]} executeMethod: method] contextAtEachStep: [:ctxt| | range debugTokens | (ctxt method == method and: ["Exclude the send of #blockCopy: or #closureCopy:copiedValues: and braceWith:with: to create the block, and the #new: and #at:'s for the indirect temp vector. This for compilation without closure bytecodes. (Note that at:put:'s correspond to stores)" (ctxt willSend and: [(#(closureCopy:copiedValues: blockCopy: new: at: braceWith:with:) includes: ctxt selectorToSendOrSelf) not]) "Exclude the store of the argument into the home context (for BlueBook blocks) and the store of an indirection vector into an initial temp" or: [(ctxt willStore and: [(ctxt isBlock and: [ctxt pc = ctxt startpc]) not and: [(ctxt isBlock not and: [(method usesClosureBytecodes and: [ctxt abstractPC = 2])]) not]]) or: [ctxt willReturn]]]) ifTrue: [debugTokens := debugTokenSequence at: (debugCount := debugCount + 1) ifAbsent: [#(bogusToken)]. self assert: (sourceMap includesKey: ctxt abstractPC). range := sourceMap at: ctxt abstractPC ifAbsent: [(1 to: 0)]. self assert: (Scanner new scanTokens: (source copyFrom: range first to: range last)) = debugTokens]]. self assert: evaluationCount = 2! Item was changed: ----- Method: PackageDependencyTest>>testKernel (in category 'tests') ----- testKernel self testPackage: #Kernel dependsExactlyOn: #( #'Chronology-Core' Collections Compiler Environments Files - Multilingual System #'ToolBuilder-Kernel' ).! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 20 06:57:46 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 20 Apr 2021 08:57:46 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <,> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, > [...]  subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > even a string can be non-trivial, for instance, "String value: 1234", where I only will see a question mark unless I inspect the result. That's why I would only skip ByteString, not WideString. > Also, in all situations where you do some experiments concerning identity, an inspector would be very helpful to track individual instances. For most of the literals (or primitive kinds) I listed, object identity does not matter. Small integers and characters are immediate. Symbols are internalized. There is only one "nil", "true", "false." From the top of my head, I cannot think of an example, where you would be interested in two ByteStrings having the same identity. :-) Best, Marcel Am 19.04.2021 19:29:16 schrieb Thiede, Christoph : Hi Marcel, hi all, I keeping considering this type check as something bad and unexpected. :-) First, as I have mentioned earlier, subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example. Second, even a string can be non-trivial, for instance, "String value: 1234", where I only will see a question mark unless I inspect the result. Yes, in the second example, I could also trouble the Compiler again for a new inspect-it, but I just don't see why we should restrict these useful links for certain types of results. Also, in all situations where you do some experiments concerning identity, an inspector would be very helpful to track individual instances. Re-evaluating the expression would not be a solution here. To summarize, I just would not say that any object in Squeak can have a boring structure. It's just the other way around, these clickable results are a great way to make the inspector more visible in the system. PS: We should also consider making the new links available for print-its in the search bar. Best, Christoph Von: Squeak-dev im Auftrag von K K Subbu Gesendet: Montag, 19. April 2021 18:23:22 An: squeak-dev at lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz   All, How about:   Object>>isInspectable ^true   ByteString>>isInspectable ^false   Number>>isInspectable ^false   ... so inspectors can skip unitary objects? Just a thought .. Subbu On 19/04/21 8:36 pm, Marcel Taeumel wrote: > Hi Christoph, hi all. > > I think that we should not highlight the following kinds of Objects to > reserve this feature for really interesting structures that are worth > inspecting without an extra evaluate. The kinds to ignore are: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > So, we can use both (1) visuals and (2) interactivity to let the more > complex objects say: "Hey, I have interesting structure! Did you mix up > print-it with inspect-it? No worries, just click on me." > > This effect will not be if any stoopid literal gets this treatment. :-) > > Best, > Marcel >> >> Am 19.04.2021 13:21:53 schrieb Thiede, Christoph >> : >> >> Hi Marcel, >> >> >> I still stumble upon this edge case for some print-it results that do >> not support click-to-inspect. Why do we need this exception? :-) >> >> >> > > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> > >> > Looks fine. >> >> I don't think it looks fine, why do you think so? :-) >> >> Best, >> Christoph >> ------------------------------------------------------------------------ >> *Von:* Squeak-dev im >> Auftrag von Taeumel, Marcel >> *Gesendet:* Freitag, 16. April 2021 19:52:16 >> *An:* squeak-dev >> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >> Hi Christoph, >> >> I think that this clickable link is a compromise between printString >> and storeString. For mouse navigation, you can always choose "inspect >> it" from the context menu on that text selection. ;-) I also found the >> link color annyoing for simple literals. >> >> > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> >> Looks fine. ^__^ I am certain that we will collect more feedback on >> this feature during the next weeks and months. Let's refine it then. >> >> Best, >> Marcel >>> >>> Am 16.04.2021 18:39:10 schrieb Thiede, Christoph >>> : >>> >>> Hi Marcel, it's great that you have found a solution to this idea! :-) >>> >>> >>> > +        ^ (self class interactivePrintIt and: [(anObject isString >>> or: [anObject isNumber]) not]) >>> >>> >>> Is this necessary? I know that an inspector for a literal object like >>> these does not make great sense, but this just feels like an >>> unnecessary heuristic and limitation for me and adds complexity. I >>> would like to be able to open an inspector always. Also consider this >>> snippet where the print-link does not exist for an MCVersionName: :-) >>> >>>     MCRepository inbox allFileNames first >>> >>> >>> > CI scripts will default to "true". >>> >>> >>> Unfortunately, no, mine just timed out while preparing the image. >>> Also, my server images for @SqueakSmalltalkBot were interrupted. I'd >>> opt for keeping preamble/postscript content in the update stream >>> strictly non-interactive. :-) >>> >>> >>> Best, >>> >>> Christoph >>> >>> >>> ------------------------------------------------------------------------ >>> *Von:* Squeak-dev im >>> Auftrag von Taeumel, Marcel >>> *Gesendet:* Freitag, 16. April 2021 17:27:54 >>> *An:* squeak-dev >>> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >>> Hi all! >>> >>> It is now in Trunk. You can opt-out via the preference browser. >>> Still, you will be asked the first time when you update your image. >>> CI scripts will default to "true". >>> >>> Best, >>> Marcel >>>> >>>> Am 17.11.2019 17:36:11 schrieb Jakob Reschke : >>>> >>>> Thiede, Christoph >>> > schrieb am >>>> Fr., 15. Nov. 2019, 09:38: >>>> >>>> >>>>     Just another idea (I seem to have too many of them :D): Some >>>>     kind of UnderlyingObjectAttribute (with a better name, of >>>>     course) an editor can check the selection before compiling it >>>>     when inspectIt/exploreIt is pressed? >>>> >>>> >>>>     Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor >>>>     checks for UnderylingObjectAttribute -> none found, so the >>>>     string is compilaed as usual. >>>> >>>>     Example 2: (Text string: '2 + 3' attributes: >>>>     (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> >>>>     Editor finds an UnderylingObjectAttribute -> instead of >>>>     compiling the selection, the cached result is reused for >>>>     the inspector. >>>> >>>>     We would not even need to display this Attribute visually if it >>>>     works reliably. >>>> >>>> >>>> Make sure it is transient in some way because it would be quite >>>> annoying if the hidden object were out of date with regards to the text. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 20 07:15:50 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 20 Apr 2021 09:15:50 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <,> <,> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> Message-ID: Hi Subbu. > Object>>isInspectable ^true > ByteString>>isInspectable ^false > Number>>isInspectable ^false > ... All objects are "inspectable." I am talking about a language-specific configuration (or tweak?) for that interactive inspection feature. I argue for this small list of exceptions also because I think that this list is unlikely to change in the near future. Best, Marcel Am 19.04.2021 18:23:37 schrieb K K Subbu : All, How about: Object>>isInspectable ^true ByteString>>isInspectable ^false Number>>isInspectable ^false ... so inspectors can skip unitary objects? Just a thought .. Subbu On 19/04/21 8:36 pm, Marcel Taeumel wrote: > Hi Christoph, hi all. > > I think that we should not highlight the following kinds of Objects to > reserve this feature for really interesting structures that are worth > inspecting without an extra evaluate. The kinds to ignore are: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > So, we can use both (1) visuals and (2) interactivity to let the more > complex objects say: "Hey, I have interesting structure! Did you mix up > print-it with inspect-it? No worries, just click on me." > > This effect will not be if any stoopid literal gets this treatment. :-) > > Best, > Marcel >> >> Am 19.04.2021 13:21:53 schrieb Thiede, Christoph >> : >> >> Hi Marcel, >> >> >> I still stumble upon this edge case for some print-it results that do >> not support click-to-inspect. Why do we need this exception? :-) >> >> >> > > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> > >> > Looks fine. >> >> I don't think it looks fine, why do you think so? :-) >> >> Best, >> Christoph >> ------------------------------------------------------------------------ >> *Von:* Squeak-dev im >> Auftrag von Taeumel, Marcel >> *Gesendet:* Freitag, 16. April 2021 19:52:16 >> *An:* squeak-dev >> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >> Hi Christoph, >> >> I think that this clickable link is a compromise between printString >> and storeString. For mouse navigation, you can always choose "inspect >> it" from the context menu on that text selection. ;-) I also found the >> link color annyoing for simple literals. >> >> > Also consider this snippet where the print-link does not exist for >> an MCVersionName >> >> Looks fine. ^__^ I am certain that we will collect more feedback on >> this feature during the next weeks and months. Let's refine it then. >> >> Best, >> Marcel >>> >>> Am 16.04.2021 18:39:10 schrieb Thiede, Christoph >>> : >>> >>> Hi Marcel, it's great that you have found a solution to this idea! :-) >>> >>> >>> > +        ^ (self class interactivePrintIt and: [(anObject isString >>> or: [anObject isNumber]) not]) >>> >>> >>> Is this necessary? I know that an inspector for a literal object like >>> these does not make great sense, but this just feels like an >>> unnecessary heuristic and limitation for me and adds complexity. I >>> would like to be able to open an inspector always. Also consider this >>> snippet where the print-link does not exist for an MCVersionName: :-) >>> >>> MCRepository inbox allFileNames first >>> >>> >>> > CI scripts will default to "true". >>> >>> >>> Unfortunately, no, mine just timed out while preparing the image. >>> Also, my server images for @SqueakSmalltalkBot were interrupted. I'd >>> opt for keeping preamble/postscript content in the update stream >>> strictly non-interactive. :-) >>> >>> >>> Best, >>> >>> Christoph >>> >>> >>> ------------------------------------------------------------------------ >>> *Von:* Squeak-dev im >>> Auftrag von Taeumel, Marcel >>> *Gesendet:* Freitag, 16. April 2021 17:27:54 >>> *An:* squeak-dev >>> *Betreff:* Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz >>> Hi all! >>> >>> It is now in Trunk. You can opt-out via the preference browser. >>> Still, you will be asked the first time when you update your image. >>> CI scripts will default to "true". >>> >>> Best, >>> Marcel >>>> >>>> Am 17.11.2019 17:36:11 schrieb Jakob Reschke : >>>> >>>> Thiede, Christoph >>>> > schrieb am >>>> Fr., 15. Nov. 2019, 09:38: >>>> >>>> >>>> Just another idea (I seem to have too many of them :D): Some >>>> kind of UnderlyingObjectAttribute (with a better name, of >>>> course) an editor can check the selection before compiling it >>>> when inspectIt/exploreIt is pressed? >>>> >>>> >>>> Example 1: ('2 + 3' asText) -> User presses inspectIt -> Editor >>>> checks for UnderylingObjectAttribute -> none found, so the >>>> string is compilaed as usual. >>>> >>>> Example 2: (Text string: '2 + 3' attributes: >>>> (UnderylingObjectAttribute for: 5)) -> User presses inspectIt -> >>>> Editor finds an UnderylingObjectAttribute -> instead of >>>> compiling the selection, the cached result is reused for >>>> the inspector. >>>> >>>> We would not even need to display this Attribute visually if it >>>> works reliably. >>>> >>>> >>>> Make sure it is transient in some way because it would be quite >>>> annoying if the hidden object were out of date with regards to the text. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Tue Apr 20 07:16:24 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 20 Apr 2021 09:16:24 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Hi Jakob, Yes, the Behavior changed so that testHandlerFromAction can fire the outer handler. The handler was only deactivated during its execution, so that it would not catch the Exception that it raises itself (handlers are not reentrant, except if we specifically ask thru reamHandlerDuring:) Once the handler was finished, it was previously immediately reactivated. That's what I changed: - if the handler does not handle the exception, it is deactivated - once the handler is finished it is not reactivated, except ifCurtailed: The problem is that we have unclear expectations where we want the handler to be active again. My understanding is that the handlers should be reactivated - when we resume the exception, - when we resignalAs: a different exception, which is a specific form of resuming - and when performing the defaultAction. Side note: the currently active handler will be rearmed for handling its defaultAction, i don't even know if it should... The specifications are quite lax. Here, you submit another case where you want all the handlers to be rearmed. I don't think that rearmHandlerDuring: should rearm the other exceptions upstack. Maybe you could try (e reactivateHandlers) instead of (e rearmHandlerDuring: [...]). Let's have a look at what sendNotificationsTo: does sendNotificationsTo: aNewBlock self resume: ( workBlock value: [ :barVal | aNewBlock value: minVal value: maxVal value: barVal ] ) We recognize the same pattern as resignalAs: and nil>>handleSignal: resume will reactivateHandlers after the battle, that is after evaluating aNewBlock... I suggest this revision: sendNotificationsTo: aNewBlock self reactivateHandlers; resumeUnchecked: ( workBlock value: [ :barVal | aNewBlock value: minVal value: maxVal value: barVal ] ) I think that it makes rearmHandlerDuring: un-necessary. You also raise other points. Why the following works: Environment current. ^ self actualClassIn: Environment current Environment current sends an extra signal, so signalling twice has a different effect as signalling once. You said that it's not acceptable, but I'm not so sure... Why the debugging takes another path is another weird behavior that we should inquire... It ain't gonna be easy though. Le mar. 20 avr. 2021 à 00:08, Jakob Reschke a écrit : > > Oh by the way, this was helpful to inspect the stack in the incorrect state: > > MCMethodDefinition>> > actualClass > (thisContext sender selector == #unload) ifTrue: [thisContext > copyStack inspect]. > ^ self actualClassIn: Environment current > > In the Inspector: > | context | > context := self nextHandlerContext. > Array streamContents: [:str | > [context notNil] whileTrue: [str nextPut: context. context := > context nextHandlerContext]]. > > | context | > context := self. > Array streamContents: [:str | > [context notNil] whileTrue: [str nextPut: context. context := > context sender]]. > > Am Di., 20. Apr. 2021 um 00:02 Uhr schrieb Jakob Reschke > : > > > > Looks like this does no longer work as before: > > > > SquotImageStoreTest>> > > suppressProgressDisplayDuring: aBlock > > ... > > aBlock > > on: ProgressInitiationException do: [:e | > > ... > > e rearmHandlerDuring: > > [[e sendNotificationsTo: [:min :max :current | "silence"]] > > on: ProgressNotification do: [:notification | > > notification resume]] > > ... > > > > rearmHandlerDuring: does reactivate this current handler, but not > > handlers further up the stack. > > So e sendNotificationsTo: will evaluate the block in the package > > loader that eventually unloads the method in the test case while all > > handlers that are between the ProgressInitiationException signal > > context and this ProgressInitiationException handler context on the > > stack are deactivated, including the one that sets the correct > > Environment (and also the source file caching, by the way). Find the > > annotated stack below for a little more visualization. > > > > Previously, the handler contexts that did not fit the raised Exception > > were not deactivated. Is the ProgressInitiationException redirection > > concept broken in general now? Note that the ZeroDivide in > > ProgressInitiationException>>testWith is now no longer caught. > > > > --- The redacted stack of my failing test with some ---annotations---> > > [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The > > block under 'Installing ', pkgName displayProgressFrom: ... > > ProgressInitiationException>>sendNotificationsTo: > > [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > FullBlockClosure(BlockClosure)>>on:do: > > [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > [] in Context>>rearmHandlerDuring: > > FullBlockClosure(BlockClosure)>>ensure: > > ---reactivated #1---> Context>>rearmHandlerDuring: > > ProgressInitiationException(Exception)>>rearmHandlerDuring: > > [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > [] in Context>>handleSignal: > > FullBlockClosure(BlockClosure)>>ifCurtailed: > > Context>>handleSignal: <--- #1 sender: > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > ... > > Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: > > Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles > > class>>cacheDuring: > > Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad > > ---triggers stack walk---> ProgressInitiationException(Exception)>>signal > > ProgressInitiationException>>display:at:from:to:during: > > ... > > ByteString(String)>>displayProgressFrom:to:during: > > [] in [] in [] in [] in MCPackageLoader>>basicLoad > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > [] in [] in [] in MCPackageLoader>>basicLoad > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > CurrentReadOnlySourceFiles class>>cacheDuring: > > ... > > MCPackageLoader>>basicLoad > > ... > > MCPackageLoader>>loadWithNameLike: > > [] in SquotPackageShadow>>squotMaterializeWith: > > ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: > > Environment>>beCurrentDuring: > > SquotPackageShadow>>squotMaterializeWith: > > ... > > SquotImageStoreTest>>testApplyPatch > > SquotImageStoreTest(TestCase)>>performTest > > [] in SquotImageStoreTest>>performTest > > ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > ... > > > > Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke > > : > > > > > > Hi Nicolas, > > > > > > I seem to have a Heisenbug now because of this: > > > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > > > > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > > > > > But if I replace in MCMethodDefinition this: > > > > > > actualClass > > > ^ self actualClassIn: Environment current > > > > > > by this: > > > > > > actualClass > > > Environment current. > > > ^ self actualClassIn: Environment current > > > > > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > > > > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > > > > > Kind regards, > > > Jakob > > > > > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > > >> > > >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > > >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz > > >> > > >> ==================== Summary ==================== > > >> > > >> Name: Kernel-nice.1384 > > >> Author: nice > > >> Time: 11 April 2021, 7:33:23.487481 pm > > >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > > >> Ancestors: Kernel-mt.1383 > > >> > > >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. > > >> > > >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. > > >> > > >> =============== Diff against Kernel-mt.1383 =============== > > >> > > >> Item was changed: > > >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > > >> handleSignal: exception > > >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > > >> and the handler is active then execute my handle block (second arg), otherwise forward > > >> this message to the next handler context. If none left, execute exception's defaultAction > > >> (see nil>>handleSignal:)." > > >> > > >> | handlerActive val | > > >> "If the context has been returned from the handlerActive temp var may not be accessible." > > >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > > >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > > >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > > >> + ^self nextHandlerContext handleSignal: exception]. > > >> - [^self nextHandlerContext handleSignal: exception]. > > >> > > >> exception privHandlerContext: self contextTag. > > >> self tempAt: 3 put: false. "disable self while executing handle block" > > >> val := [(self tempAt: 2) cull: exception] > > >> + ifCurtailed: [self tempAt: 3 put: true]. > > >> - ensure: [self tempAt: 3 put: true]. > > >> self return: val "return from self if not otherwise directed in handle block" > > >> ! > > >> > > >> Item was added: > > >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > > >> + reactivateHandlers > > >> + "Private - sent to exception handler context only (on:do:). > > >> + Reactivate all the handlers into the chain" > > >> + > > >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > > >> + self nextHandlerContext reactivateHandlers! > > >> > > >> Item was added: > > >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- > > >> + reactivateHandlers > > >> + "reactivate all the exception handlers in the context chain" > > >> + self canSearchForSignalerContext > > >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! > > >> > > >> Item was changed: > > >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- > > >> resignalAs: replacementException > > >> "Signal an alternative exception in place of the receiver." > > >> > > >> + self reactivateHandlers. > > >> self resumeUnchecked: replacementException signal! > > >> > > >> Item was changed: > > >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- > > >> handleSignal: exception > > >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. > > >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." > > >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." > > >> > > >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! > > >> - ^ exception resumeUnchecked: exception defaultAction! > > >> > > >> Item was added: > > >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- > > >> + reactivateHandlers > > >> + "nothing to do for bottom context" > > >> + > > >> + ^ self! > > >> > > >> > From marcel.taeumel at hpi.de Tue Apr 20 07:49:34 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 20 Apr 2021 09:49:34 +0200 Subject: [squeak-dev] The Trunk: Morphic-mt.1751.mcz In-Reply-To: <8261ba7128424789a0a31946c97b2311@student.hpi.uni-potsdam.de> References: <33e41b5ded384590816403a6340c0ce0@student.hpi.uni-potsdam.de> <,> <8261ba7128424789a0a31946c97b2311@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, while I cannot find an example for #doButtonAction (or #performAction) being the actual action to be called, I tried something with #value.  (PluggableButtonMorph on: [ Transcript showln: 'foo' ] getState: nil action: #value) label: 'foo'; openInHand There, I noticed an issue with blocks being the target since those will not show up as receiver on the stack. For blocks, "context closure" should be compared with the target, which is different from PluggableButtonMorphPlus, where "context closure" should be compared with the action. Best, Marcel *** "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." ― Antoine de Saint-Exupéry Am 19.04.2021 19:53:24 schrieb Thiede, Christoph : Hi Marcel, here are some example selectors: #doButtonAction, #performAction, #value ... While these all are non-recommended selector names, they can occur indeed (and a have indeed a project that forwards clicks from one button to another so the selector is #doButtonAction), and this is why I think that "debug button action" should be more robust against them. :-) Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Mittwoch, 14. April 2021 13:03:41 An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Morphic-mt.1751.mcz   Hi Christoph, > In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. Can you give me 1 example? :-) Since we begin directly with calling the target ... how should anything interfere? Are you thinking about MethodWrappers? Best, Marcel Am 14.04.2021 12:25:22 schrieb Thiede, Christoph : Thank you for improving this! I already had a similar hack in my image for some time, but your solution is cleaner, of course. When putting further efforts into this construction site, I would like to kindly ask you again to take a look at System-ct.1149. :-) In particular, I think that only checking the selector but not the receiver of the context is a too weak criterion, I have already experienced a number of "wrong halts" when another method on the stack had the same selector. > I refrained from adding the debug/browse interface for button actions to Morph. I don't really see the problem here, Morph includes a lot of functionalities that are only used by certain subclasses. Anyway, could this be worth a trait, TMorphWithAction, or something similar? On the other hand, one morph might support multiple actions, so a generic solution would have its advantages ... Best, Christoph [http://www.hpi.de/] Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 14. April 2021 11:19:46 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-mt.1751.mcz   Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1751.mcz [http://source.squeak.org/trunk/Morphic-mt.1751.mcz] ==================== Summary ==================== Name: Morphic-mt.1751 Author: mt Time: 14 April 2021, 11:19:35.123489 am UUID: 8fa68c8f-44ca-4d4a-a9e7-f69619be782e Ancestors: Morphic-mt.1750 Slightly improve browsing and debugging of so-called "button actions" by also supporting #perform:orSendTo:, which yields #effectiveActionTarget and #effectiveActionSelector. (Note that this design is still to be improved. I refrained from adding the debug/browse interface for button actions to Morph. A next step might be to take a look at all implementors of #doButtonAction. Maybe this will generate some ideas.) =============== Diff against Morphic-mt.1750 =============== Item was removed: - ----- Method: MenuItemMorph>>browseAllImplementorsOfRealSelector (in category 'browse') ----- - browseAllImplementorsOfRealSelector -        SystemNavigation default browseAllImplementorsOf: self realSelector localTo: target class! Item was changed:   ----- Method: MenuItemMorph>>browseImplementationOfActionSelector (in category 'browse') -----   browseImplementationOfActionSelector            | method | +        method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. -        method := target class lookupSelector: selector.          ToolSet browse: method methodClass selector: method selector.! Item was changed:   ----- Method: MenuItemMorph>>debugAction (in category 'browse') -----   debugAction            (Process                  forBlock: [self doButtonAction] +                runUntil: [:context | context selector = self effectiveActionSelector]) -                runUntil: [:context | context selector = self selector])                          debugWithTitle: ('Debug menu action "{1}" in model "{2}"' format: {self contents. self target printString}).! Item was added: + ----- Method: MenuItemMorph>>effectiveActionSelector (in category 'browse') ----- + effectiveActionSelector +        +        ^ self selector = #perform:orSendTo: +                ifTrue: [self arguments first] +                ifFalse: [self selector]! Item was added: + ----- Method: MenuItemMorph>>effectiveActionTarget (in category 'browse') ----- + effectiveActionTarget + +        ^ (self selector = #perform:orSendTo: +                and: [(self target respondsTo: self effectiveActionSelector) not]) +                        ifTrue: [self arguments second] +                        ifFalse: [self target]! Item was removed: - ----- Method: MenuItemMorph>>realSelector (in category 'browse') ----- - realSelector -        selector == #perform:orSendTo: ifTrue: [^arguments first]. -        ^selector! Item was changed:   ----- Method: Morph>>doButtonAction (in category 'button') -----   doButtonAction +        "If the receiver has a button-action defined, do it now. The default button action of any morph is, well, to do nothing.  Note that there are several ways -- too many ways -- for morphs to have button-like actions. It is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programmatically from user scripts."! -        "If the receiver has a button-action defined, do it now.  The default button action of any morph is, well, to do nothing.  Note that there are several ways -- too many ways -- for morphs to have button-like actions.  This one refers not to the #mouseUpCodeToRun feature, nor does it refer to the Player-scripting mechanism.  Instead it is intended for morph classes whose very nature is to be buttons -- this method provides glue so that arbitrary buttons on the UI can be 'fired' programatticaly from user scripts"! Item was changed:   ----- Method: PluggableButtonMorph>>browseImplementationOfActionSelector (in category 'debug menu') -----   browseImplementationOfActionSelector            | method | +        self updateArguments. +        method := self effectiveActionTarget class lookupSelector: self effectiveActionSelector. -        method := model class lookupSelector: actionSelector.          ToolSet browse: method methodClass selector: method selector.! Item was changed:   ----- Method: PluggableButtonMorph>>debugAction (in category 'debug menu') -----   debugAction   +        self updateArguments. +          (Process +                forBlock: [self doButtonAction] +                runUntil: [:context | context selector = self effectiveActionSelector]) -                forBlock: [self performAction] -                runUntil: [:context | context selector = self actionSelector])                          debugWithTitle: ('Debug button action "{1}" in model "{2}"' format: {self label. self target printString}).! Item was added: + ----- Method: PluggableButtonMorph>>doButtonAction (in category 'button') ----- + doButtonAction + +        ^ self performAction! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionSelector (in category 'debug menu') ----- + effectiveActionSelector +        +        ^ self actionSelector = #perform:orSendTo: +                ifTrue: [arguments first] +                ifFalse: [self actionSelector]! Item was added: + ----- Method: PluggableButtonMorph>>effectiveActionTarget (in category 'debug menu') ----- + effectiveActionTarget + +        ^ (self actionSelector = #perform:orSendTo: +                and: [(self target respondsTo: self effectiveActionSelector) not]) +                        ifTrue: [arguments second] +                        ifFalse: [self target]! Item was changed: + ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>hResizing: (in category 'layout-properties') -----   hResizing: aSymbol          "We adapt our minimum extent according to our resize behavior."                   self hResizing == aSymbol ifTrue: [^ self].          super hResizing: aSymbol.          self updateMinimumExtent.! Item was changed: + ----- Method: PluggableButtonMorph>>performAction (in category 'event handling') ----- - ----- Method: PluggableButtonMorph>>performAction (in category 'accessing') -----   performAction          "Inform the model that this button has been pressed. Sent by the controller when this button is pressed. If the button's actionSelector takes any arguments, they are obtained dynamically by sending the argumentSelector to the argumentsProvider"            askBeforeChanging ifTrue: [model okToChange ifFalse: [^ self]].          actionSelector ifNotNil:                  [actionSelector numArgs = 0                          ifTrue:                                  [model perform: actionSelector]                          ifFalse: +                                [self updateArguments. -                                [argumentsProvider ifNotNil: -                                        [arguments := argumentsProvider perform: argumentsSelector].                                          model perform: actionSelector withArguments: arguments]]! Item was added: + ----- Method: PluggableButtonMorph>>updateArguments (in category 'updating') ----- + updateArguments + +        argumentsProvider ifNil: [^ self]. +        argumentsSelector ifNil: [^ self]. +        arguments := argumentsProvider perform: argumentsSelector.! Item was changed: + ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout properties') ----- - ----- Method: PluggableButtonMorph>>vResizing: (in category 'layout-properties') -----   vResizing: aSymbol          "We adapt our minimum extent according to our resize behavior."                   self vResizing == aSymbol ifTrue: [^ self].          super vResizing: aSymbol.          self updateMinimumExtent.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 20 08:01:17 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 20 Apr 2021 10:01:17 +0200 Subject: [squeak-dev] Idioms | How to send messages in Context? In-Reply-To: References: Message-ID: Hi Tim. > It might be worth considering the names of these methods in > order to make that very clear. Perhaps something like #simSend:to:with: ? Yes, "send" is very close to "perform" and #when:send:to: and #on:send:to:. :-D Yet, we are in Context. So there is already a notion of "simulation" attached to many messages in there. Looking at the protocols "controlling" and "system simulation", I don't think that adding a "sim" prefix to "controlling" messages would do any good. Best, Marcel Am 19.04.2021 18:50:40 schrieb tim Rowledge : >> >> #cannotReturn: is put onto the stack of the process being executed/simulated. #send:to:with: is part of the simulation protocol. Analogously, #resume:through: will appear on the executed process stack whereas #return:from: is used by the simulator as stated in the comment. :-) I It might be worth considering the names of these methods in order to make that very clear. Perhaps something like #simSend:to:with: ? tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Klingon Code Warrior:- 4) "This machine is a piece of GAGH! I need dual G5 processors if I am to do battle with this code!" -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 20 08:15:31 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 20 Apr 2021 10:15:31 +0200 Subject: [squeak-dev] The Trunk: Morphic-mt.1755.mcz In-Reply-To: <36794c9e20014cccbeb4fa6d349c2187@student.hpi.uni-potsdam.de> References: <,> <36794c9e20014cccbeb4fa6d349c2187@student.hpi.uni-potsdam.de> Message-ID: *scnr* https://xkcd.com/1172/ [https://xkcd.com/1172/] ^__^ Please report whether that list of recent changes makes you (want to) open the (dual) change sorter less often. Best, Marcel Am 19.04.2021 12:58:05 schrieb Thiede, Christoph : Hi Marcel, interesting concept, I will try out the usability the next time! Some first thoughts: * I very often used this button to open a change sorter window. (The new menu is not bad, but of course, it only offers a subset of all functionalities of a change sorter). Can we maybe move the "Browse" item to the top of the menu? * Also, we might want to add a link to the DualChangeSorter there. I use that tool very often and I think this would be a way to access it even faster. Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Sonntag, 18. April 2021 19:05 Uhr An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Morphic-mt.1755.mcz   Am 18.04.2021 19:01:02 schrieb commits at source.squeak.org : Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1755.mcz ==================== Summary ==================== Name: Morphic-mt.1755 Author: mt Time: 18 April 2021, 7:00:43.878254 pm UUID: e5705780-2988-a54e-b6c7-21b4194fcd5c Ancestors: Morphic-mt.1754, Morphic-ct.1659 Fix our two menu-invocating buttons to act on mouse-down and actually look like menus: (1) menu button in system window and (2) change-set button in world-main-docking-bar. Merges Morphic-ct.1659. Thanks Christoph (ct) for pointing out this issue about menu invocation through buttons. See http://forum.world.st/The-Inbox-Morphic-ct-1659-mcz-tp5116728.html By example, this commit also adds a menu to the change-set button in the docking bar. This menu lists the latest method and class changes. To make this work, the following things got addressed: - Fixes DockingBarUpdatingItemMorph, which missed several changes from DockingBarItemMorph. (Interesting specialization challenge...) - Let menus #rubberBandCells to allow for changing menu item's widths. - Adds query about latest changes to #listChangesOn:. (Feel free to improve this. Maybe add preference for number of elements?) Complements (and depends on) System-mt.1228 and Tools-mt.1042. =============== Diff against Morphic-mt.1754 =============== Item was changed: ----- Method: DockingBarMorph>>addUpdatingItem: (in category 'construction') ----- addUpdatingItem: aBlock | item | item := DockingBarUpdatingItemMorph new. aBlock value: item. + item subMenu ifNotNil: [:menu | + "Docking bar and protruding menu should appear visually merged." + menu morphicLayerNumber: self morphicLayerNumber + 1]. self addMorphBack: item! Item was changed: ----- Method: DockingBarMorph>>ensureSelectedItem: (in category 'events') ----- ensureSelectedItem: evt self selectedItem ifNil: [ self selectItem: ( self submorphs + detect: [ :each | each isMenuItemMorph ] - detect: [ :each | each isKindOf: DockingBarItemMorph ] ifNone: [ ^self ]) event: evt ]! Item was changed: ----- Method: DockingBarMorph>>filterEvent:for: (in category 'events-processing') ----- filterEvent: aKeyboardEvent for: anObject "Provide keyboard shortcuts." | index itemToSelect | aKeyboardEvent controlKeyPressed ifFalse: [^ aKeyboardEvent]. aKeyboardEvent isKeystroke ifFalse: [^ aKeyboardEvent]. "Search field." aKeyboardEvent keyCharacter = $0 ifTrue: [ self searchBarMorph ifNotNil: [ :morph | morph model activate: aKeyboardEvent in: morph ]. ^ aKeyboardEvent ignore "hit!!"]. "Select menu items." (aKeyboardEvent keyValue between: $1 asciiValue and: $9 asciiValue) ifFalse: [^ aKeyboardEvent]. index := aKeyboardEvent keyValue - $1 asciiValue + 1. itemToSelect := (self submorphs select: [ :each | + each isMenuItemMorph ]) - each isKindOf: DockingBarItemMorph ]) at: index ifAbsent: [^ aKeyboardEvent]. self activate: aKeyboardEvent. self selectItem: itemToSelect event: aKeyboardEvent. ^ aKeyboardEvent ignore "hit!!"! Item was changed: ----- Method: DockingBarMorph>>moveSelectionDown:event: (in category 'control') ----- moveSelectionDown: direction event: evt "Move the current selection up or down by one, presumably under keyboard control. direction = +/-1" | index | index := (submorphs indexOf: selectedItem ifAbsent: [1-direction]) + direction. submorphs do: "Ensure finite" [:unused | | m | m := submorphs atWrap: index. + (m isMenuItemMorph and: [m isEnabled]) ifTrue: - ((m isKindOf: DockingBarItemMorph) and: [m isEnabled]) ifTrue: [^ self selectItem: m event: evt]. "Keep looking for an enabled item" index := index + direction sign]. ^ self selectItem: nil event: evt! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>adjacentTo (in category 'selecting') ----- + adjacentTo + + | roundedCornersOffset verticalOffset | + roundedCornersOffset := MenuMorph roundedMenuCorners + ifTrue: [Morph preferredCornerRadius negated] + ifFalse: [0]. + verticalOffset := 2. + + owner isFloating + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToTop + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToLeft + ifTrue: [^ {self bounds topRight + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToBottom + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToRight + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset negated)}]. + ^ {self bounds bottomLeft + (roundedCornersOffset @ 5)}! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createSubmenu (in category 'private') ----- + createSubmenu + + ^DockingBarMenuMorph new! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createUpdatingSubmenu (in category 'private') ----- + createUpdatingSubmenu + + ^DockingBarUpdatingMenuMorph new! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'world') ----- - ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'as yet unclassified') ----- decorateOwner "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawIconOn: (in category 'drawing') ----- + drawIconOn: aCanvas + + | pos | + self hasIcon ifTrue: [ + | iconForm | + iconForm := self iconForm. + + pos := (contents + ifEmpty: [self left + (self width - iconForm width // 2)] + ifNotEmpty: [self left]) + @ (self top + (self height - iconForm height // 2)). + + aCanvas + translucentImage: iconForm + at: pos].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawLabelOn: (in category 'drawing') ----- + drawLabelOn: aCanvas + + | stringBounds | + self contents ifEmpty: [^ self]. + + stringBounds := bounds. + + self hasIcon ifTrue: [ + stringBounds := stringBounds left: stringBounds left + self iconForm width + 2 ]. + + "Vertical centering." + stringBounds := stringBounds top: stringBounds top + stringBounds bottom - self fontToUse height // 2. + "Horizontal centering." + stringBounds := stringBounds left: stringBounds left + (stringBounds width - (self fontToUse widthOfString: contents) // 2) abs. + + aCanvas + drawString: contents + in: stringBounds + font: self fontToUse + color: self colorToUse.! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawSubMenuMarkerOn: (in category 'drawing') ----- + drawSubMenuMarkerOn: aCanvas + "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseDown: (in category 'events') ----- + mouseDown: evt + "Handle a mouse down event. Menu items get activated when the mouse is over them." + + (evt shiftPressed and:[self wantsKeyboardFocusOnShiftClick]) ifTrue: [ ^super mouseDown: evt ]. "enable label editing" + isSelected + ifTrue: [ + owner selectItem: nil event: evt. ] + ifFalse: [ + owner activate: evt. "Redirect to menu for valid transitions" + owner selectItem: self event: evt. ] + ! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'events') ----- - ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'as yet unclassified') ----- mouseEnter: evt "Do not hover docking bar items directory. Mouse-down required. But if you already see a submenu, support hovering." owner selectedItem ifNotNil: [owner selectItem: self event: evt]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseUp: (in category 'events') ----- + mouseUp: evt + "Handle a mouse up event. Menu items get activated when the mouse is over them. Do nothing if we're not in a 'valid menu transition', meaning that the current hand focus must be aimed at the owning menu." + + evt hand mouseFocus == owner ifFalse: [ ^self ]. + self contentString ifNotNil: [ + self contents: self contentString withMarkers: true inverse: true. + self refreshWorld. + (Delay forMilliseconds: 200) wait ].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>select: (in category 'selecting') ----- + select: evt + + super select: evt. + subMenu ifNotNil: [ + evt hand newKeyboardFocus: subMenu ]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>wantsKeyboardFocusOnShiftClick (in category 'events') ----- + wantsKeyboardFocusOnShiftClick + "set this preference to false to prevent user editing of docking bar menu items" + ^Preferences valueOfPreference: #allowMenubarItemEditing ifAbsent: [false]! Item was added: + ----- Method: DockingBarUpdatingMenuMorph>>morphicLayerNumber: (in category 'update') ----- + morphicLayerNumber: n + + super morphicLayerNumber: n. + ! Item was changed: ----- Method: MenuMorph>>initialize (in category 'initialization') ----- initialize super initialize. self setDefaultParameters. self changeTableLayout. self listDirection: #topToBottom. self hResizing: #shrinkWrap. self vResizing: #shrinkWrap. + self rubberBandCells: true. self disableLayout: true. self morphicLayerNumber: self class menuLayer. defaultTarget := nil. selectedItem := nil. stayUp := false. popUpOwner := nil.! Item was changed: ----- Method: SystemWindow>>createMenuBox (in category 'initialization') ----- createMenuBox ^ (self createBox: self class menuBoxImage) actionSelector: #offerWindowMenu; + setBalloonText: 'window menu' translated; + actWhen: #buttonDown; + yourself! - setBalloonText: 'window menu' translated! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'right side') ----- browseChanges ChangeSorter open.! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'right side') ----- browseChangesLabel "The project name is the same as the current change set." ^ Project current name! Item was added: + ----- Method: TheWorldMainDockingBar>>changesMenuOn: (in category 'submenu - changes') ----- + changesMenuOn: aDockingBar + + aDockingBar addUpdatingItem: [:item | + item + help: 'Browse this project''s changes' translated; + wordingProvider: self + wordingSelector: #browseChangesLabel; + subMenuUpdater: self + selector: #listChangesOn:].! Item was changed: ----- Method: TheWorldMainDockingBar>>fillDockingBar: (in category 'construction') ----- fillDockingBar: aDockingBar "Private - fill the given docking bar" self menusOn: aDockingBar. aDockingBar addSpacer. + self changesMenuOn: aDockingBar. - self projectNameOn: aDockingBar. aDockingBar addSpacer. self rightSideOn: aDockingBar. aDockingBar setProperty: #mainDockingBarTimeStamp toValue: self class timeStamp.! Item was added: + ----- Method: TheWorldMainDockingBar>>listChangesOn: (in category 'submenu - changes') ----- + listChangesOn: menu + + | latestMethodChanges latestClassChanges| + latestMethodChanges := (Array streamContents: [:s | + ChangeSet current changedMethodsDo: [:method :changeType :dateAndTime :category | + s nextPut: { dateAndTime. method. changeType. category }]]) + sorted: [:a :b | a first >= b first]. + + 1 to: (10 min: latestMethodChanges size) do: [:index | | spec method | + spec := latestMethodChanges at: index. + method := spec second. + menu addItem: [:item | + item + contents: ('{1} {2} \{{3}\} \{{4}\}' format: {method methodClass. method selector. spec fourth. method methodClass category}) ; + target: ToolSet; + balloonText: spec third asString; + icon: ((#(remove addedThenRemoved) includes: spec third) ifTrue: [MenuIcons smallDeleteIcon] ifFalse: [ + spec third = #add ifTrue: [MenuIcons smallNewIcon] ifFalse: [MenuIcons blankIcon]]); + selector: (method isInstalled ifTrue: [#browseMethod:] ifFalse: [#browseMethodVersion:]); + arguments: {method}]]. + + latestClassChanges := (Array streamContents: [:s | + ChangeSet current changedClassesDo: [:class :changeTypes :dateAndTime :category | + "We are not interested in classes whose method's did only change." + changeTypes ifNotEmpty: [s nextPut: { dateAndTime. class. changeTypes. category }]]]) + sorted: [:a :b | a first >= b first]. + + latestClassChanges ifNotEmpty: [menu addLine]. + 1 to: (10 min: latestClassChanges size) do: [:index | | spec class | + spec := latestClassChanges at: index. + class := spec second. + menu addItem: [:item | + item + contents: ('{1} \{{2}\}' format: {class name. spec fourth }) ; + target: ToolSet; + balloonText: (spec third sorted joinSeparatedBy: Character space); + icon: ((spec third includesAnyOf: #(remove addedThenRemoved)) + ifTrue: [MenuIcons smallDeleteIcon] + ifFalse: [ + (spec third includes: #add) + ifTrue: [MenuIcons smallNewIcon] + ifFalse: [MenuIcons blankIcon]]); + selector: ((spec third includes: #remove) ifTrue: [#inspect:] ifFalse: [#browseClass:]); + arguments: {class}]]. + + menu addLine; addItem: [:item | + item + contents: 'Browse current change set...' translated; + target: self; + selector: #browseChanges].! Item was removed: - ----- Method: TheWorldMainDockingBar>>projectNameOn: (in category 'right side') ----- - projectNameOn: aDockingBar - - aDockingBar addUpdatingItem: [:item | - item - help: 'Browse this project''s changes'; - target: self; - selector: #browseChanges; - wordingProvider: self - wordingSelector: #browseChangesLabel].! Item was changed: + (PackageInfo named: 'Morphic') postscript: 'TheWorldMainDockingBar updateInstances.'! - (PackageInfo named: 'Morphic') postscript: 'Transcript showln: ''[NOTICE] There is a new preference called "Interactive print-it". Please check your preference browser to choose the preferred value.'''! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 160977 bytes Desc: not available URL: From commits at source.squeak.org Tue Apr 20 08:35:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 20 Apr 2021 08:35:12 0000 Subject: [squeak-dev] The Trunk: Environments-jr.82.mcz Message-ID: Marcel Taeumel uploaded a new version of Environments to project The Trunk: http://source.squeak.org/trunk/Environments-jr.82.mcz ==================== Summary ==================== Name: Environments-jr.82 Author: jr Time: 10 April 2021, 12:34:34.717998 am UUID: 2935eb63-046e-c344-8fba-771fb62fb5c2 Ancestors: Environments-tonyg.81 Sending resume: from defaultAction is erroneous in the ANSI standard. In Squeak, unhandled exceptions are resumed with the answer to the defaultAction message. =============== Diff against Environments-tonyg.81 =============== Item was changed: ----- Method: EnvironmentRequest>>defaultAction (in category 'exceptionDescription') ----- defaultAction | all environment | all := Environment allInstances. environment := UIManager default chooseFrom: (all collect: [:ea | ea printString]) values: all. + ^ environment! - self resume: environment.! From commits at source.squeak.org Tue Apr 20 08:58:50 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 20 Apr 2021 08:58:50 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1756.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1756.mcz ==================== Summary ==================== Name: Morphic-mt.1756 Author: mt Time: 20 April 2021, 10:58:45.137004 am UUID: eb1e8287-cfc4-ff47-a8d1-a4e93f3be174 Ancestors: Morphic-mt.1755 In object explorers, format the different representations of numbers in groups, following the well-known practice: hex 2, oct 3, binary 4 digits. (Piggyback the removal of an #isMutator send) =============== Diff against Morphic-mt.1755 =============== Item was changed: ----- Method: Integer>>explorerContents (in category '*Morphic-Explorer') ----- explorerContents ^#( + ('hexadecimal' 16 2) + ('octal' 8 3) + ('binary' 2 4)) collect: [ :each | | label group | + group := each third. + label := self printStringBase: each second. + label := label padded: #left to: (label size roundUpTo: group) with: $0. + label := String streamContents: [:s | + (1 to: label size by: group) + do: [:index | + 1 to: group do: [:gIndex | + s nextPut: (label at: index + gIndex - 1)]] + separatedBy: [s space]]. + - ('hexadecimal' 16) - ('octal' 8) - ('binary' 2)) collect: [ :each | ObjectExplorerWrapper + with: label - with: (self printStringBase: each second) name: each first translated model: self ]! Item was changed: ----- Method: NewColorPickerMorph class>>on:colorSelector: (in category 'create') ----- on: objectToHaveItsColorSet colorSelector: colorSymbol ^ self on: objectToHaveItsColorSet getColorSelector: colorSymbol + setColorSelector: colorSymbol asSimpleSetter! - setColorSelector: colorSymbol asMutator! From commits at source.squeak.org Tue Apr 20 09:03:38 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 20 Apr 2021 09:03:38 0000 Subject: [squeak-dev] The Trunk: ToolBuilder-Kernel-nice.141.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Trunk: http://source.squeak.org/trunk/ToolBuilder-Kernel-nice.141.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-nice.141 Author: nice Time: 20 April 2021, 11:03:36.052217 am UUID: b33a2801-5d76-41b6-a323-4c4a13ff185a Ancestors: ToolBuilder-Kernel-eem.140 The handlers for other exception should not be deactivated while redirecting ProgressInitiationException thru sendNotificationsTo: directive. =============== Diff against ToolBuilder-Kernel-eem.140 =============== Item was changed: ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- sendNotificationsTo: aNewBlock + self reactivateHandlers; resumeUnchecked: ( - self resume: ( workBlock value: [ :barVal | aNewBlock value: minVal value: maxVal value: barVal ] ) ! From commits at source.squeak.org Tue Apr 20 09:08:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 20 Apr 2021 09:08:15 0000 Subject: [squeak-dev] FFI: FFI-Unix-mt.5.mcz Message-ID: Marcel Taeumel uploaded a new version of FFI-Unix to project FFI: http://source.squeak.org/FFI/FFI-Unix-mt.5.mcz ==================== Summary ==================== Name: FFI-Unix-mt.5 Author: mt Time: 20 April 2021, 11:08:15.269233 am UUID: 26f1ddfe-b5d1-8e48-b8eb-05e5c5f2ed6c Ancestors: FFI-Unix-mtf.4 Minor clean up. Auto-generated field accessors are no longer put into the same package but a separate "autogenerated" protocol to avoid checking in platform-specific "code caches". =============== Diff against FFI-Unix-mtf.4 =============== Item was changed: + X11ID subclass: #X11Drawable - Object subclass: #X11Drawable instanceVariableNames: 'display xid' classVariableNames: '' poolDictionaries: '' category: 'FFI-Unix-Examples'! Item was removed: - ----- Method: X11Drawable class>>fields (in category 'field definition') ----- - fields - "X11Drawable defineFields" - ^#( nil 'void*' )! Item was removed: - ----- Method: X11Drawable class>>none (in category 'instance creation') ----- - none - "Universal null resource or null atom" - ^ self new! Item was added: + ExternalTypeAlias subclass: #X11ID + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'FFI-Unix-Examples'! + + !X11ID commentStamp: 'mt 6/4/2020 19:16' prior: 0! + I am an opaque handle in X11.! Item was added: + ----- Method: X11ID class>>originalTypeName (in category 'field definition') ----- + originalTypeName + " + self defineFields + " + ^ 'size_t' "or always uint32_t ??"! Item was changed: + X11ID subclass: #X11Window - X11Drawable subclass: #X11Window instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Unix-Examples'! From marcel.taeumel at hpi.de Tue Apr 20 10:29:34 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 20 Apr 2021 12:29:34 +0200 Subject: [squeak-dev] #identityCaseOf: In-Reply-To: References: <9d7b625fce5847c187d77d373430ceb9@student.hpi.uni-potsdam.de> <66bbc643fbea41c088a15e9b5497c19d@student.hpi.uni-potsdam.de> Message-ID: Hi all! #caseOf:(otherwise:) has its uses. I would probably rarely use it for lookup tables with less than 3-4 rows, especially when there is no reason to believe that the list will grow soon. But even then, I tend to use ad-hoc dictionaries for the lookup, which might be not-so-good for performance. In my opinion, good examples for #caseOf:(otherwise:) include (but are not limited to): PNMReadWriter >> #nextImage CompiledCode >> #scanFor: Character >> #isSeparator Context >> #exceptionMessage DoItFirst >> #keyFor: HandMorph >> #processEvents Inspector >> #inspectorKey:from: ProcessBrowser >> #processListKey:from: MimeConverter class >> #forEncoding: WebUtils class >> #jsonDecode: Well, not-so-good examples include (but are not limited to): MenuMorph >> #handleFiltering: Text >> #format: CompiledMethod >> #scanForInstructionPattern: There, I would opt for the good-ol' #ifTrue:ifFalse:. Or maybe an "extract method"-refactoring might improve the intend and readability of those. Any change to #caseOf: MUST account for the Decompiler. Even the introduction of an #identityCaseOf:(otherwise:). "true caseOf: { ... }" is an anti pattern. Please don't do that. :-) Best, Marcel Am 07.04.2021 20:13:45 schrieb Jakob Reschke : Having started out with Delphi, I do not mind caseOf:. But I more often wish for Lisp's cond. true caseOf: looks somehow strange and like a hack to me—just a feeling—though I admit it does make sense when I force myself to read it as English: "For the true case of the following, do..." Regarding letting people choose their protocols, just make sure that Smalltalk does not end up being a write-only-for-me language like Perl. :-) I think there has already been this discussion about how many shortcuts and utility methods should be in the language and which should rather stay out. Am Mi., 7. Apr. 2021 um 17:53 Uhr schrieb Thiede, Christoph : Woah, I didn't know that this topic has been such a hot potato. :-) [http://www.hpi.de/] In my opinion, people can always abuse a (domain-specific) language to write bad code and you cannot really stop them from doing so by limiting the features of the language. Instead of banning a protocol, people should understand *why* and *when* it is a bad idea to use them. #caseOf: & Co. can be used and can be abused, so I vote for keeping and legalizing it (otherwise we have to destroy every bread knife, too). If we stigmatize #caseOf:, we could also stigmatize or even deprecate #isKindOf: because very often, it is abused - but still, it can be useful in many situations where you need metaprogramming indeed, for example, Exception class >> #handles:. LBNL, I often consider both concepts as the first step of a larger refactoring. Alone for this purpose, I would like to keep these selectors. Best, Christoph Von: Squeak-dev im Auftrag von tim Rowledge Gesendet: Sonntag, 28. März 2021 19:07:58 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] #identityCaseOf:   > On 2021-03-28, at 4:09 AM, Thiede, Christoph wrote: > > @Tim: > > > Far too like C. > > Again, why please? :-) I'm not a big fan of C either, but IMO switch/select/case is not the worst concept when it allows you to eliminate some duplication. It (both C and caseOf*) has its uses but my practical issue with caseOf* in Smalltalk is that I keep (very subjective and personal experience dependant) seeing it get used in ways that completely sidestep Smalltalk and implement bad C idiom. A bit like isKindOf: and isBlahClass. e.g. foo class         caseOf: {                 [Rabbit] -> [foo doRabbitThing].                 [Fox] -> [foo doFoxThing]} ... which of course merely (badly) replicates class lookup/inheritance/message-sending. It suggests a writer that cannot escape the mental prison of C-like assault coding. isKindOf: is a useful meta-programming idiom that I've seen used inside inner loops to do the same sort of not-message-sending. I've even had people try to justify is on the grounds that "sending messages is so slow and I want ot avoid it", which is just nuts. isBlahClass is almost as horrible but at least has the excuse of (hopefully) being part of a not yet completed cleaning of other nastiness. Part of the problem is that language flexibility always ends up being a tool that lets annoying people write bad FORTRAN in any language. And then somebody has to spend a too large fraction of their life trying to fix it. tim -- tim Rowledge; tim at rowledge.org [mailto:tim at rowledge.org]; http://www.rowledge.org/tim [http://www.rowledge.org/tim] Useful random insult:- Not enough sense to come in out of the rain. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Tue Apr 20 11:55:18 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Tue, 20 Apr 2021 11:55:18 +0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1755.mcz In-Reply-To: References: <,> <36794c9e20014cccbeb4fa6d349c2187@student.hpi.uni-potsdam.de>, Message-ID: Fair point and nice comic! :-) I will keep this in mind and report back later ... Maybe we could need some kind of telemetry solution to make such evaluation more efficient. :D Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Dienstag, 20. April 2021 10:15:31 An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Morphic-mt.1755.mcz *scnr* https://xkcd.com/1172/ ^__^ Please report whether that list of recent changes makes you (want to) open the (dual) change sorter less often. Best, Marcel Am 19.04.2021 12:58:05 schrieb Thiede, Christoph : Hi Marcel, interesting concept, I will try out the usability the next time! Some first thoughts: * I very often used this button to open a change sorter window. (The new menu is not bad, but of course, it only offers a subset of all functionalities of a change sorter). Can we maybe move the "Browse" item to the top of the menu? * Also, we might want to add a link to the DualChangeSorter there. I use that tool very often and I think this would be a way to access it even faster. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Sonntag, 18. April 2021 19:05 Uhr An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Morphic-mt.1755.mcz [cid:94efd291-fc7a-4b8c-af47-720794ff5704] Am 18.04.2021 19:01:02 schrieb commits at source.squeak.org : Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1755.mcz ==================== Summary ==================== Name: Morphic-mt.1755 Author: mt Time: 18 April 2021, 7:00:43.878254 pm UUID: e5705780-2988-a54e-b6c7-21b4194fcd5c Ancestors: Morphic-mt.1754, Morphic-ct.1659 Fix our two menu-invocating buttons to act on mouse-down and actually look like menus: (1) menu button in system window and (2) change-set button in world-main-docking-bar. Merges Morphic-ct.1659. Thanks Christoph (ct) for pointing out this issue about menu invocation through buttons. See http://forum.world.st/The-Inbox-Morphic-ct-1659-mcz-tp5116728.html By example, this commit also adds a menu to the change-set button in the docking bar. This menu lists the latest method and class changes. To make this work, the following things got addressed: - Fixes DockingBarUpdatingItemMorph, which missed several changes from DockingBarItemMorph. (Interesting specialization challenge...) - Let menus #rubberBandCells to allow for changing menu item's widths. - Adds query about latest changes to #listChangesOn:. (Feel free to improve this. Maybe add preference for number of elements?) Complements (and depends on) System-mt.1228 and Tools-mt.1042. =============== Diff against Morphic-mt.1754 =============== Item was changed: ----- Method: DockingBarMorph>>addUpdatingItem: (in category 'construction') ----- addUpdatingItem: aBlock | item | item := DockingBarUpdatingItemMorph new. aBlock value: item. + item subMenu ifNotNil: [:menu | + "Docking bar and protruding menu should appear visually merged." + menu morphicLayerNumber: self morphicLayerNumber + 1]. self addMorphBack: item! Item was changed: ----- Method: DockingBarMorph>>ensureSelectedItem: (in category 'events') ----- ensureSelectedItem: evt self selectedItem ifNil: [ self selectItem: ( self submorphs + detect: [ :each | each isMenuItemMorph ] - detect: [ :each | each isKindOf: DockingBarItemMorph ] ifNone: [ ^self ]) event: evt ]! Item was changed: ----- Method: DockingBarMorph>>filterEvent:for: (in category 'events-processing') ----- filterEvent: aKeyboardEvent for: anObject "Provide keyboard shortcuts." | index itemToSelect | aKeyboardEvent controlKeyPressed ifFalse: [^ aKeyboardEvent]. aKeyboardEvent isKeystroke ifFalse: [^ aKeyboardEvent]. "Search field." aKeyboardEvent keyCharacter = $0 ifTrue: [ self searchBarMorph ifNotNil: [ :morph | morph model activate: aKeyboardEvent in: morph ]. ^ aKeyboardEvent ignore "hit!!"]. "Select menu items." (aKeyboardEvent keyValue between: $1 asciiValue and: $9 asciiValue) ifFalse: [^ aKeyboardEvent]. index := aKeyboardEvent keyValue - $1 asciiValue + 1. itemToSelect := (self submorphs select: [ :each | + each isMenuItemMorph ]) - each isKindOf: DockingBarItemMorph ]) at: index ifAbsent: [^ aKeyboardEvent]. self activate: aKeyboardEvent. self selectItem: itemToSelect event: aKeyboardEvent. ^ aKeyboardEvent ignore "hit!!"! Item was changed: ----- Method: DockingBarMorph>>moveSelectionDown:event: (in category 'control') ----- moveSelectionDown: direction event: evt "Move the current selection up or down by one, presumably under keyboard control. direction = +/-1" | index | index := (submorphs indexOf: selectedItem ifAbsent: [1-direction]) + direction. submorphs do: "Ensure finite" [:unused | | m | m := submorphs atWrap: index. + (m isMenuItemMorph and: [m isEnabled]) ifTrue: - ((m isKindOf: DockingBarItemMorph) and: [m isEnabled]) ifTrue: [^ self selectItem: m event: evt]. "Keep looking for an enabled item" index := index + direction sign]. ^ self selectItem: nil event: evt! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>adjacentTo (in category 'selecting') ----- + adjacentTo + + | roundedCornersOffset verticalOffset | + roundedCornersOffset := MenuMorph roundedMenuCorners + ifTrue: [Morph preferredCornerRadius negated] + ifFalse: [0]. + verticalOffset := 2. + + owner isFloating + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToTop + ifTrue: [^ {self bounds bottomLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToLeft + ifTrue: [^ {self bounds topRight + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToBottom + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset)}]. + owner isAdheringToRight + ifTrue: [^ {self bounds topLeft + (roundedCornersOffset @ verticalOffset negated)}]. + ^ {self bounds bottomLeft + (roundedCornersOffset @ 5)}! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createSubmenu (in category 'private') ----- + createSubmenu + + ^DockingBarMenuMorph new! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>createUpdatingSubmenu (in category 'private') ----- + createUpdatingSubmenu + + ^DockingBarUpdatingMenuMorph new! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'world') ----- - ----- Method: DockingBarUpdatingItemMorph>>decorateOwner (in category 'as yet unclassified') ----- decorateOwner "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawIconOn: (in category 'drawing') ----- + drawIconOn: aCanvas + + | pos | + self hasIcon ifTrue: [ + | iconForm | + iconForm := self iconForm. + + pos := (contents + ifEmpty: [self left + (self width - iconForm width // 2)] + ifNotEmpty: [self left]) + @ (self top + (self height - iconForm height // 2)). + + aCanvas + translucentImage: iconForm + at: pos].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawLabelOn: (in category 'drawing') ----- + drawLabelOn: aCanvas + + | stringBounds | + self contents ifEmpty: [^ self]. + + stringBounds := bounds. + + self hasIcon ifTrue: [ + stringBounds := stringBounds left: stringBounds left + self iconForm width + 2 ]. + + "Vertical centering." + stringBounds := stringBounds top: stringBounds top + stringBounds bottom - self fontToUse height // 2. + "Horizontal centering." + stringBounds := stringBounds left: stringBounds left + (stringBounds width - (self fontToUse widthOfString: contents) // 2) abs. + + aCanvas + drawString: contents + in: stringBounds + font: self fontToUse + color: self colorToUse.! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>drawSubMenuMarkerOn: (in category 'drawing') ----- + drawSubMenuMarkerOn: aCanvas + "Ignore."! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseDown: (in category 'events') ----- + mouseDown: evt + "Handle a mouse down event. Menu items get activated when the mouse is over them." + + (evt shiftPressed and:[self wantsKeyboardFocusOnShiftClick]) ifTrue: [ ^super mouseDown: evt ]. "enable label editing" + isSelected + ifTrue: [ + owner selectItem: nil event: evt. ] + ifFalse: [ + owner activate: evt. "Redirect to menu for valid transitions" + owner selectItem: self event: evt. ] + ! Item was changed: + ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'events') ----- - ----- Method: DockingBarUpdatingItemMorph>>mouseEnter: (in category 'as yet unclassified') ----- mouseEnter: evt "Do not hover docking bar items directory. Mouse-down required. But if you already see a submenu, support hovering." owner selectedItem ifNotNil: [owner selectItem: self event: evt]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>mouseUp: (in category 'events') ----- + mouseUp: evt + "Handle a mouse up event. Menu items get activated when the mouse is over them. Do nothing if we're not in a 'valid menu transition', meaning that the current hand focus must be aimed at the owning menu." + + evt hand mouseFocus == owner ifFalse: [ ^self ]. + self contentString ifNotNil: [ + self contents: self contentString withMarkers: true inverse: true. + self refreshWorld. + (Delay forMilliseconds: 200) wait ].! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>select: (in category 'selecting') ----- + select: evt + + super select: evt. + subMenu ifNotNil: [ + evt hand newKeyboardFocus: subMenu ]! Item was added: + ----- Method: DockingBarUpdatingItemMorph>>wantsKeyboardFocusOnShiftClick (in category 'events') ----- + wantsKeyboardFocusOnShiftClick + "set this preference to false to prevent user editing of docking bar menu items" + ^Preferences valueOfPreference: #allowMenubarItemEditing ifAbsent: [false]! Item was added: + ----- Method: DockingBarUpdatingMenuMorph>>morphicLayerNumber: (in category 'update') ----- + morphicLayerNumber: n + + super morphicLayerNumber: n. + ! Item was changed: ----- Method: MenuMorph>>initialize (in category 'initialization') ----- initialize super initialize. self setDefaultParameters. self changeTableLayout. self listDirection: #topToBottom. self hResizing: #shrinkWrap. self vResizing: #shrinkWrap. + self rubberBandCells: true. self disableLayout: true. self morphicLayerNumber: self class menuLayer. defaultTarget := nil. selectedItem := nil. stayUp := false. popUpOwner := nil.! Item was changed: ----- Method: SystemWindow>>createMenuBox (in category 'initialization') ----- createMenuBox ^ (self createBox: self class menuBoxImage) actionSelector: #offerWindowMenu; + setBalloonText: 'window menu' translated; + actWhen: #buttonDown; + yourself! - setBalloonText: 'window menu' translated! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChanges (in category 'right side') ----- browseChanges ChangeSorter open.! Item was changed: + ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'submenu - changes') ----- - ----- Method: TheWorldMainDockingBar>>browseChangesLabel (in category 'right side') ----- browseChangesLabel "The project name is the same as the current change set." ^ Project current name! Item was added: + ----- Method: TheWorldMainDockingBar>>changesMenuOn: (in category 'submenu - changes') ----- + changesMenuOn: aDockingBar + + aDockingBar addUpdatingItem: [:item | + item + help: 'Browse this project''s changes' translated; + wordingProvider: self + wordingSelector: #browseChangesLabel; + subMenuUpdater: self + selector: #listChangesOn:].! Item was changed: ----- Method: TheWorldMainDockingBar>>fillDockingBar: (in category 'construction') ----- fillDockingBar: aDockingBar "Private - fill the given docking bar" self menusOn: aDockingBar. aDockingBar addSpacer. + self changesMenuOn: aDockingBar. - self projectNameOn: aDockingBar. aDockingBar addSpacer. self rightSideOn: aDockingBar. aDockingBar setProperty: #mainDockingBarTimeStamp toValue: self class timeStamp.! Item was added: + ----- Method: TheWorldMainDockingBar>>listChangesOn: (in category 'submenu - changes') ----- + listChangesOn: menu + + | latestMethodChanges latestClassChanges| + latestMethodChanges := (Array streamContents: [:s | + ChangeSet current changedMethodsDo: [:method :changeType :dateAndTime :category | + s nextPut: { dateAndTime. method. changeType. category }]]) + sorted: [:a :b | a first >= b first]. + + 1 to: (10 min: latestMethodChanges size) do: [:index | | spec method | + spec := latestMethodChanges at: index. + method := spec second. + menu addItem: [:item | + item + contents: ('{1} {2} \{{3}\} \{{4}\}' format: {method methodClass. method selector. spec fourth. method methodClass category}) ; + target: ToolSet; + balloonText: spec third asString; + icon: ((#(remove addedThenRemoved) includes: spec third) ifTrue: [MenuIcons smallDeleteIcon] ifFalse: [ + spec third = #add ifTrue: [MenuIcons smallNewIcon] ifFalse: [MenuIcons blankIcon]]); + selector: (method isInstalled ifTrue: [#browseMethod:] ifFalse: [#browseMethodVersion:]); + arguments: {method}]]. + + latestClassChanges := (Array streamContents: [:s | + ChangeSet current changedClassesDo: [:class :changeTypes :dateAndTime :category | + "We are not interested in classes whose method's did only change." + changeTypes ifNotEmpty: [s nextPut: { dateAndTime. class. changeTypes. category }]]]) + sorted: [:a :b | a first >= b first]. + + latestClassChanges ifNotEmpty: [menu addLine]. + 1 to: (10 min: latestClassChanges size) do: [:index | | spec class | + spec := latestClassChanges at: index. + class := spec second. + menu addItem: [:item | + item + contents: ('{1} \{{2}\}' format: {class name. spec fourth }) ; + target: ToolSet; + balloonText: (spec third sorted joinSeparatedBy: Character space); + icon: ((spec third includesAnyOf: #(remove addedThenRemoved)) + ifTrue: [MenuIcons smallDeleteIcon] + ifFalse: [ + (spec third includes: #add) + ifTrue: [MenuIcons smallNewIcon] + ifFalse: [MenuIcons blankIcon]]); + selector: ((spec third includes: #remove) ifTrue: [#inspect:] ifFalse: [#browseClass:]); + arguments: {class}]]. + + menu addLine; addItem: [:item | + item + contents: 'Browse current change set...' translated; + target: self; + selector: #browseChanges].! Item was removed: - ----- Method: TheWorldMainDockingBar>>projectNameOn: (in category 'right side') ----- - projectNameOn: aDockingBar - - aDockingBar addUpdatingItem: [:item | - item - help: 'Browse this project''s changes'; - target: self; - selector: #browseChanges; - wordingProvider: self - wordingSelector: #browseChangesLabel].! Item was changed: + (PackageInfo named: 'Morphic') postscript: 'TheWorldMainDockingBar updateInstances.'! - (PackageInfo named: 'Morphic') postscript: 'Transcript showln: ''[NOTICE] There is a new preference called "Interactive print-it". Please check your preference browser to choose the preferred value.'''! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 160977 bytes Desc: image.png URL: From commits at source.squeak.org Tue Apr 20 15:16:21 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 20 Apr 2021 15:16:21 0000 Subject: [squeak-dev] FFI: FFI-Kernel-mt.120.mcz Message-ID: Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI: http://source.squeak.org/FFI/FFI-Kernel-mt.120.mcz ==================== Summary ==================== Name: FFI-Kernel-mt.120 Author: mt Time: 20 April 2021, 5:16:20.338768 pm UUID: 217ce793-267e-446b-9fea-61066a2b7741 Ancestors: FFI-Kernel-mt.119 ExternalData - Clarify content-type and container-type (Thanks Nicolas!!! Yet there is still work to be done to support n-ary pointer types) - Ensure that container-type is always a pointer type - Remove unnecessary checks in #at:(put:) - Make #from:to: retain the external address for empty results - More code clean-up ByteArray vs. ExternalAddress - Clarify the role of byte arrays through #isInternalMemory - Offer an #isNull: check using an external type to better support aliases on pointer-types ExternalStructure - Removes (my st00pid) notion of "stable representation" from ExternalStructure - Updates print-string to surround name with brackets [...] whenever the handle is a ByteArray (i.e. #isInternalMemory) --- and drop all those "*" for external addresses, which is the default, I suppose =============== Diff against FFI-Kernel-mt.119 =============== Item was changed: + ----- Method: ByteArray>>isExternalAddress (in category '*FFI-Kernel-testing') ----- - ----- Method: ByteArray>>isExternalAddress (in category '*FFI-Kernel') ----- isExternalAddress "Return true if the receiver describes the address of an object in the outside world" ^false! Item was added: + ----- Method: ByteArray>>isInternalMemory (in category '*FFI-Kernel-testing') ----- + isInternalMemory + + ^ true! Item was changed: + ----- Method: ByteArray>>isNull (in category '*FFI-Kernel-testing') ----- - ----- Method: ByteArray>>isNull (in category '*FFI-Kernel') ----- isNull + "Answer false since only pointers can be null, which is easy for external addresses but unknown for byte arrays without a proper external type for interpretation. See #isTypeAliasForPointer." + + ^ false! - "Answer false since only external addresses can be null" - ^false! Item was added: + ----- Method: ByteArray>>isNull: (in category '*FFI-Kernel-testing') ----- + isNull: externalType + "Given the external type, answer whether the receiver holds all null bytes representing a null pointer." + + "self assert: [self isInternalMemory]." + ^ externalType isTypeAliasForPointer + and: [externalType byteSize = self size] + and: [self allSatisfy: [:byte | byte = 0]]! Item was added: + ----- Method: ExternalAddress>>isInternalMemory (in category 'testing') ----- + isInternalMemory + + ^ false! Item was added: + ----- Method: ExternalAddress>>isNull: (in category 'testing') ----- + isNull: externalType + "Overridden to make use of #isNull. This fails if the provided pointer size does not match, which indicates an inconsistency in the system's type objects for the current platform. See 'housekeeping' protocol in ExternalType." + + self assert: [externalType pointerSize = self size]. + ^ self isNull! Item was changed: ----- Method: ExternalData>>asExternalStructure (in category 'converting') ----- asExternalStructure self + assert: [self contentType referentClass includesBehavior: ExternalStructure] - assert: [type referentClass includesBehavior: ExternalStructure] description: 'Wrong type'. + ^ self contentType referentClass fromHandle: handle! - ^ type referentClass fromHandle: handle! Item was changed: ----- Method: ExternalData>>asExternalUnion (in category 'converting') ----- asExternalUnion self + assert: [self contentType referentClass includesBehavior: ExternalUnion] - assert: [type referentClass includesBehavior: ExternalUnion] description: 'Wrong type'. + ^ self contentType referentClass fromHandle: handle! - ^ type referentClass fromHandle: handle! Item was added: + ----- Method: ExternalData>>asString (in category 'converting') ----- + asString + + ^ size + ifNil: [self fromCString] + ifNotNil: [self fromStringBounded]! Item was changed: ----- Method: ExternalData>>assert:at: (in category 'accessing') ----- assert: expectedType at: index self + assert: [self contentType = expectedType] + description: 'Wrong content type'. - assert: [type = expectedType asPointerType] - description: 'Wrong type'. ^ self at: index! Item was changed: ----- Method: ExternalData>>assert:at:put: (in category 'accessing') ----- assert: expectedType at: index put: value self + assert: [self contentType = expectedType] + description: 'Wrong content type'. - assert: [type = expectedType] - description: 'Wrong type'. ^ self at: index put: value! Item was changed: ----- Method: ExternalData>>at: (in category 'accessing') ----- at: index - self - assert: [index = 1 or: [type isAtomic]] - description: 'Should not read non-atomic pointer as array'. - ((1 > index) or: [size notNil and: [index > size]]) ifTrue: [^ self errorSubscriptBounds: index]. + ^ self contentType - ^ type asNonPointerType handle: handle + at: ((index-1) * self contentType byteSize) + 1! - at: ((index-1) * type asNonPointerType byteSize) + 1! Item was changed: ----- Method: ExternalData>>at:put: (in category 'accessing') ----- at: index put: value - self - assert: [index = 1 or: [type isAtomic]] - description: 'Should not read non-atomic pointer as array'. - ((1 > index) or: [size notNil and: [index > size]]) ifTrue: [^ self errorSubscriptBounds: index]. + ^ self contentType - ^ type asNonPointerType handle: handle + at: ((index-1) * self contentType byteSize) + 1 - at: ((index-1) * type asNonPointerType byteSize) + 1 put: value! Item was added: + ----- Method: ExternalData>>containerType (in category 'accessing - types') ----- + containerType + + ^ type! Item was added: + ----- Method: ExternalData>>contentType (in category 'accessing - types') ----- + contentType + + self flag: #todo. "mt: For n-ary pointer types, we typically just want to reducy arity by one." + ^ type asNonPointerType! Item was changed: + ----- Method: ExternalData>>externalType (in category 'accessing - types') ----- - ----- Method: ExternalData>>externalType (in category 'accessing') ----- externalType ^ type! Item was changed: ----- Method: ExternalData>>from:to: (in category 'accessing') ----- from: firstIndex to: lastIndex + "Only copy data if already in object memory, that is, as byte array. Only check size if configured." - "Only copy data if already in object memory, that is, as byte array." + | byteOffset numElements byteSize newType | - | byteOffset numElements byteSize | - lastIndex < firstIndex ifTrue: [ - ^ (ExternalData fromHandle: #[] type: type) - size: 0; yourself]. - ((1 > firstIndex) or: [size notNil and: [lastIndex > size]]) ifTrue: [^ self errorSubscriptBounds: lastIndex]. + byteOffset := ((firstIndex-1) * self contentType byteSize)+1. - byteOffset := ((firstIndex-1) * type asNonPointerType byteSize)+1. numElements := lastIndex - firstIndex + 1. + byteSize := numElements * self contentType byteSize. + + "For portions of a null-terminated C string, change the type from char* to byte* to avoid confusion." + newType := self containerType = ExternalType string + ifTrue: [ExternalType byte asPointerType] + ifFalse: [self containerType "No change"]. - byteSize := size * type asNonPointerType byteSize. + ^ lastIndex < firstIndex + ifTrue: [ + handle isExternalAddress + ifTrue: [(ExternalData + fromHandle: handle + (byteOffset - 1) "Keep pointer." + type: newType) size: 0; yourself] + ifFalse: [(ExternalData + fromHandle: #[] "Empty memory" + type: newType) size: 0; yourself]] + ifFalse: [ + handle isExternalAddress + ifTrue: [(ExternalData + fromHandle: handle + (byteOffset - 1) + type: newType) size: numElements; yourself] + ifFalse: [(ExternalData + fromHandle: (handle copyFrom: byteOffset to: byteOffset+byteSize) + type: newType) size: numElements; yourself]]! - ^ handle isExternalAddress - ifTrue: [(ExternalData - fromHandle: handle + byteOffset - 1 - type: type) size: numElements; yourself] - ifFalse: [(ExternalData - fromHandle: (handle copyFrom: byteOffset to: byteOffset+byteSize) - type: type) size: numElements; yourself]! Item was changed: + ----- Method: ExternalData>>fromCString (in category 'converting - support') ----- - ----- Method: ExternalData>>fromCString (in category 'converting') ----- fromCString "Assume that the receiver represents a C string and convert it to a Smalltalk string. hg 2/25/2000 14:18" | stream index char | self + assert: [self containerType = ExternalType string] + description: 'Wrong content type'. - assert: [self externalType = ExternalType string] - description: 'Wrong type'. stream := WriteStream on: String new. index := 1. [(char := self at: index) = 0 asCharacter] whileFalse: [ stream nextPut: char. index := index + 1]. ^stream contents! Item was changed: + ----- Method: ExternalData>>fromCStrings (in category 'converting - support') ----- - ----- Method: ExternalData>>fromCStrings (in category 'converting') ----- fromCStrings "Assume that the receiver represents a set of C strings and is teerminated by a empty string and convert it to a Smalltalk ordered collection of strings" | stream index char strings str | type isPointerType ifFalse: [self error: 'External object is not a pointer type.']. + self flag: #bogus. "mt: This format seems to be rather specific to some library. There would normally be pointers to pointers for such a structure. Or does the C standard mention such a format somehow? 'abcd\0efg\0hijklmnopq\0rstuvwxyz\0\0' ??? " strings := OrderedCollection new. index := 1. [ stream := WriteStream on: String new. [(char := handle unsignedCharAt: index) = 0 asCharacter] whileFalse: [ stream nextPut: char. index := index + 1 ]. str := stream contents. strings addLast: str. str size = 0 ] whileFalse. ^strings! Item was added: + ----- Method: ExternalData>>fromStringBounded (in category 'converting - support') ----- + fromStringBounded + "Read byte* as bounded string. You have to set a #size first." + + | offset step | + self + assert: [self contentType = ExternalType byte] + description: 'Wrong content type'. + + self sizeCheck. + + offset := 1. + step := self contentType byteSize. + + ^ String streamContents: [:s | + size timesRepeat: [ + s nextPut: (handle unsignedCharAt: offset). + offset := offset + step]]! Item was changed: ----- Method: ExternalData>>getExternalData (in category 'accessing - external structures') ----- getExternalData + "Reads all bytes into object memory. Note that this does not flatten all bytes into a single array by repeatedly calling it. It does just work once for an external address." - "Reads all bytes into object memory." | data | handle isExternalAddress ifFalse: [^ self]. self sizeCheck. + data := ByteArray new: size * self contentType byteSize. - data := ByteArray new: size * type asNonPointerType byteSize. 1 to: data size do: [:index | data unsignedByteAt: index put: (handle unsignedByteAt: index)]. ^ (ExternalData fromHandle: data + type: self contentType) - type: type asNonPointerType) size: size! Item was changed: ----- Method: ExternalData>>getExternalStructure (in category 'accessing - external structures') ----- getExternalStructure "Reads an external structure from this external data. If the receiver's handle is an external address, the structure's fields will be copied into object memory. Use #asExternalStructure if you want to avoid this copy." self + assert: [self contentType referentClass includesBehavior: ExternalStructure] + description: 'Wrong content type'. - assert: [type referentClass includesBehavior: ExternalStructure] - description: 'Wrong type'. ^ handle isExternalAddress + ifTrue: [self getExternalData asExternalStructure] + ifFalse: [self asExternalStructure]! - ifTrue: [self getExternalData getExternalStructure] - ifFalse: [type referentClass fromHandle: handle]! Item was changed: ----- Method: ExternalData>>getExternalUnion (in category 'accessing - external structures') ----- getExternalUnion "Reads an external union from this external data. If the receiver's handle is an external address, the union's fields will be copied into object memory. Use #asExternalUnion if you want to avoid this copy." self + assert: [self contentType referentClass includesBehavior: ExternalUnion] + description: 'Wrong content type'. - assert: [type referentClass includesBehavior: ExternalUnion] - description: 'Wrong type'. ^ handle isExternalAddress + ifTrue: [self getExternalData asExternalUnion] + ifFalse: [self asExternalUnion]! - ifTrue: [self getExternalData getExternalUnion] - ifFalse: [type referentClass fromHandle: handle]! Item was added: + ----- Method: ExternalData>>printContentTypeOn: (in category 'printing') ----- + printContentTypeOn: stream + + stream + nextPut: $<; + print: self contentType; + nextPut: $>.! Item was changed: ----- Method: ExternalData>>printOn: (in category 'printing') ----- printOn: stream super printOn: stream. + self printContentTypeOn: stream.! - self printTypeOn: stream.! Item was removed: - ----- Method: ExternalData>>printPointerOn: (in category 'printing') ----- - printPointerOn: stream - "Ignore since it is part of the type, e.g. char* or int[] etc."! Item was removed: - ----- Method: ExternalData>>printTypeOn: (in category 'printing') ----- - printTypeOn: stream - - stream - nextPut: $<; - print: type; - nextPut: $>.! Item was changed: ----- Method: ExternalData>>setHandle:type: (in category 'private') ----- setHandle: aHandle type: aType handle := aHandle. + type := aType asPointerType.! - type := aType.! Item was changed: ----- Method: ExternalStructure>>externalType (in category 'accessing') ----- externalType + ^ self class externalType! - | type | - self flag: #ffiDesignSmell. "mt: Note that type aliases to pointer types store pointers via handle as ByteArray, not ExternalAddress." - type := self class externalType. - ^ handle class == ExternalAddress - ifTrue: [type asPointerType] - ifFalse: [type]! Item was removed: - ----- Method: ExternalStructure>>hasStableRepresentation (in category 'testing') ----- - hasStableRepresentation - "Answers whether the contents of this structure have a stable representation in memory. Basically, every handle that is not a ByteArray can be considered a stable representation. The primary examples would be handles that are 'nil' or an ExternalAddress. Additionally, there can be type aliases to atomic types, which then store the Smalltalk object, e.g. Integer or Float, for such an atomic, e.g. long or float, directly in 'handle'. Those Smalltalk objects are typically immediate (e.g., integers, characters). Note that strings map to char*, which is an (atomic) pointer type and thus accessible only through an ExternalData, which itself always holds an external address as its handle." - - ^ handle class ~~ ByteArray! Item was changed: ----- Method: ExternalStructure>>isNull (in category 'testing') ----- isNull + handle isInternalMemory + ifTrue: [^ handle isNull: self externalType]. + handle isExternalAddress + ifTrue: [^ handle isNull]. + ^ handle isNil! - self flag: #ffiDesignSmell. "Type aliases to atomic types store data via handle as Smalltalk object. Consequently, #isNull and #isExternalAddress must not be sent to 'handle' without care. Actually, #isExternalAddress is rather useless at the moment." - - handle class == ExternalAddress ifTrue: [^ handle isNull]. - self hasStableRepresentation ifTrue: [^ handle isNil]. - - self flag: #ffiDesignSmell. "Type aliases to pointer types store pointers via handle as ByteArray, not ExternalAddress (like regular pointer types). Consequently, it is tricky to detect a NULL pointer in the general sense. Here, try to check for #isTypeAliasForPointer and only then check for all bytes being 0 in the byte array." - - "self assert: [self externalType isTypeAliasForPointer => [handle class == ByteArray]]." - ^ self externalType isTypeAliasForPointer - and: [handle allSatisfy: [:byte | byte = 0 ]]! Item was changed: ----- Method: ExternalStructure>>printIdentityOn: (in category 'printing') ----- printIdentityOn: stream + "Reveal information about this external object's identity so that users can quickly assess the need for inspecting its contents. Users can also infer lifetime properties and consider those when passing this object around in the system." - "Reveal information about this external object's identity so that users can quickly assess the need for inspecting its contents. Users can also infer lifetime properties and consider those when passing this object around in the system. For example, objects that are created on-the-fly when accessing fields via an external address may be of less value compared to objects that are actually hold at those external addresses. See #printPointerOn:." handle ifNil: [ ^ stream nextPutAll: '']. self isNull ifTrue: [ + ^ stream nextPutAll: ''].! - ^ stream nextPutAll: '']. - - self hasStableRepresentation - ifTrue: ["Object has a stable representation. No need to expose its memory address in the UI." - ^ self] - ifFalse: ["Inform the user that this data was copied into object memory." - ^ stream nextPut: $<; print: handle identityHash; nextPut: $>]. - ! Item was changed: ----- Method: ExternalStructure>>printOn: (in category 'printing') ----- printOn: stream + handle ifNil: [stream nextPutAll: '? ']. + handle isInternalMemory ifTrue: [stream nextPutAll: '[']. + super printOn: stream. + handle ifNil: [stream nextPutAll: ' ?']. + handle isInternalMemory ifTrue: [stream nextPutAll: ']']. + - self printPointerOn: stream. self printIdentityOn: stream.! Item was removed: - ----- Method: ExternalStructure>>printPointerOn: (in category 'printing') ----- - printPointerOn: stream - "Indicate whether this structure points to an external address or whether its contents got copied into a byte array in object memory." - - handle ifNil: [^ stream nextPutAll: '']. - - handle class == ExternalAddress - ifTrue: [stream nextPutAll: '*'].! Item was added: + ----- Method: ExternalType>>isTypeAlias (in category 'testing') ----- + isTypeAlias + + ^ false! Item was added: + ----- Method: ExternalType>>isTypeAliasForPointer (in category 'testing') ----- + isTypeAliasForPointer + + ^ false! Item was added: + ----- Method: Object>>isExternalAddress (in category '*FFI-Kernel') ----- + isExternalAddress + "Return true if the receiver describes the address of an object in the outside world. NOTE that this backstop is in Object because atomic types store actual objects (e.g., numbers) as their handle." + + ^ false! Item was added: + ----- Method: Object>>isInternalMemory (in category '*FFI-Kernel') ----- + isInternalMemory + "Return true if the receiver describes a region of memory (within Squeak's object memory) to be interpreted (e.g., as external structure, pointer, ...). NOTE that this backstop is in Object because atomic types store actual objects (e.g., numbers) as their handle." + + ^ false! From commits at source.squeak.org Tue Apr 20 15:17:02 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 20 Apr 2021 15:17:02 0000 Subject: [squeak-dev] FFI: FFI-Tools-mt.21.mcz Message-ID: Marcel Taeumel uploaded a new version of FFI-Tools to project FFI: http://source.squeak.org/FFI/FFI-Tools-mt.21.mcz ==================== Summary ==================== Name: FFI-Tools-mt.21 Author: mt Time: 20 April 2021, 5:17:02.045768 pm UUID: 7def1cf3-e037-4cbc-ba03-c673cf7c0d27 Ancestors: FFI-Tools-mt.20 Complements FFI-Kernel-mt.120 =============== Diff against FFI-Tools-mt.20 =============== Item was changed: ----- Method: ExternalData>>explorerContentsMetaFields (in category '*FFI-Tools') ----- explorerContentsMetaFields + "Skip _type because our external type is already in the basic explorer fields because it is an instance variable. Add _contentType for clarification." + + ^ { + ObjectExplorerWrapper with: self containerType name: '_containerType' model: self. + ObjectExplorerWrapper with: self contentType name: '_contentType' model: self. + }! - "Ignore because our type is already in the basic explorer fields because it is an instance variable." - ^ #()! Item was changed: ----- Method: ExternalData>>explorerContentsStructFields (in category '*FFI-Tools') ----- explorerContentsStructFields "In case some data interpretation omitted to convert char*, which is a (null-terminated) C string, to Smalltalk string." + ^ (self isNull not and: [self containerType = ExternalType string]) ifFalse: [#()] ifTrue: [ - ^ (self isNull not and: [type = ExternalType string]) ifFalse: [#()] ifTrue: [ {ObjectExplorerWrapper with: self fromCString name: 'as C string' model: self}]! Item was changed: ----- Method: ExternalData>>hasContentsInExplorer (in category '*FFI-Tools') ----- hasContentsInExplorer ^ super hasContentsInExplorer + or: [self isNull not and: [self containerType = ExternalType string]]! - or: [self isNull not and: [type = ExternalType string]]! From tonyg at leastfixedpoint.com Tue Apr 20 15:42:32 2021 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Tue, 20 Apr 2021 17:42:32 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph Message-ID: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> Hi all, I finally blogged about OnScreenKeyboardMorph: https://eighty-twenty.org/2021/04/20/on-screen-keyboard-morph Cheers, Tony From kirtai+st at gmail.com Tue Apr 20 16:07:46 2021 From: kirtai+st at gmail.com (Douglas Brebner) Date: Tue, 20 Apr 2021 17:07:46 +0100 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> Message-ID: <5c705863-e902-81b1-5a14-a405239daa26@gmail.com> On 20/04/2021 16:42, Tony Garnock-Jones wrote: > Hi all, > > I finally blogged about OnScreenKeyboardMorph: > https://eighty-twenty.org/2021/04/20/on-screen-keyboard-morph > This is very cool. From jakres+squeak at gmail.com Tue Apr 20 16:59:54 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Tue, 20 Apr 2021 18:59:54 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Hi, Am Di., 20. Apr. 2021 um 09:16 Uhr schrieb Nicolas Cellier : > > Here, you submit another case where you want all the handlers to be rearmed. > I don't think that rearmHandlerDuring: should rearm the other > exceptions upstack. > Maybe you could try (e reactivateHandlers) instead of (e > rearmHandlerDuring: [...]). I also do not think that rearm should rearm all handlers. I shall think a bit more whether reactivateHandlers is the right choice or whether it cannot also reactivate too much. > Let's have a look at what sendNotificationsTo: does > > sendNotificationsTo: aNewBlock > self resume: ( > workBlock value: [ :barVal | > aNewBlock value: minVal value: maxVal value: barVal > ] > ) > > We recognize the same pattern as resignalAs: and nil>>handleSignal: > resume will reactivateHandlers after the battle, that is after > evaluating aNewBlock... > I suggest this revision: > > sendNotificationsTo: aNewBlock > self reactivateHandlers; resumeUnchecked: ( > workBlock value: [ :barVal | > aNewBlock value: minVal value: maxVal value: barVal > ] > ) > > I think that it makes rearmHandlerDuring: un-necessary. ...which means that now the use of sendNotificationsTo: cannot be used to deal with just one layer of progress. It will always also apply to multiple nested progress bars. Not a problem for my use case, but I wonder what the general expectations of it are. > > You also raise other points. > Why the following works: > Environment current. > ^ self actualClassIn: Environment current > Environment current sends an extra signal, so signalling twice has a > different effect as signalling once. > You said that it's not acceptable, but I'm not so sure... What I find not acceptable (or, let's rather say questionable) is the hidden side effect. After a signal is fully handled and has returned to the signal sender, I would naïvely expect that the stack (exception environment) is in the same state as before the signal. If custom exceptions or handler blocks implement their own side effects or state, so shall they. But in my opinion the base implementation should not have such confusing side effects on the stack, and on totally unrelated exception handlers in particular. Kind regards, Jakob > > Why the debugging takes another path is another weird behavior that we > should inquire... > It ain't gonna be easy though. > > Le mar. 20 avr. 2021 à 00:08, Jakob Reschke a écrit : > > > > Oh by the way, this was helpful to inspect the stack in the incorrect state: > > > > MCMethodDefinition>> > > actualClass > > (thisContext sender selector == #unload) ifTrue: [thisContext > > copyStack inspect]. > > ^ self actualClassIn: Environment current > > > > In the Inspector: > > | context | > > context := self nextHandlerContext. > > Array streamContents: [:str | > > [context notNil] whileTrue: [str nextPut: context. context := > > context nextHandlerContext]]. > > > > | context | > > context := self. > > Array streamContents: [:str | > > [context notNil] whileTrue: [str nextPut: context. context := > > context sender]]. > > > > Am Di., 20. Apr. 2021 um 00:02 Uhr schrieb Jakob Reschke > > : > > > > > > Looks like this does no longer work as before: > > > > > > SquotImageStoreTest>> > > > suppressProgressDisplayDuring: aBlock > > > ... > > > aBlock > > > on: ProgressInitiationException do: [:e | > > > ... > > > e rearmHandlerDuring: > > > [[e sendNotificationsTo: [:min :max :current | "silence"]] > > > on: ProgressNotification do: [:notification | > > > notification resume]] > > > ... > > > > > > rearmHandlerDuring: does reactivate this current handler, but not > > > handlers further up the stack. > > > So e sendNotificationsTo: will evaluate the block in the package > > > loader that eventually unloads the method in the test case while all > > > handlers that are between the ProgressInitiationException signal > > > context and this ProgressInitiationException handler context on the > > > stack are deactivated, including the one that sets the correct > > > Environment (and also the source file caching, by the way). Find the > > > annotated stack below for a little more visualization. > > > > > > Previously, the handler contexts that did not fit the raised Exception > > > were not deactivated. Is the ProgressInitiationException redirection > > > concept broken in general now? Note that the ZeroDivide in > > > ProgressInitiationException>>testWith is now no longer caught. > > > > > > --- The redacted stack of my failing test with some ---annotations---> > > > [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The > > > block under 'Installing ', pkgName displayProgressFrom: ... > > > ProgressInitiationException>>sendNotificationsTo: > > > [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > FullBlockClosure(BlockClosure)>>on:do: > > > [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > [] in Context>>rearmHandlerDuring: > > > FullBlockClosure(BlockClosure)>>ensure: > > > ---reactivated #1---> Context>>rearmHandlerDuring: > > > ProgressInitiationException(Exception)>>rearmHandlerDuring: > > > [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > [] in Context>>handleSignal: > > > FullBlockClosure(BlockClosure)>>ifCurtailed: > > > Context>>handleSignal: <--- #1 sender: > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > ... > > > Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: > > > Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles > > > class>>cacheDuring: > > > Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad > > > ---triggers stack walk---> ProgressInitiationException(Exception)>>signal > > > ProgressInitiationException>>display:at:from:to:during: > > > ... > > > ByteString(String)>>displayProgressFrom:to:during: > > > [] in [] in [] in [] in MCPackageLoader>>basicLoad > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > [] in [] in [] in MCPackageLoader>>basicLoad > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > CurrentReadOnlySourceFiles class>>cacheDuring: > > > ... > > > MCPackageLoader>>basicLoad > > > ... > > > MCPackageLoader>>loadWithNameLike: > > > [] in SquotPackageShadow>>squotMaterializeWith: > > > ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: > > > Environment>>beCurrentDuring: > > > SquotPackageShadow>>squotMaterializeWith: > > > ... > > > SquotImageStoreTest>>testApplyPatch > > > SquotImageStoreTest(TestCase)>>performTest > > > [] in SquotImageStoreTest>>performTest > > > ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > ... > > > > > > Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke > > > : > > > > > > > > Hi Nicolas, > > > > > > > > I seem to have a Heisenbug now because of this: > > > > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > > > > > > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > > > > > > > But if I replace in MCMethodDefinition this: > > > > > > > > actualClass > > > > ^ self actualClassIn: Environment current > > > > > > > > by this: > > > > > > > > actualClass > > > > Environment current. > > > > ^ self actualClassIn: Environment current > > > > > > > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > > > > > > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > > > > > > > Kind regards, > > > > Jakob > > > > > > > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > > > >> > > > >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > > > >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz > > > >> > > > >> ==================== Summary ==================== > > > >> > > > >> Name: Kernel-nice.1384 > > > >> Author: nice > > > >> Time: 11 April 2021, 7:33:23.487481 pm > > > >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > > > >> Ancestors: Kernel-mt.1383 > > > >> > > > >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. > > > >> > > > >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. > > > >> > > > >> =============== Diff against Kernel-mt.1383 =============== > > > >> > > > >> Item was changed: > > > >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > > > >> handleSignal: exception > > > >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > > > >> and the handler is active then execute my handle block (second arg), otherwise forward > > > >> this message to the next handler context. If none left, execute exception's defaultAction > > > >> (see nil>>handleSignal:)." > > > >> > > > >> | handlerActive val | > > > >> "If the context has been returned from the handlerActive temp var may not be accessible." > > > >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > > > >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > > > >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > > > >> + ^self nextHandlerContext handleSignal: exception]. > > > >> - [^self nextHandlerContext handleSignal: exception]. > > > >> > > > >> exception privHandlerContext: self contextTag. > > > >> self tempAt: 3 put: false. "disable self while executing handle block" > > > >> val := [(self tempAt: 2) cull: exception] > > > >> + ifCurtailed: [self tempAt: 3 put: true]. > > > >> - ensure: [self tempAt: 3 put: true]. > > > >> self return: val "return from self if not otherwise directed in handle block" > > > >> ! > > > >> > > > >> Item was added: > > > >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > > > >> + reactivateHandlers > > > >> + "Private - sent to exception handler context only (on:do:). > > > >> + Reactivate all the handlers into the chain" > > > >> + > > > >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > > > >> + self nextHandlerContext reactivateHandlers! > > > >> > > > >> Item was added: > > > >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- > > > >> + reactivateHandlers > > > >> + "reactivate all the exception handlers in the context chain" > > > >> + self canSearchForSignalerContext > > > >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! > > > >> > > > >> Item was changed: > > > >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- > > > >> resignalAs: replacementException > > > >> "Signal an alternative exception in place of the receiver." > > > >> > > > >> + self reactivateHandlers. > > > >> self resumeUnchecked: replacementException signal! > > > >> > > > >> Item was changed: > > > >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- > > > >> handleSignal: exception > > > >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. > > > >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." > > > >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." > > > >> > > > >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! > > > >> - ^ exception resumeUnchecked: exception defaultAction! > > > >> > > > >> Item was added: > > > >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- > > > >> + reactivateHandlers > > > >> + "nothing to do for bottom context" > > > >> + > > > >> + ^ self! > > > >> > > > >> > > > From Das.Linux at gmx.de Tue Apr 20 17:49:21 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Tue, 20 Apr 2021 19:49:21 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> Message-ID: Hey Tony > On 20. Apr 2021, at 17:42, Tony Garnock-Jones wrote: > > Hi all, > > I finally blogged about OnScreenKeyboardMorph: https://eighty-twenty.org/2021/04/20/on-screen-keyboard-morph This is mighty cool! Best regards -Tobias From nicolas.cellier.aka.nice at gmail.com Wed Apr 21 09:48:58 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed, 21 Apr 2021 11:48:58 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Hi Jakob, Le mar. 20 avr. 2021 à 19:00, Jakob Reschke a écrit : > > Hi, > > Am Di., 20. Apr. 2021 um 09:16 Uhr schrieb Nicolas Cellier > : > > > > Here, you submit another case where you want all the handlers to be rearmed. > > I don't think that rearmHandlerDuring: should rearm the other > > exceptions upstack. > > Maybe you could try (e reactivateHandlers) instead of (e > > rearmHandlerDuring: [...]). > > I also do not think that rearm should rearm all handlers. I shall > think a bit more whether reactivateHandlers is the right choice or > whether it cannot also reactivate too much. > > > Let's have a look at what sendNotificationsTo: does > > > > sendNotificationsTo: aNewBlock > > self resume: ( > > workBlock value: [ :barVal | > > aNewBlock value: minVal value: maxVal value: barVal > > ] > > ) > > > > We recognize the same pattern as resignalAs: and nil>>handleSignal: > > resume will reactivateHandlers after the battle, that is after > > evaluating aNewBlock... > > I suggest this revision: > > > > sendNotificationsTo: aNewBlock > > self reactivateHandlers; resumeUnchecked: ( > > workBlock value: [ :barVal | > > aNewBlock value: minVal value: maxVal value: barVal > > ] > > ) > > > > I think that it makes rearmHandlerDuring: un-necessary. > > ...which means that now the use of sendNotificationsTo: cannot be used > to deal with just one layer of progress. It will always also apply to > multiple nested progress bars. Not a problem for my use case, but I > wonder what the general expectations of it are. > Ah, I wondered exactly about that case... What we want to achieve is really contradictory here. We want to handle the case when a new exception is signalled during the handling (during execution of 2nd arg of on:do:) #testHandlerFromAction specifies that shallower handlerContext shall be bypassed, and that next handler shall be searched deeper than active one. The solution in https://source.squeak.org/treated/Kernel-nice.857.diff was to let handleSignal: be detected as a handlerContext (), because it already knows the active handlerContext, it's easy to continue stack scanning from there... Same scheme was later adopted in Cuis (see https://source.squeak.org/treated/Kernel-fbs.870.diff). #testHandlerReentrancy on the other hand specifies that not all the shallower handlerContext shall be bypassed, but that some can be rearmed and stay active. This is challenging to implement with a solution like in Cuis, but I think it should be possible... The new Squeak solution is much simpler: deactivate when we backtrack the stack, reactivate when we resume the exception... That also means that it's less fine-grained. My understanding here is that you have yet another set of expectations: - the shallower handlers shall be active during current exception handling so as to intercept other kinds of Exception Note that this would not work in Cuis - except the already fired handlers that have not been rearmed... (what you call the stack state) It's not only challenging, it's questionable whether this can possibly fit with above expectations... > > > > You also raise other points. > > Why the following works: > > Environment current. > > ^ self actualClassIn: Environment current > > Environment current sends an extra signal, so signalling twice has a > > different effect as signalling once. > > You said that it's not acceptable, but I'm not so sure... > > What I find not acceptable (or, let's rather say questionable) is the > hidden side effect. After a signal is fully handled and has returned > to the signal sender, I would naïvely expect that the stack (exception > environment) is in the same state as before the signal. If custom > exceptions or handler blocks implement their own side effects or > state, so shall they. But in my opinion the base implementation should > not have such confusing side effects on the stack, and on totally > unrelated exception handlers in particular. > > Kind regards, > Jakob > Yes, but how does that happen? For returning a value to the sender of signal, one has to resume (resume:), which will reactivateHandlers. There is the case of resumeUnchecked: which leaves this responsibility to its sender, and currently, not all senders of resumeUnchecked: will reactivateHandlers. (I didn't know what to do in SpurImageSegmentLoader for example...) Ah, there is also runUntilErrorOrReturnFrom: which might explain some differences when debugging... but is it really the path of trouble here? > > > > > > Why the debugging takes another path is another weird behavior that we > > should inquire... > > It ain't gonna be easy though. > > > > Le mar. 20 avr. 2021 à 00:08, Jakob Reschke a écrit : > > > > > > Oh by the way, this was helpful to inspect the stack in the incorrect state: > > > > > > MCMethodDefinition>> > > > actualClass > > > (thisContext sender selector == #unload) ifTrue: [thisContext > > > copyStack inspect]. > > > ^ self actualClassIn: Environment current > > > > > > In the Inspector: > > > | context | > > > context := self nextHandlerContext. > > > Array streamContents: [:str | > > > [context notNil] whileTrue: [str nextPut: context. context := > > > context nextHandlerContext]]. > > > > > > | context | > > > context := self. > > > Array streamContents: [:str | > > > [context notNil] whileTrue: [str nextPut: context. context := > > > context sender]]. > > > > > > Am Di., 20. Apr. 2021 um 00:02 Uhr schrieb Jakob Reschke > > > : > > > > > > > > Looks like this does no longer work as before: > > > > > > > > SquotImageStoreTest>> > > > > suppressProgressDisplayDuring: aBlock > > > > ... > > > > aBlock > > > > on: ProgressInitiationException do: [:e | > > > > ... > > > > e rearmHandlerDuring: > > > > [[e sendNotificationsTo: [:min :max :current | "silence"]] > > > > on: ProgressNotification do: [:notification | > > > > notification resume]] > > > > ... > > > > > > > > rearmHandlerDuring: does reactivate this current handler, but not > > > > handlers further up the stack. > > > > So e sendNotificationsTo: will evaluate the block in the package > > > > loader that eventually unloads the method in the test case while all > > > > handlers that are between the ProgressInitiationException signal > > > > context and this ProgressInitiationException handler context on the > > > > stack are deactivated, including the one that sets the correct > > > > Environment (and also the source file caching, by the way). Find the > > > > annotated stack below for a little more visualization. > > > > > > > > Previously, the handler contexts that did not fit the raised Exception > > > > were not deactivated. Is the ProgressInitiationException redirection > > > > concept broken in general now? Note that the ZeroDivide in > > > > ProgressInitiationException>>testWith is now no longer caught. > > > > > > > > --- The redacted stack of my failing test with some ---annotations---> > > > > [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The > > > > block under 'Installing ', pkgName displayProgressFrom: ... > > > > ProgressInitiationException>>sendNotificationsTo: > > > > [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > FullBlockClosure(BlockClosure)>>on:do: > > > > [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > [] in Context>>rearmHandlerDuring: > > > > FullBlockClosure(BlockClosure)>>ensure: > > > > ---reactivated #1---> Context>>rearmHandlerDuring: > > > > ProgressInitiationException(Exception)>>rearmHandlerDuring: > > > > [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > [] in Context>>handleSignal: > > > > FullBlockClosure(BlockClosure)>>ifCurtailed: > > > > Context>>handleSignal: <--- #1 sender: > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > ... > > > > Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: > > > > Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles > > > > class>>cacheDuring: > > > > Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad > > > > ---triggers stack walk---> ProgressInitiationException(Exception)>>signal > > > > ProgressInitiationException>>display:at:from:to:during: > > > > ... > > > > ByteString(String)>>displayProgressFrom:to:during: > > > > [] in [] in [] in [] in MCPackageLoader>>basicLoad > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > [] in [] in [] in MCPackageLoader>>basicLoad > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > CurrentReadOnlySourceFiles class>>cacheDuring: > > > > ... > > > > MCPackageLoader>>basicLoad > > > > ... > > > > MCPackageLoader>>loadWithNameLike: > > > > [] in SquotPackageShadow>>squotMaterializeWith: > > > > ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: > > > > Environment>>beCurrentDuring: > > > > SquotPackageShadow>>squotMaterializeWith: > > > > ... > > > > SquotImageStoreTest>>testApplyPatch > > > > SquotImageStoreTest(TestCase)>>performTest > > > > [] in SquotImageStoreTest>>performTest > > > > ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > ... > > > > > > > > Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke > > > > : > > > > > > > > > > Hi Nicolas, > > > > > > > > > > I seem to have a Heisenbug now because of this: > > > > > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > > > > > > > > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > > > > > > > > > But if I replace in MCMethodDefinition this: > > > > > > > > > > actualClass > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > by this: > > > > > > > > > > actualClass > > > > > Environment current. > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > > > > > > > > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > > > > > > > > > Kind regards, > > > > > Jakob > > > > > > > > > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > > > > >> > > > > >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > > > > >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz > > > > >> > > > > >> ==================== Summary ==================== > > > > >> > > > > >> Name: Kernel-nice.1384 > > > > >> Author: nice > > > > >> Time: 11 April 2021, 7:33:23.487481 pm > > > > >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > > > > >> Ancestors: Kernel-mt.1383 > > > > >> > > > > >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. > > > > >> > > > > >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. > > > > >> > > > > >> =============== Diff against Kernel-mt.1383 =============== > > > > >> > > > > >> Item was changed: > > > > >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > > > > >> handleSignal: exception > > > > >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > > > > >> and the handler is active then execute my handle block (second arg), otherwise forward > > > > >> this message to the next handler context. If none left, execute exception's defaultAction > > > > >> (see nil>>handleSignal:)." > > > > >> > > > > >> | handlerActive val | > > > > >> "If the context has been returned from the handlerActive temp var may not be accessible." > > > > >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > > > > >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > > > > >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > > > > >> + ^self nextHandlerContext handleSignal: exception]. > > > > >> - [^self nextHandlerContext handleSignal: exception]. > > > > >> > > > > >> exception privHandlerContext: self contextTag. > > > > >> self tempAt: 3 put: false. "disable self while executing handle block" > > > > >> val := [(self tempAt: 2) cull: exception] > > > > >> + ifCurtailed: [self tempAt: 3 put: true]. > > > > >> - ensure: [self tempAt: 3 put: true]. > > > > >> self return: val "return from self if not otherwise directed in handle block" > > > > >> ! > > > > >> > > > > >> Item was added: > > > > >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > > > > >> + reactivateHandlers > > > > >> + "Private - sent to exception handler context only (on:do:). > > > > >> + Reactivate all the handlers into the chain" > > > > >> + > > > > >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > > > > >> + self nextHandlerContext reactivateHandlers! > > > > >> > > > > >> Item was added: > > > > >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- > > > > >> + reactivateHandlers > > > > >> + "reactivate all the exception handlers in the context chain" > > > > >> + self canSearchForSignalerContext > > > > >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! > > > > >> > > > > >> Item was changed: > > > > >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- > > > > >> resignalAs: replacementException > > > > >> "Signal an alternative exception in place of the receiver." > > > > >> > > > > >> + self reactivateHandlers. > > > > >> self resumeUnchecked: replacementException signal! > > > > >> > > > > >> Item was changed: > > > > >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- > > > > >> handleSignal: exception > > > > >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. > > > > >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." > > > > >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." > > > > >> > > > > >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! > > > > >> - ^ exception resumeUnchecked: exception defaultAction! > > > > >> > > > > >> Item was added: > > > > >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- > > > > >> + reactivateHandlers > > > > >> + "nothing to do for bottom context" > > > > >> + > > > > >> + ^ self! > > > > >> > > > > >> > > > > > > From kirtai+st at gmail.com Wed Apr 21 13:36:09 2021 From: kirtai+st at gmail.com (Douglas Brebner) Date: Wed, 21 Apr 2021 14:36:09 +0100 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> Message-ID: <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> On 20/04/2021 16:42, Tony Garnock-Jones wrote: > Hi all, > > I finally blogged about OnScreenKeyboardMorph: > https://eighty-twenty.org/2021/04/20/on-screen-keyboard-morph > > Cheers, >   Tony I just remembered, Squeak has (used to have?) a handwriting recognition system called Genie. That may make a useful addition to a phone UI. Maybe even resurrect graffiti from the palm pdas :) From tomjonabc at gmail.com Wed Apr 21 13:53:45 2021 From: tomjonabc at gmail.com (Tom Beckmann) Date: Wed, 21 Apr 2021 15:53:45 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> Message-ID: Hi Douglas, hi Tony, > I just remembered, Squeak has (used to have?) a handwriting recognition > system called Genie. That may make a useful addition to a phone UI. > Maybe even resurrect graffiti from the palm pdas :) Chiming in on that note, I had experimented with that a while ago as well and it turned out pretty fun I think, here's a quick demo video [1] and the source code [2]. I believe it would be rather easy to make work if combined with your keypress generation logic, Tony. Best, Tom [1] https://archive.org/details/handwriting-2021-04-21_15.44.40 [2] https://github.com/tom95/sandblocks/blob/master/packages/Sandblocks-Core/SBHandWritingInput.class.st On Wed, Apr 21, 2021 at 3:36 PM Douglas Brebner wrote: > On 20/04/2021 16:42, Tony Garnock-Jones wrote: > > Hi all, > > > > I finally blogged about OnScreenKeyboardMorph: > > https://eighty-twenty.org/2021/04/20/on-screen-keyboard-morph > > > > Cheers, > > Tony > > > I just remembered, Squeak has (used to have?) a handwriting recognition > system called Genie. That may make a useful addition to a phone UI. > Maybe even resurrect graffiti from the palm pdas :) > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Apr 21 17:45:25 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 21 Apr 2021 17:45:25 +0000 Subject: [squeak-dev] forum.world.st offline Message-ID: <04ee2ea533f2412d9669aef73df183a1@student.hpi.uni-potsdam.de> Hi all, http://forum.world.st/ appears to be offline for a few hours now. The website is no longer reachable, but earlier today, Marcel was still able to access the site when I was not, so probably this is a DNS problem. Has the domain registration expired? Maybe someone who feels responsible could take a look into that? :-) Thanks in advance, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Wed Apr 21 19:28:07 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Wed, 21 Apr 2021 21:28:07 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: I think from a user/client perspective, there are three different problems here: 1. ProgressInitiationException, 2. what to rearm/reactivate after resuming from a signal, a.k.a. the odd effect that signalling an exception twice from the same context might now handle them with different exception environments (my "unacceptable"), 3. different behavior if the debugger is used. I just stumbled upon all three problems on a single test case in a matter of hours. ;-) What is special about ProgressInitiationException is that you are supposed to install a handler deeper in the stack and it will run some code that is supposed to be run further up in the stack. For this use case it does not feel right to deactivate all the handlers in between because, after all, redirecting the progress should not really be exception handling; it just establishes a different context for certain operations, like a DynamicVariable. I would argue that the code in the "workBlock" of the ProgressInitiationException is supposed to be run in the same exception environment as the signalling of the ProgressInitiationException (maybe minus the progress handler itself unless rearm is used), because why should progress redirection interfere with other exception handlers? Maybe this is futile and an error in the design of ProgressInitiationException. Its implementation just happened to work with the previous implementation of exceptions in Squeak. If I read the ANSI standard correctly, it leans more towards your fix: "If a matching handler is found, the exception action of the handler is evaluated in the exception environment that was current when the handler was created [...]" (p. 91, ANSI Smalltalk Standard Draft v1.9), and in the specification of "on: selector do: action": "Before evaluating the receiver the current state of the exception environment is captured as the handler environment. [...] If signaling of an exception results in evaluation of action the evaluation will occur in the context of the handler environment." (p. 85, ibid). Trying to fix ProgressInitiationException by introducing the reactivateHandlers as you suggested, would also reactivate handlers that have already fired, wouldn't it? For example: 1. One context at the top of the stack signals an error. 2. It is handled by an exception handler from the middle of the stack. 3. The handler in 2. runs a lengthy operation that displays progress, signalling a ProgressInitiationException. Could download a missing file, for example. 4. Let some more unrelated exception handlers be below that in the stack. They do not handle the ProgressInitiationException. 5. Even further down the stack, a ProgressInitiationException handler will handle what was signalled as progress in 3. If this progress handler in 5. would rearm all handlers, it would also rearm the handler from 2. that really handles an error situation out of scope of the current activity (the lengthy recovery operation in 3). So I think 5. must not rearm the handler in 2., but the handlers in 4. should remain active (special case for ProgressInitiationException) because otherwise the progress handling effectively strips away all established exception handling while the workBlock of the ProgressInitiationException is evaluated. If 5. eventually resumes the ProgressInitiationException, it should return to 3., but it should not rearm the handler in 2. since it is still being evaluated. In ProgressInitiationException class>>testWith, the ZeroDivide exception is an example of an exception like in 3. above. Its handler gets stripped away now. Another example of it is my Environment>>beCurrentDuring: that is ignored now with this version. Could you please check whether resuming from 5. to 3. in the example above would rearm the handler in 2. now? I might think more about ProgressInitiationException on Friday or the weekend. Am Mi., 21. Apr. 2021 um 11:49 Uhr schrieb Nicolas Cellier : > > Hi Jakob, > > Le mar. 20 avr. 2021 à 19:00, Jakob Reschke a écrit : > > > > Hi, > > > > Am Di., 20. Apr. 2021 um 09:16 Uhr schrieb Nicolas Cellier > > : > > > > > > Here, you submit another case where you want all the handlers to be rearmed. > > > I don't think that rearmHandlerDuring: should rearm the other > > > exceptions upstack. > > > Maybe you could try (e reactivateHandlers) instead of (e > > > rearmHandlerDuring: [...]). > > > > I also do not think that rearm should rearm all handlers. I shall > > think a bit more whether reactivateHandlers is the right choice or > > whether it cannot also reactivate too much. > > > > > Let's have a look at what sendNotificationsTo: does > > > > > > sendNotificationsTo: aNewBlock > > > self resume: ( > > > workBlock value: [ :barVal | > > > aNewBlock value: minVal value: maxVal value: barVal > > > ] > > > ) > > > > > > We recognize the same pattern as resignalAs: and nil>>handleSignal: > > > resume will reactivateHandlers after the battle, that is after > > > evaluating aNewBlock... > > > I suggest this revision: > > > > > > sendNotificationsTo: aNewBlock > > > self reactivateHandlers; resumeUnchecked: ( > > > workBlock value: [ :barVal | > > > aNewBlock value: minVal value: maxVal value: barVal > > > ] > > > ) > > > > > > I think that it makes rearmHandlerDuring: un-necessary. > > > > ...which means that now the use of sendNotificationsTo: cannot be used > > to deal with just one layer of progress. It will always also apply to > > multiple nested progress bars. Not a problem for my use case, but I > > wonder what the general expectations of it are. > > > > Ah, I wondered exactly about that case... > What we want to achieve is really contradictory here. > We want to handle the case when a new exception is signalled during > the handling (during execution of 2nd arg of on:do:) > #testHandlerFromAction specifies that shallower handlerContext shall > be bypassed, and that next handler shall be searched deeper than > active one. > The solution in https://source.squeak.org/treated/Kernel-nice.857.diff > was to let handleSignal: be detected as a handlerContext > (), > because it already knows the active handlerContext, it's easy to > continue stack scanning from there... > Same scheme was later adopted in Cuis (see > https://source.squeak.org/treated/Kernel-fbs.870.diff). > > #testHandlerReentrancy on the other hand specifies that not all the > shallower handlerContext shall be bypassed, but that some can be > rearmed and stay active. > This is challenging to implement with a solution like in Cuis, but I > think it should be possible... > The new Squeak solution is much simpler: deactivate when we backtrack > the stack, reactivate when we resume the exception... > That also means that it's less fine-grained. > > My understanding here is that you have yet another set of expectations: > - the shallower handlers shall be active during current exception > handling so as to intercept other kinds of Exception > Note that this would not work in Cuis > - except the already fired handlers that have not been rearmed... > (what you call the stack state) > It's not only challenging, it's questionable whether this can possibly > fit with above expectations... > > > > > > > You also raise other points. > > > Why the following works: > > > Environment current. > > > ^ self actualClassIn: Environment current > > > Environment current sends an extra signal, so signalling twice has a > > > different effect as signalling once. > > > You said that it's not acceptable, but I'm not so sure... > > > > What I find not acceptable (or, let's rather say questionable) is the > > hidden side effect. After a signal is fully handled and has returned > > to the signal sender, I would naïvely expect that the stack (exception > > environment) is in the same state as before the signal. If custom > > exceptions or handler blocks implement their own side effects or > > state, so shall they. But in my opinion the base implementation should > > not have such confusing side effects on the stack, and on totally > > unrelated exception handlers in particular. > > > > Kind regards, > > Jakob > > > > Yes, but how does that happen? > For returning a value to the sender of signal, one has to resume > (resume:), which will reactivateHandlers. > There is the case of resumeUnchecked: which leaves this responsibility > to its sender, and currently, not all senders of resumeUnchecked: will > reactivateHandlers. > (I didn't know what to do in SpurImageSegmentLoader for example...) > Ah, there is also runUntilErrorOrReturnFrom: which might explain some > differences when debugging... > but is it really the path of trouble here? > > > > > > > > > > > > Why the debugging takes another path is another weird behavior that we > > > should inquire... > > > It ain't gonna be easy though. > > > > > > Le mar. 20 avr. 2021 à 00:08, Jakob Reschke a écrit : > > > > > > > > Oh by the way, this was helpful to inspect the stack in the incorrect state: > > > > > > > > MCMethodDefinition>> > > > > actualClass > > > > (thisContext sender selector == #unload) ifTrue: [thisContext > > > > copyStack inspect]. > > > > ^ self actualClassIn: Environment current > > > > > > > > In the Inspector: > > > > | context | > > > > context := self nextHandlerContext. > > > > Array streamContents: [:str | > > > > [context notNil] whileTrue: [str nextPut: context. context := > > > > context nextHandlerContext]]. > > > > > > > > | context | > > > > context := self. > > > > Array streamContents: [:str | > > > > [context notNil] whileTrue: [str nextPut: context. context := > > > > context sender]]. > > > > > > > > Am Di., 20. Apr. 2021 um 00:02 Uhr schrieb Jakob Reschke > > > > : > > > > > > > > > > Looks like this does no longer work as before: > > > > > > > > > > SquotImageStoreTest>> > > > > > suppressProgressDisplayDuring: aBlock > > > > > ... > > > > > aBlock > > > > > on: ProgressInitiationException do: [:e | > > > > > ... > > > > > e rearmHandlerDuring: > > > > > [[e sendNotificationsTo: [:min :max :current | "silence"]] > > > > > on: ProgressNotification do: [:notification | > > > > > notification resume]] > > > > > ... > > > > > > > > > > rearmHandlerDuring: does reactivate this current handler, but not > > > > > handlers further up the stack. > > > > > So e sendNotificationsTo: will evaluate the block in the package > > > > > loader that eventually unloads the method in the test case while all > > > > > handlers that are between the ProgressInitiationException signal > > > > > context and this ProgressInitiationException handler context on the > > > > > stack are deactivated, including the one that sets the correct > > > > > Environment (and also the source file caching, by the way). Find the > > > > > annotated stack below for a little more visualization. > > > > > > > > > > Previously, the handler contexts that did not fit the raised Exception > > > > > were not deactivated. Is the ProgressInitiationException redirection > > > > > concept broken in general now? Note that the ZeroDivide in > > > > > ProgressInitiationException>>testWith is now no longer caught. > > > > > > > > > > --- The redacted stack of my failing test with some ---annotations---> > > > > > [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The > > > > > block under 'Installing ', pkgName displayProgressFrom: ... > > > > > ProgressInitiationException>>sendNotificationsTo: > > > > > [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > FullBlockClosure(BlockClosure)>>on:do: > > > > > [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > [] in Context>>rearmHandlerDuring: > > > > > FullBlockClosure(BlockClosure)>>ensure: > > > > > ---reactivated #1---> Context>>rearmHandlerDuring: > > > > > ProgressInitiationException(Exception)>>rearmHandlerDuring: > > > > > [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > [] in Context>>handleSignal: > > > > > FullBlockClosure(BlockClosure)>>ifCurtailed: > > > > > Context>>handleSignal: <--- #1 sender: > > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > ... > > > > > Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: > > > > > Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles > > > > > class>>cacheDuring: > > > > > Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad > > > > > ---triggers stack walk---> ProgressInitiationException(Exception)>>signal > > > > > ProgressInitiationException>>display:at:from:to:during: > > > > > ... > > > > > ByteString(String)>>displayProgressFrom:to:during: > > > > > [] in [] in [] in [] in MCPackageLoader>>basicLoad > > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > > [] in [] in [] in MCPackageLoader>>basicLoad > > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > > CurrentReadOnlySourceFiles class>>cacheDuring: > > > > > ... > > > > > MCPackageLoader>>basicLoad > > > > > ... > > > > > MCPackageLoader>>loadWithNameLike: > > > > > [] in SquotPackageShadow>>squotMaterializeWith: > > > > > ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: > > > > > Environment>>beCurrentDuring: > > > > > SquotPackageShadow>>squotMaterializeWith: > > > > > ... > > > > > SquotImageStoreTest>>testApplyPatch > > > > > SquotImageStoreTest(TestCase)>>performTest > > > > > [] in SquotImageStoreTest>>performTest > > > > > ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: > > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > ... > > > > > > > > > > Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke > > > > > : > > > > > > > > > > > > Hi Nicolas, > > > > > > > > > > > > I seem to have a Heisenbug now because of this: > > > > > > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > > > > > > > > > > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > > > > > > > > > > > But if I replace in MCMethodDefinition this: > > > > > > > > > > > > actualClass > > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > > > by this: > > > > > > > > > > > > actualClass > > > > > > Environment current. > > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > > > > > > > > > > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > > > > > > > > > > > Kind regards, > > > > > > Jakob > > > > > > > > > > > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > > > > > >> > > > > > >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > > > > > >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz > > > > > >> > > > > > >> ==================== Summary ==================== > > > > > >> > > > > > >> Name: Kernel-nice.1384 > > > > > >> Author: nice > > > > > >> Time: 11 April 2021, 7:33:23.487481 pm > > > > > >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > > > > > >> Ancestors: Kernel-mt.1383 > > > > > >> > > > > > >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. > > > > > >> > > > > > >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. > > > > > >> > > > > > >> =============== Diff against Kernel-mt.1383 =============== > > > > > >> > > > > > >> Item was changed: > > > > > >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > > > > > >> handleSignal: exception > > > > > >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > > > > > >> and the handler is active then execute my handle block (second arg), otherwise forward > > > > > >> this message to the next handler context. If none left, execute exception's defaultAction > > > > > >> (see nil>>handleSignal:)." > > > > > >> > > > > > >> | handlerActive val | > > > > > >> "If the context has been returned from the handlerActive temp var may not be accessible." > > > > > >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > > > > > >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > > > > > >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > > > > > >> + ^self nextHandlerContext handleSignal: exception]. > > > > > >> - [^self nextHandlerContext handleSignal: exception]. > > > > > >> > > > > > >> exception privHandlerContext: self contextTag. > > > > > >> self tempAt: 3 put: false. "disable self while executing handle block" > > > > > >> val := [(self tempAt: 2) cull: exception] > > > > > >> + ifCurtailed: [self tempAt: 3 put: true]. > > > > > >> - ensure: [self tempAt: 3 put: true]. > > > > > >> self return: val "return from self if not otherwise directed in handle block" > > > > > >> ! > > > > > >> > > > > > >> Item was added: > > > > > >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > > > > > >> + reactivateHandlers > > > > > >> + "Private - sent to exception handler context only (on:do:). > > > > > >> + Reactivate all the handlers into the chain" > > > > > >> + > > > > > >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > > > > > >> + self nextHandlerContext reactivateHandlers! > > > > > >> > > > > > >> Item was added: > > > > > >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- > > > > > >> + reactivateHandlers > > > > > >> + "reactivate all the exception handlers in the context chain" > > > > > >> + self canSearchForSignalerContext > > > > > >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! > > > > > >> > > > > > >> Item was changed: > > > > > >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- > > > > > >> resignalAs: replacementException > > > > > >> "Signal an alternative exception in place of the receiver." > > > > > >> > > > > > >> + self reactivateHandlers. > > > > > >> self resumeUnchecked: replacementException signal! > > > > > >> > > > > > >> Item was changed: > > > > > >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- > > > > > >> handleSignal: exception > > > > > >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. > > > > > >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." > > > > > >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." > > > > > >> > > > > > >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! > > > > > >> - ^ exception resumeUnchecked: exception defaultAction! > > > > > >> > > > > > >> Item was added: > > > > > >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- > > > > > >> + reactivateHandlers > > > > > >> + "nothing to do for bottom context" > > > > > >> + > > > > > >> + ^ self! > > > > > >> > > > > > >> > > > > > > > > > > From craig at blackpagedigital.com Wed Apr 21 20:54:48 2021 From: craig at blackpagedigital.com (Craig Latta) Date: Wed, 21 Apr 2021 13:54:48 -0700 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> Message-ID: Hi-- Douglas Brebner wrote: > I just remembered, Squeak has (used to have?) a handwriting > recognition system called Genie. That may make a useful addition to a > phone UI. Maybe even resurrect graffiti from the palm pdas :) And on the iPad, there's Scribble. I wrote SqueakJS support for it. I hide an invisible HTML text input element underneath wherever you're entering text, and Scribble recognizes it. It does both ink-based recognition and the sliding-around-on-an-onscreen-keyboard thing, which I really like. https://vimeo.com/494744698 -C -- Craig Latta :: research computer scientist Black Page Digital :: Berkeley, California 663137D7940BF5C0AFC :: 1349FB2ADA32C4D5314CE From vanessa at codefrau.net Wed Apr 21 22:23:58 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Wed, 21 Apr 2021 15:23:58 -0700 Subject: [squeak-dev] SqueakJS keyboard input (was: Wrote a little about OnScreenKeyboardMorph) In-Reply-To: References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> Message-ID: On Wed, Apr 21, 2021 at 1:55 PM Craig Latta wrote: > > Hi-- > > Douglas Brebner wrote: > > > I just remembered, Squeak has (used to have?) a handwriting > > recognition system called Genie. That may make a useful addition to a > > phone UI. Maybe even resurrect graffiti from the palm pdas :) > > And on the iPad, there's Scribble. I wrote SqueakJS support for > it. I hide an invisible HTML text input element underneath wherever > you're entering text, and Scribble recognizes it. It does both ink-based > recognition and the sliding-around-on-an-onscreen-keyboard thing, which > I really like. > > https://vimeo.com/494744698 > Oh cool! Does it need image-side support? If not I'd love to get this into SqueakJS proper - I think having a hidden text field might solve the various issues we have on e.g. Android, or with copy/paste on Safari. Vanessa -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Thu Apr 22 06:57:44 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 22 Apr 2021 08:57:44 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Hi Jakob, hi Nicolas, hi all. > For this use case it does not feel right to deactivate all the handlers > in between because, after all, redirecting the progress should not > really be exception handling; it just establishes a different context for > certain operations, like a DynamicVariable.  Just a reminder: Yes, it should remain possible to use Squeak's exception mechanism for dynamic scoping, which is a different way of how DynamicVariable does it. An example for such exception-based dynamic scoping is CurrentReadOnlySourceFiles. :-) Best, Marcel Am 21.04.2021 21:28:26 schrieb Jakob Reschke : I think from a user/client perspective, there are three different problems here: 1. ProgressInitiationException, 2. what to rearm/reactivate after resuming from a signal, a.k.a. the odd effect that signalling an exception twice from the same context might now handle them with different exception environments (my "unacceptable"), 3. different behavior if the debugger is used. I just stumbled upon all three problems on a single test case in a matter of hours. ;-) What is special about ProgressInitiationException is that you are supposed to install a handler deeper in the stack and it will run some code that is supposed to be run further up in the stack. For this use case it does not feel right to deactivate all the handlers in between because, after all, redirecting the progress should not really be exception handling; it just establishes a different context for certain operations, like a DynamicVariable. I would argue that the code in the "workBlock" of the ProgressInitiationException is supposed to be run in the same exception environment as the signalling of the ProgressInitiationException (maybe minus the progress handler itself unless rearm is used), because why should progress redirection interfere with other exception handlers? Maybe this is futile and an error in the design of ProgressInitiationException. Its implementation just happened to work with the previous implementation of exceptions in Squeak. If I read the ANSI standard correctly, it leans more towards your fix: "If a matching handler is found, the exception action of the handler is evaluated in the exception environment that was current when the handler was created [...]" (p. 91, ANSI Smalltalk Standard Draft v1.9), and in the specification of "on: selector do: action": "Before evaluating the receiver the current state of the exception environment is captured as the handler environment. [...] If signaling of an exception results in evaluation of action the evaluation will occur in the context of the handler environment." (p. 85, ibid). Trying to fix ProgressInitiationException by introducing the reactivateHandlers as you suggested, would also reactivate handlers that have already fired, wouldn't it? For example: 1. One context at the top of the stack signals an error. 2. It is handled by an exception handler from the middle of the stack. 3. The handler in 2. runs a lengthy operation that displays progress, signalling a ProgressInitiationException. Could download a missing file, for example. 4. Let some more unrelated exception handlers be below that in the stack. They do not handle the ProgressInitiationException. 5. Even further down the stack, a ProgressInitiationException handler will handle what was signalled as progress in 3. If this progress handler in 5. would rearm all handlers, it would also rearm the handler from 2. that really handles an error situation out of scope of the current activity (the lengthy recovery operation in 3). So I think 5. must not rearm the handler in 2., but the handlers in 4. should remain active (special case for ProgressInitiationException) because otherwise the progress handling effectively strips away all established exception handling while the workBlock of the ProgressInitiationException is evaluated. If 5. eventually resumes the ProgressInitiationException, it should return to 3., but it should not rearm the handler in 2. since it is still being evaluated. In ProgressInitiationException class>>testWith, the ZeroDivide exception is an example of an exception like in 3. above. Its handler gets stripped away now. Another example of it is my Environment>>beCurrentDuring: that is ignored now with this version. Could you please check whether resuming from 5. to 3. in the example above would rearm the handler in 2. now? I might think more about ProgressInitiationException on Friday or the weekend. Am Mi., 21. Apr. 2021 um 11:49 Uhr schrieb Nicolas Cellier : > > Hi Jakob, > > Le mar. 20 avr. 2021 à 19:00, Jakob Reschke a écrit : > > > > Hi, > > > > Am Di., 20. Apr. 2021 um 09:16 Uhr schrieb Nicolas Cellier > > : > > > > > > Here, you submit another case where you want all the handlers to be rearmed. > > > I don't think that rearmHandlerDuring: should rearm the other > > > exceptions upstack. > > > Maybe you could try (e reactivateHandlers) instead of (e > > > rearmHandlerDuring: [...]). > > > > I also do not think that rearm should rearm all handlers. I shall > > think a bit more whether reactivateHandlers is the right choice or > > whether it cannot also reactivate too much. > > > > > Let's have a look at what sendNotificationsTo: does > > > > > > sendNotificationsTo: aNewBlock > > > self resume: ( > > > workBlock value: [ :barVal | > > > aNewBlock value: minVal value: maxVal value: barVal > > > ] > > > ) > > > > > > We recognize the same pattern as resignalAs: and nil>>handleSignal: > > > resume will reactivateHandlers after the battle, that is after > > > evaluating aNewBlock... > > > I suggest this revision: > > > > > > sendNotificationsTo: aNewBlock > > > self reactivateHandlers; resumeUnchecked: ( > > > workBlock value: [ :barVal | > > > aNewBlock value: minVal value: maxVal value: barVal > > > ] > > > ) > > > > > > I think that it makes rearmHandlerDuring: un-necessary. > > > > ...which means that now the use of sendNotificationsTo: cannot be used > > to deal with just one layer of progress. It will always also apply to > > multiple nested progress bars. Not a problem for my use case, but I > > wonder what the general expectations of it are. > > > > Ah, I wondered exactly about that case... > What we want to achieve is really contradictory here. > We want to handle the case when a new exception is signalled during > the handling (during execution of 2nd arg of on:do:) > #testHandlerFromAction specifies that shallower handlerContext shall > be bypassed, and that next handler shall be searched deeper than > active one. > The solution in https://source.squeak.org/treated/Kernel-nice.857.diff > was to let handleSignal: be detected as a handlerContext > (), > because it already knows the active handlerContext, it's easy to > continue stack scanning from there... > Same scheme was later adopted in Cuis (see > https://source.squeak.org/treated/Kernel-fbs.870.diff). > > #testHandlerReentrancy on the other hand specifies that not all the > shallower handlerContext shall be bypassed, but that some can be > rearmed and stay active. > This is challenging to implement with a solution like in Cuis, but I > think it should be possible... > The new Squeak solution is much simpler: deactivate when we backtrack > the stack, reactivate when we resume the exception... > That also means that it's less fine-grained. > > My understanding here is that you have yet another set of expectations: > - the shallower handlers shall be active during current exception > handling so as to intercept other kinds of Exception > Note that this would not work in Cuis > - except the already fired handlers that have not been rearmed... > (what you call the stack state) > It's not only challenging, it's questionable whether this can possibly > fit with above expectations... > > > > > > > You also raise other points. > > > Why the following works: > > > Environment current. > > > ^ self actualClassIn: Environment current > > > Environment current sends an extra signal, so signalling twice has a > > > different effect as signalling once. > > > You said that it's not acceptable, but I'm not so sure... > > > > What I find not acceptable (or, let's rather say questionable) is the > > hidden side effect. After a signal is fully handled and has returned > > to the signal sender, I would naïvely expect that the stack (exception > > environment) is in the same state as before the signal. If custom > > exceptions or handler blocks implement their own side effects or > > state, so shall they. But in my opinion the base implementation should > > not have such confusing side effects on the stack, and on totally > > unrelated exception handlers in particular. > > > > Kind regards, > > Jakob > > > > Yes, but how does that happen? > For returning a value to the sender of signal, one has to resume > (resume:), which will reactivateHandlers. > There is the case of resumeUnchecked: which leaves this responsibility > to its sender, and currently, not all senders of resumeUnchecked: will > reactivateHandlers. > (I didn't know what to do in SpurImageSegmentLoader for example...) > Ah, there is also runUntilErrorOrReturnFrom: which might explain some > differences when debugging... > but is it really the path of trouble here? > > > > > > > > > > > > Why the debugging takes another path is another weird behavior that we > > > should inquire... > > > It ain't gonna be easy though. > > > > > > Le mar. 20 avr. 2021 à 00:08, Jakob Reschke a écrit : > > > > > > > > Oh by the way, this was helpful to inspect the stack in the incorrect state: > > > > > > > > MCMethodDefinition>> > > > > actualClass > > > > (thisContext sender selector == #unload) ifTrue: [thisContext > > > > copyStack inspect]. > > > > ^ self actualClassIn: Environment current > > > > > > > > In the Inspector: > > > > | context | > > > > context := self nextHandlerContext. > > > > Array streamContents: [:str | > > > > [context notNil] whileTrue: [str nextPut: context. context := > > > > context nextHandlerContext]]. > > > > > > > > | context | > > > > context := self. > > > > Array streamContents: [:str | > > > > [context notNil] whileTrue: [str nextPut: context. context := > > > > context sender]]. > > > > > > > > Am Di., 20. Apr. 2021 um 00:02 Uhr schrieb Jakob Reschke > > > > : > > > > > > > > > > Looks like this does no longer work as before: > > > > > > > > > > SquotImageStoreTest>> > > > > > suppressProgressDisplayDuring: aBlock > > > > > ... > > > > > aBlock > > > > > on: ProgressInitiationException do: [:e | > > > > > ... > > > > > e rearmHandlerDuring: > > > > > [[e sendNotificationsTo: [:min :max :current | "silence"]] > > > > > on: ProgressNotification do: [:notification | > > > > > notification resume]] > > > > > ... > > > > > > > > > > rearmHandlerDuring: does reactivate this current handler, but not > > > > > handlers further up the stack. > > > > > So e sendNotificationsTo: will evaluate the block in the package > > > > > loader that eventually unloads the method in the test case while all > > > > > handlers that are between the ProgressInitiationException signal > > > > > context and this ProgressInitiationException handler context on the > > > > > stack are deactivated, including the one that sets the correct > > > > > Environment (and also the source file caching, by the way). Find the > > > > > annotated stack below for a little more visualization. > > > > > > > > > > Previously, the handler contexts that did not fit the raised Exception > > > > > were not deactivated. Is the ProgressInitiationException redirection > > > > > concept broken in general now? Note that the ZeroDivide in > > > > > ProgressInitiationException>>testWith is now no longer caught. > > > > > > > > > > --- The redacted stack of my failing test with some ---annotations---> > > > > > [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The > > > > > block under 'Installing ', pkgName displayProgressFrom: ... > > > > > ProgressInitiationException>>sendNotificationsTo: > > > > > [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > FullBlockClosure(BlockClosure)>>on:do: > > > > > [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > [] in Context>>rearmHandlerDuring: > > > > > FullBlockClosure(BlockClosure)>>ensure: > > > > > ---reactivated #1---> Context>>rearmHandlerDuring: > > > > > ProgressInitiationException(Exception)>>rearmHandlerDuring: > > > > > [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > [] in Context>>handleSignal: > > > > > FullBlockClosure(BlockClosure)>>ifCurtailed: > > > > > Context>>handleSignal: <--- #1 sender: > > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > ... > > > > > Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: > > > > > Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles > > > > > class>>cacheDuring: > > > > > Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad > > > > > ---triggers stack walk---> ProgressInitiationException(Exception)>>signal > > > > > ProgressInitiationException>>display:at:from:to:during: > > > > > ... > > > > > ByteString(String)>>displayProgressFrom:to:during: > > > > > [] in [] in [] in [] in MCPackageLoader>>basicLoad > > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > > [] in [] in [] in MCPackageLoader>>basicLoad > > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > > CurrentReadOnlySourceFiles class>>cacheDuring: > > > > > ... > > > > > MCPackageLoader>>basicLoad > > > > > ... > > > > > MCPackageLoader>>loadWithNameLike: > > > > > [] in SquotPackageShadow>>squotMaterializeWith: > > > > > ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: > > > > > Environment>>beCurrentDuring: > > > > > SquotPackageShadow>>squotMaterializeWith: > > > > > ... > > > > > SquotImageStoreTest>>testApplyPatch > > > > > SquotImageStoreTest(TestCase)>>performTest > > > > > [] in SquotImageStoreTest>>performTest > > > > > ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: > > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > ... > > > > > > > > > > Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke > > > > > : > > > > > > > > > > > > Hi Nicolas, > > > > > > > > > > > > I seem to have a Heisenbug now because of this: > > > > > > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > > > > > > > > > > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > > > > > > > > > > > But if I replace in MCMethodDefinition this: > > > > > > > > > > > > actualClass > > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > > > by this: > > > > > > > > > > > > actualClass > > > > > > Environment current. > > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > > > > > > > > > > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > > > > > > > > > > > Kind regards, > > > > > > Jakob > > > > > > > > > > > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > > > > > >> > > > > > >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > > > > > >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz > > > > > >> > > > > > >> ==================== Summary ==================== > > > > > >> > > > > > >> Name: Kernel-nice.1384 > > > > > >> Author: nice > > > > > >> Time: 11 April 2021, 7:33:23.487481 pm > > > > > >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > > > > > >> Ancestors: Kernel-mt.1383 > > > > > >> > > > > > >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. > > > > > >> > > > > > >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. > > > > > >> > > > > > >> =============== Diff against Kernel-mt.1383 =============== > > > > > >> > > > > > >> Item was changed: > > > > > >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > > > > > >> handleSignal: exception > > > > > >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > > > > > >> and the handler is active then execute my handle block (second arg), otherwise forward > > > > > >> this message to the next handler context. If none left, execute exception's defaultAction > > > > > >> (see nil>>handleSignal:)." > > > > > >> > > > > > >> | handlerActive val | > > > > > >> "If the context has been returned from the handlerActive temp var may not be accessible." > > > > > >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > > > > > >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > > > > > >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > > > > > >> + ^self nextHandlerContext handleSignal: exception]. > > > > > >> - [^self nextHandlerContext handleSignal: exception]. > > > > > >> > > > > > >> exception privHandlerContext: self contextTag. > > > > > >> self tempAt: 3 put: false. "disable self while executing handle block" > > > > > >> val := [(self tempAt: 2) cull: exception] > > > > > >> + ifCurtailed: [self tempAt: 3 put: true]. > > > > > >> - ensure: [self tempAt: 3 put: true]. > > > > > >> self return: val "return from self if not otherwise directed in handle block" > > > > > >> ! > > > > > >> > > > > > >> Item was added: > > > > > >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > > > > > >> + reactivateHandlers > > > > > >> + "Private - sent to exception handler context only (on:do:). > > > > > >> + Reactivate all the handlers into the chain" > > > > > >> + > > > > > >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > > > > > >> + self nextHandlerContext reactivateHandlers! > > > > > >> > > > > > >> Item was added: > > > > > >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- > > > > > >> + reactivateHandlers > > > > > >> + "reactivate all the exception handlers in the context chain" > > > > > >> + self canSearchForSignalerContext > > > > > >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! > > > > > >> > > > > > >> Item was changed: > > > > > >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- > > > > > >> resignalAs: replacementException > > > > > >> "Signal an alternative exception in place of the receiver." > > > > > >> > > > > > >> + self reactivateHandlers. > > > > > >> self resumeUnchecked: replacementException signal! > > > > > >> > > > > > >> Item was changed: > > > > > >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- > > > > > >> handleSignal: exception > > > > > >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. > > > > > >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." > > > > > >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." > > > > > >> > > > > > >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! > > > > > >> - ^ exception resumeUnchecked: exception defaultAction! > > > > > >> > > > > > >> Item was added: > > > > > >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- > > > > > >> + reactivateHandlers > > > > > >> + "nothing to do for bottom context" > > > > > >> + > > > > > >> + ^ self! > > > > > >> > > > > > >> > > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Thu Apr 22 07:02:37 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 22 Apr 2021 09:02:37 +0200 Subject: [squeak-dev] forum.world.st offline In-Reply-To: <04ee2ea533f2412d9669aef73df183a1@student.hpi.uni-potsdam.de> References: <04ee2ea533f2412d9669aef73df183a1@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, seems to work again. Even from the mobile network, where it was broken yesterday for me, too. Best, Marcel Am 21.04.2021 19:45:38 schrieb Thiede, Christoph : Hi all, http://forum.world.st/ [http://forum.world.st/] appears to be offline for a few hours now. The website is no longer reachable, but earlier today, Marcel was still able to access the site when I was not, so probably this is a DNS problem. Has the domain registration expired? Maybe someone who feels responsible could take a look into that? :-) Thanks in advance, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Thu Apr 22 07:09:52 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Thu, 22 Apr 2021 09:09:52 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Am Do., 22. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel : > An example for such exception-based dynamic scoping is CurrentReadOnlySourceFiles. > ...which also got disarmed in my test case. Although that was not obvious until I inspected the stack. From nicolas.cellier.aka.nice at gmail.com Thu Apr 22 08:09:06 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 22 Apr 2021 10:09:06 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Le mer. 21 avr. 2021 à 21:28, Jakob Reschke a écrit : > > I think from a user/client perspective, there are three different problems here: > 1. ProgressInitiationException, > 2. what to rearm/reactivate after resuming from a signal, a.k.a. the > odd effect that signalling an exception twice from the same context > might now handle them with different exception environments (my > "unacceptable"), > 3. different behavior if the debugger is used. > > I just stumbled upon all three problems on a single test case in a > matter of hours. ;-) > Absolutely scary indeed ... > What is special about ProgressInitiationException is that you are > supposed to install a handler deeper in the stack and it will run some > code that is supposed to be run further up in the stack. For this use > case it does not feel right to deactivate all the handlers in between > because, after all, redirecting the progress should not really be > exception handling; it just establishes a different context for > certain operations, like a DynamicVariable. I would argue that the > code in the "workBlock" of the ProgressInitiationException is supposed > to be run in the same exception environment as the signalling of the > ProgressInitiationException (maybe minus the progress handler itself > unless rearm is used), because why should progress redirection > interfere with other exception handlers? > > Maybe this is futile and an error in the design of > ProgressInitiationException. Its implementation just happened to work > with the previous implementation of exceptions in Squeak. > > If I read the ANSI standard correctly, it leans more towards your fix: > "If a matching handler is found, the exception action of the handler > is evaluated in the exception environment that was current when the > handler was created [...]" (p. 91, ANSI Smalltalk Standard Draft > v1.9), and in the specification of "on: selector do: action": "Before > evaluating the receiver the current state of the exception environment > is captured as the handler environment. [...] If signaling of an > exception results in evaluation of action the evaluation will occur in > the context of the handler environment." (p. 85, ibid). > Exactly. That's why maintaining previous ProgressInitiationException behavior is challenging... > Trying to fix ProgressInitiationException by introducing the > reactivateHandlers as you suggested, would also reactivate handlers > that have already fired, wouldn't it? > Yes, that's far from ideal...It may reactivate too broadly. It currently rearm the ProgressInitiationException handler itself and all such inner handlers. This is forbidding proper nested ProgressInitiationException handlers as you already noticed. And it may reactivate inner handlers that should not like you notice below... > For example: > 1. One context at the top of the stack signals an error. > 2. It is handled by an exception handler from the middle of the stack. > 3. The handler in 2. runs a lengthy operation that displays progress, > signalling a ProgressInitiationException. Could download a missing > file, for example. > 4. Let some more unrelated exception handlers be below that in the > stack. They do not handle the ProgressInitiationException. > 5. Even further down the stack, a ProgressInitiationException handler > will handle what was signalled as progress in 3. > > If this progress handler in 5. would rearm all handlers, it would also > rearm the handler from 2. that really handles an error situation out > of scope of the current activity (the lengthy recovery operation in > 3). So I think 5. must not rearm the handler in 2., but the handlers > in 4. should remain active (special case for > ProgressInitiationException) because otherwise the progress handling > effectively strips away all established exception handling while the > workBlock of the ProgressInitiationException is evaluated. If 5. > eventually resumes the ProgressInitiationException, it should return > to 3., but it should not rearm the handler in 2. since it is still > being evaluated. > > In ProgressInitiationException class>>testWith, the ZeroDivide > exception is an example of an exception like in 3. above. Its handler > gets stripped away now. Another example of it is my > Environment>>beCurrentDuring: that is ignored now with this version. > > Could you please check whether resuming from 5. to 3. in the example > above would rearm the handler in 2. now? I might think more about > ProgressInitiationException on Friday or the weekend. > I've been thinking of this exact situation in parallel. We should write test case with complex nesting scenarii. I think that it should be possible to enhance my earlier (Cuis-like) solution so as to also scan for rearmed handlers. But, still, it does not provide a solution for letting the ProgressInitiationException work... All we want to do is to change the workBlock value after all and resume... Is there more? Ah yes, we don't want the handler to remain active if we do not explicitly rearm it? > Am Mi., 21. Apr. 2021 um 11:49 Uhr schrieb Nicolas Cellier > : > > > > Hi Jakob, > > > > Le mar. 20 avr. 2021 à 19:00, Jakob Reschke a écrit : > > > > > > Hi, > > > > > > Am Di., 20. Apr. 2021 um 09:16 Uhr schrieb Nicolas Cellier > > > : > > > > > > > > Here, you submit another case where you want all the handlers to be rearmed. > > > > I don't think that rearmHandlerDuring: should rearm the other > > > > exceptions upstack. > > > > Maybe you could try (e reactivateHandlers) instead of (e > > > > rearmHandlerDuring: [...]). > > > > > > I also do not think that rearm should rearm all handlers. I shall > > > think a bit more whether reactivateHandlers is the right choice or > > > whether it cannot also reactivate too much. > > > > > > > Let's have a look at what sendNotificationsTo: does > > > > > > > > sendNotificationsTo: aNewBlock > > > > self resume: ( > > > > workBlock value: [ :barVal | > > > > aNewBlock value: minVal value: maxVal value: barVal > > > > ] > > > > ) > > > > > > > > We recognize the same pattern as resignalAs: and nil>>handleSignal: > > > > resume will reactivateHandlers after the battle, that is after > > > > evaluating aNewBlock... > > > > I suggest this revision: > > > > > > > > sendNotificationsTo: aNewBlock > > > > self reactivateHandlers; resumeUnchecked: ( > > > > workBlock value: [ :barVal | > > > > aNewBlock value: minVal value: maxVal value: barVal > > > > ] > > > > ) > > > > > > > > I think that it makes rearmHandlerDuring: un-necessary. > > > > > > ...which means that now the use of sendNotificationsTo: cannot be used > > > to deal with just one layer of progress. It will always also apply to > > > multiple nested progress bars. Not a problem for my use case, but I > > > wonder what the general expectations of it are. > > > > > > > Ah, I wondered exactly about that case... > > What we want to achieve is really contradictory here. > > We want to handle the case when a new exception is signalled during > > the handling (during execution of 2nd arg of on:do:) > > #testHandlerFromAction specifies that shallower handlerContext shall > > be bypassed, and that next handler shall be searched deeper than > > active one. > > The solution in https://source.squeak.org/treated/Kernel-nice.857.diff > > was to let handleSignal: be detected as a handlerContext > > (), > > because it already knows the active handlerContext, it's easy to > > continue stack scanning from there... > > Same scheme was later adopted in Cuis (see > > https://source.squeak.org/treated/Kernel-fbs.870.diff). > > > > #testHandlerReentrancy on the other hand specifies that not all the > > shallower handlerContext shall be bypassed, but that some can be > > rearmed and stay active. > > This is challenging to implement with a solution like in Cuis, but I > > think it should be possible... > > The new Squeak solution is much simpler: deactivate when we backtrack > > the stack, reactivate when we resume the exception... > > That also means that it's less fine-grained. > > > > My understanding here is that you have yet another set of expectations: > > - the shallower handlers shall be active during current exception > > handling so as to intercept other kinds of Exception > > Note that this would not work in Cuis > > - except the already fired handlers that have not been rearmed... > > (what you call the stack state) > > It's not only challenging, it's questionable whether this can possibly > > fit with above expectations... > > > > > > > > > > You also raise other points. > > > > Why the following works: > > > > Environment current. > > > > ^ self actualClassIn: Environment current > > > > Environment current sends an extra signal, so signalling twice has a > > > > different effect as signalling once. > > > > You said that it's not acceptable, but I'm not so sure... > > > > > > What I find not acceptable (or, let's rather say questionable) is the > > > hidden side effect. After a signal is fully handled and has returned > > > to the signal sender, I would naïvely expect that the stack (exception > > > environment) is in the same state as before the signal. If custom > > > exceptions or handler blocks implement their own side effects or > > > state, so shall they. But in my opinion the base implementation should > > > not have such confusing side effects on the stack, and on totally > > > unrelated exception handlers in particular. > > > > > > Kind regards, > > > Jakob > > > > > > > Yes, but how does that happen? > > For returning a value to the sender of signal, one has to resume > > (resume:), which will reactivateHandlers. > > There is the case of resumeUnchecked: which leaves this responsibility > > to its sender, and currently, not all senders of resumeUnchecked: will > > reactivateHandlers. > > (I didn't know what to do in SpurImageSegmentLoader for example...) > > Ah, there is also runUntilErrorOrReturnFrom: which might explain some > > differences when debugging... > > but is it really the path of trouble here? > > > > > > > > > > > > > > > > > > Why the debugging takes another path is another weird behavior that we > > > > should inquire... > > > > It ain't gonna be easy though. > > > > > > > > Le mar. 20 avr. 2021 à 00:08, Jakob Reschke a écrit : > > > > > > > > > > Oh by the way, this was helpful to inspect the stack in the incorrect state: > > > > > > > > > > MCMethodDefinition>> > > > > > actualClass > > > > > (thisContext sender selector == #unload) ifTrue: [thisContext > > > > > copyStack inspect]. > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > In the Inspector: > > > > > | context | > > > > > context := self nextHandlerContext. > > > > > Array streamContents: [:str | > > > > > [context notNil] whileTrue: [str nextPut: context. context := > > > > > context nextHandlerContext]]. > > > > > > > > > > | context | > > > > > context := self. > > > > > Array streamContents: [:str | > > > > > [context notNil] whileTrue: [str nextPut: context. context := > > > > > context sender]]. > > > > > > > > > > Am Di., 20. Apr. 2021 um 00:02 Uhr schrieb Jakob Reschke > > > > > : > > > > > > > > > > > > Looks like this does no longer work as before: > > > > > > > > > > > > SquotImageStoreTest>> > > > > > > suppressProgressDisplayDuring: aBlock > > > > > > ... > > > > > > aBlock > > > > > > on: ProgressInitiationException do: [:e | > > > > > > ... > > > > > > e rearmHandlerDuring: > > > > > > [[e sendNotificationsTo: [:min :max :current | "silence"]] > > > > > > on: ProgressNotification do: [:notification | > > > > > > notification resume]] > > > > > > ... > > > > > > > > > > > > rearmHandlerDuring: does reactivate this current handler, but not > > > > > > handlers further up the stack. > > > > > > So e sendNotificationsTo: will evaluate the block in the package > > > > > > loader that eventually unloads the method in the test case while all > > > > > > handlers that are between the ProgressInitiationException signal > > > > > > context and this ProgressInitiationException handler context on the > > > > > > stack are deactivated, including the one that sets the correct > > > > > > Environment (and also the source file caching, by the way). Find the > > > > > > annotated stack below for a little more visualization. > > > > > > > > > > > > Previously, the handler contexts that did not fit the raised Exception > > > > > > were not deactivated. Is the ProgressInitiationException redirection > > > > > > concept broken in general now? Note that the ZeroDivide in > > > > > > ProgressInitiationException>>testWith is now no longer caught. > > > > > > > > > > > > --- The redacted stack of my failing test with some ---annotations---> > > > > > > [] in [] in [] in [] in [] in MCPackageLoader>>basicLoad <--- The > > > > > > block under 'Installing ', pkgName displayProgressFrom: ... > > > > > > ProgressInitiationException>>sendNotificationsTo: > > > > > > [] in [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > > FullBlockClosure(BlockClosure)>>on:do: > > > > > > [] in [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > > [] in Context>>rearmHandlerDuring: > > > > > > FullBlockClosure(BlockClosure)>>ensure: > > > > > > ---reactivated #1---> Context>>rearmHandlerDuring: > > > > > > ProgressInitiationException(Exception)>>rearmHandlerDuring: > > > > > > [] in SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > > [] in Context>>handleSignal: > > > > > > FullBlockClosure(BlockClosure)>>ifCurtailed: > > > > > > Context>>handleSignal: <--- #1 sender: > > > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > > ... > > > > > > Context>>handleSignal: <--- #2 sender: Environment beCurrentDuring: > > > > > > Context>>handleSignal: <--- sender: CurrentReadOnlySourceFiles > > > > > > class>>cacheDuring: > > > > > > Context>>handleSignal: <--- sender: [] in [] in [] in MCPackageLoader basicLoad > > > > > > ---triggers stack walk---> ProgressInitiationException(Exception)>>signal > > > > > > ProgressInitiationException>>display:at:from:to:during: > > > > > > ... > > > > > > ByteString(String)>>displayProgressFrom:to:during: > > > > > > [] in [] in [] in [] in MCPackageLoader>>basicLoad > > > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > > > [] in [] in [] in MCPackageLoader>>basicLoad > > > > > > ---deactivated---> FullBlockClosure(BlockClosure)>>on:do: > > > > > > CurrentReadOnlySourceFiles class>>cacheDuring: > > > > > > ... > > > > > > MCPackageLoader>>basicLoad > > > > > > ... > > > > > > MCPackageLoader>>loadWithNameLike: > > > > > > [] in SquotPackageShadow>>squotMaterializeWith: > > > > > > ---deactivated #2---> FullBlockClosure(BlockClosure)>>on:do: > > > > > > Environment>>beCurrentDuring: > > > > > > SquotPackageShadow>>squotMaterializeWith: > > > > > > ... > > > > > > SquotImageStoreTest>>testApplyPatch > > > > > > SquotImageStoreTest(TestCase)>>performTest > > > > > > [] in SquotImageStoreTest>>performTest > > > > > > ---rearmed handler #1---> FullBlockClosure(BlockClosure)>>on:do: > > > > > > SquotImageStoreTest>>suppressProgressDisplayDuring: > > > > > > ... > > > > > > > > > > > > Am Mo., 19. Apr. 2021 um 22:37 Uhr schrieb Jakob Reschke > > > > > > : > > > > > > > > > > > > > > Hi Nicolas, > > > > > > > > > > > > > > I seem to have a Heisenbug now because of this: > > > > > > > In case you have the Git tools loaded, you should have a SquotImageStoreTest in your image. After loading this version and the follow-up fix versions of Kernel, the test SquotImageStoreTest>>testApplyPatch fails. > > > > > > > > > > > > > > The test fails because an initialize method is not removed from the class to be patched. When the method is about to be MCMethodDefinition>>#unload-ed, it makes a CurrentEnvironment lookup in MCMethodDefiction>>actualClass, and it returns a wrong environment. It seems that the handler to set the dynamic Environment further up in the stack is not activated for this particular lookup. Yet if I debug through the procedure, everything works as it should. If I let the test run on its own, it fails. > > > > > > > > > > > > > > But if I replace in MCMethodDefinition this: > > > > > > > > > > > > > > actualClass > > > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > > > > > by this: > > > > > > > > > > > > > > actualClass > > > > > > > Environment current. > > > > > > > ^ self actualClassIn: Environment current > > > > > > > > > > > > > > Then the test is suddenly green again. I suppose that is not acceptable. ;-) > > > > > > > > > > > > > > It also works with Notification signal instead of the extraneous Environment current, so it seems like the signal handler stack is somehow in a wrong state, which is corrected by emitting an extraneous signal. And when I halt there to debug the situation, it also has to deal with extra signals, which corrects the state, so I cannot inspect the incorrect one. I didn't identify the reason for this behavior yet, so I am not sure whether my exception handling has bugs somewhere or whether Squeak's exception handling is bugged now. > > > > > > > > > > > > > > Kind regards, > > > > > > > Jakob > > > > > > > > > > > > > > Am So., 11. Apr. 2021 um 19:33 Uhr schrieb : > > > > > > >> > > > > > > >> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: > > > > > > >> http://source.squeak.org/trunk/Kernel-nice.1384.mcz > > > > > > >> > > > > > > >> ==================== Summary ==================== > > > > > > >> > > > > > > >> Name: Kernel-nice.1384 > > > > > > >> Author: nice > > > > > > >> Time: 11 April 2021, 7:33:23.487481 pm > > > > > > >> UUID: ecb5db19-59bc-45f0-85d3-d9296a936a68 > > > > > > >> Ancestors: Kernel-mt.1383 > > > > > > >> > > > > > > >> Another attempt at fixing #testHandlerFromAction. Unlike previous attempts, this one preserves the expectations of #testHandlerReentrancy. > > > > > > >> > > > > > > >> The solution is to de-activate the handlers as we backtrack the stack, but to reactivate them before performing final exception handling actions (like resuming, resignalling or performing defaultAction). Indeed, those handlers must be able to handle a secondary exception raised in the course of this action. > > > > > > >> > > > > > > >> =============== Diff against Kernel-mt.1383 =============== > > > > > > >> > > > > > > >> Item was changed: > > > > > > >> ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > > > > > > >> handleSignal: exception > > > > > > >> "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > > > > > > >> and the handler is active then execute my handle block (second arg), otherwise forward > > > > > > >> this message to the next handler context. If none left, execute exception's defaultAction > > > > > > >> (see nil>>handleSignal:)." > > > > > > >> > > > > > > >> | handlerActive val | > > > > > > >> "If the context has been returned from the handlerActive temp var may not be accessible." > > > > > > >> handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > > > > > > >> (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > > > > > > >> + [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > > > > > > >> + ^self nextHandlerContext handleSignal: exception]. > > > > > > >> - [^self nextHandlerContext handleSignal: exception]. > > > > > > >> > > > > > > >> exception privHandlerContext: self contextTag. > > > > > > >> self tempAt: 3 put: false. "disable self while executing handle block" > > > > > > >> val := [(self tempAt: 2) cull: exception] > > > > > > >> + ifCurtailed: [self tempAt: 3 put: true]. > > > > > > >> - ensure: [self tempAt: 3 put: true]. > > > > > > >> self return: val "return from self if not otherwise directed in handle block" > > > > > > >> ! > > > > > > >> > > > > > > >> Item was added: > > > > > > >> + ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > > > > > > >> + reactivateHandlers > > > > > > >> + "Private - sent to exception handler context only (on:do:). > > > > > > >> + Reactivate all the handlers into the chain" > > > > > > >> + > > > > > > >> + self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > > > > > > >> + self nextHandlerContext reactivateHandlers! > > > > > > >> > > > > > > >> Item was added: > > > > > > >> + ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- > > > > > > >> + reactivateHandlers > > > > > > >> + "reactivate all the exception handlers in the context chain" > > > > > > >> + self canSearchForSignalerContext > > > > > > >> + ifTrue: [signalContext nextHandlerContext reactivateHandlers]! > > > > > > >> > > > > > > >> Item was changed: > > > > > > >> ----- Method: Exception>>resignalAs: (in category 'handling') ----- > > > > > > >> resignalAs: replacementException > > > > > > >> "Signal an alternative exception in place of the receiver." > > > > > > >> > > > > > > >> + self reactivateHandlers. > > > > > > >> self resumeUnchecked: replacementException signal! > > > > > > >> > > > > > > >> Item was changed: > > > > > > >> ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- > > > > > > >> handleSignal: exception > > > > > > >> + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. > > > > > > >> + Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." > > > > > > >> - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." > > > > > > >> > > > > > > >> + ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! > > > > > > >> - ^ exception resumeUnchecked: exception defaultAction! > > > > > > >> > > > > > > >> Item was added: > > > > > > >> + ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- > > > > > > >> + reactivateHandlers > > > > > > >> + "nothing to do for bottom context" > > > > > > >> + > > > > > > >> + ^ self! > > > > > > >> > > > > > > >> > > > > > > > > > > > > > > > From nicolas.cellier.aka.nice at gmail.com Thu Apr 22 08:19:11 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 22 Apr 2021 10:19:11 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: Le jeu. 22 avr. 2021 à 09:10, Jakob Reschke a écrit : > > Am Do., 22. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > : > > An example for such exception-based dynamic scoping is CurrentReadOnlySourceFiles. > > > > ...which also got disarmed in my test case. Although that was not > obvious until I inspected the stack. > CurrentReadOnlySourceFiles is working for me. I see a single readOnly copy created. Jakob, maybe you have tried it before i fixed resume:? (resume: didn't reactivateHandlers in my first version). The question is whether nested usage works properly, for example nested Environment>>beCurrentDuring: I think that it should, but I've not checked this one. We ought to write more tests to document our expectations. BTW, did someone try (Environment allInstances) recently. I've got 52 instances... So we might want to add some tests, but we shall do so carefully. From marcel.taeumel at hpi.de Thu Apr 22 08:41:15 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 22 Apr 2021 10:41:15 +0200 Subject: [squeak-dev] Please try it out | Fixing the input mapping for keystroke events Message-ID: Hi all! Please find attached a changeset that improves the cross-platform base for keystroke events. Please try it out and take a look at it. Report issues ASAP so that I can merge it into Trunk soon. Thanks to Tom (tobe), the new promising idea is to replace the existing attempt: Duplicate all control and alt keys Duplicate control and alt keys Swap control and alt keys With the following preferences: [X] Map ASCII control characters to printable characters  - Default is TRUE  - Only affects events that have the CONTROL modifier set (e.g. CTRL+J)  - Rather application-specific than platform-specific [X] Map CONTROL keys to COMMAND keys  - Checked at image start-up  - TRUE on Windows/Linux  - FALSE on macOS [X] Map ALT keys to OPTION keys  - Checked at image start-up  - TRUE on Windows/Linux  - FALSE on macOS (bc. ALT==CMD on recent Linux/Windows VMs) Please take a look at KeyboardEvent >> #checkCommandKey to learn about the fundamental trade-off we have solved. Please try out your preferred applications. Feel free to add logging to HandMorph >> #logEvent: for more convenient testing: (anEvent isKeyboard and: [anEvent isKeystroke])    ifTrue: [Transcript showln: anEvent]. Thanks! Best, Marcel (and Tom) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: key-mapping.5.cs Type: application/octet-stream Size: 19803 bytes Desc: not available URL: From tonyg at leastfixedpoint.com Thu Apr 22 08:55:52 2021 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Thu, 22 Apr 2021 10:55:52 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> Message-ID: On 4/21/21 3:53 PM, Tom Beckmann wrote: > Chiming in on that note, I had experimented with that a while ago as > well and it turned out pretty fun I think, here's a quick demo video [1] > and the source code [2]. I believe it would be rather easy to make work > if combined with your keypress generation logic, Tony. That's awesome! It'd make a great addition to a phone-based Smalltalk. I've set a bookmark to come back to this once I have more of the infrastructure worked out. Regards, Tony From craig at blackpagedigital.com Thu Apr 22 20:13:11 2021 From: craig at blackpagedigital.com (Craig Latta) Date: Thu, 22 Apr 2021 13:13:11 -0700 Subject: [squeak-dev] SqueakJS keyboard input (was: Wrote a little about OnScreenKeyboardMorph) In-Reply-To: References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> Message-ID: I wrote: > ...on the iPad, there's Scribble. I wrote SqueakJS support for it. I > hide an invisible HTML text input element underneath wherever you're > entering text, and Scribble recognizes it. It does both ink-based > recognition and the sliding-around-on-an-onscreen-keyboard thing, > which I really like. > > https://vimeo.com/494744698 Vanessa responds: > Oh cool! Does it need image-side support? If not I'd love to get this > into SqueakJS proper - I think having a hidden text field might solve > the various issues we have on e.g. Android, or with copy/paste on > Safari. Yeah! This use case involves a tiny bit of image-side support, so that the hidden recognizer is moved properly whenever a Smalltalk window is activated. I'll submit a pull request for the rest of it. -C -- Craig Latta :: research computer scientist Black Page Digital :: Berkeley, California 663137D7940BF5C0AFC :: 1349FB2ADA32C4D5314CE From m at jaromir.net Thu Apr 22 21:40:35 2021 From: m at jaromir.net (Jaromir Matas) Date: Thu, 22 Apr 2021 16:40:35 -0500 (CDT) Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: References: Message-ID: <1619127635897-0.post@n4.nabble.com> Hi Nicolas, Jacob, Apologies if this has nothing to do with your issue (I’m unable to follow really) but I can see an inconsistency in the exception ‘return’ behavior: There are two types of return – explicit and implicit and I expected them to behave identically, however it doesn’t seem to be the case: [self error] on: Error do: [:ex | ex return ] ---> rearms handlerActive [self error] on: Error do: [:ex | ex ] ---> doesn’t rearm handlerActive The problem (if there’s any) is here: handleSignal: exception “…” self tempAt: 3 put: false. "disable self while executing handle block" val := [(self tempAt: 2) cull: exception] ifCurtailed: [self tempAt: 3 put: true]. ---> self return: val "return from self if not otherwise directed in handle block" `self return: val` is only executed if the handle block doesn’t contain an explicit exception message (retry, return etc) but unlike its explicit `ex return` counterpart it has no unwind block... In any case – is this an issue? Should the two forms of return really behave identically as I assumed? Thanks, Jaromir ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From nicolas.cellier.aka.nice at gmail.com Thu Apr 22 22:52:16 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 23 Apr 2021 00:52:16 +0200 Subject: [squeak-dev] The Trunk: Kernel-nice.1384.mcz In-Reply-To: <1619127635897-0.post@n4.nabble.com> References: <1619127635897-0.post@n4.nabble.com> Message-ID: Hi Jaromir, Le jeu. 22 avr. 2021 à 23:40, Jaromir Matas a écrit : > > Hi Nicolas, Jacob, > Apologies if this has nothing to do with your issue (I’m unable to follow > really) but I can see an inconsistency in the exception ‘return’ behavior: > There are two types of return – explicit and implicit and I expected them to > behave identically, however it doesn’t seem to be the case: > > [self error] on: Error do: [:ex | ex return ] > ---> rearms handlerActive > > [self error] on: Error do: [:ex | ex ] > ---> doesn’t rearm handlerActive > > The problem (if there’s any) is here: > handleSignal: exception > “…” > self tempAt: 3 put: false. "disable self while executing > handle block" > val := [(self tempAt: 2) cull: exception] > ifCurtailed: [self tempAt: 3 > put: true]. > ---> self return: val "return from self if not otherwise directed in > handle block" > > `self return: val` is only executed if the handle block doesn’t contain an > explicit exception message (retry, return etc) but unlike its explicit `ex > return` counterpart it has no unwind block... > > In any case – is this an issue? Should the two forms of return really behave > identically as I assumed? > > Thanks, > Jaromir > > Yes. In the former case we fire the ifCurtailed: block. in the latter, we do not. However, that does not make a difference, after we return, the handler is not anymore on the stack. What I wonder is whether the ifCurtailed: block is required at all. I think that it is not. In my first attempt, some reactivateHandlers were missing, and some tests would fail without the rearm in ifCurtailed:. Now, all tests pass without. > > > ----- > ^[^ Jaromir > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > From vanessa at codefrau.net Fri Apr 23 01:11:52 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Thu, 22 Apr 2021 18:11:52 -0700 Subject: [squeak-dev] SqueakJS keyboard input (was: Wrote a little about OnScreenKeyboardMorph) In-Reply-To: References: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> <45775300-3516-f3cc-e77a-642dd83efd2c@gmail.com> Message-ID: On Thu, Apr 22, 2021 at 1:13 PM Craig Latta wrote: > > I wrote: > > > ...on the iPad, there's Scribble. I wrote SqueakJS support for it. I > > hide an invisible HTML text input element underneath wherever you're > > entering text, and Scribble recognizes it. It does both ink-based > > recognition and the sliding-around-on-an-onscreen-keyboard thing, > > which I really like. > > > > https://vimeo.com/494744698 > > Vanessa responds: > > > Oh cool! Does it need image-side support? If not I'd love to get this > > into SqueakJS proper - I think having a hidden text field might solve > > the various issues we have on e.g. Android, or with copy/paste on > > Safari. > > Yeah! This use case involves a tiny bit of image-side support, so > that the hidden recognizer is moved properly whenever a Smalltalk window > is activated. I'll submit a pull request for the rest of it. > Does it use the setCompositionWindow mechanism? I always thought we should change ImmAbstractPlatform to call a generic primSetCompositionWindowPosition in ImmPlugin, which doesn't exist right now, but would allow platforms to hook into that mechanism without image changes. Then again, a focus / blur primitive would be good too so we can show/hide the soft keyboard automatically. It should get the bounds of the text area, and possibly the cursor position, too. With that information the VM could automatically zoom to a text field on phones ... So maybe a new SoftKeyboardPlugin? Vanessa -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Fri Apr 23 08:20:06 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 23 Apr 2021 10:20:06 +0200 Subject: [squeak-dev] Nested Environments demo In-Reply-To: References: Message-ID: Hi Tony! Thanks for the demo! I like the simplicity of your approach and learned things about import/export in environments I did not know about. Please find attached a changeset with some ideas for Environments-tonyg.79 (INBOX). (Think I could live with the term "namespace" ... even though "nested environment" might be better for newcomers to distinguish other notions of namespace in the system such as selectors in classes, temp names in methods etc.) Best, Marcel Am 30.03.2021 14:12:59 schrieb Tony Garnock-Jones : Hi all, I recorded a little screencast of the EnvironmentBrowser I've been playing with: https://www.youtube.com/watch?v=1UOyca5-72Y it's ~11 minutes long if you watch it at 1:1. In the description of the video is the outline that I was following as I recorded the talk. I'll paste it below as well. Cheers, Tony -=-=-=-=- [Here's the outline I was following as I recorded this talk.] Hi everyone. I'm Tony Garnock-Jones, it's March 30th 2021, and I'm going to walk through the experimentation I've been doing on nested Namespaces in Squeak Smalltalk. This work builds on Squeak's Environments, which I think are originally due to Colin Putney with some recent work by Jakob Reschke. I've made some small additions to Environment, and a little subclass called Namespace, which allows one to expose Environments via ordinary variable reference, if one so chooses. It doesn't change anything about how Environments work otherwise, so existing uses should remain unchanged. I've also added a variant of Browser that shows these accessible Environments in a hierarchy, and allows you to manage their imports and exports. Here it is. [Open an EnvironmentBrowser] [Navigate to EnvironmentBrowser] The tool is called EnvironmentBrowser, and it's a very thin veneer over the existing underlying Environment machinery. You can see that compared to the default browser, it has a couple of extra panels. This one [on the left] is a tree of environments. The idea is to take Environment's Instances as "well-known" roots for this tree: Environment wellKnownInstances Smalltalk is already in there, and at the moment there are no others. >From the roots, we recursively scan each environment for globals that are also Environments. This scan is a part of Environment itself: [Navigate to Environment's namespaceTreeDo: method] This other panel [on the left, just below the tree of environments] shows the imports and exports of this environment. Here you can see that the default environment, Smalltalk, imports all its own bindings, so they're visible to its own classes, and exports all its bindings to other Environments that import from Smalltalk. [Create namespace NS1] [Create class String, extends Object, inst var length, category Demo] [Create accessors] printOn: aStream aStream nextPutAll: 'I am a ball of wool ', length, ' metres long' [class side] new: size ^ self new length: size [Proceed on the warning] [Open workspace in Smalltalk] String new: 3 [Open workspace in NS1] String new: 3 [Rename NS1 to Fabric] [Create namespace NS2] [Import Fabric with prefix Fabric] [Open workspace in NS2] String new: 3 FabricString new: 3 "Oh! It didn't work! We didn't export it from Fabric." [Export all from Fabric] [Try again - still doesn't work] [Redo the import] [Try again - works now!] There are still some issues with, I think, Environments themselves propagating changes to each other. Fabric String new: 3 [Unlink Fabric] Now we see: String new: 3 FabricString new: 3 Fabric String new: 3 "error on this, Fabric is missing" [Remove the policy importing Fabric to NS2] Didn't remove it. Still some bugs. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: nested-environments-mt-comments.1.cs Type: application/octet-stream Size: 9645 bytes Desc: not available URL: From commits at source.squeak.org Fri Apr 23 08:58:52 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 23 Apr 2021 08:58:52 0000 Subject: [squeak-dev] The Inbox: Kernel-nice.1391.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Inbox: http://source.squeak.org/inbox/Kernel-nice.1391.mcz ==================== Summary ==================== Name: Kernel-nice.1391 Author: nice Time: 23 April 2021, 10:58:48.925778 am UUID: bde1d6d3-e3ba-48ad-b432-3ac5a1531880 Ancestors: Kernel-nice.1390 Remove the questionable ifCurtailed: block that did reactivate the handler in handleSignal:, and make the handling symetric, whether the handlerAction explicitily use exception return or not. Document the mysterious tempAt:/tempAt:put: intention by using proper method names as requested by Marcel. The slowdown shall be marginal, and system understanding should be improved. Provide messages to selectively reactivate some handler contexts. For gurus: handle with care! =============== Diff against Kernel-nice.1390 =============== Item was changed: ----- Method: Context>>canHandleSignal: (in category 'private-exceptions') ----- canHandleSignal: exception "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception then return true, otherwise forward this message to the next handler context. If none left, return false (see nil>>canHandleSignal:)" + ^ (self willHandleSignal: exception) - ^ (((self tempAt: 1) handles: exception) and: [self tempAt: 3]) or: [self nextHandlerContext canHandleSignal: exception]. ! Item was added: + ----- Method: Context>>deactivateHandler (in category 'private-exceptions') ----- + deactivateHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 3 ifTrue: [self tempAt: 3 put: false] "this is temporary handlerActive in #on:do:"! Item was added: + ----- Method: Context>>fireHandlerActionWith: (in category 'private-exceptions') ----- + fireHandlerActionWith: exception + "Sent to handler (on:do:) contexts only. + Perform the second argument, which is the handler action" + + ^(self tempAt: 2) cull: exception! Item was changed: ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- handleSignal: exception "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception and the handler is active then execute my handle block (second arg), otherwise forward this message to the next handler context. If none left, execute exception's defaultAction (see nil>>handleSignal:)." + | val | + (self willHandleSignal: exception) ifFalse: + [self deactivateHandler. - | handlerActive val | - "If the context has been returned from the handlerActive temp var may not be accessible." - handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. - (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: - [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. ^self nextHandlerContext handleSignal: exception]. exception privHandlerContext: self contextTag. + self deactivateHandler. "disable self while executing handle block" + val := self fireHandlerActionWith: exception. - self tempAt: 3 put: false. "disable self while executing handle block" - val := [(self tempAt: 2) cull: exception] - ifCurtailed: [self tempAt: 3 put: true]. self return: val "return from self if not otherwise directed in handle block" ! Item was added: + ----- Method: Context>>isHandlerActive (in category 'private-exceptions') ----- + isHandlerActive + "Private - sent to exception handler context only (on:do:)" + + ^stackp >= 3 and: [(self tempAt: 3) == true] "this is temporary handlerActive in #on:do:"! Item was added: + ----- Method: Context>>reactivateHandler (in category 'private-exceptions') ----- + reactivateHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 3 ifTrue: [self tempAt: 3 put: true] "this is temporary handlerActive in #on:do:"! Item was changed: ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- reactivateHandlers "Private - sent to exception handler context only (on:do:). Reactivate all the handlers into the chain" + self reactivateHandler. - self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" self nextHandlerContext reactivateHandlers! Item was added: + ----- Method: Context>>reactivateHandlersUpTo: (in category 'private-exceptions') ----- + reactivateHandlersUpTo: aHandlerContext + "Private - sent to exception handler context only (on:do:). + Reactivate the inner handlers into the chain, up to, but not including, aHandlerContext" + + self == aHandlerContext ifTrue: [^self]. + self reactivateHandler. + self nextHandlerContext reactivateHandlersUpTo: aHandlerContext! Item was added: + ----- Method: Context>>reactivateHandlersWhich:upTo: (in category 'private-exceptions') ----- + reactivateHandlersWhich: selectBlock upTo: aHandlerContext + "Private - sent to exception handler context only (on:do:). + Reactivate the inner handlers into the chain, up to, but not including, aHandlerContext, that satisfy the selectBlock predicate" + + self == aHandlerContext ifTrue: [^self]. + (selectBlock value: self) ifTrue: [self reactivateHandler]. + self nextHandlerContext reactivateHandlersWhich: selectBlock upTo: aHandlerContext! Item was changed: ----- Method: Context>>rearmHandlerDuring: (in category 'private-exceptions') ----- rearmHandlerDuring: aBlock "Sent to handler (on:do:) contexts only. Makes me re-entrant for the duration of aBlock. Only works in a closure-enabled image" + ^ [self reactivateHandler. aBlock value] + ensure: [self deactivateHandler]! - ^ [self tempAt: 3 put: true. aBlock value] - ensure: [self tempAt: 3 put: false]! Item was added: + ----- Method: Context>>willHandleSignal: (in category 'private-exceptions') ----- + willHandleSignal: exception + "Sent to handler (on:do:) contexts only." + + ^self isHandlerActive and: [(self tempAt: 1) handles: exception] + ! Item was added: + ----- Method: Exception>>reactivateHandlersUpTo: (in category 'priv handling') ----- + reactivateHandlersUpTo: aHandlerContext + "reactivate all the exception handlers in the context chain" + self canSearchForSignalerContext + ifTrue: [signalContext nextHandlerContext reactivateHandlersUpTo: aHandlerContext]! Item was added: + ----- Method: UndefinedObject>>reactivateHandlersUpTo: (in category 'bottom context') ----- + reactivateHandlersUpTo: aHandlerContext + + ^ self! Item was added: + ----- Method: UndefinedObject>>reactivateHandlersWhich:upTo: (in category 'bottom context') ----- + reactivateHandlersWhich: selectBlock upTo: aHandlerContext + + ^ self! From commits at source.squeak.org Fri Apr 23 09:06:36 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 23 Apr 2021 09:06:36 0000 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.142.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.142.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-nice.142 Author: nice Time: 23 April 2021, 11:06:34.400228 am UUID: 93216f25-69b2-43c3-b355-36a28cfd3588 Ancestors: ToolBuilder-Kernel-nice.141 Attempt to allow nested sendNotificationsTo: handling. Requires Kernel-nice.1391. The idea is that the handler shall not be active during the handlerAction. But still, we want he inner handlers to be active as was the case with former exception handling. Please write TestCase documenting expectations and review if this can possibly fit. =============== Diff against ToolBuilder-Kernel-nice.141 =============== Item was changed: ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- sendNotificationsTo: aNewBlock + | val | + "Reactivate inner handlers so as to let them handle other exceptions" + self + reactivateHandlersWhich: [:aHandlerContext | (aHandlerContext willHandleSignal: self) not] + upTo: handlerContext. + val := workBlock value: [ :barVal | - - self reactivateHandlers; resumeUnchecked: ( - workBlock value: [ :barVal | aNewBlock value: minVal value: maxVal value: barVal + ]. + handlerContext ifNotNil: [handlerContext reactivateHandler]. + self resumeUnchecked: val - ] - ) ! From marcel.taeumel at hpi.de Fri Apr 23 16:23:22 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 23 Apr 2021 18:23:22 +0200 Subject: [squeak-dev] Please try it out | Fixing the input mapping for keystroke events In-Reply-To: References: Message-ID: Hi all! Please find attached an updated changeset with a "KeyboardExerciser" to help you test and inspect the incoming keyboard events. You can find it also in the parts bin nearby the "ClickExerciser". The visuals are supposed to look platform-specific. However, the event data contains information to make your application work across platforms. See KeyboardEvent >> #checkCommandKey for more explanations. Try [CTRL]+[C] for keyStroke, keyDown, and keyUp. Note that the visuals might not look right for keyUp and keyDown events due to missing lookup tables for the raw, platform-specific key codes. On my machine, for example, [,] and [.] and [-] look odd: Nothing to worry about because all keyboard shortcuts in Squeak use keyStroke events at the moment. Best, Marcel Am 22.04.2021 10:41:15 schrieb Marcel Taeumel : Hi all! Please find attached a changeset that improves the cross-platform base for keystroke events. Please try it out and take a look at it. Report issues ASAP so that I can merge it into Trunk soon. Thanks to Tom (tobe), the new promising idea is to replace the existing attempt: Duplicate all control and alt keys Duplicate control and alt keys Swap control and alt keys With the following preferences: [X] Map ASCII control characters to printable characters  - Default is TRUE  - Only affects events that have the CONTROL modifier set (e.g. CTRL+J)  - Rather application-specific than platform-specific [X] Map CONTROL keys to COMMAND keys  - Checked at image start-up  - TRUE on Windows/Linux  - FALSE on macOS [X] Map ALT keys to OPTION keys  - Checked at image start-up  - TRUE on Windows/Linux  - FALSE on macOS (bc. ALT==CMD on recent Linux/Windows VMs) Please take a look at KeyboardEvent >> #checkCommandKey to learn about the fundamental trade-off we have solved. Please try out your preferred applications. Feel free to add logging to HandMorph >> #logEvent: for more convenient testing: (anEvent isKeyboard and: [anEvent isKeystroke])    ifTrue: [Transcript showln: anEvent]. Thanks! Best, Marcel (and Tom) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 37054 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 9239 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: key-mapping.10.cs Type: application/octet-stream Size: 31892 bytes Desc: not available URL: From jrmaffeo at gmail.com Fri Apr 23 17:22:46 2021 From: jrmaffeo at gmail.com (John-Reed Maffeo) Date: Fri, 23 Apr 2021 10:22:46 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: In the interest of having a surfit of candidates I am putting myself (John-Reed Maffeo) up for re-election to the board. I am a hobby programmer who got interested in Squeak ~20 years ago when I was trying to decide which language I wanted to use to develop an application for personal use which required interfacing with a complex data structure. I tried to get traction with a variety of languages including c, fortran, pascal, and others. They all seemed to be difficult to use and code manage and limited to a single OS for implementation. I stumbled on Squeak and gave it a try and I started being productive in just a few weeks. (I had seen a marketing presentation of Smalltalk and realized how powerful it was when one of the suits asked it it could XYZ and the answer was no not right now; after the next coffee break the presenter started of with "By the way, Smalltalk can now do XYZ") Being on the board has been very rewarding to me, and though my contributions have been meger, I would like to continue because I bring a different perspective to the board as a user rather than a developer. I encourage anyone who is interested in Squeak to consider becoming a board member. It is a good way to learn more about Squeak as a project, and help keep development moving forward. John-Reed Maffeo [ | ] On Fri, Apr 2, 2021 at 1:10 AM Rein, Patrick wrote: > Hi All, > > It's that time again (although with a new person telling you this). > Time to raise your voices and elect your leaders! Can you believe > it's been over a year already? > > It's a time for you to stand up, help your community and volunteer to > serve! > > Squeak wants you! > > Every year we elect the SOB (Squeak Oversight Board) consisting of > seven members from our community. The current board members are: > 1. Vanessa Freudenberg > 2. Tim Rowledge > 3. Marcel Taeumel > 4. Craig Latta > 5. David T. Lewis > 6. Chris Muller > 7. John-Reed Maffeo > > For more info on the board please see: > https://squeakboard.wordpress.com/our-mission/ > > Everything about the election, including schedule and more, can be tracked > here: > http://wiki.squeak.org/squeak/6656 > > Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members > and campaigning! > > Candidates should nominate themselves and start their campaign on the > squeak-dev mailing list. Or if you nominate someone else, make sure > that person really wants to run. :) I will not put anyone on the > candidate list until that person makes it known on squeak-dev that > he/she intends to run. > > During this period, the candidates should ideally present themselves > on squeak-dev, unless they have already done so, and the community can > ask questions. > > I encourage you to reach out to potential candidates, people that are > active in the community and represent your views, and ask them to run. > Some people will not run without encouragement. Also, I know that > some people wait to the last minute to run for the board to see if > others will run but please consider getting this year off to a faster > start and just jump right in! > > The schedule and process are as follows: > > Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members > and campaigning! > Friday 16th of April 2021, 18.00 UTC: Candidate list is finalized. > Friday 16th of April 2021, 19.00 UTC: Online election starts. > Friday 30th of April 2021, 19.00 UTC: Online election ends. > Results will be announced immediately after the election ends. > > The voting period is two week long and ballots are sent out via email. > > And how do you end up on the voter list? See below. :) > > IMPORTANT: New voters will NOT be added once the election is started. > You MUST try to get on the voter list before the 16th of April 2021 > or you will NOT be able to vote. If your Email has changed please try > to make sure it is changed on the list of voters before the election > starts. > > -------------------------- > > If you were invited to vote last year you are already on the voter > list, no worries! If you are a new Squeaker and wish to vote you > should do ONE of the following: > > * Get a "known" Squeaker to vouch for you. If a known Squeaker > sends an email to voters (at) squeak.org giving me a name and email > for you, then I will add you. > > * Send an email to voters (at) squeak.org yourself (and CC to > squeak-dev if you like) with information/arguments showing me that you > are indeed serious about voting and that you are indeed a Squeaker. > > When the voting period starts all voters will receive an email with > instructions and a link to the voting website. > > If there are any further questions, just reply *in this thread* and I > will closely track it - or send email to voters (at) squeak.org which > is updated and points to me. > > ...so let's get on with it! > > All the best, > Patrick Rein > > -- John-Reed Maffeo -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Fri Apr 23 17:31:25 2021 From: tim at rowledge.org (tim Rowledge) Date: Fri, 23 Apr 2021 10:31:25 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: I want to add emphasis to a few words from John-Reed > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: > > I encourage anyone who is interested in Squeak to consider becoming a board member. It is a good way to learn more about Squeak as a project, and help keep development moving forward. Please don't think there is some need to be a Soopa-Uber-Hacker of Squeak in order to be a valuable Board member. If you love Squeak, if you have some time and effort you can spare to help keep the community going, then you'd be an asset. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Oxymorons: Resident alien From eric.gade at gmail.com Fri Apr 23 17:32:38 2021 From: eric.gade at gmail.com (Eric Gade) Date: Fri, 23 Apr 2021 13:32:38 -0400 Subject: [squeak-dev] Nested Environments demo In-Reply-To: References: Message-ID: Hi Tony, This is really cool. I have a question that might have an obvious answer. If you were to load some code in via Metacello baseline, or even via Squot, inside one of these environments would the installed packages be scoped as expected? On Fri, Apr 23, 2021 at 4:20 AM Marcel Taeumel wrote: > Hi Tony! > > Thanks for the demo! > > I like the simplicity of your approach and learned things about > import/export in environments I did not know about. > > Please find attached a changeset with some ideas for Environments-tonyg.79 > (INBOX). > > (Think I could live with the term "namespace" ... even though "nested > environment" might be better for newcomers to distinguish other notions of > namespace in the system such as selectors in classes, temp names in methods > etc.) > > Best, > Marcel > > Am 30.03.2021 14:12:59 schrieb Tony Garnock-Jones < > tonyg at leastfixedpoint.com>: > Hi all, > > I recorded a little screencast of the EnvironmentBrowser I've been > playing with: > > https://www.youtube.com/watch?v=1UOyca5-72Y > > it's ~11 minutes long if you watch it at 1:1. In the description of the > video is the outline that I was following as I recorded the talk. > > I'll paste it below as well. > > Cheers, > Tony > > -=-=-=-=- > > [Here's the outline I was following as I recorded this talk.] > > Hi everyone. > > I'm Tony Garnock-Jones, it's March 30th 2021, and I'm going to walk > through the experimentation I've been doing on nested Namespaces in > Squeak Smalltalk. > > This work builds on Squeak's Environments, which I think are originally > due to Colin Putney with some recent work by Jakob Reschke. > > I've made some small additions to Environment, and a little subclass > called Namespace, which allows one to expose Environments via ordinary > variable reference, if one so chooses. It doesn't change anything about > how Environments work otherwise, so existing uses should remain unchanged. > > I've also added a variant of Browser that shows these accessible > Environments in a hierarchy, and allows you to manage their imports and > exports. Here it is. > > [Open an EnvironmentBrowser] > [Navigate to EnvironmentBrowser] > > The tool is called EnvironmentBrowser, and it's a very thin veneer over > the existing underlying Environment machinery. > > You can see that compared to the default browser, it has a couple of > extra panels. > > This one [on the left] is a tree of environments. The idea is to take > Environment's Instances as "well-known" roots for this tree: > > Environment wellKnownInstances > > Smalltalk is already in there, and at the moment there are no others. > > From the roots, we recursively scan each environment for globals that > are also Environments. This scan is a part of Environment itself: > > [Navigate to Environment's namespaceTreeDo: method] > > This other panel [on the left, just below the tree of environments] > shows the imports and exports of this environment. > > Here you can see that the default environment, Smalltalk, imports all > its own bindings, so they're visible to its own classes, and exports all > its bindings to other Environments that import from Smalltalk. > > [Create namespace NS1] > [Create class String, extends Object, inst var length, category Demo] > [Create accessors] > > printOn: aStream > aStream nextPutAll: 'I am a ball of wool ', length, ' metres long' > > [class side] > new: size > ^ self new length: size > [Proceed on the warning] > > [Open workspace in Smalltalk] > String new: 3 > > [Open workspace in NS1] > String new: 3 > > [Rename NS1 to Fabric] > [Create namespace NS2] > [Import Fabric with prefix Fabric] > > [Open workspace in NS2] > String new: 3 > FabricString new: 3 > "Oh! It didn't work! We didn't export it from Fabric." > > [Export all from Fabric] > [Try again - still doesn't work] > [Redo the import] > [Try again - works now!] > > There are still some issues with, I think, Environments themselves > propagating changes to each other. > > Fabric String new: 3 > > [Unlink Fabric] > > Now we see: > > String new: 3 > FabricString new: 3 > Fabric String new: 3 "error on this, Fabric is missing" > > [Remove the policy importing Fabric to NS2] > > Didn't remove it. Still some bugs. > > > -- Eric -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron at usmedrec.com Fri Apr 23 17:40:45 2021 From: ron at usmedrec.com (Ron Teitelbaum) Date: Fri, 23 Apr 2021 13:40:45 -0400 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: Wow talk about waiting till the last minute. From my calculator you had 29 minutes left to announce your candidacy. Well as I write this there is still 20 minutes left! All the best, Ron On Fri, Apr 23, 2021 at 1:31 PM tim Rowledge wrote: > I want to add emphasis to a few words from John-Reed > > > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: > > > > I encourage anyone who is interested in Squeak to consider becoming a > board member. It is a good way to learn more about Squeak as a project, and > help keep development moving forward. > > Please don't think there is some need to be a Soopa-Uber-Hacker of Squeak > in order to be a valuable Board member. If you love Squeak, if you have > some time and effort you can spare to help keep the community going, then > you'd be an asset. > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > Oxymorons: Resident alien > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bruce.oneel at pckswarms.ch Fri Apr 23 17:47:55 2021 From: bruce.oneel at pckswarms.ch (Bruce O'Neel) Date: Fri, 23 Apr 2021 19:47:55 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> What!?!?!  There is still time left? Ok, I'll throw my hat in the ring as well. I have used Squeak for 20 some years for fun projects.  Before that for a few glorious hours I had my hands on a Tex 4404 Smalltalk system and lusted for a Smalltalk of my own ever since. My involvement has been to keep the planet Squeak site somewhat up to date and to keep debug Linux VM build errors. cheers bruce > I want to add emphasis to a few words from John-Reed > > > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: > > > > I encourage anyone who is interested in Squeak to consider becoming a board member. It is a good way to learn more about Squeak as a project, and help keep development moving forward. > > Please don't think there is some need to be a Soopa-Uber-Hacker of Squeak in order to be a valuable Board member. If you love Squeak, if you have some time and effort you can spare to help keep the community going, then you'd be an asset. > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > Oxymorons: Resident alien -------------- next part -------------- An HTML attachment was scrubbed... URL: From Patrick.Rein at hpi.de Fri Apr 23 18:58:23 2021 From: Patrick.Rein at hpi.de (Rein, Patrick) Date: Fri, 23 Apr 2021 18:58:23 +0000 Subject: [squeak-dev] SOB Election: Voting started Message-ID: Hi everyone, voting in the Squeak Oversight Board election has started! We have great candidates, so please vote! If you have not received a voting mail yet: On Monday I will review the email logs and write to every email adress that is on the voters list but was not opted-in for. This email will list the email address that was used to register on the voters list so you can opt-in for the correct email address. During the week, I will periodically resend voting emails for previously failed mail addresses. Cheers, Patrick From ron at usmedrec.com Fri Apr 23 19:15:08 2021 From: ron at usmedrec.com (Ron Teitelbaum) Date: Fri, 23 Apr 2021 15:15:08 -0400 Subject: [squeak-dev] SOB Election: Voting started In-Reply-To: References: Message-ID: Hi all, I'm sure everyone can use google translate. If you don't speak German, I did it for you. :) Um Ihre Stimme abzugeben, rufen Sie bitte die folgende URL auf: means: To cast your vote, please go to the following URL: Please go find your Abstimmung email and VOTE! All the best, Ron On Fri, Apr 23, 2021 at 2:58 PM Rein, Patrick wrote: > Hi everyone, > > voting in the Squeak Oversight Board election has started! We have great > candidates, so please vote! > > If you have not received a voting mail yet: On Monday I will review the > email logs and write to every email adress that is on the voters list but > was not opted-in for. This email will list the email address that was used > to register on the voters list so you can opt-in for the correct email > address. During the week, I will periodically resend voting emails for > previously failed mail addresses. > > Cheers, > Patrick > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Sat Apr 24 09:43:06 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sat, 24 Apr 2021 11:43:06 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, hi Marcel, Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel : > > Hi Christoph, > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > I am struggling to understand how your arguments address each other person's concerns. Did I understand your points correctly: - Christoph wants to get rid of the type check. He argues that sometimes even for the objects with "primitive" structure you may want to get the link. For example, MCVersionName loses its type information when printed, so when you would inspect the result, you would get a String instead of an MCVersionName. The other example is when you want to track identity. Indeed, sometimes it is useful to check whether one String is the same as another one retrieved (inspected) from somewhere else. I do this regularly in Squot when debugging the capturing and materialization (although seldom for Strings at this time because for these it already works as expected). - Marcel says that the links are unnecessary for what are essentially value objects that are not complex enough to need inspection beyond just looking at the print string. Supposedly, one can just reevaluate the result or the expression. Adding the links there produces visual clutter and is distracting. Inspecting an MCVersionName would reveal no further information about the object than the print string does (that is, except for the type!). Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") I fully agree with Marcel on the immediates and singletons (true, false, nil, Symbols). While the type check might not be really necessary, avoiding visual clutter can be a good thing. Tradeoff is with having the special case in the code. Unfortunately(?), Strings in Squeak/Smalltalk are not quite value objects, since they are mutable, can be used as buffers, etc. Depends on the application. On the other hand, Points are mostly used as value objects, but did not get the special case treatment. Though strictly, technically speaking, they are not different from Strings in this regard. Inspecting the result string or the revaluating the original expression to do so is only safe if it does not provoke side effects. For Marcel's selection of classes, there are no side effects of reevaluating the result string. But reevaluating the original expression might not be free of side effects. I guess you would not reevaluate the expression to inspect an immediate or singleton, but for those objects that do have object identity, such as Strings, or where the type of the result is not obvious, MCVersionName, you might want to do that. How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. Then there would be no visual clutter, and if you know that the feature is there (and you have subsequently turned off the preference, for example), you would also not easily forget that you can use it. Kind regards, Jakob From jakres+squeak at gmail.com Sat Apr 24 12:23:19 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sat, 24 Apr 2021 14:23:19 +0200 Subject: [squeak-dev] FFI: FFI-Kernel-mt.120.mcz In-Reply-To: References: Message-ID: schrieb am Di., 20. Apr. 2021 > > Item was changed: > + ----- Method: ExternalData>>fromCStrings (in category 'converting - > support') ----- > - ----- Method: ExternalData>>fromCStrings (in category 'converting') ----- > fromCStrings > "Assume that the receiver represents a set of C strings and is > teerminated by a empty string and convert it to a Smalltalk ordered > collection of strings" > > | stream index char strings str | > type isPointerType ifFalse: [self error: 'External object is not a > pointer type.']. > + self flag: #bogus. "mt: This format seems to be rather specific to > some library. There would normally be pointers to pointers for such a > structure. Or does the C standard mention such a format somehow? > 'abcd\0efg\0hijklmnopq\0rstuvwxyz\0\0' ??? " > strings := OrderedCollection new. > index := 1. > [ > stream := WriteStream on: String new. > [(char := handle unsignedCharAt: index) = 0 asCharacter] > whileFalse: [ > stream nextPut: char. > index := index + 1 > ]. > str := stream contents. > strings addLast: str. > str size = 0 > ] whileFalse. > ^strings! > Seems to be an API specific thing: https://devblogs.microsoft.com/oldnewthing/20110511-00/?p=10693 https://devblogs.microsoft.com/oldnewthing/20091008-00/?p=16443 -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Sat Apr 24 13:41:53 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sat, 24 Apr 2021 13:41:53 +0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> , Message-ID: Hi Jakob, Hi Marcel, thank you for reviving this discussion! :-) > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") Definitively also the latter. > While the type check might not be really necessary, avoiding visual clutter can be a good thing. -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Jakob Reschke Gesendet: Samstag, 24. April 2021 11:43:06 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz Hi Christoph, hi Marcel, Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel : > > Hi Christoph, > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > I am struggling to understand how your arguments address each other person's concerns. Did I understand your points correctly: - Christoph wants to get rid of the type check. He argues that sometimes even for the objects with "primitive" structure you may want to get the link. For example, MCVersionName loses its type information when printed, so when you would inspect the result, you would get a String instead of an MCVersionName. The other example is when you want to track identity. Indeed, sometimes it is useful to check whether one String is the same as another one retrieved (inspected) from somewhere else. I do this regularly in Squot when debugging the capturing and materialization (although seldom for Strings at this time because for these it already works as expected). - Marcel says that the links are unnecessary for what are essentially value objects that are not complex enough to need inspection beyond just looking at the print string. Supposedly, one can just reevaluate the result or the expression. Adding the links there produces visual clutter and is distracting. Inspecting an MCVersionName would reveal no further information about the object than the print string does (that is, except for the type!). Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") I fully agree with Marcel on the immediates and singletons (true, false, nil, Symbols). While the type check might not be really necessary, avoiding visual clutter can be a good thing. Tradeoff is with having the special case in the code. Unfortunately(?), Strings in Squeak/Smalltalk are not quite value objects, since they are mutable, can be used as buffers, etc. Depends on the application. On the other hand, Points are mostly used as value objects, but did not get the special case treatment. Though strictly, technically speaking, they are not different from Strings in this regard. Inspecting the result string or the revaluating the original expression to do so is only safe if it does not provoke side effects. For Marcel's selection of classes, there are no side effects of reevaluating the result string. But reevaluating the original expression might not be free of side effects. I guess you would not reevaluate the expression to inspect an immediate or singleton, but for those objects that do have object identity, such as Strings, or where the type of the result is not obvious, MCVersionName, you might want to do that. How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. Then there would be no visual clutter, and if you know that the feature is there (and you have subsequently turned off the preference, for example), you would also not easily forget that you can use it. Kind regards, Jakob -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Sat Apr 24 15:42:58 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sat, 24 Apr 2021 17:42:58 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> <,> Message-ID: Hi Jakob, thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. Hey Christoph, a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? Hi all, here is again the list of objects I think we should exclude from having a text action on their print-it result: ByteString ByteSymbol Number Boolean UndefinedObject If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) Reducing visual clutter is worth a few lines of extra source code. Best, Marcel Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : Hi Jakob, Hi Marcel, thank you for reviving this discussion! :-) > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") Definitively also the latter. > While the type check might not be really necessary, avoiding visual clutter can be a good thing. -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... Best, Christoph Von: Squeak-dev im Auftrag von Jakob Reschke Gesendet: Samstag, 24. April 2021 11:43:06 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz   Hi Christoph, hi Marcel, Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel : > > Hi Christoph, > > > [...]  subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > I am struggling to understand how your arguments address each other person's concerns. Did I understand your points correctly: - Christoph wants to get rid of the type check. He argues that sometimes even for the objects with "primitive" structure you may want to get the link. For example, MCVersionName loses its type information when printed, so when you would inspect the result, you would get a String instead of an MCVersionName. The other example is when you want to track identity. Indeed, sometimes it is useful to check whether one String is the same as another one retrieved (inspected) from somewhere else. I do this regularly in Squot when debugging the capturing and materialization (although seldom for Strings at this time because for these it already works as expected). - Marcel says that the links are unnecessary for what are essentially value objects that are not complex enough to need inspection beyond just looking at the print string. Supposedly, one can just reevaluate the result or the expression. Adding the links there produces visual clutter and is distracting. Inspecting an MCVersionName would reveal no further information about the object than the print string does (that is, except for the type!). Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") I fully agree with Marcel on the immediates and singletons (true, false, nil, Symbols). While the type check might not be really necessary, avoiding visual clutter can be a good thing. Tradeoff is with having the special case in the code. Unfortunately(?), Strings in Squeak/Smalltalk are not quite value objects, since they are mutable, can be used as buffers, etc. Depends on the application. On the other hand, Points are mostly used as value objects, but did not get the special case treatment. Though strictly, technically speaking, they are not different from Strings in this regard. Inspecting the result string or the revaluating the original expression to do so is only safe if it does not provoke side effects. For Marcel's selection of classes, there are no side effects of reevaluating the result string. But reevaluating the original expression might not be free of side effects. I guess you would not reevaluate the expression to inspect an immediate or singleton, but for those objects that do have object identity, such as Strings, or where the type of the result is not obvious, MCVersionName, you might want to do that. How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. Then there would be no visual clutter, and if you know that the feature is there (and you have subsequently turned off the preference, for example), you would also not easily forget that you can use it. Kind regards, Jakob -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Sat Apr 24 18:58:35 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sat, 24 Apr 2021 20:58:35 +0200 Subject: [squeak-dev] Please try it out | Fixing the input mapping for keystroke events In-Reply-To: References: Message-ID: Hi Marcel, I tried it on macos and windows, no problem so far. I had some fun with the exercizer, some combinations are surprising indeed... Le ven. 23 avr. 2021 à 18:23, Marcel Taeumel a écrit : > Hi all! > > Please find attached an updated changeset with a "KeyboardExerciser" to > help you test and inspect the incoming keyboard events. You can find it > also in the parts bin nearby the "ClickExerciser". > > > The visuals are supposed to look platform-specific. However, the event > data contains information to make your application work across platforms. > See KeyboardEvent >> #checkCommandKey for more explanations. > > Try [CTRL]+[C] for keyStroke, keyDown, and keyUp. > > Note that the visuals might not look right for keyUp and keyDown events > due to missing lookup tables for the raw, platform-specific key codes. On > my machine, for example, [,] and [.] and [-] look odd: > > > > Nothing to worry about because all keyboard shortcuts in Squeak use > keyStroke events at the moment. > > Best, > Marcel > > Am 22.04.2021 10:41:15 schrieb Marcel Taeumel : > Hi all! > > Please find attached a changeset that improves the cross-platform base for > keystroke events. Please try it out and take a look at it. Report issues > ASAP so that I can merge it into Trunk soon. > > Thanks to Tom (tobe), the new promising idea is to replace the existing > attempt: > > Duplicate all control and alt keys > Duplicate control and alt keys > Swap control and alt keys > > With the following preferences: > > [X] Map ASCII control characters to printable characters > - Default is TRUE > - Only affects events that have the CONTROL modifier set (e.g. CTRL+J) > - Rather application-specific than platform-specific > [X] Map CONTROL keys to COMMAND keys > - Checked at image start-up > - TRUE on Windows/Linux > - FALSE on macOS > [X] Map ALT keys to OPTION keys > - Checked at image start-up > - TRUE on Windows/Linux > - FALSE on macOS (bc. ALT==CMD on recent Linux/Windows VMs) > > Please take a look at KeyboardEvent >> #checkCommandKey to learn about the > fundamental trade-off we have solved. > > Please try out your preferred applications. Feel free to add logging to > HandMorph >> #logEvent: for more convenient testing: > > (anEvent isKeyboard and: [anEvent isKeystroke]) > ifTrue: [Transcript showln: anEvent]. > > Thanks! > > Best, > Marcel (and Tom) > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 37054 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 9239 bytes Desc: not available URL: From m at jaromir.net Sat Apr 24 19:32:00 2021 From: m at jaromir.net (Jaromir Matas) Date: Sat, 24 Apr 2021 14:32:00 -0500 (CDT) Subject: [squeak-dev] The Inbox: Kernel-nice.1391.mcz In-Reply-To: References: Message-ID: <1619292720661-0.post@n4.nabble.com> Hi Nicolas, > Remove the questionable ifCurtailed: block that did reactivate the handler > in handleSignal:, and > make the handling symetric, whether the handlerAction explicitily use > exception return or not. I'd like to suggest the following change to really make handling `return` the same whether it's called explicitly or not: The last line should send `return: val` to exception instead of self - the `exception return` calls `handlerContext return` and at the moment it's true the `self` is the handlerContext. But in theory someone can e.g. change `return` definition and then the two returns won't be the same... Plus I think this is more consistent and readable. Thanks, handleSignal: exception "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception and the handler is active then execute my handle block (second arg), otherwise forward this message to the next handler context. If none left, execute exception's defaultAction (see nil>>handleSignal:)." | val | (self willHandleSignal: exception) ifFalse: [self deactivateHandler. ^self nextHandlerContext handleSignal: exception]. exception privHandlerContext: self contextTag. self deactivateHandler. "disable self while executing handle block" val := self fireHandlerActionWith: exception. + exception return: val "return as default action if not otherwise directed in handle block" - self return: val "return from self if not otherwise directed in handle block" ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From commits at source.squeak.org Sun Apr 25 06:25:10 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 06:25:10 0000 Subject: [squeak-dev] The Trunk: Kernel-mt.1391.mcz Message-ID: Marcel Taeumel uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-mt.1391.mcz ==================== Summary ==================== Name: Kernel-mt.1391 Author: mt Time: 25 April 2021, 8:25:06.787934 am UUID: 9ab61f3b-e0c8-c545-82fd-49bf4a28fbf4 Ancestors: Kernel-nice.1390 Changes keystroke mappings for better cross-platform compatibility. See http://forum.world.st/Please-try-it-out-Fixing-the-input-mapping-for-keystroke-events-td5129004.html =============== Diff against Kernel-nice.1390 =============== Item was changed: Object subclass: #EventSensor instanceVariableNames: 'mouseButtons mousePosition mouseWheelDelta keyboardBuffer interruptKey interruptSemaphore eventQueue inputSemaphore lastEventPoll hasInputSemaphore lastEventTime' + classVariableNames: 'ButtonDecodeTable EventPollPeriod EventTicklerProcess InterruptWatcherProcess KeyDecodePreferences KeyDecodeTable' - classVariableNames: 'ButtonDecodeTable EventPollPeriod EventTicklerProcess InterruptWatcherProcess KeyDecodeTable' poolDictionaries: 'EventSensorConstants' category: 'Kernel-Processes'! !EventSensor commentStamp: 'mt 12/13/2019 14:38' prior: 0! An EventSensor is an interface to the user input devices. There is at least one instance of EventSensor named Sensor in the system. EventSensor is a replacement for the earlier InputSensor implementation based on a set of (optional) event primitives. An EventSensor updates its state when events are received so that all state based users of Sensor (e.g., Sensor keyboard, Sensor leftShiftDown, Sensor mouseButtons) will work exactly as before, by moving the current VM mechanisms into EventSensor itself. An optional input semaphore is part of the new design. For platforms that support true asynchronous event notification, the semaphore will be signaled to indicate pending events. On platforms that do not support asynchronous notifications about events, the UI will have to poll EventSensor periodically to read events from the VM. Instance variables: mouseButtons - mouse button state as replacement for primMouseButtons mousePosition - mouse position as replacement for primMousePt keyboardBuffer - keyboard input buffer interruptKey - currently defined interrupt key interruptSemaphore - the semaphore signaled when the interruptKey is detected eventQueue - an optional event queue for event driven applications inputSemaphore - the semaphore signaled by the VM if asynchronous event notification is supported lastEventPoll - the last millisecondClockValue at which we called fetchMoreEvents hasInputSemaphore - true if my inputSemaphore has actually been signaled at least once. Class variables: ButtonDecodeTable - maps mouse buttons as reported by the VM to ones reported in the events. KeyDecodeTable SmallInteger>> - maps some keys and their modifiers to other keys (used for instance to map Ctrl-X to Alt-X) InterruptSemaphore - signalled by the the VM and/or the event loop upon receiving an interrupt keystroke. InterruptWatcherProcess - waits on the InterruptSemaphore and then responds as appropriate. EventPollPeriod - the number of milliseconds to wait between polling for more events in the userInterruptHandler. EventTicklerProcess - the process that makes sure that events are polled for often enough (at least every EventPollPeriod milliseconds). Event format: The current event format is very simple. Each event is recorded into an 8 element array. All events must provide some SmallInteger ID (the first field in the event buffer) and a time stamp (the second field in the event buffer), so that the difference between the time stamp of an event and the current time can be reported. Currently, the following events are defined: Null event ============= The Null event is returned when the ST side asks for more events but no more events are available. Structure: [1] - event type 0 [2-8] - unused Mouse event structure ========================== Mouse events are generated when mouse input is detected. [1] - event type 1 [2] - time stamp [3] - mouse x position [4] - mouse y position [5] - button state; bitfield with the following entries: 1 - 2r001 yellow (e.g., right) button 2 - 2r010 blue (e.g., middle) button 4 - 2r100 red (e.g., left) button [all other bits are currently undefined] [6] - modifier keys; bitfield with the following entries: 1 - shift key 2 - ctrl key 4 - (Mac specific) option key 8 - Cmd/Alt key [all other bits are currently undefined] [7] - reserved. [8] - host window id. Keyboard events ==================== Keyboard events are generated when keyboard input is detected. [1] - event type 2 [2] - time stamp [3] - character code (Ascii) For now the character code is in Mac Roman encoding. See #macToSqueak. For key press/release (see [4]), character codes are normalized. [4] - press state; integer with the following meaning 0 - character (aka. key stroke or key still pressed) 1 - key press (aka. key down) 2 - key release (aka. key up) [5] - modifier keys (same as in mouse events) For key press/release (see [4]), modifier keys are still accessible. [6] - character code (Unicode UTF32) Manual decoding via KeyboardInputInterpreter possible. For key press/release (see [4]), character codes are normalized. [7] - reserved. [8] - host window id. Mouse-wheel event structure ========================== Mouse-wheel events are generated when mouse-wheel input is detected. [1] - event type 7 [2] - time stamp [3] - horizontal scroll delta [4] - vertical scroll delta [5] - button state (same as in mouse events) [6] - modifier keys (same as in mouse events) [7] - reserved. [8] - host window id. ! Item was removed: - ----- Method: EventSensor class>>defaultCrossPlatformKeys (in category 'class initialization') ----- - defaultCrossPlatformKeys - "Answer a list of key letters that are used for common editing operations - on different platforms." - ^{ $c . $x . $v . $a . $s . $f . $g . $z } - ! Item was removed: - ----- Method: EventSensor class>>duplicateAllControlAndAltKeysChanged (in category 'preference change notification') ----- - duplicateAllControlAndAltKeysChanged - "The Preference for duplicateAllControlAndAltKeys has changed; reset the other two." - "At some point the various exclusive CtrlAlt-key prefs should become a radio button set, then these methods wouldn't be needed." - (Preferences - valueOfFlag: #swapControlAndAltKeys - ifAbsent: [false]) ifTrue: [ - self inform: 'Resetting swapControlAndAltKeys preference'. - (Preferences preferenceAt: #swapControlAndAltKeys) rawValue: false. - ]. - (Preferences - valueOfFlag: #duplicateControlAndAltKeys - ifAbsent: [false]) ifTrue: [ - self inform: 'Resetting duplicateControlAndAltKeys preference'. - (Preferences preferenceAt: #duplicateControlAndAltKeys) rawValue: false. - ]. - self installKeyDecodeTable. - ! Item was changed: ----- Method: EventSensor class>>duplicateControlAndAltKeys: (in category 'public') ----- duplicateControlAndAltKeys: aBoolean "EventSensor duplicateControlAndAltKeys: true" + self flag: #deprecated. + self + mapControlKeysToCommandKeys: aBoolean; + mapAltKeysToOptionKeys: false.! - Preferences setPreference: #duplicateControlAndAltKeys toValue: aBoolean. - self installKeyDecodeTable - ! Item was removed: - ----- Method: EventSensor class>>duplicateControlAndAltKeysChanged (in category 'preference change notification') ----- - duplicateControlAndAltKeysChanged - "The Preference for duplicateControlAndAltKeys has changed; reset the other two." - (Preferences - valueOfFlag: #swapControlAndAltKeys - ifAbsent: [false]) ifTrue: [ - self inform: 'Resetting swapControlAndAltKeys preference'. - (Preferences preferenceAt: #swapControlAndAltKeys) rawValue: false. - ]. - (Preferences - valueOfFlag: #duplicateAllControlAndAltKeys - ifAbsent: [false]) ifTrue: [ - self inform: 'Resetting duplicateAllControlAndAltKeys preference'. - (Preferences preferenceAt: #duplicateAllControlAndAltKeys) rawValue: false. - ]. - self installKeyDecodeTable. - ! Item was added: + ----- Method: EventSensor class>>fixControlCharacters (in category 'key decode table') ----- + fixControlCharacters + "Assure that all keyboard events that arrive with the CONTROL modifier actually have control characters set." + + 64 "$@" to: 95 "$_"do: [:upper | + KeyDecodeTable + at: { upper . 2 bitOr: 1 "ctrl+shift" } + put: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" }]. + 96 "$`" to: 126 "$~" do: [:lower | "Ignore 127" + KeyDecodeTable + at: { lower . 2 "ctrl" } + put: { lower bitAnd: 16r9F . 2 "ctrl" }]. + + self flag: #linuxOnly. "mt: For Linux VMs as of version 201911282316, no control characters will be sent from the VM. Avoid check for #platformName because the extra mapping will not affect others anyway." + self flag: #windowsOnly. "mt: CTRL+m would not arrive as CTRL+CR, which is rather inconsistent."! Item was changed: ----- Method: EventSensor class>>initialize (in category 'class initialization') ----- initialize + - Smalltalk addToStartUpList: self before: ProcessorScheduler. Smalltalk addToShutDownList: self. + KeyDecodePreferences := Dictionary new. + self installKeyDecodeTable. + self installMouseDecodeTable.! - self installMouseDecodeTable. - self install. - - ! Item was removed: - ----- Method: EventSensor class>>installDuplicateKeyEntryFor: (in category 'key decode table') ----- - installDuplicateKeyEntryFor: aPrintableCharacter - "Updates the key-decode table, which maps between pairs of {character code . modifier code}. - See the class comment for more information. - The purpose of this change is to let ctrl+key act like cmd+key (Mac) or alt+key (linux/windows). - It is especially usefull on windows VM where default feel is to use ctrl as shortcut (ctrl+C = copy, etc...). - Note that the bitmask 16r9F removes the high bits, which subtracts 64 from the key code for (upper) $A to $Z and 96 for (lower) $a to $z. The VM sends non-printable control characters for [ctrl]+[A-Za-Z] in ASCII < 32, but the given character is expected to be ASCII >= 32 and thus printable. So we have to convert control characters to printable characters in this mapping table." - - | upper lower | - upper := aPrintableCharacter asUppercase asInteger. - lower := aPrintableCharacter asLowercase asInteger. - - KeyDecodeTable at: { lower bitAnd: 16r9F . 2 "ctrl" } put: { lower . 8 "cmd/alt" }. - KeyDecodeTable at: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl + shift" } put: { upper . 8 bitOr: 1 "cmd/alt + shift" }.! Item was changed: ----- Method: EventSensor class>>installKeyDecodeTable (in category 'class initialization') ----- installKeyDecodeTable "Create a decode table that swaps or duplicates some keys if the respective preference is set." KeyDecodeTable := Dictionary new. + self mapControlKeysToCommandKeys + ifTrue: [self installMappingToCommandKeys] + ifFalse: [self mapControlCharactersToPrintableCharacters + ifTrue: [self installMappingToPrintableCharacters] + ifFalse: [self fixControlCharacters "mt: Due to platform-specific VM behavior."]]. - Preferences swapControlAndAltKeys - ifTrue: [ (Character allByteCharacters select: [:ea | ea isAlphaNumeric]) do: - [ :c | self installSwappedKeyEntryFor: c ] ]. - Preferences duplicateAllControlAndAltKeys - ifTrue: [ (Character allByteCharacters select: [:ea | ea isAlphaNumeric]) do: - [ :c | self installDuplicateKeyEntryFor: c ] ]. + self mapAltKeysToOptionKeys + ifTrue: [self installMappingToOptionKeys].! - self flag: #toDeprecate. "mt: This mapping should be deprecated in the future." - Preferences duplicateControlAndAltKeys - ifTrue: [ self defaultCrossPlatformKeys do: - [ :c | self installDuplicateKeyEntryFor: c ] ]. - ! Item was added: + ----- Method: EventSensor class>>installMappingToCommandKeys (in category 'key decode table') ----- + installMappingToCommandKeys + "Maps all keyboard events that arrive with the CONTROL modifier to also have the COMMAND modifier set. This mapping also considers the preference #mapControlCharactersToPrintableCharacters." + + | controlMask | + 0 "NUL" to: 27 "ESC" do: [:control | + controlMask := self mapControlCharactersToPrintableCharacters + ifTrue: [16r60] ifFalse: [0]. + KeyDecodeTable + at: { control . 2r0010 "ctrl" } + put: { control bitOr: controlMask . 2r1010 "cmd+ctrl" }. + controlMask := self mapControlCharactersToPrintableCharacters + ifTrue: [16r40] ifFalse: [0]. + KeyDecodeTable + at: { control . 2r0011 "ctrl+shift" } + put: { control bitOr: controlMask . 2r1011 "cmd+ctrl+shift" }]. + + 28 "arrow keys" to: 126 "$~" do: [:arrowAndPrintable | + KeyDecodeTable + at: { arrowAndPrintable . 2r0010 "ctrl" } + put: { arrowAndPrintable . 2r1010 "cmd+ctrl" }. + KeyDecodeTable + at: { arrowAndPrintable . 2r0011 "ctrl + shift" } + put: { arrowAndPrintable . 2r1011 "cmd + shift" }].! Item was added: + ----- Method: EventSensor class>>installMappingToOptionKeys (in category 'key decode table') ----- + installMappingToOptionKeys + "Maps all keyboard events that arrive with the COMMAND modifier to also have the OPTION modifier set. See preference #mapAltKeysToOptionKeys." + + self flag: #windowsOnly. "mt: In Windows VMs version 202104182333, pressing the (physical) ALT key arrives as CMD modifier in the image. Should this ever change, this mapping MUST be adapted, too." + self flag: #linuxOnly. "mt: See #windowsOnly." + self flag: #macOSOnly. "mt: This mapping should be ignored to not overshadow events that have the actual OPTION modifier set." + + CharacterSet ascii do: [:character | + KeyDecodeTable + at: { character asInteger . 2r1000 "cmd" } + put: { character asInteger . 2r1100 "cmd+opt" }. + KeyDecodeTable + at: { character asInteger . 2r1001 "cmd + shift" } + put: { character asInteger . 2r1101 "cmd + opt + shift" }].! Item was added: + ----- Method: EventSensor class>>installMappingToPrintableCharacters (in category 'key decode table') ----- + installMappingToPrintableCharacters + "Only applies when the CONTROL modifier is present!! Control characters that can directly be triggered -- such as CR, ENTER, BS, DEL, POS1, END -- will not be mapped." + + self flag: #windowsOnly. "mt: The CONTROL modifier might directly change the control character. Examples: CTRL+CR(13) arrives as CTRL+LF(10), CTRL+BS(8) arrives as CTRL+DEL(127). If you have no other means to input LF(10) or DEL(127), you might have to disable this mapping to printable characters." + + 0 "NUL" to: 27 "ESC" do: [:control | + KeyDecodeTable + at: { control . 2r0010 "ctrl" } + put: { control bitOr: 16r60 "+96" . 2 "ctrl" }. + KeyDecodeTable + at: { control . 2r0011 "ctrl+shift" } + put: { control bitOr: 16r40 "+64" . 2r0011 "ctrl+shift" }].! Item was removed: - ----- Method: EventSensor class>>installSwappedKeyEntryFor: (in category 'key decode table') ----- - installSwappedKeyEntryFor: aPrintableCharacter - "Updates the key-decode table, which maps between pairs of {character code . modifier code}. See the class comment for more information. - Note that the bitmask 16r9F removes the high bits, which subtracts 64 from the key code for (upper) $A to $Z and 96 for (lower) $a to $z. The VM sends non-printable control characters for [ctrl]+[A-Za-Z] in ASCII < 32, but the given character is expected to be ASCII >= 32 and thus printable. So we have to convert printable characters to control characters in this mapping table." - - | upper lower | - upper := aPrintableCharacter asUppercase asInteger. - lower := aPrintableCharacter asLowercase asInteger. - - KeyDecodeTable at: { lower bitAnd: 16r9F . 2 "ctrl" } put: { lower . 8 "cmd/alt" }. - KeyDecodeTable at: { lower . 8 "cmd/alt" } put: { lower bitAnd: 16r9F . 2 "ctrl" }. - KeyDecodeTable at: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" } put: { upper . 8 bitOr: 1 "cmd/alt+shift" }. - KeyDecodeTable at: { upper . 8 bitOr: 1 "cmd/alt+shift" } put: { upper bitAnd: 16r9F . 2 bitOr: 1 "ctrl+shift" }.! Item was added: + ----- Method: EventSensor class>>mapAltKeysToOptionKeys (in category 'preferences') ----- + mapAltKeysToOptionKeys + + + ^ KeyDecodePreferences + at: #mapAltKeysToOptionKeys + ifAbsent: [false]! Item was added: + ----- Method: EventSensor class>>mapAltKeysToOptionKeys: (in category 'preferences') ----- + mapAltKeysToOptionKeys: aBooleanOrNil + + aBooleanOrNil = self mapAltKeysToOptionKeys + ifTrue: [^ self]. + + aBooleanOrNil + ifNil: [ + KeyDecodePreferences + removeKey: #mapAltKeysToOptionKeys] + ifNotNil: [ + KeyDecodePreferences + at: #mapAltKeysToOptionKeys + put: aBooleanOrNil]. + + self installKeyDecodeTable.! Item was added: + ----- Method: EventSensor class>>mapControlCharactersToPrintableCharacters (in category 'preferences') ----- + mapControlCharactersToPrintableCharacters + + + ^ KeyDecodePreferences + at: #mapControlCharactersToPrintableCharacters + ifAbsent: [true]! Item was added: + ----- Method: EventSensor class>>mapControlCharactersToPrintableCharacters: (in category 'preferences') ----- + mapControlCharactersToPrintableCharacters: aBooleanOrNil + + aBooleanOrNil + ifNil: [ + KeyDecodePreferences + removeKey: #mapControlCharactersToPrintableCharacters] + ifNotNil: [ + KeyDecodePreferences + at: #mapControlCharactersToPrintableCharacters + put: aBooleanOrNil]. + + self installKeyDecodeTable.! Item was added: + ----- Method: EventSensor class>>mapControlKeysToCommandKeys (in category 'preferences') ----- + mapControlKeysToCommandKeys + + + ^ KeyDecodePreferences + at: #mapControlKeysToCommandKeys + ifAbsent: [true]! Item was added: + ----- Method: EventSensor class>>mapControlKeysToCommandKeys: (in category 'preferences') ----- + mapControlKeysToCommandKeys: aBooleanOrNil + + aBooleanOrNil + ifNil: [ + KeyDecodePreferences + removeKey: #mapControlKeysToCommandKeys] + ifNotNil: [ + KeyDecodePreferences + at: #mapControlKeysToCommandKeys + put: aBooleanOrNil]. + + self installKeyDecodeTable.! Item was changed: ----- Method: EventSensor class>>startUp (in category 'system startup') ----- startUp + Smalltalk platformName = 'Mac OS' + ifTrue: [ + self mapAltKeysToOptionKeys: false. + self mapControlKeysToCommandKeys: false] + ifFalse: [ + self mapAltKeysToOptionKeys: true. + self mapControlKeysToCommandKeys: true]. + + self default startUp.! - self installMouseDecodeTable. - self installKeyDecodeTable. - self default startUp! Item was changed: ----- Method: EventSensor class>>swapControlAndAltKeys: (in category 'public') ----- swapControlAndAltKeys: aBoolean - "EventSensor swapControlAndAltKeys: true" + self deprecated: 'You cannnot swap CONTROL and ALT modifiers anymore. Please use other key-mapping preferences to fit your needs.'.! - Preferences setPreference: #swapControlAndAltKeys toValue: aBoolean. - self installKeyDecodeTable! Item was removed: - ----- Method: EventSensor class>>swapControlAndAltKeysChanged (in category 'preference change notification') ----- - swapControlAndAltKeysChanged - "The Preference for swapControlAndAltKeys has changed; reset the other two." - (Preferences - valueOfFlag: #duplicateControlAndAltKeys - ifAbsent: [false]) ifTrue: [ - self inform: 'Resetting duplicateControlAndAltKeys preference'. - (Preferences preferenceAt: #duplicateControlAndAltKeys) rawValue: false. - ]. - (Preferences - valueOfFlag: #duplicateAllControlAndAltKeys - ifAbsent: [false]) ifTrue: [ - self inform: 'Resetting duplicateAllControlAndAltKeys preference'. - (Preferences preferenceAt: #duplicateAllControlAndAltKeys) rawValue: false. - ]. - self installKeyDecodeTable. - ! Item was changed: ----- Method: EventSensor>>anyModifierKeyPressed (in category 'modifier keys') ----- anyModifierKeyPressed + "ignore, however, the shift keys 'cause that's not REALLY a modifier key" - "ignore, however, the shift keys 'cause that's not REALLY a command key" + ^ self peekButtons anyMask: (2r1110 "cmd | opt | ctrl" bitShift: MouseEvent numButtons)! - ^ self peekButtons anyMask: 16r70 "cmd | opt | ctrl"! Item was changed: ----- Method: EventSensor>>commandKeyPressed (in category 'modifier keys') ----- commandKeyPressed "Answer whether the command key on the keyboard is being held down." + ^ self peekButtons anyMask: (2r1000 "cmd" bitShift: MouseEvent numButtons)! - ^ self peekButtons anyMask: (1 bitShift: MouseEvent numButtons + 3)! Item was changed: ----- Method: EventSensor>>controlKeyPressed (in category 'modifier keys') ----- controlKeyPressed "Answer whether the control key on the keyboard is being held down." + ^ self peekButtons anyMask: (2r0010 "ctrl" bitShift: MouseEvent numButtons)! - ^self peekButtons anyMask: (1 bitShift: MouseEvent numButtons + 1)! Item was added: + ----- Method: EventSensor>>optionKeyPressed (in category 'modifier keys') ----- + optionKeyPressed + "Answer whether the option key on the Macintosh keyboard is being held down. Macintosh specific. Clients are discouraged from calling this directly, since it circumvents bert's attempt to eradicate option-key checks" + + ^ self peekButtons anyMask: (2r0100 "opt" bitShift: MouseEvent numButtons)! Item was changed: ----- Method: EventSensor>>processEvent: (in category 'private-I/O') ----- processEvent: evt "Process a single event. This method is run at high priority." | type buttons window | type := evt at: 1. lastEventTime := evt at: 2. "Only process main window events, forward others to host window proxies" window := evt at: 8. (window isNil or: [window isZero]) ifTrue: [window := 1. evt at: 8 put: window]. window = 1 ifFalse: [ ^Smalltalk at: #HostWindowProxy ifPresent: [:w | w processEvent: evt]]. "Tackle mouse events and mouse wheel events first" (type = EventTypeMouse or: [type = EventTypeMouseWheel]) ifTrue: [buttons := (ButtonDecodeTable at: (evt at: 5) + 1). evt at: 5 put: (Smalltalk platformName = 'Mac OS' ifTrue: [ buttons ] ifFalse: [ self mapButtons: buttons modifiers: (evt at: 6) ]). self queueEvent: evt. type = EventTypeMouseWheel ifTrue: [^ self processMouseWheelEvent: evt]. type = EventTypeMouse ifTrue: [^ self processMouseEvent: evt]]. "Store the event in the queue if there's any" type = EventTypeKeyboard ifTrue: [ "Check if the event is a user interrupt" ((evt at: 4) = EventKeyChar and: [((evt at: 3) bitOr: (((evt at: 5) bitAnd: 8) bitShift: 8)) = interruptKey]) ifTrue: ["interrupt key is meta - not reported as event" ^ interruptSemaphore signal]. + "Decode keys for characters (e.g., map ctrl -> cmd)." - "Decode keys for characters (i.e., duplicate or swap, ctrl <-> alt/cmd)." (evt at: 4) = EventKeyChar ifTrue: [ | unicode ascii | "Copy lookup key first in case of key swap." unicode := {evt at: 6. evt at: 5}. ascii := {evt at: 3. evt at: 5}. KeyDecodeTable "Unicode character first" at: unicode ifPresent: [:a | evt at: 6 put: a first; at: 5 put: a second]. KeyDecodeTable "ASCII character second" at: ascii ifPresent: [:a | evt at: 3 put: a first; at: 5 put: a second]]. self queueEvent: evt. self processKeyboardEvent: evt . ^self ]. "Handle all events other than Keyboard or Mouse." self queueEvent: evt. ! Item was changed: ----- Method: EventSensor>>rawMacOptionKeyPressed (in category 'modifier keys') ----- rawMacOptionKeyPressed "Answer whether the option key on the Macintosh keyboard is being held down. Macintosh specific. Clients are discouraged from calling this directly, since it circumvents bert's attempt to eradicate option-key checks" + self deprecated: 'Use #optionKeyPressed instead.'. + ^ self optionKeyPressed! - ^ self peekButtons anyMask: 32! Item was changed: ----- Method: EventSensor>>shiftPressed (in category 'modifier keys') ----- shiftPressed "Answer whether the shift key on the keyboard is being held down." + ^ self peekButtons anyMask: (2r0001 "shift" bitShift: MouseEvent numButtons)! - ^ self peekButtons anyMask: (1 bitShift: MouseEvent numButtons)! Item was changed: + (PackageInfo named: 'Kernel') postscript: 'EventSensor initialize. + EventSensor startUp.'! - (PackageInfo named: 'Kernel') postscript: '"recompile all methods containing blocks with the wrong outerCode" - (self systemNavigation allMethodsSelect: [:m| m literals anySatisfy: [:l| l isCompiledCode and: [l isCompiledBlock and: [l outerCode ~~ m]]]]) do: - [:mr| mr actualClass recompile: mr selector]'! From commits at source.squeak.org Sun Apr 25 06:26:58 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 06:26:58 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1757.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1757.mcz ==================== Summary ==================== Name: Morphic-mt.1757 Author: mt Time: 25 April 2021, 8:26:52.104934 am UUID: 433d3730-4e0c-7e42-a021-a53d5b4092c8 Ancestors: Morphic-mt.1756 Complements Kernel-mt.1391. Please read comment in #checkCommandKey. Also see http://forum.world.st/Please-try-it-out-Fixing-the-input-mapping-for-keystroke-events-td5129004.html =============== Diff against Morphic-mt.1756 =============== Item was changed: SystemOrganization addCategory: #'Morphic-Balloon'! SystemOrganization addCategory: #'Morphic-Basic'! SystemOrganization addCategory: #'Morphic-Basic-NewCurve'! SystemOrganization addCategory: #'Morphic-Borders'! SystemOrganization addCategory: #'Morphic-Collections-Arrayed'! SystemOrganization addCategory: #'Morphic-Demo'! SystemOrganization addCategory: #'Morphic-Events'! SystemOrganization addCategory: #'Morphic-Explorer'! SystemOrganization addCategory: #'Morphic-Kernel'! SystemOrganization addCategory: #'Morphic-Layouts'! SystemOrganization addCategory: #'Morphic-Menus'! SystemOrganization addCategory: #'Morphic-Menus-DockingBar'! SystemOrganization addCategory: #'Morphic-Pluggable Widgets'! SystemOrganization addCategory: #'Morphic-Sound-Synthesis'! SystemOrganization addCategory: #'Morphic-Support'! SystemOrganization addCategory: #'Morphic-Text Support'! SystemOrganization addCategory: #'Morphic-TrueType'! SystemOrganization addCategory: #'Morphic-Widgets'! SystemOrganization addCategory: #'Morphic-Windows'! SystemOrganization addCategory: #'Morphic-Worlds'! + SystemOrganization addCategory: #Morphic! Item was added: + ----- Method: KeyboardEvent>>asMorph (in category 'converting') ----- + asMorph + "Answers a graphical reprsentation for this keyboard event. Does not work for keyUp and keyDown because we do not have platform-specific mapping tables for the key codes." + + | box color hasModifiers | + box := Morph new + color: Color transparent; + layoutPolicy: TableLayout new; + listDirection: #leftToRight; + hResizing: #shrinkWrap; + vResizing: #shrinkWrap; + cellGap: 2; + yourself. + color := self userInterfaceTheme get: #textColor for: #PluggableButtonMorph. + + self labelsForPhysicalModifiers + do: [:modifier | + hasModifiers := true. + box addMorphBack: (ToolIcons keyboardButtonLabeled: modifier dyed: color) asMorph] + separatedBy: [ + box addMorphBack: (('+' asText addAttribute: (TextColor color: color); asMorph) lock)]. + + (self isKeystroke not + and: [self keyValue between: 16 and: 18] + and: [hasModifiers == true "some VMs are strange!!"]) + ifTrue: [ "keyUp and keyDown; just the raw modifier keys" + ^ box]. + + hasModifiers == true ifTrue: [ + box addMorphBack: (('+' asText addAttribute: (TextColor color: color); asMorph) lock)]. + + (self keyValue between: 28 and: 31) + ifTrue: [ "arrow keys" + box addMorphBack: (ToolIcons keyboardButtonLabeled: ( + ScrollBar + arrowOfDirection: (#(left right top bottom) at: self keyValue - 27) + size: Preferences standardButtonFont height + color: Color black) dyed: color) asMorph. + ^ box]. + + box addMorphBack: (ToolIcons keyboardButtonLabeled: self labelForPhysicalKey dyed: color) asMorph. + + ^ box! Item was added: + ----- Method: KeyboardEvent>>checkCommandKey (in category 'debugging') ----- + checkCommandKey + + self flag: #debuggingOnly. "mt: This check documents a trade-off for having platform-specific modifiers and writing cross-platform compatible applications. If you want to support all three modifiers (i.e. CTRL, CMD, OPT), be aware that + (1) you should first check for CTRL/OPT then CMD, because + (2) physical CTRL and ALT keys on Linux/Windows are mapped to the pairs CTRL+CMD and CMD+OPT respectively and thus overshadow some key bindings if checked in the wrong order -- and that's why + (3) you should effectively only use CTRL/CMD, OPT/CMD, or CTRL/OPT in an application on Linux/Windows. And communicate the physical keys being CTRL and ALT. + + Note that point (3) documents the best practice for handling keystroke (not keyUp or keyDown) events while maintaining cross-platform compatibility." + + ^ self commandKeyPressed + and: [self controlKeyPressed not + and: [self optionKeyPressed not]]! Item was added: + ----- Method: KeyboardEvent>>labelForPhysicalKey (in category 'printing') ----- + labelForPhysicalKey + + ^ (self keyValue <= 32 or: [self keyValue = 127]) + ifFalse: [ + self keyCharacter asUppercase asString] + ifTrue: [ + (self isKeystroke and: [self controlKeyPressed] and: [self keyValue < 28 "no arrows or space"]) + ifTrue: [ + "Most likely a physical key with a readable (uppercase) label. Be aware that this cannot cover the cases where the physical contro key was pressed together with the CTRL modifier." + (self keyValue bitOr: 16r40) asCharacter asString "+64"] + ifFalse: [ + self keyValue caseOf: { + [ 1 ] -> [ 'Home' translated ]. + [ 4 ] -> [ 'End' translated ]. + [ 5 ] -> [ 'Insert' translated ]. + [ 8 ] -> [ 'Backspace' translated ]. + [ 9 ] -> [ 'Tab' ]. + [ 10 ] -> [ 'LF' ]. + [ 11 ] -> [ 'PageUp' translated ]. + [ 12 ] -> [ 'PageDown' translated ]. + [ 13 ] -> [ 'Return' translated "CR" ]. + [ 16 ] -> [ 'Shift' translated "Windows only?!!" ]. + [ 17 ] -> [ 'Ctrl' translated "Windows only?!!" ]. + [ 18 ] -> [ 'Alt' "Windows only?!!" ]. + [ 27 ] -> [ 'Esc' ]. + [ 32 ] -> [ 'Space' translated ]. + [ 127 ] -> [ 'Del' translated ]. + } otherwise: [ + 'ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]]]! Item was added: + ----- Method: KeyboardEvent>>labelForPhysicalKeyDown (in category 'printing') ----- + labelForPhysicalKeyDown + "#keyDown and #keyUp -- needs platform-specific mapping for virtual key codes" + + ^ (self keyValue <= 32 or: [self keyValue = 127]) + ifFalse: [ + (self keyValue between: 65 and: 90) "Windows" + ifTrue: [self keyCharacter asUppercase asString] + ifFalse: ['ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]] + ifTrue: [ + self keyValue caseOf: { + [ 1 ] -> [ 'Home' translated ]. + [ 4 ] -> [ 'End' translated ]. + [ 5 ] -> [ 'Insert' translated ]. + [ 8 ] -> [ 'Backspace' translated ]. + [ 9 ] -> [ 'Tab' ]. + [ 10 ] -> [ 'LF' ]. + [ 11 ] -> [ 'PageUp' translated ]. + [ 12 ] -> [ 'PageDown' translated ]. + [ 13 ] -> [ 'Return' translated "CR" ]. + [ 16 ] -> [ 'Shift' translated "Windows only?!!" ]. + [ 17 ] -> [ 'Ctrl' translated "Windows only?!!" ]. + [ 18 ] -> [ 'Alt' "Windows only?!!" ]. + [ 27 ] -> [ 'Esc' ]. + [ 32 ] -> [ 'Space' translated ]. + [ 127 ] -> [ 'Del' translated ]. + } otherwise: [ + 'ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]]! Item was added: + ----- Method: KeyboardEvent>>labelForPhysicalKeyStroke (in category 'printing') ----- + labelForPhysicalKeyStroke + + ^ (self keyValue <= 32 or: [self keyValue = 127]) + ifFalse: [ + self keyCharacter asUppercase asString] + ifTrue: [ + (self controlKeyPressed and: [self keyValue < 28 "no arrows or space"]) + ifTrue: [ + "Most likely a physical key with a readable (uppercase) label. Be aware that this cannot cover the cases where the physical contro key was pressed together with the CTRL modifier." + (self keyValue bitOr: 16r40) asCharacter asString "+64"] + ifFalse: [ + self keyValue caseOf: { + [ 1 ] -> [ 'Home' translated ]. + [ 4 ] -> [ 'End' translated ]. + [ 5 ] -> [ 'Insert' translated ]. + [ 8 ] -> [ 'Backspace' translated ]. + [ 9 ] -> [ 'Tab' ]. + [ 10 ] -> [ 'LF' ]. + [ 11 ] -> [ 'PageUp' translated ]. + [ 12 ] -> [ 'PageDown' translated ]. + [ 13 ] -> [ 'Return' translated "CR" ]. + [ 16 ] -> [ 'Shift' translated "Windows only?!!" ]. + [ 17 ] -> [ 'Ctrl' translated "Windows only?!!" ]. + [ 18 ] -> [ 'Alt' "Windows only?!!" ]. + [ 27 ] -> [ 'Esc' ]. + [ 32 ] -> [ 'Space' translated ]. + [ 127 ] -> [ 'Del' translated ]. + } otherwise: [ + 'ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]]]! Item was added: + ----- Method: KeyboardEvent>>labelsForPhysicalModifiers (in category 'printing') ----- + labelsForPhysicalModifiers + "Help users understand the physical modifier keys that where involved in this event. Note that, due to historical reasons, the SHIFT modifier comes first on macOS but last on other platforms." + + | result | + result := OrderedCollection new. + + Smalltalk platformName = 'Mac OS' + ifTrue: [ + self shiftPressed ifTrue: [result add: 'Shift']. + self controlKeyPressed ifTrue: [result add: 'Ctrl']. + self optionKeyPressed ifTrue: [result add: 'Opt']. + self commandKeyPressed ifTrue: [result add: 'Cmd']] + ifFalse: [ "Linux/Windows" + self controlKeyPressed + ifTrue: [result add: 'Ctrl'] + ifFalse: [ + Smalltalk platformName = 'Win32' + ifTrue: [ + (self commandKeyPressed or: [self optionKeyPressed]) + ifTrue: [result add: 'Alt']] + ifFalse: ["Linux/ARM" + self commandKeyPressed + ifTrue: [result add: 'Alt'] + ifFalse: [self optionKeyPressed + ifTrue: [ + result add: 'Strg'. + result add: 'Alt']]]]. + self shiftPressed ifTrue: [result add: 'Shift']]. + ^ result! Item was changed: ----- Method: KeyboardEvent>>printKeyStringOn: (in category 'printing') ----- printKeyStringOn: aStream "Print a readable string representing the receiver on a given stream" | kc inBrackets firstBracket keyString | kc := self keyCharacter. inBrackets := false. firstBracket := [ inBrackets ifFalse: [ aStream nextPut: $<. inBrackets := true ]]. self controlKeyPressed ifTrue: [ firstBracket value. aStream nextPutAll: 'Ctrl-' ]. self commandKeyPressed ifTrue: [ firstBracket value. aStream nextPutAll: 'Cmd-' ]. + self optionKeyPressed ifTrue: [ firstBracket value. aStream nextPutAll: 'Opt-' ]. + self shiftPressed ifTrue: [ firstBracket value. aStream nextPutAll: 'Shift-' ]. - (buttons anyMask: 32) ifTrue: [ firstBracket value. aStream nextPutAll: 'Opt-' ]. - (self shiftPressed and: [ (keyValue between: 1 and: 31) or: [self keyCharacter = Character delete ]]) - ifTrue: [ firstBracket value. aStream nextPutAll: 'Shift-' ]. keyString := (kc caseOf: { [ Character space ] -> [ 'space' ]. [ Character tab ] -> [ 'tab' ]. [ Character cr ] -> [ 'cr' ]. [ Character lf ] -> [ 'lf' ]. [ Character enter ] -> [ 'enter' ]. [ Character backspace ] -> [ 'backspace' ]. [ Character delete ] -> [ 'delete' ]. [ Character escape ] -> [ 'escape' ]. [ Character arrowDown ] -> [ 'down' ]. [ Character arrowUp ] -> [ 'up' ]. [ Character arrowLeft ] -> [ 'left' ]. [ Character arrowRight ] -> [ 'right' ]. [ Character end ] -> [ 'end' ]. [ Character home ] -> [ 'home' ]. [ Character pageDown ] -> [ 'pageDown' ]. [ Character pageUp ] -> [ 'pageUp' ]. [ Character euro ] -> [ 'euro' ]. [ Character insert ] -> [ 'insert' ]. } otherwise: [ String with: kc ]). keyString size > 1 ifTrue: [ firstBracket value ]. aStream nextPutAll: keyString. inBrackets ifTrue: [aStream nextPut: $> ]! Item was changed: ----- Method: KeyboardEvent>>printOn: (in category 'printing') ----- printOn: aStream "Print the receiver on a stream" aStream nextPut: $[. aStream nextPutAll: self cursorPoint printString; space. aStream nextPutAll: type; space. self isKeystroke ifTrue: [ aStream nextPutAll: ''''. self printKeyStringOn: aStream. + aStream nextPut: $'; space. + aStream nextPutAll: '['. + self printPhysicalModifiersOn: aStream. + aStream nextPutAll: '] ']. - aStream nextPut: $'; space]. aStream nextPut: $(. aStream nextPutAll: keyValue printString. aStream nextPut: $); space. aStream nextPutAll: timeStamp printString. aStream nextPut: $]! Item was added: + ----- Method: KeyboardEvent>>printPhysicalModifiersOn: (in category 'printing') ----- + printPhysicalModifiersOn: aStream + "Help users understand the physical modifier keys that where involved in this event." + + self labelsForPhysicalModifiers + do: [:modifier | aStream nextPutAll: modifier] + separatedBy: [aStream nextPutAll: ' + '].! Item was added: + Morph subclass: #KeyboardExerciser + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'Morphic-Demo'! Item was added: + ----- Method: KeyboardExerciser class>>descriptionForPartsBin (in category 'parts bin') ----- + descriptionForPartsBin + "KeyboardExerciser descriptionForPartsBin" + ^ self partName: 'Exercise Keyboard' + categories: #('Demo') + documentation: 'An exerciser for key stroke, key down, and key up'! Item was added: + ----- Method: KeyboardExerciser>>checkButton: (in category 'initialization') ----- + checkButton: checkIndex + + 1 to: 3 do: [:index | + (self submorphs at: index) + state: #off]. + + (self submorphs at: checkIndex) state: #on.! Item was added: + ----- Method: KeyboardExerciser>>clear (in category 'initialization') ----- + clear + + (self submorphs allButFirst: 3) do: [:m | m delete].! Item was added: + ----- Method: KeyboardExerciser>>drawOn: (in category 'drawing') ----- + drawOn: aCanvas + + super drawOn: aCanvas. + + aCanvas + drawString: 'Move your mouse cursor to here and start typing. Try modifiers, too.' + at: self topLeft + font: Preferences standardButtonFont + color: Color gray.! Item was added: + ----- Method: KeyboardExerciser>>handleEvent:deemphasize: (in category 'actions') ----- + handleEvent: mouseEvent deemphasize: morph + + morph color: Color transparent.! Item was added: + ----- Method: KeyboardExerciser>>handleEvent:emphasize: (in category 'actions') ----- + handleEvent: mouseEvent emphasize: morph + + morph color: (self userInterfaceTheme get: #selectionColor for: #PluggableListMorph).! Item was added: + ----- Method: KeyboardExerciser>>handleEvent:inspect: (in category 'actions') ----- + handleEvent: mouseEvent inspect: morph + + mouseEvent shiftPressed + ifTrue: [(morph valueOfProperty: #event) explore] + ifFalse: [(morph valueOfProperty: #event) inspect].! Item was added: + ----- Method: KeyboardExerciser>>handlesKeyboard: (in category 'event handling') ----- + handlesKeyboard: evt + + ^ (self valueOfProperty: #eventCheck) value: evt! Item was added: + ----- Method: KeyboardExerciser>>handlesMouseOver: (in category 'event handling') ----- + handlesMouseOver: evt + + ^ true! Item was added: + ----- Method: KeyboardExerciser>>initialize (in category 'initialization') ----- + initialize + + super initialize. + + self + color: (self userInterfaceTheme get: #color for: #ScrollPane); + extent: 300 at 50; + layoutPolicy: TableLayout new; + listDirection: #leftToRight; + wrapDirection: #topToBottom; + hResizing: #rigid; + vResizing: #shrinkWrap; + cellGap: 10; + layoutInset: 20; + yourself. + + #(processKeyStroke 'Test key stroke' + processKeyDown 'Test key down' + processKeyUp 'Test key up') + groupsDo: [:selector :label | + self addMorphBack: (ThreePhaseButtonMorph checkBox + target: self; + actionSelector: selector; + label: label; + yourself)]. + + self processKeyStroke.! Item was added: + ----- Method: KeyboardExerciser>>keyDown: (in category 'event handling') ----- + keyDown: evt + + self logEvent: evt.! Item was added: + ----- Method: KeyboardExerciser>>keyStroke: (in category 'event handling') ----- + keyStroke: evt + + self logEvent: evt.! Item was added: + ----- Method: KeyboardExerciser>>keyUp: (in category 'event handling') ----- + keyUp: evt + + self logEvent: evt.! Item was added: + ----- Method: KeyboardExerciser>>logEvent: (in category 'event handling') ----- + logEvent: evt + + | eventMorph | + eventMorph := evt asMorph. + eventMorph + balloonText: 'Click to inspect. Shift+click to explore.\\' withCRs, evt printString; + setProperty: #event toValue: evt copy. + + eventMorph + on: #mouseEnter send: #handleEvent:emphasize: to: self; + on: #mouseLeave send: #handleEvent:deemphasize: to: self; + on: #mouseDown send: #handleEvent:inspect: to: self. + + self addMorphBack: eventMorph.! Item was added: + ----- Method: KeyboardExerciser>>mouseEnter: (in category 'event handling') ----- + mouseEnter: evt + + self comeToFront. + evt hand newKeyboardFocus: self.! Item was added: + ----- Method: KeyboardExerciser>>processKeyDown (in category 'initialization') ----- + processKeyDown + + self setProperty: #eventCheck toValue: [:evt | evt isKeyDown]. + self checkButton: 2. + self clear.! Item was added: + ----- Method: KeyboardExerciser>>processKeyStroke (in category 'initialization') ----- + processKeyStroke + + self setProperty: #eventCheck toValue: [:evt | evt isKeystroke]. + self checkButton: 1. + self clear.! Item was added: + ----- Method: KeyboardExerciser>>processKeyUp (in category 'initialization') ----- + processKeyUp + + self setProperty: #eventCheck toValue: [:evt | evt isKeyUp]. + self checkButton: 3. + self clear.! Item was changed: ----- Method: UserInputEvent>>anyModifierKeyPressed (in category 'modifier state') ----- anyModifierKeyPressed + "ignore, however, the shift keys 'cause that's not REALLY a modifier key " - "ignore, however, the shift keys 'cause that's not REALLY a command key " + ^ self buttons anyMask: (2r1110 "cmd | opt | ctrl" bitShift: MouseEvent numButtons)! - ^ self buttons anyMask: 16r70 "cmd | opt | ctrl"! Item was changed: ----- Method: UserInputEvent>>commandKeyPressed (in category 'modifier state') ----- commandKeyPressed "Answer true if the command key on the keyboard was being held down when this event occurred." + ^ self buttons anyMask: (2r1000 "cmd" bitShift: MouseEvent numButtons)! - ^buttons anyMask: (1 bitShift: MouseEvent numButtons + 3)! Item was changed: ----- Method: UserInputEvent>>controlKeyPressed (in category 'modifier state') ----- controlKeyPressed "Answer if the control key on the keyboard was being held down when this event occurred." + ^ self buttons anyMask: (2r0010 "ctrl" bitShift: MouseEvent numButtons)! - ^buttons anyMask: (1 bitShift: MouseEvent numButtons + 1)! Item was added: + ----- Method: UserInputEvent>>optionKeyPressed (in category 'modifier state') ----- + optionKeyPressed + "Answer if the option key on the keyboard was being held down when this event occurred." + + ^ self buttons anyMask: (2r0100 "opt" bitShift: MouseEvent numButtons)! Item was changed: ----- Method: UserInputEvent>>shiftPressed (in category 'modifier state') ----- shiftPressed "Answer true if the shift key on the keyboard was being held down when this event occurred." + ^ self buttons anyMask: (2r0001 "shift" bitShift: MouseEvent numButtons)! - ^buttons anyMask: (1 bitShift: MouseEvent numButtons) - ! From commits at source.squeak.org Sun Apr 25 06:27:59 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 06:27:59 0000 Subject: [squeak-dev] The Trunk: System-mt.1230.mcz Message-ID: Marcel Taeumel uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-mt.1230.mcz ==================== Summary ==================== Name: System-mt.1230 Author: mt Time: 25 April 2021, 8:27:53.818934 am UUID: 00bb7c06-0609-f241-a266-ee6916226487 Ancestors: System-mt.1229 Complements Kernel-mt.1391. Also see http://forum.world.st/Please-try-it-out-Fixing-the-input-mapping-for-keystroke-events-td5129004.html =============== Diff against System-mt.1229 =============== Item was removed: - ----- Method: Preferences class>>duplicateAllControlAndAltKeys (in category 'standard queries') ----- - duplicateAllControlAndAltKeys - ^ self - valueOfFlag: #duplicateAllControlAndAltKeys - ifAbsent: [ true ]! Item was removed: - ----- Method: Preferences class>>duplicateControlAndAltKeys (in category 'standard queries') ----- - duplicateControlAndAltKeys - ^ self - valueOfFlag: #duplicateControlAndAltKeys - ifAbsent: [ false ]! Item was removed: - ----- Method: Preferences class>>swapControlAndAltKeys (in category 'standard queries') ----- - swapControlAndAltKeys - ^ self - valueOfFlag: #swapControlAndAltKeys - ifAbsent: [ false ]! Item was changed: + (PackageInfo named: 'System') postscript: 'SystemNavigation initializeAuthors. + Preferences removePreference: #duplicateControlAndAltKeys. + Preferences removePreference: #duplicateAllControlAndAltKeys. + Preferences removePreference: #swapControlAndAltKeys.'! - (PackageInfo named: 'System') postscript: 'SystemNavigation initializeAuthors.......'! From commits at source.squeak.org Sun Apr 25 06:29:00 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 06:29:00 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1043.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1043.mcz ==================== Summary ==================== Name: Tools-mt.1043 Author: mt Time: 25 April 2021, 8:28:55.388934 am UUID: 9a01fd42-a193-4843-a890-68749b797e70 Ancestors: Tools-mt.1042 Complements Morphic-mt.1757 (and Kernel-mt.1391). =============== Diff against Tools-mt.1042 =============== Item was added: + ----- Method: ToolIcons class>>keyboardButtonLabeled: (in category 'buttons') ----- + keyboardButtonLabeled: stringOrForm + + ^ self keyboardButtonLabeled: stringOrForm dyed: Color black! Item was added: + ----- Method: ToolIcons class>>keyboardButtonLabeled:dyed: (in category 'buttons') ----- + keyboardButtonLabeled: anObject dyed: aColor + + | id form c width height elevation thickness font margins color label | + thickness := RealEstateAgent scaleFactor rounded. + + anObject isForm + ifTrue: [label := anObject] + ifFalse: [ + label := anObject asString. + id := (#button, label, thickness) asSymbol. + self icons at: id ifPresent: [:icon | + ^ aColor ~= Color black + ifTrue: [icon dyed: aColor] + ifFalse: [icon]]]. + + elevation := (thickness * 2.5) rounded. + font := Preferences standardButtonFont. + color := Color black. + + margins := (font widthOf: $x) @ (font height // 2). + width := label isForm ifTrue: [label width] ifFalse: [font widthOfString: label]. + height := label isForm ifTrue: [label height] ifFalse: [font height]. + + form := Form + extent: (width + (2* margins x)) @ (height + (2* margins y) + elevation) + depth: 32. + + c := form getCanvas. + c + frameRoundRect: (0 at 0 extent: form extent - (0 at elevation)) + radius: thickness * 5 + width: thickness + color: Color black. + + elevation > 0 ifTrue: [ + c + clipBy: (0@ (form height // 2) corner: form width @ form height) + during: [:c2 | + c2 + frameRoundRect: (0@ elevation extent: form extent - (0 at elevation)) + radius: thickness * 5 + width: thickness + color: Color black]]. + + label isForm + ifTrue: [ c paintImage: label at: margins x @ (margins y)] + ifFalse: [ + c + drawString: label + at: margins x @ (margins y) + font: font + color: color]. + + id ifNotNil: [self icons at: id put: form]. + + ^ aColor ~= Color black + ifTrue: [form dyed: aColor] + ifFalse: [form]! From commits at source.squeak.org Sun Apr 25 06:32:32 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 06:32:32 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1758.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1758.mcz ==================== Summary ==================== Name: Morphic-mt.1758 Author: mt Time: 25 April 2021, 8:32:26.219887 am UUID: 14abcbf1-dfe1-914c-b610-011859985aa8 Ancestors: Morphic-mt.1757 Removes two unused methods from previous commit. Sorry for the noise. =============== Diff against Morphic-mt.1757 =============== Item was removed: - ----- Method: KeyboardEvent>>labelForPhysicalKeyDown (in category 'printing') ----- - labelForPhysicalKeyDown - "#keyDown and #keyUp -- needs platform-specific mapping for virtual key codes" - - ^ (self keyValue <= 32 or: [self keyValue = 127]) - ifFalse: [ - (self keyValue between: 65 and: 90) "Windows" - ifTrue: [self keyCharacter asUppercase asString] - ifFalse: ['ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]] - ifTrue: [ - self keyValue caseOf: { - [ 1 ] -> [ 'Home' translated ]. - [ 4 ] -> [ 'End' translated ]. - [ 5 ] -> [ 'Insert' translated ]. - [ 8 ] -> [ 'Backspace' translated ]. - [ 9 ] -> [ 'Tab' ]. - [ 10 ] -> [ 'LF' ]. - [ 11 ] -> [ 'PageUp' translated ]. - [ 12 ] -> [ 'PageDown' translated ]. - [ 13 ] -> [ 'Return' translated "CR" ]. - [ 16 ] -> [ 'Shift' translated "Windows only?!!" ]. - [ 17 ] -> [ 'Ctrl' translated "Windows only?!!" ]. - [ 18 ] -> [ 'Alt' "Windows only?!!" ]. - [ 27 ] -> [ 'Esc' ]. - [ 32 ] -> [ 'Space' translated ]. - [ 127 ] -> [ 'Del' translated ]. - } otherwise: [ - 'ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]]! Item was removed: - ----- Method: KeyboardEvent>>labelForPhysicalKeyStroke (in category 'printing') ----- - labelForPhysicalKeyStroke - - ^ (self keyValue <= 32 or: [self keyValue = 127]) - ifFalse: [ - self keyCharacter asUppercase asString] - ifTrue: [ - (self controlKeyPressed and: [self keyValue < 28 "no arrows or space"]) - ifTrue: [ - "Most likely a physical key with a readable (uppercase) label. Be aware that this cannot cover the cases where the physical contro key was pressed together with the CTRL modifier." - (self keyValue bitOr: 16r40) asCharacter asString "+64"] - ifFalse: [ - self keyValue caseOf: { - [ 1 ] -> [ 'Home' translated ]. - [ 4 ] -> [ 'End' translated ]. - [ 5 ] -> [ 'Insert' translated ]. - [ 8 ] -> [ 'Backspace' translated ]. - [ 9 ] -> [ 'Tab' ]. - [ 10 ] -> [ 'LF' ]. - [ 11 ] -> [ 'PageUp' translated ]. - [ 12 ] -> [ 'PageDown' translated ]. - [ 13 ] -> [ 'Return' translated "CR" ]. - [ 16 ] -> [ 'Shift' translated "Windows only?!!" ]. - [ 17 ] -> [ 'Ctrl' translated "Windows only?!!" ]. - [ 18 ] -> [ 'Alt' "Windows only?!!" ]. - [ 27 ] -> [ 'Esc' ]. - [ 32 ] -> [ 'Space' translated ]. - [ 127 ] -> [ 'Del' translated ]. - } otherwise: [ - 'ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]]]! From commits at source.squeak.org Sun Apr 25 10:05:37 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 10:05:37 0000 Subject: [squeak-dev] The Trunk: Kernel-mt.1392.mcz Message-ID: Marcel Taeumel uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-mt.1392.mcz ==================== Summary ==================== Name: Kernel-mt.1392 Author: mt Time: 25 April 2021, 12:05:33.297546 pm UUID: 29af9533-b510-49d5-8bde-86666d35f486 Ancestors: Kernel-mt.1391 Small fix. On Linux, uses non-printable control characters when "map CTRL to CMD" is enabled but "map non-printable to printable" is disabled. Due to limitations of physical modifier keys across platforms, this is not super important but it is nice to get consistent event data across platforms. I suppose that checking for non-printable control characters in keyboard handlers should be avoided to ensure cross-platform compatibility. See commentary in KeyboardEvent >> #checkCommandKey for more information. =============== Diff against Kernel-mt.1391 =============== Item was changed: ----- Method: EventSensor class>>installMappingToCommandKeys (in category 'key decode table') ----- installMappingToCommandKeys "Maps all keyboard events that arrive with the CONTROL modifier to also have the COMMAND modifier set. This mapping also considers the preference #mapControlCharactersToPrintableCharacters." | controlMask | 0 "NUL" to: 27 "ESC" do: [:control | controlMask := self mapControlCharactersToPrintableCharacters ifTrue: [16r60] ifFalse: [0]. KeyDecodeTable at: { control . 2r0010 "ctrl" } put: { control bitOr: controlMask . 2r1010 "cmd+ctrl" }. controlMask := self mapControlCharactersToPrintableCharacters ifTrue: [16r40] ifFalse: [0]. KeyDecodeTable at: { control . 2r0011 "ctrl+shift" } + put: { control bitOr: controlMask . 2r1011 "cmd+ctrl+shift" }]. - put: { control bitOr: controlMask . 2r1011 "cmd+ctrl+shift" }]. 28 "arrow keys" to: 126 "$~" do: [:arrowAndPrintable | KeyDecodeTable at: { arrowAndPrintable . 2r0010 "ctrl" } put: { arrowAndPrintable . 2r1010 "cmd+ctrl" }. KeyDecodeTable + at: { arrowAndPrintable . 2r0011 "ctrl+shift" } + put: { arrowAndPrintable . 2r1011 "cmd+ctrl+shift" }]. + + self mapControlCharactersToPrintableCharacters ifFalse: [ + "See #fixControlCharacters. #linuxOnly" + 64 "$@" to: 95 "$_"do: [:upper | + KeyDecodeTable + at: { upper . 2r0011 "ctrl+shift" } + put: { upper bitAnd: 16r9F . 2r1011 "cmd+ctrl+shift" }]. + 96 "$`" to: 126 "$~" do: [:lower | "Ignore 127" + KeyDecodeTable + at: { lower . 2r0010 "ctrl" } + put: { lower bitAnd: 16r9F . 2r1010 "cmd+ctrl" }]].! - at: { arrowAndPrintable . 2r0011 "ctrl + shift" } - put: { arrowAndPrintable . 2r1011 "cmd + shift" }].! From commits at source.squeak.org Sun Apr 25 13:42:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 13:42:26 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1759.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1759.mcz ==================== Summary ==================== Name: Morphic-mt.1759 Author: mt Time: 25 April 2021, 3:42:18.642592 pm UUID: 456105c7-734e-db41-8488-8d64c1c096e1 Ancestors: Morphic-mt.1758 Until we have a proper cross-platform mapping between virtual key codes to symbols (or characters), let the keyboard exerciser not deceive the user with a broken ad-hoc mapping. Just show the raw key code. This conforms to how a keyboard event's #printString looks like at the moment; it only shows key characters for keyStroke events, not keyUp or keyDown. Note that, on some platforms, the keyDown for, e.g., CTRL will also raise the fitting modifier. Sometimes even more than that. Take a look at keyDown for SHIFT on Linux/X11. =============== Diff against Morphic-mt.1758 =============== Item was changed: ----- Method: KeyboardEvent>>asMorph (in category 'converting') ----- asMorph "Answers a graphical reprsentation for this keyboard event. Does not work for keyUp and keyDown because we do not have platform-specific mapping tables for the key codes." + | box color | - | box color hasModifiers | box := Morph new color: Color transparent; layoutPolicy: TableLayout new; listDirection: #leftToRight; hResizing: #shrinkWrap; vResizing: #shrinkWrap; cellGap: 2; yourself. color := self userInterfaceTheme get: #textColor for: #PluggableButtonMorph. self labelsForPhysicalModifiers do: [:modifier | + box addMorphBack: (ToolIcons keyboardButtonLabeled: modifier dyed: color) asMorph. - hasModifiers := true. - box addMorphBack: (ToolIcons keyboardButtonLabeled: modifier dyed: color) asMorph] - separatedBy: [ box addMorphBack: (('+' asText addAttribute: (TextColor color: color); asMorph) lock)]. + - - (self isKeystroke not - and: [self keyValue between: 16 and: 18] - and: [hasModifiers == true "some VMs are strange!!"]) - ifTrue: [ "keyUp and keyDown; just the raw modifier keys" - ^ box]. - - hasModifiers == true ifTrue: [ - box addMorphBack: (('+' asText addAttribute: (TextColor color: color); asMorph) lock)]. - (self keyValue between: 28 and: 31) ifTrue: [ "arrow keys" box addMorphBack: (ToolIcons keyboardButtonLabeled: ( ScrollBar arrowOfDirection: (#(left right top bottom) at: self keyValue - 27) size: Preferences standardButtonFont height color: Color black) dyed: color) asMorph. ^ box]. + box addMorphBack: (ToolIcons + keyboardButtonLabeled: (self isKeystroke + ifTrue: [self labelForPhysicalKeyStroke] + ifFalse: [self labelForPhysicalKeyDown]) + dyed: color) asMorph. - box addMorphBack: (ToolIcons keyboardButtonLabeled: self labelForPhysicalKey dyed: color) asMorph. ^ box! Item was removed: - ----- Method: KeyboardEvent>>labelForPhysicalKey (in category 'printing') ----- - labelForPhysicalKey - - ^ (self keyValue <= 32 or: [self keyValue = 127]) - ifFalse: [ - self keyCharacter asUppercase asString] - ifTrue: [ - (self isKeystroke and: [self controlKeyPressed] and: [self keyValue < 28 "no arrows or space"]) - ifTrue: [ - "Most likely a physical key with a readable (uppercase) label. Be aware that this cannot cover the cases where the physical contro key was pressed together with the CTRL modifier." - (self keyValue bitOr: 16r40) asCharacter asString "+64"] - ifFalse: [ - self keyValue caseOf: { - [ 1 ] -> [ 'Home' translated ]. - [ 4 ] -> [ 'End' translated ]. - [ 5 ] -> [ 'Insert' translated ]. - [ 8 ] -> [ 'Backspace' translated ]. - [ 9 ] -> [ 'Tab' ]. - [ 10 ] -> [ 'LF' ]. - [ 11 ] -> [ 'PageUp' translated ]. - [ 12 ] -> [ 'PageDown' translated ]. - [ 13 ] -> [ 'Return' translated "CR" ]. - [ 16 ] -> [ 'Shift' translated "Windows only?!!" ]. - [ 17 ] -> [ 'Ctrl' translated "Windows only?!!" ]. - [ 18 ] -> [ 'Alt' "Windows only?!!" ]. - [ 27 ] -> [ 'Esc' ]. - [ 32 ] -> [ 'Space' translated ]. - [ 127 ] -> [ 'Del' translated ]. - } otherwise: [ - 'ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]]]! Item was added: + ----- Method: KeyboardEvent>>labelForPhysicalKeyDown (in category 'printing') ----- + labelForPhysicalKeyDown + "#keyDown and #keyUp -- needs platform-specific mapping for virtual key codes" + + ^ 'VK-0x', (self keyValue printPaddedWith: $0 to: 2 base: 16)! Item was added: + ----- Method: KeyboardEvent>>labelForPhysicalKeyStroke (in category 'printing') ----- + labelForPhysicalKeyStroke + + ^ (self keyValue <= 32 or: [self keyValue = 127]) + ifFalse: [ + self keyCharacter asUppercase asString] + ifTrue: [ + (self controlKeyPressed and: [self keyValue < 28 "no arrows or space"]) + ifTrue: [ + "Most likely a physical key with a readable (uppercase) label. Be aware that this cannot cover the cases where the physical contro key was pressed together with the CTRL modifier." + (self keyValue bitOr: 16r40) asCharacter asString "+64"] + ifFalse: [ + self keyValue caseOf: { + [ 1 ] -> [ 'Home' translated ]. + [ 4 ] -> [ 'End' translated ]. + [ 5 ] -> [ 'Insert' translated ]. + [ 8 ] -> [ 'Backspace' translated ]. + [ 9 ] -> [ 'Tab' ]. + [ 10 ] -> [ 'LF' ]. + [ 11 ] -> [ 'PageUp' translated ]. + [ 12 ] -> [ 'PageDown' translated ]. + [ 13 ] -> [ 'Return' translated "CR" ]. + [ 27 ] -> [ 'Esc' ]. + [ 32 ] -> [ 'Space' translated ]. + [ 127 ] -> [ 'Del' translated ]. + } otherwise: [ + 'ASCII-', (self keyValue printPaddedWith: $0 to: 2 base: 10)]]]! Item was changed: ----- Method: KeyboardExerciser>>logEvent: (in category 'event handling') ----- logEvent: evt | eventMorph | eventMorph := evt asMorph. eventMorph + setProperty: #event toValue: evt copy; + balloonText: ('Click to inspect. Shift+click to explore.\\Key value: 0x{1} ({2}) \Key character: {3}\Virtual modifiers: {4}\Physical modifiers: {5}\\{6}' withCRs format: { + evt keyValue printPaddedWith: $0 to: 2 base: 16. + evt keyValue. + evt isKeystroke ifTrue: [evt keyCharacter printString] ifFalse: ['-']. + evt modifierString. + (evt labelsForPhysicalModifiers joinSeparatedBy: ' ') asUppercase. + evt printString}). + - balloonText: 'Click to inspect. Shift+click to explore.\\' withCRs, evt printString; - setProperty: #event toValue: evt copy. - eventMorph on: #mouseEnter send: #handleEvent:emphasize: to: self; on: #mouseLeave send: #handleEvent:deemphasize: to: self; on: #mouseDown send: #handleEvent:inspect: to: self. self addMorphBack: eventMorph.! Item was changed: ----- Method: UserInputEvent>>modifierString (in category 'printing') ----- modifierString "Return a string identifying the currently pressed modifiers" | string | string := ''. + self controlKeyPressed ifTrue:[string := string,'CTRL ']. + self optionKeyPressed ifTrue:[string := string,'OPT ']. self commandKeyPressed ifTrue:[string := string,'CMD ']. self shiftPressed ifTrue:[string := string,'SHIFT ']. - self controlKeyPressed ifTrue:[string := string,'CTRL ']. ^string! From commits at source.squeak.org Sun Apr 25 14:24:08 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 14:24:08 0000 Subject: [squeak-dev] The Trunk: Kernel-bp.1393.mcz Message-ID: Bernhard Pieber uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-bp.1393.mcz ==================== Summary ==================== Name: Kernel-bp.1393 Author: bp Time: 25 April 2021, 4:16:12.156698 pm UUID: 6ff1afed-6782-42ad-a968-4c98da9d2c2b Ancestors: Kernel-mt.1392 Add missing Object>>#isScaledDecimal which is already implemented in the subclass ScaledDecimal. =============== Diff against Kernel-mt.1392 =============== Item was added: + ----- Method: Object>>isScaledDecimal (in category 'testing') ----- + isScaledDecimal + ^false! From marcel.taeumel at hpi.de Sun Apr 25 14:27:02 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Sun, 25 Apr 2021 16:27:02 +0200 Subject: [squeak-dev] The Trunk: Kernel-bp.1393.mcz In-Reply-To: References: Message-ID: Hi Bernhard, nice catch! Thank you :-) Best, Marcel Am 25.04.2021 16:24:20 schrieb commits at source.squeak.org : Bernhard Pieber uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-bp.1393.mcz ==================== Summary ==================== Name: Kernel-bp.1393 Author: bp Time: 25 April 2021, 4:16:12.156698 pm UUID: 6ff1afed-6782-42ad-a968-4c98da9d2c2b Ancestors: Kernel-mt.1392 Add missing Object>>#isScaledDecimal which is already implemented in the subclass ScaledDecimal. =============== Diff against Kernel-mt.1392 =============== Item was added: + ----- Method: Object>>isScaledDecimal (in category 'testing') ----- + isScaledDecimal + ^false! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Sun Apr 25 15:31:07 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 15:31:07 0000 Subject: [squeak-dev] The Inbox: Tests-jr.456.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-jr.456.mcz ==================== Summary ==================== Name: Tests-jr.456 Author: jr Time: 25 April 2021, 5:31:14.946128 pm UUID: 2bc77074-a400-4842-b306-6b1cff37aaba Ancestors: Tests-nice.455 Test case for precise handler reactivation when nested exceptions are signalled. At the moment of writing this, this is broken in Squeak Trunk and the test case would run endlessly if there were no timeout. The reason is that the inner error handler is reactivated when the signal emitted by it is resumed. Related versions: - Kernel-nice.1384 - Kernel-nice.1391 - ToolBuilder-Kernel-nice.141 - Kernel-nice.142 =============== Diff against Tests-nice.455 =============== Item was added: + ----- Method: ExceptionTests>>testHandlersReactivatedOnResume (in category 'tests - outer') ----- + testHandlersReactivatedOnResume + + | result | + result := [ + [ + [self error: 'to be handled by the inner handler'] + on: Error do: + [:e | + Warning signal: 'to be resumed by the middle handler'. + "After resuming from the Warning, its handler must be active again." + Warning signal: 'to be resumed by the middle handler'. + self error: 'to be handled by the outer handler'. + e return: 'inner result']] + on: Warning do: + [:e | e resume "This must not rearm the inner Error handler above"]] + on: Error do: + [:e | e return: 'outer result']. + self assert: 'outer result' equals: result.! From jakres+squeak at gmail.com Sun Apr 25 15:33:58 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 17:33:58 +0200 Subject: [squeak-dev] The Inbox: Kernel-nice.1391.mcz In-Reply-To: References: Message-ID: Hi Nicolas, Please find Tests-jr.456 in the Inbox. It contains a test case that reveals that reactivateHandlers is too eager at the moment. I tested it with Kernel-nice.1391 loaded. Kind regards, Jakob Am Fr., 23. Apr. 2021 um 10:58 Uhr schrieb : > > Nicolas Cellier uploaded a new version of Kernel to project The Inbox: > http://source.squeak.org/inbox/Kernel-nice.1391.mcz > > ==================== Summary ==================== > > Name: Kernel-nice.1391 > Author: nice > Time: 23 April 2021, 10:58:48.925778 am > UUID: bde1d6d3-e3ba-48ad-b432-3ac5a1531880 > Ancestors: Kernel-nice.1390 > > Remove the questionable ifCurtailed: block that did reactivate the handler in handleSignal:, and make the handling symetric, whether the handlerAction explicitily use exception return or not. > > Document the mysterious tempAt:/tempAt:put: intention by using proper method names as requested by Marcel. > The slowdown shall be marginal, and system understanding should be improved. > > Provide messages to selectively reactivate some handler contexts. For gurus: handle with care! > > =============== Diff against Kernel-nice.1390 =============== > > Item was changed: > ----- Method: Context>>canHandleSignal: (in category 'private-exceptions') ----- > canHandleSignal: exception > "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception then return true, otherwise forward this message to the next handler context. If none left, return false (see nil>>canHandleSignal:)" > > + ^ (self willHandleSignal: exception) > - ^ (((self tempAt: 1) handles: exception) and: [self tempAt: 3]) > or: [self nextHandlerContext canHandleSignal: exception]. > ! > > Item was added: > + ----- Method: Context>>deactivateHandler (in category 'private-exceptions') ----- > + deactivateHandler > + "Private - sent to exception handler context only (on:do:)" > + > + stackp >= 3 ifTrue: [self tempAt: 3 put: false] "this is temporary handlerActive in #on:do:"! > > Item was added: > + ----- Method: Context>>fireHandlerActionWith: (in category 'private-exceptions') ----- > + fireHandlerActionWith: exception > + "Sent to handler (on:do:) contexts only. > + Perform the second argument, which is the handler action" > + > + ^(self tempAt: 2) cull: exception! > > Item was changed: > ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- > handleSignal: exception > "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception > and the handler is active then execute my handle block (second arg), otherwise forward > this message to the next handler context. If none left, execute exception's defaultAction > (see nil>>handleSignal:)." > > + | val | > + (self willHandleSignal: exception) ifFalse: > + [self deactivateHandler. > - | handlerActive val | > - "If the context has been returned from the handlerActive temp var may not be accessible." > - handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. > - (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: > - [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. > ^self nextHandlerContext handleSignal: exception]. > > exception privHandlerContext: self contextTag. > + self deactivateHandler. "disable self while executing handle block" > + val := self fireHandlerActionWith: exception. > - self tempAt: 3 put: false. "disable self while executing handle block" > - val := [(self tempAt: 2) cull: exception] > - ifCurtailed: [self tempAt: 3 put: true]. > self return: val "return from self if not otherwise directed in handle block" > ! > > Item was added: > + ----- Method: Context>>isHandlerActive (in category 'private-exceptions') ----- > + isHandlerActive > + "Private - sent to exception handler context only (on:do:)" > + > + ^stackp >= 3 and: [(self tempAt: 3) == true] "this is temporary handlerActive in #on:do:"! > > Item was added: > + ----- Method: Context>>reactivateHandler (in category 'private-exceptions') ----- > + reactivateHandler > + "Private - sent to exception handler context only (on:do:)" > + > + stackp >= 3 ifTrue: [self tempAt: 3 put: true] "this is temporary handlerActive in #on:do:"! > > Item was changed: > ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- > reactivateHandlers > "Private - sent to exception handler context only (on:do:). > Reactivate all the handlers into the chain" > > + self reactivateHandler. > - self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" > self nextHandlerContext reactivateHandlers! > > Item was added: > + ----- Method: Context>>reactivateHandlersUpTo: (in category 'private-exceptions') ----- > + reactivateHandlersUpTo: aHandlerContext > + "Private - sent to exception handler context only (on:do:). > + Reactivate the inner handlers into the chain, up to, but not including, aHandlerContext" > + > + self == aHandlerContext ifTrue: [^self]. > + self reactivateHandler. > + self nextHandlerContext reactivateHandlersUpTo: aHandlerContext! > > Item was added: > + ----- Method: Context>>reactivateHandlersWhich:upTo: (in category 'private-exceptions') ----- > + reactivateHandlersWhich: selectBlock upTo: aHandlerContext > + "Private - sent to exception handler context only (on:do:). > + Reactivate the inner handlers into the chain, up to, but not including, aHandlerContext, that satisfy the selectBlock predicate" > + > + self == aHandlerContext ifTrue: [^self]. > + (selectBlock value: self) ifTrue: [self reactivateHandler]. > + self nextHandlerContext reactivateHandlersWhich: selectBlock upTo: aHandlerContext! > > Item was changed: > ----- Method: Context>>rearmHandlerDuring: (in category 'private-exceptions') ----- > rearmHandlerDuring: aBlock > "Sent to handler (on:do:) contexts only. Makes me re-entrant for the duration of aBlock. Only works in a closure-enabled image" > > + ^ [self reactivateHandler. aBlock value] > + ensure: [self deactivateHandler]! > - ^ [self tempAt: 3 put: true. aBlock value] > - ensure: [self tempAt: 3 put: false]! > > Item was added: > + ----- Method: Context>>willHandleSignal: (in category 'private-exceptions') ----- > + willHandleSignal: exception > + "Sent to handler (on:do:) contexts only." > + > + ^self isHandlerActive and: [(self tempAt: 1) handles: exception] > + ! > > Item was added: > + ----- Method: Exception>>reactivateHandlersUpTo: (in category 'priv handling') ----- > + reactivateHandlersUpTo: aHandlerContext > + "reactivate all the exception handlers in the context chain" > + self canSearchForSignalerContext > + ifTrue: [signalContext nextHandlerContext reactivateHandlersUpTo: aHandlerContext]! > > Item was added: > + ----- Method: UndefinedObject>>reactivateHandlersUpTo: (in category 'bottom context') ----- > + reactivateHandlersUpTo: aHandlerContext > + > + ^ self! > > Item was added: > + ----- Method: UndefinedObject>>reactivateHandlersWhich:upTo: (in category 'bottom context') ----- > + reactivateHandlersWhich: selectBlock upTo: aHandlerContext > + > + ^ self! > > From jakres+squeak at gmail.com Sun Apr 25 15:36:39 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 17:36:39 +0200 Subject: [squeak-dev] The Inbox: Tests-jr.456.mcz In-Reply-To: References: Message-ID: Great, a copy & paste error slipped into the commit message. Should have been ToolBuilder-Kernel-nice.142, not Kernel-nice.142. Will submit again based on the same parent version with the message fixed. Should be Tests-jr.457 then. Please move this to Treated. Am So., 25. Apr. 2021 um 17:31 Uhr schrieb : > > A new version of Tests was added to project The Inbox: > http://source.squeak.org/inbox/Tests-jr.456.mcz > > ==================== Summary ==================== > > Name: Tests-jr.456 > Author: jr > Time: 25 April 2021, 5:31:14.946128 pm > UUID: 2bc77074-a400-4842-b306-6b1cff37aaba > Ancestors: Tests-nice.455 > > Test case for precise handler reactivation when nested exceptions are signalled. > > At the moment of writing this, this is broken in Squeak Trunk and the test case would run endlessly if there were no timeout. The reason is that the inner error handler is reactivated when the signal emitted by it is resumed. > > Related versions: > - Kernel-nice.1384 > - Kernel-nice.1391 > - ToolBuilder-Kernel-nice.141 > - Kernel-nice.142 > > =============== Diff against Tests-nice.455 =============== > > Item was added: > + ----- Method: ExceptionTests>>testHandlersReactivatedOnResume (in category 'tests - outer') ----- > + testHandlersReactivatedOnResume > + > + | result | > + result := [ > + [ > + [self error: 'to be handled by the inner handler'] > + on: Error do: > + [:e | > + Warning signal: 'to be resumed by the middle handler'. > + "After resuming from the Warning, its handler must be active again." > + Warning signal: 'to be resumed by the middle handler'. > + self error: 'to be handled by the outer handler'. > + e return: 'inner result']] > + on: Warning do: > + [:e | e resume "This must not rearm the inner Error handler above"]] > + on: Error do: > + [:e | e return: 'outer result']. > + self assert: 'outer result' equals: result.! > > From commits at source.squeak.org Sun Apr 25 15:39:35 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 15:39:35 0000 Subject: [squeak-dev] The Inbox: Tests-jr.457.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-jr.457.mcz ==================== Summary ==================== Name: Tests-jr.457 Author: jr Time: 25 April 2021, 5:39:42.729128 pm UUID: 38bb7c0a-ba18-0e43-866f-4f252c20a2d8 Ancestors: Tests-nice.455 Test case for precise handler reactivation when nested exceptions are signalled and resumed. At the moment of writing this, this is broken in Squeak Trunk and the test case would run endlessly if there were no timeout. The reason is that the inner error handler is reactivated when the signal emitted by it is resumed. Related versions: - Kernel-nice.1384 - Kernel-nice.1391 - ToolBuilder-Kernel-nice.141 - ToolBuilder-Kernel-nice.142 =============== Diff against Tests-nice.455 =============== Item was added: + ----- Method: ExceptionTests>>testHandlersReactivatedOnResume (in category 'tests - outer') ----- + testHandlersReactivatedOnResume + + | result | + result := [ + [ + [self error: 'to be handled by the inner handler'] + on: Error do: + [:e | + Warning signal: 'to be resumed by the middle handler'. + "After resuming from the Warning, its handler must be active again." + Warning signal: 'to be resumed by the middle handler'. + self error: 'to be handled by the outer handler'. + e return: 'inner result']] + on: Warning do: + [:e | e resume "This must not rearm the inner Error handler above"]] + on: Error do: + [:e | e return: 'outer result']. + self assert: 'outer result' equals: result.! From jakres+squeak at gmail.com Sun Apr 25 16:37:04 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 18:37:04 +0200 Subject: [squeak-dev] The Inbox: Kernel-mt.1390.mcz In-Reply-To: References: Message-ID: Hi, Sounds like a step towards restarts as found in Common Lisp, which I like. Do I understand correctly that you denote the point of restart with #restartFromHere (where "here" is a bit misleading since it is written in a different block) and that you trigger the restart with RestartContextRequest signal? And #fromContextSuchThat: does both? Now we would just need the possibility to give the restart context a logical identifier (a name, a purpose), and the UI to interactively choose from those identifiers that are on the stack; then we have a higher-level error recovery tool or a mightier debugger notifier. For API, the equivalent would be a specialization of fromContextSuchThat:, which selects from those identifiers. "Proceed" and "Abandon" are special cases with implicit restart contexts: with everything left on the stack, and with nothing left on the stack, respectively. Kind regards, Jakob Am Mo., 19. Apr. 2021 um 17:50 Uhr schrieb Marcel Taeumel < marcel.taeumel at hpi.de>: > Here are the two options in an exapmle: > > > Am 19.04.2021 17:48:03 schrieb commits at source.squeak.org < > commits at source.squeak.org>: > A new version of Kernel was added to project The Inbox: > http://source.squeak.org/inbox/Kernel-mt.1390.mcz > > ==================== Summary ==================== > > Name: Kernel-mt.1390 > Author: mt > Time: 19 April 2021, 5:47:51.865053 pm > UUID: c36ac126-16de-3d41-be90-6b7fd46bc0c7 > Ancestors: Kernel-nice.1389 > > Proposal. Better support for hot code updates by restarting from a denoted > (i.e. domain-specific) context (or active method). For example, this could > be used to better update the McmUpdater as soon as a code change in itself > is detected. Two options: either mark the restart context with an on:do: > handler or process a query to look up that context such as by package name. > > =============== Diff against Kernel-nice.1389 =============== > > Item was added: > + Notification subclass: #RestartContextRequest > + instanceVariableNames: '' > + classVariableNames: '' > + poolDictionaries: '' > + category: 'Kernel-Exceptions'! > > Item was added: > + ----- Method: RestartContextRequest class>>fromContextSuchThat: (in > category 'as yet unclassified') ----- > + fromContextSuchThat: block > + "Use this to restart from an arbitrary context on the stack." > + > + | context | > + context := thisContext sender. > + [context notNil] whileTrue: [ > + (block value: context) ifTrue: [ > + ^ self new restartFrom: context]. > + context := context sender]. > + self error: 'No context found!!'.! > > Item was added: > + ----- Method: RestartContextRequest>>restartFrom: (in category 'as yet > unclassified') ----- > + restartFrom: aContext > + > + | process actualContext unwindError | > + aContext ifNil: [^ self error: 'No context to restart!!']. > + > + process := Processor activeProcess. > + > + [actualContext := process popTo: aContext. > + unwindError := actualContext ~= aContext. > + unwindError > + ifTrue: [process resume] > + ifFalse: [process restartTop; stepToSendOrReturn; resume] > + ] fork. > + > + process suspend.! > > Item was added: > + ----- Method: RestartContextRequest>>restartFromHere (in category 'as > yet unclassified') ----- > + restartFromHere > + "Use this to restart from an exception handler." > + self restartFrom: handlerContext.! > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 158062 bytes Desc: not available URL: From christoph.thiede at student.hpi.uni-potsdam.de Sun Apr 25 17:14:18 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Sun, 25 Apr 2021 19:14:18 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <95b949c8-c304-3893-c7f3-053dd329c9ec@leastfixedpoint.com> Message-ID: <045abb52-2eed-408f-972b-88926f3bc5b4@email.android.com> An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Sun Apr 25 17:38:35 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 19:38:35 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: Hi Marcel, What is your stance towards using inspectors to quickly check identity, regarding ByteString? Note: to make this practical, one needs to turn on the "Reuse windows" preference. Example workflow: 1. Expression print-it. 2. "Oh I have seen this string before, is it the same instance or another one?" 3. (Click on the result to open the inspector on the result object.) 4. Open an inspector on the other, previously encountered occurrence of the string (might be in another tool). If a second inspector appears, these are two distinct String instances. To further motivate the question in 2., imagine that this ByteString is big, say, a several hundred MB CLOB. :-) Kind regards, Jakob Am Sa., 24. Apr. 2021 um 17:43 Uhr schrieb Marcel Taeumel : > > Hi Jakob, > > thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. > > Hey Christoph, > > a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. > > I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. > > Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? > > Hi all, > > here is again the list of objects I think we should exclude from having a text action on their print-it result: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) > > Reducing visual clutter is worth a few lines of extra source code. > > Best, > Marcel > > Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : > > Hi Jakob, Hi Marcel, > > > thank you for reviving this discussion! :-) > > > > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") > > > Definitively also the latter. > > > While the type check might not be really necessary, avoiding visual clutter can be a good thing. > > -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > > > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. > > This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Jakob Reschke > Gesendet: Samstag, 24. April 2021 11:43:06 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > Hi Christoph, hi Marcel, > > Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > : > > > > Hi Christoph, > > > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > > > > I am struggling to understand how your arguments address each other > person's concerns. Did I understand your points correctly: > > - Christoph wants to get rid of the type check. He argues that > sometimes even for the objects with "primitive" structure you may want > to get the link. For example, MCVersionName loses its type information > when printed, so when you would inspect the result, you would get a > String instead of an MCVersionName. The other example is when you want > to track identity. Indeed, sometimes it is useful to check whether one > String is the same as another one retrieved (inspected) from somewhere > else. I do this regularly in Squot when debugging the capturing and > materialization (although seldom for Strings at this time because for > these it already works as expected). > > - Marcel says that the links are unnecessary for what are essentially > value objects that are not complex enough to need inspection beyond > just looking at the print string. Supposedly, one can just reevaluate > the result or the expression. Adding the links there produces visual > clutter and is distracting. Inspecting an MCVersionName would reveal > no further information about the object than the print string does > (that is, except for the type!). > > Christoph, when you inspect your MCVersionNames, do you already know > that these are version names or do you inspect them to find out what > they are? ("What is this, a String or an MCVersionName?") > > I fully agree with Marcel on the immediates and singletons (true, > false, nil, Symbols). While the type check might not be really > necessary, avoiding visual clutter can be a good thing. Tradeoff is > with having the special case in the code. > > Unfortunately(?), Strings in Squeak/Smalltalk are not quite value > objects, since they are mutable, can be used as buffers, etc. Depends > on the application. > > On the other hand, Points are mostly used as value objects, but did > not get the special case treatment. Though strictly, technically > speaking, they are not different from Strings in this regard. > > Inspecting the result string or the revaluating the original > expression to do so is only safe if it does not provoke side effects. > For Marcel's selection of classes, there are no side effects of > reevaluating the result string. But reevaluating the original > expression might not be free of side effects. I guess you would not > reevaluate the expression to inspect an immediate or singleton, but > for those objects that do have object identity, such as Strings, or > where the type of the result is not obvious, MCVersionName, you might > want to do that. > > How about allowing to turn off the highlighting of the result? I mean, > make it still clickable, but do not paint it blue. Then there would be > no visual clutter, and if you know that the feature is there (and you > have subsequently turned off the preference, for example), you would > also not easily forget that you can use it. > > Kind regards, > Jakob > > From jakres+squeak at gmail.com Sun Apr 25 17:43:19 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 19:43:19 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: Hi all, So visual consistency for Christoph means: all results are highlighted(/click-inspectable). Whereas for Marcel it means: all complex/interesting results are highlighted/click-inspectable. What does everyone else think about this? I sometimes wish that the print-it results in the workspace would be treated differently than the text that I typed myself. Highlighting them (link or otherwise) could help to spot the frontier between expression and result after some more actions, but would otherwise not help me much. When I intended to use the printed result in my next expression, highlighting it as a result would be inappropriate, but I rarely ever want to do this. For most complex objects, this is not even possible because their print strings are not Smalltalk expressions. But I cannot use a non-Smalltalk expression with a link on it in my next expression either, so the feature does not help me in that case anyway. (What I would rather need is a "put this into a variable" command, kind of a refactoring operation for the Workspace.) If I wanted to send further messages to a returned 'String' I would most likely move it onto its own line for convenient Cmd-p/i first anyway, I would not keep it to the right of the expression that evaluated to the 'String'. With this reasoning, I would rather lean towards Christoph's interpretation now. (Also I believe it does not hurt so much if one can also inspect the primitive results.) But I have not used the feature in practice so far, so I will let some time pass for now. Kind regards, Jakob Am Sa., 24. Apr. 2021 um 17:43 Uhr schrieb Marcel Taeumel : > > Hi Jakob, > > thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. > > Hey Christoph, > > a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. > > I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. > > Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? > > Hi all, > > here is again the list of objects I think we should exclude from having a text action on their print-it result: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) > > Reducing visual clutter is worth a few lines of extra source code. > > Best, > Marcel > > Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : > > Hi Jakob, Hi Marcel, > > > thank you for reviving this discussion! :-) > > > > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") > > > Definitively also the latter. > > > While the type check might not be really necessary, avoiding visual clutter can be a good thing. > > -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > > > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. > > This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Jakob Reschke > Gesendet: Samstag, 24. April 2021 11:43:06 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > Hi Christoph, hi Marcel, > > Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > : > > > > Hi Christoph, > > > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > > > > I am struggling to understand how your arguments address each other > person's concerns. Did I understand your points correctly: > > - Christoph wants to get rid of the type check. He argues that > sometimes even for the objects with "primitive" structure you may want > to get the link. For example, MCVersionName loses its type information > when printed, so when you would inspect the result, you would get a > String instead of an MCVersionName. The other example is when you want > to track identity. Indeed, sometimes it is useful to check whether one > String is the same as another one retrieved (inspected) from somewhere > else. I do this regularly in Squot when debugging the capturing and > materialization (although seldom for Strings at this time because for > these it already works as expected). > > - Marcel says that the links are unnecessary for what are essentially > value objects that are not complex enough to need inspection beyond > just looking at the print string. Supposedly, one can just reevaluate > the result or the expression. Adding the links there produces visual > clutter and is distracting. Inspecting an MCVersionName would reveal > no further information about the object than the print string does > (that is, except for the type!). > > Christoph, when you inspect your MCVersionNames, do you already know > that these are version names or do you inspect them to find out what > they are? ("What is this, a String or an MCVersionName?") > > I fully agree with Marcel on the immediates and singletons (true, > false, nil, Symbols). While the type check might not be really > necessary, avoiding visual clutter can be a good thing. Tradeoff is > with having the special case in the code. > > Unfortunately(?), Strings in Squeak/Smalltalk are not quite value > objects, since they are mutable, can be used as buffers, etc. Depends > on the application. > > On the other hand, Points are mostly used as value objects, but did > not get the special case treatment. Though strictly, technically > speaking, they are not different from Strings in this regard. > > Inspecting the result string or the revaluating the original > expression to do so is only safe if it does not provoke side effects. > For Marcel's selection of classes, there are no side effects of > reevaluating the result string. But reevaluating the original > expression might not be free of side effects. I guess you would not > reevaluate the expression to inspect an immediate or singleton, but > for those objects that do have object identity, such as Strings, or > where the type of the result is not obvious, MCVersionName, you might > want to do that. > > How about allowing to turn off the highlighting of the result? I mean, > make it still clickable, but do not paint it blue. Then there would be > no visual clutter, and if you know that the feature is there (and you > have subsequently turned off the preference, for example), you would > also not easily forget that you can use it. > > Kind regards, > Jakob > > From jakres+squeak at gmail.com Sun Apr 25 17:47:29 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 19:47:29 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: You could also conduct/enforce an informal user study by just changing the decision in Trunk after a few months, and count the number of complaints before and after. ;-) Am So., 25. Apr. 2021 um 19:43 Uhr schrieb Jakob Reschke : > > Hi all, > > So visual consistency for Christoph means: all results are > highlighted(/click-inspectable). > Whereas for Marcel it means: all complex/interesting results are > highlighted/click-inspectable. > > What does everyone else think about this? > > I sometimes wish that the print-it results in the workspace would be > treated differently than the text that I typed myself. Highlighting > them (link or otherwise) could help to spot the frontier between > expression and result after some more actions, but would otherwise not > help me much. When I intended to use the printed result in my next > expression, highlighting it as a result would be inappropriate, but I > rarely ever want to do this. For most complex objects, this is not > even possible because their print strings are not Smalltalk > expressions. But I cannot use a non-Smalltalk expression with a link > on it in my next expression either, so the feature does not help me in > that case anyway. (What I would rather need is a "put this into a > variable" command, kind of a refactoring operation for the Workspace.) > If I wanted to send further messages to a returned 'String' I would > most likely move it onto its own line for convenient Cmd-p/i first > anyway, I would not keep it to the right of the expression that > evaluated to the 'String'. > > With this reasoning, I would rather lean towards Christoph's > interpretation now. (Also I believe it does not hurt so much if one > can also inspect the primitive results.) But I have not used the > feature in practice so far, so I will let some time pass for now. > > Kind regards, > Jakob > > Am Sa., 24. Apr. 2021 um 17:43 Uhr schrieb Marcel Taeumel > : > > > > Hi Jakob, > > > > thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. > > > > Hey Christoph, > > > > a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. > > > > I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. > > > > Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? > > > > Hi all, > > > > here is again the list of objects I think we should exclude from having a text action on their print-it result: > > > > ByteString > > ByteSymbol > > Number > > Boolean > > UndefinedObject > > > > If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) > > > > Reducing visual clutter is worth a few lines of extra source code. > > > > Best, > > Marcel > > > > Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : > > > > Hi Jakob, Hi Marcel, > > > > > > thank you for reviving this discussion! :-) > > > > > > > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") > > > > > > Definitively also the latter. > > > > > While the type check might not be really necessary, avoiding visual clutter can be a good thing. > > > > -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > > > > > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. > > > > This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... > > > > Best, > > Christoph > > > > ________________________________ > > Von: Squeak-dev im Auftrag von Jakob Reschke > > Gesendet: Samstag, 24. April 2021 11:43:06 > > An: The general-purpose Squeak developers list > > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > > > Hi Christoph, hi Marcel, > > > > Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > > : > > > > > > Hi Christoph, > > > > > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > > > > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > > > > > > > I am struggling to understand how your arguments address each other > > person's concerns. Did I understand your points correctly: > > > > - Christoph wants to get rid of the type check. He argues that > > sometimes even for the objects with "primitive" structure you may want > > to get the link. For example, MCVersionName loses its type information > > when printed, so when you would inspect the result, you would get a > > String instead of an MCVersionName. The other example is when you want > > to track identity. Indeed, sometimes it is useful to check whether one > > String is the same as another one retrieved (inspected) from somewhere > > else. I do this regularly in Squot when debugging the capturing and > > materialization (although seldom for Strings at this time because for > > these it already works as expected). > > > > - Marcel says that the links are unnecessary for what are essentially > > value objects that are not complex enough to need inspection beyond > > just looking at the print string. Supposedly, one can just reevaluate > > the result or the expression. Adding the links there produces visual > > clutter and is distracting. Inspecting an MCVersionName would reveal > > no further information about the object than the print string does > > (that is, except for the type!). > > > > Christoph, when you inspect your MCVersionNames, do you already know > > that these are version names or do you inspect them to find out what > > they are? ("What is this, a String or an MCVersionName?") > > > > I fully agree with Marcel on the immediates and singletons (true, > > false, nil, Symbols). While the type check might not be really > > necessary, avoiding visual clutter can be a good thing. Tradeoff is > > with having the special case in the code. > > > > Unfortunately(?), Strings in Squeak/Smalltalk are not quite value > > objects, since they are mutable, can be used as buffers, etc. Depends > > on the application. > > > > On the other hand, Points are mostly used as value objects, but did > > not get the special case treatment. Though strictly, technically > > speaking, they are not different from Strings in this regard. > > > > Inspecting the result string or the revaluating the original > > expression to do so is only safe if it does not provoke side effects. > > For Marcel's selection of classes, there are no side effects of > > reevaluating the result string. But reevaluating the original > > expression might not be free of side effects. I guess you would not > > reevaluate the expression to inspect an immediate or singleton, but > > for those objects that do have object identity, such as Strings, or > > where the type of the result is not obvious, MCVersionName, you might > > want to do that. > > > > How about allowing to turn off the highlighting of the result? I mean, > > make it still clickable, but do not paint it blue. Then there would be > > no visual clutter, and if you know that the feature is there (and you > > have subsequently turned off the preference, for example), you would > > also not easily forget that you can use it. > > > > Kind regards, > > Jakob > > > > From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 17:58:48 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 17:58:48 +0000 Subject: [squeak-dev] Please try it out | Fixing the input mapping for keystroke events In-Reply-To: References: , Message-ID: Hi Marcel, great idea, thanks for your work. It works fine on Windows as well as WSL/Ubuntu/VvXsrv for all my usual workflows. :-) I noted some "breaking change", but actually it is a fix: When pressing something like Ctrl + ArrowLeft, the keystroke event no longer answers true for #commandKeyPressed but for #optionKeyPressed instead. This makes a workaround in WindowAcrobatics [1] superfluous. The KeyboardExerciser is also a great tool. It gives a good overview of what is still left to do for the input mapping - that is (on Windows): * Ctrl + (Insert | Home | End | PageUp | PageDown) is mapped incorrectly to Ctrl + (A | D | L | ...) * Ctrl + Alt + is not recorded * Ctrl + Shift + Space is not recorded * In my image, Shift + Alt + U does not work - is this a strange bug or do I have an unknown global keyboard filter? And here is some - though minor - notes about the exerciser tool: * The "Move your mouse cursor" instruction message does not fit into the morph in my image and is not word-wrapped but misses a draw invalidation instead. Also, it is not multilanguage-safe, but since it is in the "Demo" system category, I guess this is okay. :D Best, Christoph [1] https://github.com/hpi-swa-teaching/WindowAcrobatics/blob/3398eb951d674360a37fe422710340e53a69bd84/packages/WindowAcrobatics-Core.package/WAHandler.class/instance/handle..st#L5 ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Samstag, 24. April 2021 20:58 Uhr An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Please try it out | Fixing the input mapping for keystroke events Hi Marcel, I tried it on macos and windows, no problem so far. I had some fun with the exercizer, some combinations are surprising indeed... Le ven. 23 avr. 2021 à 18:23, Marcel Taeumel > a écrit : Hi all! Please find attached an updated changeset with a "KeyboardExerciser" to help you test and inspect the incoming keyboard events. You can find it also in the parts bin nearby the "ClickExerciser". [cid:179053dbf6dcb971f161] The visuals are supposed to look platform-specific. However, the event data contains information to make your application work across platforms. See KeyboardEvent >> #checkCommandKey for more explanations. Try [CTRL]+[C] for keyStroke, keyDown, and keyUp. Note that the visuals might not look right for keyUp and keyDown events due to missing lookup tables for the raw, platform-specific key codes. On my machine, for example, [,] and [.] and [-] look odd: [cid:179053dbf6ecb971f162] Nothing to worry about because all keyboard shortcuts in Squeak use keyStroke events at the moment. Best, Marcel Am 22.04.2021 10:41:15 schrieb Marcel Taeumel >: Hi all! Please find attached a changeset that improves the cross-platform base for keystroke events. Please try it out and take a look at it. Report issues ASAP so that I can merge it into Trunk soon. Thanks to Tom (tobe), the new promising idea is to replace the existing attempt: Duplicate all control and alt keys Duplicate control and alt keys Swap control and alt keys With the following preferences: [X] Map ASCII control characters to printable characters - Default is TRUE - Only affects events that have the CONTROL modifier set (e.g. CTRL+J) - Rather application-specific than platform-specific [X] Map CONTROL keys to COMMAND keys - Checked at image start-up - TRUE on Windows/Linux - FALSE on macOS [X] Map ALT keys to OPTION keys - Checked at image start-up - TRUE on Windows/Linux - FALSE on macOS (bc. ALT==CMD on recent Linux/Windows VMs) Please take a look at KeyboardEvent >> #checkCommandKey to learn about the fundamental trade-off we have solved. Please try out your preferred applications. Feel free to add logging to HandMorph >> #logEvent: for more convenient testing: (anEvent isKeyboard and: [anEvent isKeystroke]) ifTrue: [Transcript showln: anEvent]. Thanks! Best, Marcel (and Tom) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 37054 bytes Desc: image.png URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 9239 bytes Desc: image.png URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 18:05:23 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 18:05:23 +0000 Subject: [squeak-dev] The Inbox: Kernel-mt.1390.mcz In-Reply-To: References: , Message-ID: <79bc441b75b94ef1a116b5ba348940fd@student.hpi.uni-potsdam.de> Hi Marcel, these are interesting concepts though hard to evaluate without real-world examples, I guess. But it does seem to be a crucial core concept to me. Maybe this would better fit into the System package? I'd like to keep the Kernel package as small as possible and this one is rather advanced stuff ... 😊 Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 19. April 2021 17:50:02 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Kernel-mt.1390.mcz Here are the two options in an exapmle: [cid:96ea598e-8551-44ae-8472-e87b1efbb447] Am 19.04.2021 17:48:03 schrieb commits at source.squeak.org : A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-mt.1390.mcz ==================== Summary ==================== Name: Kernel-mt.1390 Author: mt Time: 19 April 2021, 5:47:51.865053 pm UUID: c36ac126-16de-3d41-be90-6b7fd46bc0c7 Ancestors: Kernel-nice.1389 Proposal. Better support for hot code updates by restarting from a denoted (i.e. domain-specific) context (or active method). For example, this could be used to better update the McmUpdater as soon as a code change in itself is detected. Two options: either mark the restart context with an on:do: handler or process a query to look up that context such as by package name. =============== Diff against Kernel-nice.1389 =============== Item was added: + Notification subclass: #RestartContextRequest + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'Kernel-Exceptions'! Item was added: + ----- Method: RestartContextRequest class>>fromContextSuchThat: (in category 'as yet unclassified') ----- + fromContextSuchThat: block + "Use this to restart from an arbitrary context on the stack." + + | context | + context := thisContext sender. + [context notNil] whileTrue: [ + (block value: context) ifTrue: [ + ^ self new restartFrom: context]. + context := context sender]. + self error: 'No context found!!'.! Item was added: + ----- Method: RestartContextRequest>>restartFrom: (in category 'as yet unclassified') ----- + restartFrom: aContext + + | process actualContext unwindError | + aContext ifNil: [^ self error: 'No context to restart!!']. + + process := Processor activeProcess. + + [actualContext := process popTo: aContext. + unwindError := actualContext ~= aContext. + unwindError + ifTrue: [process resume] + ifFalse: [process restartTop; stepToSendOrReturn; resume] + ] fork. + + process suspend.! Item was added: + ----- Method: RestartContextRequest>>restartFromHere (in category 'as yet unclassified') ----- + restartFromHere + "Use this to restart from an exception handler." + self restartFrom: handlerContext.! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 158062 bytes Desc: image.png URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 18:10:45 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 18:10:45 +0000 Subject: [squeak-dev] The Trunk: MorphicExtras-eem.293.mcz In-Reply-To: References: Message-ID: <4b3c438ee7184e39ba1d5c58463376fd@student.hpi.uni-potsdam.de> Hi Eliot, do you plan to add support for cameras to Windows? Or should this already work and something is broken here? At the moment, primOpenCamera always fails for me without an error code ... :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Samstag, 17. April 2021 04:14:18 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: MorphicExtras-eem.293.mcz Eliot Miranda uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-eem.293.mcz ==================== Summary ==================== Name: MorphicExtras-eem.293 Author: eem Time: 16 April 2021, 7:14:15.621938 pm UUID: 27489c5b-4cc5-4581-905d-881e877c32d6 Ancestors: MorphicExtras-mt.292 Add frame buffering to the CameraInterface (i.e. if possible the CameraPlugin copies data directly into a pinned bitmap instead of into an internal buffer which is then copied into the bitmap in getFrameForCamera:into:. Update the camera:framesDo:while: utility to use buffering and/or interrupt notification if possible. =============== Diff against MorphicExtras-mt.292 =============== Item was added: + ----- Method: CameraInterface class>>bufferedInterruptDrivenVideoTest: (in category 'test') ----- + bufferedInterruptDrivenVideoTest: camNum + "A quick test of video input. Displays video on the screen until the mouse is pressed. + Answer nil if the interrupt-driven interface is unavailable." + "self bufferedInterruptDrivenVideoTest: 1" + "self bufferedInterruptDrivenVideoTest: 2" + "[self bufferedInterruptDrivenVideoTest: 2] fork. + self bufferedInterruptDrivenVideoTest: 1" + + | semaphore height frameExtent frameBuffer | + height := 16. + 1 to: camNum - 1 do: + [:camIndex| "N.B. the extent of an unopened camera is 0 at 0" + height := height + (self frameExtent: camIndex) y + 16]. + (self cameraIsOpen: camNum) ifFalse: + [(self openCamera: camNum width: 352 height: 288) ifNil: + [self inform: 'no camera'. + ^nil]]. + frameExtent := self frameExtent: camNum. + frameBuffer := Form extent: frameExtent depth: 32. + frameBuffer bits pin. + self camera: camNum setFrameBuffer: frameBuffer bits. + + semaphore := Semaphore new. + [self camera: camNum setSemaphore: (Smalltalk registerExternalObject: semaphore)] + on: Error + do: [:err| + Smalltalk unregisterExternalObject: semaphore. + self inform: 'interrupt-driven camera interface unavailable: ', err messageText. + ^nil]. + [| n startTime frameCount msecs fps | + [semaphore wait. + startTime ifNil: + [frameCount := 0. + frameExtent := self frameExtent: camNum. + "N.B. the actual frame size may not be determined until delivery of the first frame. + So resize the form if necessary." + frameExtent ~= frameBuffer extent ifTrue: + [frameBuffer := Form extent: frameExtent depth: 32 bits: frameBuffer bits]. + startTime := Time millisecondClockValue]. + Sensor anyButtonPressed] whileFalse: + [n := self getFrameForCamera: camNum into: frameBuffer bits. + n > 0 ifTrue: + [frameCount := frameCount + 1. + frameBuffer displayAt: 16 @ height]]. + msecs := Time millisecondClockValue - startTime. + fps := (frameCount * 1000) // msecs. + ^(self cameraName: camNum), ': ', frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'] + ensure: + [self closeCamera: camNum. + Smalltalk unregisterExternalObject: semaphore. + Sensor waitNoButton]! Item was changed: ----- Method: CameraInterface class>>camera:framesDo:while: (in category 'utilities') ----- camera: cameraNum framesDo: aBlock while: whileBlock + "Evaluate aBlock every time a frame becomes available. Answer a tuple of frames per second + and the number of 16ms delays per second if polling is used, plus indications of which schemes + were used. Be destructive; use only one bitmap, overwriting its contents with each successive frame. + Use the buffered interface if possible. It is the sender's responsibility to open and close the camera." + | form bitmap schemes delay start duration frameCount delayCount semaphore | - "Evaluate aBlock every time a frame becomes available. Answer a tuple of frames per second and number of 16ms delays per second. - Be destructive; use only one bitmap, overwriting its contents with each successive frame. - It is the sender's responsibility to open and close the camera." - | form bitmap delay start duration frameCount delayCount | form := Form extent: (self frameExtent: cameraNum) depth: 32. bitmap := form bits. + bitmap pin. + schemes := Array new writeStream. + [self camera: cameraNum setFrameBuffer: bitmap. + schemes nextPut: 'buffered'] + on: Error + do: [:err| + bitmap unpin. + schemes nextPut: 'copied']. + semaphore := Semaphore new. + [self camera: cameraNum setSemaphore: (Smalltalk registerExternalObject: semaphore). + schemes nextPut: 'interrupt driven'] + on: Error + do: [:err| + Smalltalk unregisterExternalObject: semaphore. + semaphore := nil. + schemes nextPut: 'polling']. delay := Delay forMilliseconds: (1000 / 60) asInteger. "60 fps is fast" + start := Time utcMicrosecondClock. frameCount := delayCount := 0. + [semaphore ifNotNil: + [semaphore wait]. + [(self getFrameForCamera: cameraNum into: bitmap) <= 0] whileTrue: - [[(self camera: cameraNum getParam: 1) <= 0] whileTrue: [delay wait. delayCount := delayCount + 1]. - self getFrameForCamera: cameraNum into: bitmap. frameCount := frameCount + 1. aBlock value: form. whileBlock value] whileTrue. ^{ frameCount * 1.0e6 / (duration := Time utcMicrosecondClock - start). + delayCount * 1.0e6 / duration }, + schemes contents - delayCount * 1.0e6 / duration } "| cameraNum | self openCamera: (cameraNum := 1) width: 640 height: 480. self waitForCameraStart: cameraNum. [self camera: cameraNum framesDo: [:bitmap| bitmap display] while: [Sensor noButtonPressed]] ensure: [self closeCamera: cameraNum]"! Item was added: + ----- Method: CameraInterface class>>camera:setFrameBuffer: (in category 'camera ops') ----- + camera: cameraNum setFrameBuffer: frameBuffer + "Set a pinned non-pointer object as the frame buffer for the camera. + Fail if cameraNum does not reference an open camera, or if the buffer is not large enough." + + ^self primitiveFailed! Item was added: + ----- Method: CameraInterface class>>camera:setFrameBufferA:B: (in category 'camera ops') ----- + camera: cameraNum setFrameBufferA: frameBufferA B: frameBufferBOrNil + "Set a pair of pinned non-pointer objects as the frame buffers for the camera. + If both are non-nil the plugin will fill them alternating between first frameBufferA and second frameBufferBOrNil. + Fail if frameBufferBOrNil is not nil and a different size from frameBufferA. + Fail if cameraNum does not reference an open camera, or if the buffers are not large enough." + + ^self primitiveFailed! Item was changed: ----- Method: CameraInterface class>>interruptDrivenVideoTest: (in category 'test') ----- interruptDrivenVideoTest: camNum "A quick test of video input. Displays video on the screen until the mouse is pressed. Answer nil if the interrupt-driven interface is unavailable." "self interruptDrivenVideoTest: 1" "self interruptDrivenVideoTest: 2" "[self interruptDrivenVideoTest: 2] fork. self interruptDrivenVideoTest: 1" | semaphore height frameExtent | height := 16. 1 to: camNum - 1 do: + [:camIndex| "N.B. the extent of an unopened camera is 0 at 0" - [:camIndex| "N.B. the of an unopened camera is 0 at 0" height := height + (self frameExtent: camIndex) y + 16]. (self cameraIsOpen: camNum) ifFalse: [(self openCamera: camNum width: 352 height: 288) ifNil: [self inform: 'no camera'. ^nil]]. semaphore := Semaphore new. [self camera: camNum setSemaphore: (Smalltalk registerExternalObject: semaphore)] on: Error do: [:err| Smalltalk unregisterExternalObject: semaphore. self inform: 'interrupt-driven camera interface unavailable: ', err messageText. ^nil]. [| f n startTime frameCount msecs fps | [semaphore wait. "N.B. the frame extent may not be known until the delivery of the first frame. So we have to delay initialization." startTime ifNil: [(frameExtent := self frameExtent: camNum) x = 0 ifTrue: [self inform: 'no camera'. ^nil]. f := Form extent: (self frameExtent: camNum) depth: 32. frameCount := 0. startTime := Time millisecondClockValue]. Sensor anyButtonPressed] whileFalse: [n := self getFrameForCamera: camNum into: f bits. n > 0 ifTrue: [frameCount := frameCount + 1. f displayAt: 16 @ height]]. msecs := Time millisecondClockValue - startTime. fps := (frameCount * 1000) // msecs. ^(self cameraName: camNum), ': ', frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'] ensure: [self closeCamera: camNum. Smalltalk unregisterExternalObject: semaphore. Sensor waitNoButton]! Item was changed: ----- Method: CameraInterface class>>videoTest: (in category 'test') ----- videoTest: camNum "A quick test of video input. Displays video on the screen until the mouse is pressed." "self videoTest: 1" "self videoTest: 2" | frameExtent f n startTime frameCount msecs fps | + (self cameraIsOpen: camNum) ifFalse: + [(self openCamera: camNum width: 320 height: 240) ifNil: + [self inform: 'no camera'. + ^nil]]. - (self openCamera: camNum width: 320 height: 240) ifNil: [^ self inform: 'no camera']. self waitForCameraStart: camNum. (frameExtent := self frameExtent: camNum) x = 0 ifTrue: [^ self inform: 'no camera']. f := Form extent: (self frameExtent: camNum) depth: 32. frameCount := 0. startTime := nil. [Sensor anyButtonPressed] whileFalse: [n := self getFrameForCamera: camNum into: f bits. n > 0 ifTrue: [startTime ifNil: [startTime := Time millisecondClockValue]. frameCount := frameCount + 1. f display]]. Sensor waitNoButton. msecs := Time millisecondClockValue - startTime. self closeCamera: camNum. fps := frameCount * 1000 // msecs. + ^(self cameraName: camNum), ': ', frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'! - ^frameExtent printString, ' ', frameCount printString, ' frames at ', fps printString, ' frames/sec'! -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 18:23:18 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 18:23:18 +0000 Subject: [squeak-dev] The Trunk: MorphicTests-nice.75.mcz In-Reply-To: References: , Message-ID: <232ff796ffbc4528a61a3bdd3ecc88c8@student.hpi.uni-potsdam.de> Hi Marcel, we already have #setPreference:toValue:during: on Preferences class. I also had to remember this proposal + discussion: The Inbox: System-ct.1119.mcz Your counter-proposal with the preferences sandbox also sounds interesting, we could do this as well. (Just now, I am wondering whether preferences should be process-local ... But that's enough stuff for its own discussion. :-)) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Donnerstag, 15. April 2021 09:39:57 An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: MorphicTests-nice.75.mcz Hi Nicolas. Thanks. We might want to think about a more generic way to specify system-wide preferences for tests. Maybe a new feature in TestCase (or SUnit). While I would never want to change such preferences in a specific test, I also see that the setUp-way (with that extra "reset" instVar) is quite cumbersome. Best, Marcel Am 14.04.2021 19:14:23 schrieb commits at source.squeak.org : Nicolas Cellier uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-nice.75.mcz ==================== Summary ==================== Name: MorphicTests-nice.75 Author: nice Time: 14 April 2021, 7:14:06.997889 pm UUID: d87c50dd-4e44-5242-9120-37e0452ca781 Ancestors: MorphicTests-eem.74 Fix loss of useRetractableScrollBars preference =============== Diff against MorphicTests-eem.74 =============== Item was changed: ----- Method: TableLayoutTest>>setUp (in category 'running') ----- setUp super setUp. - reset := { ([:enable | [self useRetractableScrollBars: enable]] value: self useRetractableScrollBars) + }. + self useRetractableScrollBars: false! - in: [:block | self useRetractableScrollBars: false]. - }.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Sun Apr 25 18:28:47 2021 From: tim at rowledge.org (tim Rowledge) Date: Sun, 25 Apr 2021 11:28:47 -0700 Subject: [squeak-dev] The Trunk: MorphicExtras-eem.293.mcz In-Reply-To: <4b3c438ee7184e39ba1d5c58463376fd@student.hpi.uni-potsdam.de> References: <4b3c438ee7184e39ba1d5c58463376fd@student.hpi.uni-potsdam.de> Message-ID: <3606ED07-135C-4773-8CCB-EF46D6C97A21@rowledge.org> > On 2021-04-25, at 11:10 AM, Thiede, Christoph wrote: > > Hi Eliot, > > do you plan to add support for cameras to Windows? Or should this already work and something is broken here? At the moment, primOpenCamera always fails for me without an error code ... :-) I'm pretty sure the CameraPlugin stuff would have worked at some point since it was originally part of the Scratch development. Scratch (original Squeak version) was used by multiple millions of kids around the world on all sorts of machines so no camera on Windows would have been noticed. Most likely Windows changed and broke it; after all that seems to be the primary purpose of Windows. As an aside, the extended and improved Squeak based Scratch is still part of the default Raspberry Pi setup and is still used by enough people that I just did an update release. Still used on the ISS apparently. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Oxymorons: Alone together From christoph.thiede at student.hpi.uni-potsdam.de Sun Apr 25 18:30:10 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Sun, 25 Apr 2021 13:30:10 -0500 (CDT) Subject: [squeak-dev] Solving multiple termination bugs - summary & proposal In-Reply-To: <1618126794263-0.post@n4.nabble.com> References: <1617642027172-0.post@n4.nabble.com> <1618045093475-0.post@n4.nabble.com> <1618126794263-0.post@n4.nabble.com> Message-ID: <1619375410272-0.post@n4.nabble.com> Hi Jaromir, I am extremely sorry for not giving any feedback on all your fixes and proposals earlier. A few weeks ago, I was on holiday, then back at home, I was greeted by a huge inbox with 100+ unread emails, and somehow I just lost track of all your important updates ... Luckily, Nicolas has shown more energy than me and has helped your contributions to find their way into the Trunk! 🎉 Your summary in this post was extremely helpful for me to get an overview of all the ongoing changes. I think I understood most of it, but here are some open questions and to-dos from my point of view: 1. Regarding issue no. #5 in your list above ("Bug in Process>>#terminate | Returning from unwind contexts" [1]): Do you consider this thread resolved by now or is my answer to it still being expected? At the moment, this snippet you mentioned fails to unwind completely: x := nil. [self error: 'x1'] ensure: [ [self error: 'x2'] ensure: [ [self error: 'x3'] ensure: [ x:=3]. x:=2]. x:=1]. 2. What is the current state of this thread [2]? If all issues are resolved from your perspective, there is no need to discuss anything further - otherwise, I guess it's your turn to answer again. :) 3. I noticed that Process >> #terminate contains multiple direct sends to #runUntilErrorOrReturnFrom:. There are multiple real and potential problems with this: 3.1 Consider the following snippet: | p | p := Processor activeProcess. Transcript showln: p == Processor activeProcess. [Transcript showln: p == Processor activeProcess] ensure: [ Transcript showln: p == Processor activeProcess]. p Debug it, then step into the first block, and abandon the debugger. We would expect to see another "true" in the Transcript, but instead, we see a "false". This is because #runUntilErrorOrReturnFrom: does not honor process-faithful debugging. The protocol on Process, on the other hand, does so. So probably we would want to wrap these sends into #evaluate:onBehalfOf:. 3.2 As I think I mentioned somewhere else already, the result of #runUntilErrorOrReturnFrom: *must* be checked to make sure that the execution or the unwinding has not halted halfway. I don't see this in Process >> #terminate either. This might be the cause of the bug I mentioned in #1 of this post. Probably it's the best idea to discuss this in [1], too. :-) 4. What's the current state of tests? Have you contributed tests for all the issues you mentioned above? This would be awesome. :-) Organizational notes: For sake of overview, I propose to keep this thread of the current level of abstraction and discuss all the implementation details in separate threads such as [1]. Ideally, we should also "close" all the different threads about Process issues by adding another message to each of them in order to help our future selves to keep an overview of their solutions ... Happy processing! Best, Christoph [1] http://forum.world.st/Bug-in-Process-gt-gt-terminate-Returning-from-unwind-contexts-td5127570.html [2] http://forum.world.st/Refactoring-terminate-to-get-rid-of-cannot-return-errors-etc-td5127732.html ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 18:41:08 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 18:41:08 +0000 Subject: [squeak-dev] Smalltalk Zoo not written in Smalltalk Message-ID: Hi all, just a short and curious questions, but not guaranteed to be completely unprovoking. :-) Why is Smalltalk Zoo, the virtual exhibition which compares different milestones in the history of Squeak/Smalltalk, not implemented in Smalltalk itself but in JavaScript, a language which cannot compile itself, is quite the oppposite of Smalltalk in terms of clearness of expression, and escapes control of the actual application? While I love the idea in general, I think it's a shame that the zoo of a language that aims to be implemented in itself is not implemented in that language itself. :D Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 18:49:02 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 18:49:02 +0000 Subject: [squeak-dev] The Trunk: Tools-mt.1029.mcz In-Reply-To: References: , Message-ID: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> I did not realize this new feature before I was cleaning up my inbox today. Great idea (probably inspired from Vivide?)! :-) Maybe reconsider the initialExtent of pure CodeHolders? By default, the look a bit too large to me. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Donnerstag, 4. März 2021 15:46:49 An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Tools-mt.1029.mcz Here is an example: [cid:bc6ba135-6701-4506-b25c-a2e8edfb33a1] Am 04.03.2021 15:38:47 schrieb commits at source.squeak.org : Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1029.mcz ==================== Summary ==================== Name: Tools-mt.1029 Author: mt Time: 4 March 2021, 3:38:36.350661 pm UUID: bef0c471-6ff1-774d-860e-8958e1aa508b Ancestors: Tools-mt.1028 Enable source-code dragging through a browser's message list to be dropped into the world to open a compact code editor. Complements Tools-mt.1028, ToolBuilder-Kernel-mt.139, ToolBuilder-Morphic-mt.274, and Morphic-mt.1733. =============== Diff against Tools-mt.1028 =============== Item was changed: ----- Method: Browser>>buildMessageListWith: (in category 'toolbuilder') ----- buildMessageListWith: builder | listSpec | listSpec := builder pluggableListSpec new. listSpec model: self; list: #messageList; getIndex: #messageListIndex; setIndex: #messageListIndex:; icon: #messageIconAt:; helpItem: #messageHelpAt:; menu: #messageListMenu:shifted:; keyPress: #messageListKey:from:. + SystemBrowser browseWithDragNDrop ifTrue: [ + listSpec + dragItem: #dragFromMessageList:; + dragType: #dragTypeForMessageListAt:]. - SystemBrowser browseWithDragNDrop - ifTrue:[listSpec dragItem: #dragFromMessageList:]. ^listSpec ! Item was added: + ----- Method: Browser>>dragTypeForMessageListAt: (in category 'drag and drop') ----- + dragTypeForMessageListAt: index + + ^ #sourceCode! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 412422 bytes Desc: image.png URL: From jakres+squeak at gmail.com Sun Apr 25 19:14:47 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 21:14:47 +0200 Subject: [squeak-dev] The Inbox: Kernel-mt.1390.mcz In-Reply-To: <79bc441b75b94ef1a116b5ba348940fd@student.hpi.uni-potsdam.de> References: <79bc441b75b94ef1a116b5ba348940fd@student.hpi.uni-potsdam.de> Message-ID: Real world example use cases if we had the Common Lisp experience: Try to install something via Metacello. Metacello would register "retry" restarts before downloading a package. The download of the last of dozens of packages fails three times, so Metacello errs out, you get a debugger notifier. You would click on "retry" to restart the package download instead of seeking out the correct context for that (requires Metacello knowledge), or instead of restarting the whole installation, which would needlessly repeat the dependency resolution up to the failed package. Similar: when hitting the "Connection closed" error after pushing to GitHub from the Git Browser, retry the upload without computing the set of commits and compiling the pack file again... I guess with extra (domain-specific) message box programming, this would already be feasible now: 1. Register upload error handler that prompts for retrying (GUI layer). 2. Compute the file to be uploaded. (3. Register restart context for upload retry.) 4. Register handler for Connection closed error; the handler will signal upload error. 5. Attempt upload, which hits Connection closed. 6. Gets handled, signals upload error for the GUI. 7. Gets handled, GUI prompts whether to retry. 8. User chooses "Yes", GUI lets resume from upload error with that choice. 9. Connection closed handler receives this choice, restarts from the retry context. With the extra mile UI stuff in the debugger/notifier, one would not need to write domain code for the steps 1, 4, 6, 7, 8, 9. So the only additional code would be registering the restart context (with a nice description text). Am So., 25. Apr. 2021 um 20:05 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > Hi Marcel, > > > these are interesting concepts though hard to evaluate without real-world > examples, I guess. But it does seem to be a crucial core concept to me. > Maybe this would better fit into the System package? I'd like to keep the > Kernel package as small as possible and this one is rather advanced stuff > ... 😊 > > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Taeumel, Marcel > *Gesendet:* Montag, 19. April 2021 17:50:02 > *An:* squeak-dev > *Betreff:* Re: [squeak-dev] The Inbox: Kernel-mt.1390.mcz > > Here are the two options in an exapmle: > > > Am 19.04.2021 17:48:03 schrieb commits at source.squeak.org < > commits at source.squeak.org>: > A new version of Kernel was added to project The Inbox: > http://source.squeak.org/inbox/Kernel-mt.1390.mcz > > ==================== Summary ==================== > > Name: Kernel-mt.1390 > Author: mt > Time: 19 April 2021, 5:47:51.865053 pm > UUID: c36ac126-16de-3d41-be90-6b7fd46bc0c7 > Ancestors: Kernel-nice.1389 > > Proposal. Better support for hot code updates by restarting from a denoted > (i.e. domain-specific) context (or active method). For example, this could > be used to better update the McmUpdater as soon as a code change in itself > is detected. Two options: either mark the restart context with an on:do: > handler or process a query to look up that context such as by package name. > > =============== Diff against Kernel-nice.1389 =============== > > Item was added: > + Notification subclass: #RestartContextRequest > + instanceVariableNames: '' > + classVariableNames: '' > + poolDictionaries: '' > + category: 'Kernel-Exceptions'! > > Item was added: > + ----- Method: RestartContextRequest class>>fromContextSuchThat: (in > category 'as yet unclassified') ----- > + fromContextSuchThat: block > + "Use this to restart from an arbitrary context on the stack." > + > + | context | > + context := thisContext sender. > + [context notNil] whileTrue: [ > + (block value: context) ifTrue: [ > + ^ self new restartFrom: context]. > + context := context sender]. > + self error: 'No context found!!'.! > > Item was added: > + ----- Method: RestartContextRequest>>restartFrom: (in category 'as yet > unclassified') ----- > + restartFrom: aContext > + > + | process actualContext unwindError | > + aContext ifNil: [^ self error: 'No context to restart!!']. > + > + process := Processor activeProcess. > + > + [actualContext := process popTo: aContext. > + unwindError := actualContext ~= aContext. > + unwindError > + ifTrue: [process resume] > + ifFalse: [process restartTop; stepToSendOrReturn; resume] > + ] fork. > + > + process suspend.! > > Item was added: > + ----- Method: RestartContextRequest>>restartFromHere (in category 'as > yet unclassified') ----- > + restartFromHere > + "Use this to restart from an exception handler." > + self restartFrom: handlerContext.! > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 158062 bytes Desc: not available URL: From jakres+squeak at gmail.com Sun Apr 25 19:16:36 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 21:16:36 +0200 Subject: [squeak-dev] The Trunk: Tools-mt.1029.mcz In-Reply-To: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> Message-ID: Now that I receive the list emails properly again as opposed to when this was committed: I also like this very much, thank you Marcel. :-) Am So., 25. Apr. 2021 um 20:49 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > I did not realize this new feature before I was cleaning up my inbox > today. Great idea (probably inspired from Vivide?)! :-) > > > Maybe reconsider the initialExtent of pure CodeHolders? By default, the > look a bit too large to me. > > > Best, > > Christoph > > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Taeumel, Marcel > *Gesendet:* Donnerstag, 4. März 2021 15:46:49 > *An:* squeak-dev > *Betreff:* Re: [squeak-dev] The Trunk: Tools-mt.1029.mcz > > Here is an example: > > > Am 04.03.2021 15:38:47 schrieb commits at source.squeak.org < > commits at source.squeak.org>: > Marcel Taeumel uploaded a new version of Tools to project The Trunk: > http://source.squeak.org/trunk/Tools-mt.1029.mcz > > ==================== Summary ==================== > > Name: Tools-mt.1029 > Author: mt > Time: 4 March 2021, 3:38:36.350661 pm > UUID: bef0c471-6ff1-774d-860e-8958e1aa508b > Ancestors: Tools-mt.1028 > > Enable source-code dragging through a browser's message list to be dropped > into the world to open a compact code editor. > > Complements Tools-mt.1028, ToolBuilder-Kernel-mt.139, > ToolBuilder-Morphic-mt.274, and Morphic-mt.1733. > > =============== Diff against Tools-mt.1028 =============== > > Item was changed: > ----- Method: Browser>>buildMessageListWith: (in category 'toolbuilder') > ----- > buildMessageListWith: builder > | listSpec | > listSpec := builder pluggableListSpec new. > listSpec > model: self; > list: #messageList; > getIndex: #messageListIndex; > setIndex: #messageListIndex:; > icon: #messageIconAt:; > helpItem: #messageHelpAt:; > menu: #messageListMenu:shifted:; > keyPress: #messageListKey:from:. > + SystemBrowser browseWithDragNDrop ifTrue: [ > + listSpec > + dragItem: #dragFromMessageList:; > + dragType: #dragTypeForMessageListAt:]. > - SystemBrowser browseWithDragNDrop > - ifTrue:[listSpec dragItem: #dragFromMessageList:]. > ^listSpec > ! > > Item was added: > + ----- Method: Browser>>dragTypeForMessageListAt: (in category 'drag and > drop') ----- > + dragTypeForMessageListAt: index > + > + ^ #sourceCode! > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 412422 bytes Desc: not available URL: From commits at source.squeak.org Sun Apr 25 19:32:01 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 19:32:01 0000 Subject: [squeak-dev] The Inbox: ToolBuilder-Tests-jr.6.mcz Message-ID: A new version of ToolBuilder-Tests was added to project The Inbox: http://source.squeak.org/inbox/ToolBuilder-Tests-jr.6.mcz ==================== Summary ==================== Name: ToolBuilder-Tests-jr.6 Author: jr Time: 25 April 2021, 9:32:10.341128 pm UUID: 3f989b9a-0bda-b446-9c00-1db787363c6c Ancestors: ToolBuilder-Tests-mt.5 Test that progress exceptions do not interfere with other exception handlers. At the time of this writing, this is broken in Squeak Trunk because too many handlers are reactivated. Related versions: - ToolBuilder-Kernel-nice.141 - ToolBuilder-Kernel-nice.142 Between the recent exception handler changes and the .141 version above, too few handlers were reactivated. =============== Diff against ToolBuilder-Tests-mt.5 =============== Item was added: + TestCase subclass: #ProgressInitiationExceptionTest + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'ToolBuilder-Tests'! Item was added: + ----- Method: ProgressInitiationExceptionTest>>testRearmedExceptionHandlers (in category 'test') ----- + testRearmedExceptionHandlers + "The work block should run with the same exception handlers active as the context that signalled the progress initiation. To verify that this test asserts the correct behavior, compare with the behavior if the ProgressInitiationException is not signalled, but just the work block executed." + | resultWithProgress resultWithoutProgress | + resultWithProgress := [ + [ + [ + [Warning signal: 'Pretend that a resource is missing'. + 'uncurtailed result' "Should not be reached"] + on: NotFound do: + [:e | e return: 'inner handler result' "Should not be reached"]] + on: Warning do: + [:e | "Pretend to download the missing resource. It takes long." + e return: + (ProgressInitiationException + display: 'some progress' from: 0 to: 1 + during: [:progress | + NotFound signal: 'should be handled by outer handler'])]] + on: NotFound do: + [:e | e return: 'outer handler result']] + on: ProgressInitiationException do: + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. + resultWithoutProgress := [ + [ + [ + [Warning signal: 'Pretend that a resource is missing'. + 'uncurtailed result' "Should not be reached"] + on: NotFound do: + [:e | e return: 'inner handler result' "Should not be reached"]] + on: Warning do: + [:e | "Pretend to download the missing resource. It takes long." + e return: + "Without ProgressInitiationException this time:" + (NotFound signal: 'should be handled by outer handler')]] + on: NotFound do: + [:e | e return: 'outer handler result']] + on: ProgressInitiationException do: + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. + self assert: resultWithoutProgress equals: resultWithProgress; + assert: 'outer handler result' equals: resultWithProgress. + "The stack should have looked like this with progress eventually: + - outer handler + - NotFound signal + - [sendNotificationsTo: silence] (reactivates outer handler) + - (found [sendNotificationsTo: silence], gets deactivated before being run) + - (outer handler gets deactivated) + - ProgressInitiationException signal + - warning handler + - (found warning handler, gets deactivated before being run) + - (inner handler gets deactivated) + - Warning signal + - on: NotFound do: inner handler + - on: Warning do: warning handler + - on: NotFound do: outer handler + - on: ProgressInitiationException do: [sendNotificationsTo: silence]"! From jakres+squeak at gmail.com Sun Apr 25 19:35:06 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sun, 25 Apr 2021 21:35:06 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.142.mcz In-Reply-To: References: Message-ID: Hi Nicolas, I got a MessageNotUnderstood with this one. Replaced the first self with thisContext nextHandlerContext to get around it. See ToolBuilder-Tests-jr.6 for a test case of what I would expect. It fails with and without this version ToolBuilder-Kernel-nice.142. Kind regards, Jakob Am Fr., 23. Apr. 2021 um 11:06 Uhr schrieb : > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.142.mcz > > ==================== Summary ==================== > > Name: ToolBuilder-Kernel-nice.142 > Author: nice > Time: 23 April 2021, 11:06:34.400228 am > UUID: 93216f25-69b2-43c3-b355-36a28cfd3588 > Ancestors: ToolBuilder-Kernel-nice.141 > > Attempt to allow nested sendNotificationsTo: handling. > Requires Kernel-nice.1391. > > The idea is that the handler shall not be active during the handlerAction. But still, we want he inner handlers to be active as was the case with former exception handling. > > Please write TestCase documenting expectations and review if this can possibly fit. > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > Item was changed: > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > sendNotificationsTo: aNewBlock > + | val | > + "Reactivate inner handlers so as to let them handle other exceptions" > + self > + reactivateHandlersWhich: [:aHandlerContext | (aHandlerContext willHandleSignal: self) not] > + upTo: handlerContext. > + val := workBlock value: [ :barVal | > - > - self reactivateHandlers; resumeUnchecked: ( > - workBlock value: [ :barVal | > aNewBlock value: minVal value: maxVal value: barVal > + ]. > + handlerContext ifNotNil: [handlerContext reactivateHandler]. > + self resumeUnchecked: val > - ] > - ) > ! > > From tim at rowledge.org Sun Apr 25 20:13:25 2021 From: tim at rowledge.org (tim Rowledge) Date: Sun, 25 Apr 2021 13:13:25 -0700 Subject: [squeak-dev] The Trunk: Tools-mt.1029.mcz In-Reply-To: References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> Message-ID: > On 2021-04-25, at 12:16 PM, Jakob Reschke wrote: > > Now that I receive the list emails properly again as opposed to when this was committed: > > I also like this very much, thank you Marcel. :-) It is indeed nice. Perhaps extendable for dragging protocols, classes or categories out as well? I remember doing some browser creation cleanup a while back that might tie in with the concept. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SLTMDL: Shift Left, Test Mask and Dim the Lights From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 20:36:36 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 20:36:36 +0000 Subject: [squeak-dev] The Trunk: Morphic-eem.1719.mcz In-Reply-To: References: <804594dd36de4be1b92d4dbecaaeb973@student.hpi.uni-potsdam.de>, Message-ID: Hi all, please find the attached changeset which fixes the regression of the smart search bar not honoring the #reuseWindows preference. Also, I added a proper implementation of #reuseWindows for browsers. Please review and/or merge! :-) Best, Christoph PS: What is packages at lists.squeakfoundation.org and why is it being cc'ed in this conversation? ________________________________ Von: Squeak-dev im Auftrag von Chris Muller Gesendet: Freitag, 5. Februar 2021 22:19:13 An: The general-purpose Squeak developers list Cc: packages at lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Morphic-eem.1719.mcz Hi Christoph! I thought this feature seemed reminiscent of Reuse Windows as well. The method to hook in each Model subclass (as needed) is #representsSameBrowseeAs:. Looking at that, you can see that simply making your code pane temporarily dirty, an additional window will be spawned. I mention that because Reuse Windows is fantastic and I hate to see your experience with it ruined over something so trivial. :) You do also have the green duplicate halo. People are happy to use "non-standard" UI features in other IDE's, but there seems to be an aversion to people using halos in Squeak. I could be wrong about that, but I find the duplicate halo useful quite often. - Chris On Thu, Feb 4, 2021 at 7:14 PM Thiede, Christoph > wrote: Hi Eliot, could you please honor the "SystemWindow reuseWindows" here? I have turned that preference off in my image because I actually use to accept a class name multiple times in the search bar in order to open multiple windows - for instance, to view different protocols of the same class side-by-side. It would be great if this would work soon again ... :-) Best, Christoph ________________________________ Von: Squeak-dev > im Auftrag von commits at source.squeak.org > Gesendet: Donnerstag, 4. Februar 2021 03:38:15 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Morphic-eem.1719.mcz Eliot Miranda uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-eem.1719.mcz ==================== Summary ==================== Name: Morphic-eem.1719 Author: eem Time: 3 February 2021, 6:38:11.11355 pm UUID: ffb981b1-7c53-4fbe-b6f4-4c8f27c79f5a Ancestors: Morphic-mt.1718 Make SearchBar>>#smartSearch:in: search existing browsers for a class name being searched for, bringing the first such browser to the front and selecting the class. This allows one to find classes in browsers either when one has very many, or when one is using multi-window browsers containing many many classes. =============== Diff against Morphic-mt.1718 =============== Item was added: + ----- Method: Browser>>displayClass: (in category '*Morphic-Menus-DockingBar-accessing') ----- + displayClass: aClass + "Assuming the receiver has answered true to isDisplayingClass:, come to the front and select the given class." + | index | + index := self multiWindowIndexForClassName: aClass. + index ~= 0 ifTrue: + [multiWindowState selectWindowIndex: index]. + self selectClass: aClass! Item was added: + ----- Method: Browser>>isDisplayingClass: (in category '*Morphic-Menus-DockingBar-accessing') ----- + isDisplayingClass: aClass + | className | + className := aClass name. + (self multiWindowIndexForClassName: className) ~= 0 ifTrue: [^true]. + ^selectedClassName = className! Item was added: + ----- Method: Browser>>multiWindowIndexForClassName: (in category '*Morphic-Menus-DockingBar-accessing') ----- + multiWindowIndexForClassName: className + "Answer the index of a browser displaying className in multiWindowState, if any. + Otherwise answer zero." + multiWindowState ifNil: [^0]. + multiWindowState models withIndexDo: + [:browser :index| + browser selectedClassName = className ifTrue: [^index]]. + ^0! Item was changed: ----- Method: SearchBar>>smartSearch:in: (in category 'searching') ----- smartSearch: text in: morph "Take the user input and perform an appropriate search" | input newContents | self removeResultsWidget. input := text asString ifEmpty:[^self]. self class useSmartSearch ifFalse: [^ ToolSet default browseMessageNames: input]. + (Symbol findInterned: input) ifNotNil: + [:symbol| input := symbol]. "If it is a global or a full class name, browse that class." + (Smalltalk bindingOf: input) ifNotNil: + [:assoc| | class | + class := (assoc value isBehavior ifTrue:[assoc value] ifFalse:[assoc value class]) theNonMetaClass. + Project current world submorphs do: + [:windowMorph| + (windowMorph isSystemWindow + and: [(windowMorph model isKindOf: Browser) + and: [windowMorph model isDisplayingClass: class]]) ifTrue: + [windowMorph beKeyWindow. + ^windowMorph model displayClass: class]]. + ^ToolSet browse: class selector: nil]. - (Smalltalk bindingOf: input) ifNotNil:[:assoc| | global | - global := assoc value. - ^ToolSet browse: (global isBehavior ifTrue:[global] ifFalse:[global class]) selector: nil]. "If it is a symbol and there are implementors of it, browse those implementors." Symbol hasInterned: input ifTrue: [:selector | (SystemNavigation new allImplementorsOf: selector) ifNotEmpty:[:list| ^SystemNavigation new browseMessageList: list name: 'Implementors of ' , input]]. "If it starts uppercase, browse classes if any. Otherwise, just search for messages." + input first isUppercase ifTrue: + [(UIManager default classFromPattern: input withCaption: '') + ifNotNil:[:aClass| ^ToolSet browse: aClass selector: nil]. + newContents := input, ' -- not found.'. + self searchTerm: newContents. + self selection: (input size+1 to: newContents size). + self currentHand newKeyboardFocus: morph textMorph. + ^ self]. + + "Default to browse message names..." + ToolSet default browseMessageNames: input! - input first isUppercase - ifTrue: [ - (UIManager default classFromPattern: input withCaption: '') - ifNotNil:[:aClass| ^ToolSet browse: aClass selector: nil] - ifNil: [ - newContents := input, ' -- not found.'. - self searchTerm: newContents. - self selection: (input size+1 to: newContents size). - self currentHand newKeyboardFocus: morph textMorph. - ^ self]] - ifFalse: [ - ToolSet default browseMessageNames: input].! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: Browser-reuseWindows.1.cs URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Sun Apr 25 21:59:01 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sun, 25 Apr 2021 21:59:01 +0000 Subject: [squeak-dev] The Trunk: Tools-mt.1029.mcz In-Reply-To: References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> , Message-ID: > Perhaps extendable for dragging protocols, classes or categories out as well? Wow, nice ideas! Please find the attached change set for a first attempt. It adds support for dragging classes, packages, system categories, and method categories from a browser into the world. For moving methods in a system browser, I have already committed some improvements recently. :-) If you like the proposal, we can rethink the dragTypeSelectors again. Maybe we should take up the proposals with MIME types again, but I am unsure how we can establish a simple but expressive drag type model. See PasteUpMorph >> #wantsDroppedTransferMorph: for a better understanding of the problem. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von tim Rowledge Gesendet: Sonntag, 25. April 2021 22:13:25 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Tools-mt.1029.mcz > On 2021-04-25, at 12:16 PM, Jakob Reschke wrote: > > Now that I receive the list emails properly again as opposed to when this was committed: > > I also like this very much, thank you Marcel. :-) It is indeed nice. Perhaps extendable for dragging protocols, classes or categories out as well? I remember doing some browser creation cleanup a while back that might tie in with the concept. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SLTMDL: Shift Left, Test Mask and Dim the Lights -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: world-drag-classes.2.cs URL: From tim at rowledge.org Sun Apr 25 23:02:01 2021 From: tim at rowledge.org (tim Rowledge) Date: Sun, 25 Apr 2021 16:02:01 -0700 Subject: [squeak-dev] Browser flash (was Re: The Trunk: Tools-mt.1029.mcz) In-Reply-To: References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> Message-ID: <12B8A259-39EC-453F-9CA2-D0F1E1BEB990@rowledge.org> > On 2021-04-25, at 2:59 PM, Thiede, Christoph wrote: > > Yeah, that's a very nice start. So, just as some thoughts relating - - how about some gesture to open a hierarchy browser instead ? Actually, a switch to change a typical browser into a hierarchy browser - in the manner of the inspect/explore switch - would be interesting - all the other browsers ought to support the drag stuff too. I see some do, but the messagetrace doesn't appear to. - drag a method into a MessageTrace browser and thus add implementors of that message to the stack. Maybe shift-drag adds senders of the message instead. Or, for a more extensive change, drop the message on the 'senders' button to see the senders, the 'implementors' to see (guess what) the implementors. Hell, have simple drop targets available to perform such actions; drag a method/class/etc onto a 'versions' drop target. Or 'fileout'. Etc. - Nothing to do with d&d, but how about a very simple way to add notes to methods in a browser? I'm thinking here of using a messagetrace browser and wanting to add little (pop-up?) notes to remind me of any points I notice as I follow the messages up and down. Why was I looking at this? What is it related to? All that stuff it is so easy to forget a week later when you start climbing back up the rabbit hole you fell into. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: BW: Branch on Whim From commits at source.squeak.org Sun Apr 25 23:50:16 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 23:50:16 0000 Subject: [squeak-dev] The Inbox: Kernel-nice.1394.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Inbox: http://source.squeak.org/inbox/Kernel-nice.1394.mcz ==================== Summary ==================== Name: Kernel-nice.1394 Author: nice Time: 26 April 2021, 1:50:12.861556 am UUID: 3a981b94-0213-44f3-8263-838dda062f8a Ancestors: Kernel-bp.1393 Revise exception handling so as to - inactivate inner handler blocks when the exception is signalled in an outer handler - except when the inner handler has been explicitely rearmed (see rearmHandlerDuring:) Implementation notes: add a marker to handleSignal:, so as to detect the case when an exception is signalled within the execution of a handler block. This induces a subtle difference: - findNextHandlerContext might now return a handleSignal: context, - while nextHandlerContext will only return a on:do: context (or nil). The new workhorse for finding the proper handler is now #nextHandlerContextForSignal: It finds and answers the (handler) context that will handle the exception, but if it finds a handleSignal: during the scan, it will restrict the search to rearmed handlers, until it reaches the handler of prior exception, at which step it continues to search normally. Due to the scanning of inner blocks, we still need a marker for blocking re-entrancy (handlerActive temp in on:do:), but also a marker for rearmed blocks (handlerRearmed in on:do:). This can't be the same marker: an example is testHandlerReentrancy: when the rearmed inner handler pass the exception to its outer handler, the outer handler must still be inactive if it raised the Exception. Borrow resumeEvaluating: to Cuis and use it in resignalAs: Use many small methods in order to make the intention more explicit than with those mysterious tempAt: tempAt:put: =============== Diff against Kernel-bp.1393 =============== Item was changed: ----- Method: BlockClosure>>on:do: (in category 'exceptions') ----- on: exceptionOrExceptionSet do: handlerAction "Evaluate the receiver in the scope of an exception handler." + | handlerActive handlerRearmed | - | handlerActive | "just a marker, fail and execute the following" handlerActive := true. + handlerRearmed := false. ^ self value! Item was changed: ----- Method: Context>>canHandleSignal: (in category 'private-exceptions') ----- canHandleSignal: exception "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception then return true, otherwise forward this message to the next handler context. If none left, return false (see nil>>canHandleSignal:)" + ^ (self willHandleSignal: exception) - ^ (((self tempAt: 1) handles: exception) and: [self tempAt: 3]) or: [self nextHandlerContext canHandleSignal: exception]. ! Item was added: + ----- Method: Context>>deactivateHandler (in category 'private-exceptions') ----- + deactivateHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 3 ifTrue: [self tempAt: 3 put: false] "this is temporary handlerActive in #on:do:"! Item was added: + ----- Method: Context>>desarmHandler (in category 'private-exceptions') ----- + desarmHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 4 ifTrue: [self tempAt: 4 put: false] "this is temporary handlerRearmed in #on:do:"! Item was added: + ----- Method: Context>>findNextHandlerContext (in category 'private-exceptions') ----- + findNextHandlerContext + "find next context marked with . + This can be either a handler context (on:do:), + or a handling context (handleSignal:)" + + ^ self sender findNextHandlerContextStarting! Item was added: + ----- Method: Context>>fireHandlerActionForSignal: (in category 'private-exceptions') ----- + fireHandlerActionForSignal: exception + "Sent to handler (on:do:) contexts only. + Perform the second argument, which is the handler action" + + ^(self tempAt: 2) cull: exception! Item was changed: ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- handleSignal: exception + "Sent to handler (on:do:) contexts only. + Execute the handler action block" - "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception - and the handler is active then execute my handle block (second arg), otherwise forward - this message to the next handler context. If none left, execute exception's defaultAction - (see nil>>handleSignal:)." + | val | + "just a marker, fail and execute the following" - | handlerActive val | - "If the context has been returned from the handlerActive temp var may not be accessible." - handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. - (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: - [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. - ^self nextHandlerContext handleSignal: exception]. - exception privHandlerContext: self contextTag. + self deactivateHandler. "Prevent re-entering the action block, unless it is explicitely rearmed" + val := [self fireHandlerActionForSignal: exception] ensure: [self reactivateHandler]. + self return: val "return from self if not otherwise directed in handle block"! - self tempAt: 3 put: false. "disable self while executing handle block" - val := [(self tempAt: 2) cull: exception] - ifCurtailed: [self tempAt: 3 put: true]. - self return: val "return from self if not otherwise directed in handle block" - ! Item was added: + ----- Method: Context>>isHandlerActive (in category 'private-exceptions') ----- + isHandlerActive + "Private - sent to exception handler context only (on:do:)" + + ^stackp >= 3 and: [(self tempAt: 3) == true] "this is temporary handlerActive in #on:do:"! Item was added: + ----- Method: Context>>isHandlerRearmed (in category 'private-exceptions') ----- + isHandlerRearmed + "Private - sent to exception handler context only (on:do:)" + + ^stackp >= 4 and: [(self tempAt: 4) == true] "this is temporary handlerRearmed in #on:do:"! Item was changed: ----- Method: Context>>nextHandlerContext (in category 'private-exceptions') ----- nextHandlerContext + "Answer the next handler context (on:do:) in the call chain. + Answer nil if none found" + + | handler | + handler := self findNextHandlerContext. + [handler ifNil: [^nil]. + handler selector == #handleSignal:] + whileTrue: [handler := handler findNextHandlerContext]. + ^handler! - - ^ self sender findNextHandlerContextStarting! Item was added: + ----- Method: Context>>nextHandlerContextForSignal: (in category 'private-exceptions') ----- + nextHandlerContextForSignal: exception + "Answer the handler context (on:do:) for this exception + Answer nil if none found" + + | handler priorHandler | + handler := self. + [(handler := handler findNextHandlerContext) ifNil: [^nil]. + handler selector == #handleSignal:] + whileFalse: [(handler willHandleSignal: exception) ifTrue: [^handler]]. + + "exception has been signalled in the scope of another signal handler (while #handleSignal:) + Check for a rearmed inner handler. If none, jump to outer handler context." + priorHandler := (handler tempAt: 1) "the exception argument to handleSignal:" + privHandlerContext. + + [(handler := handler nextHandlerContext) ifNil: [^nil]. + (handler isHandlerRearmed and: [handler willHandleSignal: exception]) ifTrue: [^handler]. + handler == priorHandler] whileFalse. + + ^priorHandler nextHandlerContextForSignal: exception! Item was added: + ----- Method: Context>>reactivateHandler (in category 'private-exceptions') ----- + reactivateHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 3 ifTrue: [self tempAt: 3 put: true] "this is temporary handlerActive in #on:do:"! Item was changed: ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- reactivateHandlers + "Private - exception handling + do nothing, this method is only here for smooth transition. + It shall be removed at next update map." - "Private - sent to exception handler context only (on:do:). - Reactivate all the handlers into the chain" + ^self! - self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" - self nextHandlerContext reactivateHandlers! Item was added: + ----- Method: Context>>rearmHandler (in category 'private-exceptions') ----- + rearmHandler + "Private - sent to exception handler context only (on:do:)" + + self reactivateHandler. + stackp >= 4 ifTrue: [self tempAt: 4 put: true] "this is temporary handlerRearmed in #on:do:"! Item was changed: ----- Method: Context>>rearmHandlerDuring: (in category 'private-exceptions') ----- rearmHandlerDuring: aBlock "Sent to handler (on:do:) contexts only. Makes me re-entrant for the duration of aBlock. Only works in a closure-enabled image" + ^ [self rearmHandler. aBlock value] + ensure: [self desarmHandler]! - ^ [self tempAt: 3 put: true. aBlock value] - ensure: [self tempAt: 3 put: false]! Item was added: + ----- Method: Context>>rearmHandlersWhich:upTo: (in category 'private-exceptions') ----- + rearmHandlersWhich: selectBlock upTo: aHandlerContext + "Private - sent to exception handler context only (on:do:). + Rearm the inner handlers into the chain, up to, but not including, aHandlerContext, that satisfy the selectBlock predicate" + + self == aHandlerContext ifTrue: [^self]. + (selectBlock value: self) ifTrue: [self rearmHandler]. + self nextHandlerContext rearmHandlersWhich: selectBlock upTo: aHandlerContext! Item was changed: ----- Method: Context>>resume: (in category 'controlling') ----- resume: value "Unwind thisContext to self and resume with value as result of last send. Execute unwind blocks when unwinding. ASSUMES self is a sender of thisContext" + ^self resumeEvaluating: [value] - | ctxt unwindBlock | - self isDead ifTrue: [self cannotReturn: value to: self]. - ctxt := thisContext. - [ ctxt := ctxt findNextUnwindContextUpTo: self. - ctxt isNil - ] whileFalse: [ - (ctxt tempAt: 2) ifNil:[ - ctxt tempAt: 2 put: true. - unwindBlock := ctxt tempAt: 1. - thisContext terminateTo: ctxt. - unwindBlock value]. - ]. - thisContext terminateTo: self. - ^ value ! Item was added: + ----- Method: Context>>resumeEvaluating: (in category 'controlling') ----- + resumeEvaluating: aBlock + "Unwind thisContext to self and resume with value as result of last send. + Execute unwind blocks when unwinding. + ASSUMES self is a sender of thisContext" + + | ctxt unwindBlock | + self isDead ifTrue: [self cannotReturn: aBlock value to: self]. + ctxt := thisContext. + [ ctxt := ctxt findNextUnwindContextUpTo: self. + ctxt isNil + ] whileFalse: [ + (ctxt tempAt: 2) ifNil:[ + ctxt tempAt: 2 put: true. + unwindBlock := ctxt tempAt: 1. + thisContext terminateTo: ctxt. + unwindBlock value]. + ]. + thisContext terminateTo: self. + ^ aBlock value + ! Item was added: + ----- Method: Context>>returnEvaluating: (in category 'controlling') ----- + returnEvaluating: aBlock + "Unwind thisContext to self and return aBlock value to self's sender. + Execute any unwind blocks while unwinding. + ASSUMES self is a sender of thisContext" + + sender ifNil: [self cannotReturn: aBlock value to: sender]. + sender resumeEvaluating: aBlock! Item was added: + ----- Method: Context>>willHandleSignal: (in category 'private-exceptions') ----- + willHandleSignal: exception + "Sent to handler (on:do:) contexts only." + + ^self isHandlerActive and: [(self tempAt: 1) handles: exception] + ! Item was changed: ----- Method: Exception>>pass (in category 'handling') ----- pass "Yield control to the enclosing exception action for the receiver." + (handlerContext nextHandlerContextForSignal: self) handleSignal: self! - handlerContext nextHandlerContext handleSignal: self! Item was added: + ----- Method: Exception>>privHandlerContext (in category 'priv handling') ----- + privHandlerContext + ^handlerContext! Item was changed: ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- reactivateHandlers + "Private - exception handling + do nothing, this method is only here for smooth transition. + It shall be removed at next update map." + + ^self! - "reactivate all the exception handlers in the context chain" - self canSearchForSignalerContext - ifTrue: [signalContext nextHandlerContext reactivateHandlers]! Item was changed: ----- Method: Exception>>resignalAs: (in category 'handling') ----- resignalAs: replacementException "Signal an alternative exception in place of the receiver." + self resumeEvaluating: [replacementException signal]! - self reactivateHandlers. - self resumeUnchecked: replacementException signal! Item was changed: ----- Method: Exception>>resume: (in category 'handling') ----- resume: resumptionValue "Return resumptionValue as the value of the signal message." self isResumable ifFalse: [IllegalResumeAttempt signal]. - self reactivateHandlers. self resumeUnchecked: resumptionValue! Item was added: + ----- Method: Exception>>resumeEvaluating: (in category 'handling') ----- + resumeEvaluating: aBlock + "Return result of evaluating aBlock as the value of #signal, unless this was called after an #outer message, then return resumptionValue as the value of #outer. + The block is only evaluated after unwinding the stack." + + | ctxt | + outerContext ifNil: [ + signalContext returnEvaluating: aBlock + ] ifNotNil: [ + ctxt := outerContext. + outerContext := ctxt tempAt: 1. "prevOuterContext in #outer" + ctxt returnEvaluating: aBlock + ]. + ! Item was changed: ----- Method: Exception>>signal (in category 'signaling') ----- signal "Ask ContextHandlers in the sender chain to handle this signal. The default is to execute and return my defaultAction." signalContext := thisContext contextTag. + ^(thisContext nextHandlerContextForSignal: self) handleSignal: self! - ^ thisContext nextHandlerContext handleSignal: self! Item was changed: ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- handleSignal: exception + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. - Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." + ^ exception resumeUnchecked: exception defaultAction! - ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! Item was removed: - ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- - reactivateHandlers - "nothing to do for bottom context" - - ^ self! Item was added: + ----- Method: UndefinedObject>>rearmHandlersWhich:upTo: (in category 'bottom context') ----- + rearmHandlersWhich: selectBlock upTo: aHandlerContext + + ^ self! From nicolas.cellier.aka.nice at gmail.com Sun Apr 25 23:50:20 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 26 Apr 2021 01:50:20 +0200 Subject: [squeak-dev] The Inbox: Tests-jr.457.mcz In-Reply-To: References: Message-ID: Thanks, that's a valid example I think. I have sketched a new solution that still enables to rearmHandlerDuring: Reminder: the semantics of rearmHandlerDuring: is to let the handler be active, even if it is an inner handler. The only solution that I've found is to have both temps in on:do: - isHandlerActive to prevent re-entrancy - isHandlerRearmed to allow both re-entrancy and inner handler activation I've started with only the last one, but I've then got an infinite loop in testHandlerReentrancy. The principle is again to mark handleSignal: with Then, during the scan for active handler, if we encounter a handleSignal: context, then it means that the exception was signalled when handling another exception (via the action block of a handler). If that's the case, instead of jumping to (handlerContext nextActiveHandler) of the prior exception (handleSignalContext tempAt: 1) like I proposed in the past (or like in Cuis), we continue scanning the stack linearly for the case of a rearmed handler... Note that we still want to rearm the inner handlers in case of ProgressInitiationException... Le dim. 25 avr. 2021 à 17:39, a écrit : > > A new version of Tests was added to project The Inbox: > http://source.squeak.org/inbox/Tests-jr.457.mcz > > ==================== Summary ==================== > > Name: Tests-jr.457 > Author: jr > Time: 25 April 2021, 5:39:42.729128 pm > UUID: 38bb7c0a-ba18-0e43-866f-4f252c20a2d8 > Ancestors: Tests-nice.455 > > Test case for precise handler reactivation when nested exceptions are signalled and resumed. > > At the moment of writing this, this is broken in Squeak Trunk and the test case would run endlessly if there were no timeout. The reason is that the inner error handler is reactivated when the signal emitted by it is resumed. > > Related versions: > - Kernel-nice.1384 > - Kernel-nice.1391 > - ToolBuilder-Kernel-nice.141 > - ToolBuilder-Kernel-nice.142 > > =============== Diff against Tests-nice.455 =============== > > Item was added: > + ----- Method: ExceptionTests>>testHandlersReactivatedOnResume (in category 'tests - outer') ----- > + testHandlersReactivatedOnResume > + > + | result | > + result := [ > + [ > + [self error: 'to be handled by the inner handler'] > + on: Error do: > + [:e | > + Warning signal: 'to be resumed by the middle handler'. > + "After resuming from the Warning, its handler must be active again." > + Warning signal: 'to be resumed by the middle handler'. > + self error: 'to be handled by the outer handler'. > + e return: 'inner result']] > + on: Warning do: > + [:e | e resume "This must not rearm the inner Error handler above"]] > + on: Error do: > + [:e | e return: 'outer result']. > + self assert: 'outer result' equals: result.! > > From commits at source.squeak.org Sun Apr 25 23:53:35 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sun, 25 Apr 2021 23:53:35 0000 Subject: [squeak-dev] The Trunk: Tests-jr.457.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-jr.457.mcz ==================== Summary ==================== Name: Tests-jr.457 Author: jr Time: 25 April 2021, 5:39:42.729128 pm UUID: 38bb7c0a-ba18-0e43-866f-4f252c20a2d8 Ancestors: Tests-nice.455 Test case for precise handler reactivation when nested exceptions are signalled and resumed. At the moment of writing this, this is broken in Squeak Trunk and the test case would run endlessly if there were no timeout. The reason is that the inner error handler is reactivated when the signal emitted by it is resumed. Related versions: - Kernel-nice.1384 - Kernel-nice.1391 - ToolBuilder-Kernel-nice.141 - ToolBuilder-Kernel-nice.142 =============== Diff against Tests-nice.455 =============== Item was added: + ----- Method: ExceptionTests>>testHandlersReactivatedOnResume (in category 'tests - outer') ----- + testHandlersReactivatedOnResume + + | result | + result := [ + [ + [self error: 'to be handled by the inner handler'] + on: Error do: + [:e | + Warning signal: 'to be resumed by the middle handler'. + "After resuming from the Warning, its handler must be active again." + Warning signal: 'to be resumed by the middle handler'. + self error: 'to be handled by the outer handler'. + e return: 'inner result']] + on: Warning do: + [:e | e resume "This must not rearm the inner Error handler above"]] + on: Error do: + [:e | e return: 'outer result']. + self assert: 'outer result' equals: result.! From commits at source.squeak.org Mon Apr 26 00:09:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 00:09:46 0000 Subject: [squeak-dev] The Trunk: ToolBuilder-Tests-jr.6.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolBuilder-Tests to project The Trunk: http://source.squeak.org/trunk/ToolBuilder-Tests-jr.6.mcz ==================== Summary ==================== Name: ToolBuilder-Tests-jr.6 Author: jr Time: 25 April 2021, 9:32:10.341128 pm UUID: 3f989b9a-0bda-b446-9c00-1db787363c6c Ancestors: ToolBuilder-Tests-mt.5 Test that progress exceptions do not interfere with other exception handlers. At the time of this writing, this is broken in Squeak Trunk because too many handlers are reactivated. Related versions: - ToolBuilder-Kernel-nice.141 - ToolBuilder-Kernel-nice.142 Between the recent exception handler changes and the .141 version above, too few handlers were reactivated. =============== Diff against ToolBuilder-Tests-mt.5 =============== Item was added: + TestCase subclass: #ProgressInitiationExceptionTest + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'ToolBuilder-Tests'! Item was added: + ----- Method: ProgressInitiationExceptionTest>>testRearmedExceptionHandlers (in category 'test') ----- + testRearmedExceptionHandlers + "The work block should run with the same exception handlers active as the context that signalled the progress initiation. To verify that this test asserts the correct behavior, compare with the behavior if the ProgressInitiationException is not signalled, but just the work block executed." + | resultWithProgress resultWithoutProgress | + resultWithProgress := [ + [ + [ + [Warning signal: 'Pretend that a resource is missing'. + 'uncurtailed result' "Should not be reached"] + on: NotFound do: + [:e | e return: 'inner handler result' "Should not be reached"]] + on: Warning do: + [:e | "Pretend to download the missing resource. It takes long." + e return: + (ProgressInitiationException + display: 'some progress' from: 0 to: 1 + during: [:progress | + NotFound signal: 'should be handled by outer handler'])]] + on: NotFound do: + [:e | e return: 'outer handler result']] + on: ProgressInitiationException do: + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. + resultWithoutProgress := [ + [ + [ + [Warning signal: 'Pretend that a resource is missing'. + 'uncurtailed result' "Should not be reached"] + on: NotFound do: + [:e | e return: 'inner handler result' "Should not be reached"]] + on: Warning do: + [:e | "Pretend to download the missing resource. It takes long." + e return: + "Without ProgressInitiationException this time:" + (NotFound signal: 'should be handled by outer handler')]] + on: NotFound do: + [:e | e return: 'outer handler result']] + on: ProgressInitiationException do: + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. + self assert: resultWithoutProgress equals: resultWithProgress; + assert: 'outer handler result' equals: resultWithProgress. + "The stack should have looked like this with progress eventually: + - outer handler + - NotFound signal + - [sendNotificationsTo: silence] (reactivates outer handler) + - (found [sendNotificationsTo: silence], gets deactivated before being run) + - (outer handler gets deactivated) + - ProgressInitiationException signal + - warning handler + - (found warning handler, gets deactivated before being run) + - (inner handler gets deactivated) + - Warning signal + - on: NotFound do: inner handler + - on: Warning do: warning handler + - on: NotFound do: outer handler + - on: ProgressInitiationException do: [sendNotificationsTo: silence]"! From nicolas.cellier.aka.nice at gmail.com Mon Apr 26 00:14:48 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 26 Apr 2021 02:14:48 +0200 Subject: [squeak-dev] The Trunk: ToolBuilder-Tests-jr.6.mcz In-Reply-To: References: Message-ID: Very good example, but this one, i don't know how to solve yet. I thought that I could use resumeEvaluating: introduced in the inbox Kernel-nice.1394 in order to evaluate the block in the context that did send the signal. But this is dangerous if the block tries to manipulate the stack (like doing a resume: or return: or...). Le lun. 26 avr. 2021 à 02:09, a écrit : > > Nicolas Cellier uploaded a new version of ToolBuilder-Tests to project The Trunk: > http://source.squeak.org/trunk/ToolBuilder-Tests-jr.6.mcz > > ==================== Summary ==================== > > Name: ToolBuilder-Tests-jr.6 > Author: jr > Time: 25 April 2021, 9:32:10.341128 pm > UUID: 3f989b9a-0bda-b446-9c00-1db787363c6c > Ancestors: ToolBuilder-Tests-mt.5 > > Test that progress exceptions do not interfere with other exception handlers. > > At the time of this writing, this is broken in Squeak Trunk because too many handlers are reactivated. > > Related versions: > - ToolBuilder-Kernel-nice.141 > - ToolBuilder-Kernel-nice.142 > > Between the recent exception handler changes and the .141 version above, too few handlers were reactivated. > > =============== Diff against ToolBuilder-Tests-mt.5 =============== > > Item was added: > + TestCase subclass: #ProgressInitiationExceptionTest > + instanceVariableNames: '' > + classVariableNames: '' > + poolDictionaries: '' > + category: 'ToolBuilder-Tests'! > > Item was added: > + ----- Method: ProgressInitiationExceptionTest>>testRearmedExceptionHandlers (in category 'test') ----- > + testRearmedExceptionHandlers > + "The work block should run with the same exception handlers active as the context that signalled the progress initiation. To verify that this test asserts the correct behavior, compare with the behavior if the ProgressInitiationException is not signalled, but just the work block executed." > + | resultWithProgress resultWithoutProgress | > + resultWithProgress := [ > + [ > + [ > + [Warning signal: 'Pretend that a resource is missing'. > + 'uncurtailed result' "Should not be reached"] > + on: NotFound do: > + [:e | e return: 'inner handler result' "Should not be reached"]] > + on: Warning do: > + [:e | "Pretend to download the missing resource. It takes long." > + e return: > + (ProgressInitiationException > + display: 'some progress' from: 0 to: 1 > + during: [:progress | > + NotFound signal: 'should be handled by outer handler'])]] > + on: NotFound do: > + [:e | e return: 'outer handler result']] > + on: ProgressInitiationException do: > + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. > + resultWithoutProgress := [ > + [ > + [ > + [Warning signal: 'Pretend that a resource is missing'. > + 'uncurtailed result' "Should not be reached"] > + on: NotFound do: > + [:e | e return: 'inner handler result' "Should not be reached"]] > + on: Warning do: > + [:e | "Pretend to download the missing resource. It takes long." > + e return: > + "Without ProgressInitiationException this time:" > + (NotFound signal: 'should be handled by outer handler')]] > + on: NotFound do: > + [:e | e return: 'outer handler result']] > + on: ProgressInitiationException do: > + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. > + self assert: resultWithoutProgress equals: resultWithProgress; > + assert: 'outer handler result' equals: resultWithProgress. > + "The stack should have looked like this with progress eventually: > + - outer handler > + - NotFound signal > + - [sendNotificationsTo: silence] (reactivates outer handler) > + - (found [sendNotificationsTo: silence], gets deactivated before being run) > + - (outer handler gets deactivated) > + - ProgressInitiationException signal > + - warning handler > + - (found warning handler, gets deactivated before being run) > + - (inner handler gets deactivated) > + - Warning signal > + - on: NotFound do: inner handler > + - on: Warning do: warning handler > + - on: NotFound do: outer handler > + - on: ProgressInitiationException do: [sendNotificationsTo: silence]"! > > From commits at source.squeak.org Mon Apr 26 00:20:22 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 00:20:22 0000 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-nice.143 Author: nice Time: 26 April 2021, 2:20:20.490026 am UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 Ancestors: ToolBuilder-Kernel-nice.141 Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal =============== Diff against ToolBuilder-Kernel-nice.141 =============== Item was changed: ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- sendNotificationsTo: aNewBlock + self resumeEvaluating: [workBlock value: [ :barVal | - - self reactivateHandlers; resumeUnchecked: ( - workBlock value: [ :barVal | aNewBlock value: minVal value: maxVal value: barVal + ]] - ] - ) ! From nicolas.cellier.aka.nice at gmail.com Mon Apr 26 00:23:26 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 26 Apr 2021 02:23:26 +0200 Subject: [squeak-dev] The Trunk: ToolBuilder-Tests-jr.6.mcz In-Reply-To: References: Message-ID: I've put the resumeEvaluating: solution in the inbox, though. Test thoroughly and report if some block cannot return... Le lun. 26 avr. 2021 à 02:14, Nicolas Cellier a écrit : > > Very good example, but this one, i don't know how to solve yet. > > I thought that I could use resumeEvaluating: introduced in the inbox > Kernel-nice.1394 in order to evaluate the block in the context that > did send the signal. > But this is dangerous if the block tries to manipulate the stack (like > doing a resume: or return: or...). > > > Le lun. 26 avr. 2021 à 02:09, a écrit : > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Tests to project The Trunk: > > http://source.squeak.org/trunk/ToolBuilder-Tests-jr.6.mcz > > > > ==================== Summary ==================== > > > > Name: ToolBuilder-Tests-jr.6 > > Author: jr > > Time: 25 April 2021, 9:32:10.341128 pm > > UUID: 3f989b9a-0bda-b446-9c00-1db787363c6c > > Ancestors: ToolBuilder-Tests-mt.5 > > > > Test that progress exceptions do not interfere with other exception handlers. > > > > At the time of this writing, this is broken in Squeak Trunk because too many handlers are reactivated. > > > > Related versions: > > - ToolBuilder-Kernel-nice.141 > > - ToolBuilder-Kernel-nice.142 > > > > Between the recent exception handler changes and the .141 version above, too few handlers were reactivated. > > > > =============== Diff against ToolBuilder-Tests-mt.5 =============== > > > > Item was added: > > + TestCase subclass: #ProgressInitiationExceptionTest > > + instanceVariableNames: '' > > + classVariableNames: '' > > + poolDictionaries: '' > > + category: 'ToolBuilder-Tests'! > > > > Item was added: > > + ----- Method: ProgressInitiationExceptionTest>>testRearmedExceptionHandlers (in category 'test') ----- > > + testRearmedExceptionHandlers > > + "The work block should run with the same exception handlers active as the context that signalled the progress initiation. To verify that this test asserts the correct behavior, compare with the behavior if the ProgressInitiationException is not signalled, but just the work block executed." > > + | resultWithProgress resultWithoutProgress | > > + resultWithProgress := [ > > + [ > > + [ > > + [Warning signal: 'Pretend that a resource is missing'. > > + 'uncurtailed result' "Should not be reached"] > > + on: NotFound do: > > + [:e | e return: 'inner handler result' "Should not be reached"]] > > + on: Warning do: > > + [:e | "Pretend to download the missing resource. It takes long." > > + e return: > > + (ProgressInitiationException > > + display: 'some progress' from: 0 to: 1 > > + during: [:progress | > > + NotFound signal: 'should be handled by outer handler'])]] > > + on: NotFound do: > > + [:e | e return: 'outer handler result']] > > + on: ProgressInitiationException do: > > + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. > > + resultWithoutProgress := [ > > + [ > > + [ > > + [Warning signal: 'Pretend that a resource is missing'. > > + 'uncurtailed result' "Should not be reached"] > > + on: NotFound do: > > + [:e | e return: 'inner handler result' "Should not be reached"]] > > + on: Warning do: > > + [:e | "Pretend to download the missing resource. It takes long." > > + e return: > > + "Without ProgressInitiationException this time:" > > + (NotFound signal: 'should be handled by outer handler')]] > > + on: NotFound do: > > + [:e | e return: 'outer handler result']] > > + on: ProgressInitiationException do: > > + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. > > + self assert: resultWithoutProgress equals: resultWithProgress; > > + assert: 'outer handler result' equals: resultWithProgress. > > + "The stack should have looked like this with progress eventually: > > + - outer handler > > + - NotFound signal > > + - [sendNotificationsTo: silence] (reactivates outer handler) > > + - (found [sendNotificationsTo: silence], gets deactivated before being run) > > + - (outer handler gets deactivated) > > + - ProgressInitiationException signal > > + - warning handler > > + - (found warning handler, gets deactivated before being run) > > + - (inner handler gets deactivated) > > + - Warning signal > > + - on: NotFound do: inner handler > > + - on: Warning do: warning handler > > + - on: NotFound do: outer handler > > + - on: ProgressInitiationException do: [sendNotificationsTo: silence]"! > > > > From nicolas.cellier.aka.nice at gmail.com Mon Apr 26 00:24:30 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 26 Apr 2021 02:24:30 +0200 Subject: [squeak-dev] The Trunk: ToolBuilder-Tests-jr.6.mcz In-Reply-To: References: Message-ID: Forgot to say, it's ToolBuilder-Kernel-nice.143 and it goes with Kernel-nice.1394 Le lun. 26 avr. 2021 à 02:23, Nicolas Cellier a écrit : > > I've put the resumeEvaluating: solution in the inbox, though. > Test thoroughly and report if some block cannot return... > > Le lun. 26 avr. 2021 à 02:14, Nicolas Cellier > a écrit : > > > > Very good example, but this one, i don't know how to solve yet. > > > > I thought that I could use resumeEvaluating: introduced in the inbox > > Kernel-nice.1394 in order to evaluate the block in the context that > > did send the signal. > > But this is dangerous if the block tries to manipulate the stack (like > > doing a resume: or return: or...). > > > > > > Le lun. 26 avr. 2021 à 02:09, a écrit : > > > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Tests to project The Trunk: > > > http://source.squeak.org/trunk/ToolBuilder-Tests-jr.6.mcz > > > > > > ==================== Summary ==================== > > > > > > Name: ToolBuilder-Tests-jr.6 > > > Author: jr > > > Time: 25 April 2021, 9:32:10.341128 pm > > > UUID: 3f989b9a-0bda-b446-9c00-1db787363c6c > > > Ancestors: ToolBuilder-Tests-mt.5 > > > > > > Test that progress exceptions do not interfere with other exception handlers. > > > > > > At the time of this writing, this is broken in Squeak Trunk because too many handlers are reactivated. > > > > > > Related versions: > > > - ToolBuilder-Kernel-nice.141 > > > - ToolBuilder-Kernel-nice.142 > > > > > > Between the recent exception handler changes and the .141 version above, too few handlers were reactivated. > > > > > > =============== Diff against ToolBuilder-Tests-mt.5 =============== > > > > > > Item was added: > > > + TestCase subclass: #ProgressInitiationExceptionTest > > > + instanceVariableNames: '' > > > + classVariableNames: '' > > > + poolDictionaries: '' > > > + category: 'ToolBuilder-Tests'! > > > > > > Item was added: > > > + ----- Method: ProgressInitiationExceptionTest>>testRearmedExceptionHandlers (in category 'test') ----- > > > + testRearmedExceptionHandlers > > > + "The work block should run with the same exception handlers active as the context that signalled the progress initiation. To verify that this test asserts the correct behavior, compare with the behavior if the ProgressInitiationException is not signalled, but just the work block executed." > > > + | resultWithProgress resultWithoutProgress | > > > + resultWithProgress := [ > > > + [ > > > + [ > > > + [Warning signal: 'Pretend that a resource is missing'. > > > + 'uncurtailed result' "Should not be reached"] > > > + on: NotFound do: > > > + [:e | e return: 'inner handler result' "Should not be reached"]] > > > + on: Warning do: > > > + [:e | "Pretend to download the missing resource. It takes long." > > > + e return: > > > + (ProgressInitiationException > > > + display: 'some progress' from: 0 to: 1 > > > + during: [:progress | > > > + NotFound signal: 'should be handled by outer handler'])]] > > > + on: NotFound do: > > > + [:e | e return: 'outer handler result']] > > > + on: ProgressInitiationException do: > > > + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. > > > + resultWithoutProgress := [ > > > + [ > > > + [ > > > + [Warning signal: 'Pretend that a resource is missing'. > > > + 'uncurtailed result' "Should not be reached"] > > > + on: NotFound do: > > > + [:e | e return: 'inner handler result' "Should not be reached"]] > > > + on: Warning do: > > > + [:e | "Pretend to download the missing resource. It takes long." > > > + e return: > > > + "Without ProgressInitiationException this time:" > > > + (NotFound signal: 'should be handled by outer handler')]] > > > + on: NotFound do: > > > + [:e | e return: 'outer handler result']] > > > + on: ProgressInitiationException do: > > > + [:e | e sendNotificationsTo: [:min :max :value | "silence"]]. > > > + self assert: resultWithoutProgress equals: resultWithProgress; > > > + assert: 'outer handler result' equals: resultWithProgress. > > > + "The stack should have looked like this with progress eventually: > > > + - outer handler > > > + - NotFound signal > > > + - [sendNotificationsTo: silence] (reactivates outer handler) > > > + - (found [sendNotificationsTo: silence], gets deactivated before being run) > > > + - (outer handler gets deactivated) > > > + - ProgressInitiationException signal > > > + - warning handler > > > + - (found warning handler, gets deactivated before being run) > > > + - (inner handler gets deactivated) > > > + - Warning signal > > > + - on: NotFound do: inner handler > > > + - on: Warning do: warning handler > > > + - on: NotFound do: outer handler > > > + - on: ProgressInitiationException do: [sendNotificationsTo: silence]"! > > > > > > From marcel.taeumel at hpi.de Mon Apr 26 06:31:41 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 08:31:41 +0200 Subject: [squeak-dev] FFI: FFI-Kernel-mt.120.mcz In-Reply-To: References: Message-ID: Hi Jakob, aha! Thanks for the "pointer." :-) *scnr* Best, Marcel Am 24.04.2021 14:23:42 schrieb Jakob Reschke : schrieb am Di., 20. Apr. 2021 Item was changed: + ----- Method: ExternalData>>fromCStrings (in category 'converting - support') ----- - ----- Method: ExternalData>>fromCStrings (in category 'converting') -----   fromCStrings         "Assume that the receiver represents a set of C strings and is teerminated by a empty string and convert it to a Smalltalk ordered collection of strings"         | stream index char strings str |         type isPointerType ifFalse: [self error: 'External object is not a pointer type.']. +       self flag: #bogus. "mt: This format seems to be rather specific to some library. There would normally be pointers to pointers for such a structure. Or does the C standard mention such a format somehow? 'abcd\0efg\0hijklmnopq\0rstuvwxyz\0\0' ??? "         strings := OrderedCollection new.         index := 1.         [                 stream := WriteStream on: String new.                 [(char := handle unsignedCharAt: index) = 0 asCharacter]                         whileFalse: [                                 stream nextPut: char.                                 index := index + 1                         ].                 str := stream contents.                 strings addLast: str.                 str size = 0         ] whileFalse.         ^strings! Seems to be an API specific thing: https://devblogs.microsoft.com/oldnewthing/20110511-00/?p=10693 [https://devblogs.microsoft.com/oldnewthing/20110511-00/?p=10693] https://devblogs.microsoft.com/oldnewthing/20091008-00/?p=16443 [https://devblogs.microsoft.com/oldnewthing/20091008-00/?p=16443] -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 26 06:34:56 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 08:34:56 +0200 Subject: [squeak-dev] Smalltalk Zoo not written in Smalltalk In-Reply-To: References: Message-ID: Hi Christoph. > Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Why is SqueakJS (https://squeak.js.org/ [https://squeak.js.org/]) not what you are looking for? Best, Marcel Am 25.04.2021 20:41:17 schrieb Thiede, Christoph : Hi all, just a short and curious questions, but not guaranteed to be completely unprovoking. :-) Why is Smalltalk Zoo, the virtual exhibition which compares different milestones in the history of Squeak/Smalltalk, not implemented in Smalltalk itself but in JavaScript, a language which cannot compile itself, is quite the oppposite of Smalltalk in terms of clearness of expression, and escapes control of the actual application? While I love the idea in general, I think it's a shame that the zoo of a language that aims to be implemented in itself is not implemented in that language itself. :D Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 26 06:40:39 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 08:40:39 +0200 Subject: [squeak-dev] Please try it out | Fixing the input mapping for keystroke events In-Reply-To: References: <,> Message-ID: Hi Christoph. > When pressing something like Ctrl + ArrowLeft, the keystroke event no longer answers true for #commandKeyPressed but for #optionKeyPressed instead.  Could you be more specific? With the current default settings on Linux and Windows (see EventSensor class >> #startUp), you should get both #controlKeyPressed and #commandKeyPressed for [CTRL]+[ArrowLeft]. When you press [ALT]+[ArrowLeft], wenn you get true for #commandKeyPressed and #optionKeyPressed. Could you understand my explanations in KeyboardEvent >> #checkCommandKey regarding cross-platform compatibility? If not, what is missing? Best, Marcel Am 25.04.2021 19:59:00 schrieb Thiede, Christoph : Hi Marcel, great idea, thanks for your work. It works fine on Windows as well as WSL/Ubuntu/VvXsrv for all my usual workflows. :-) I noted some "breaking change", but actually it is a fix: When pressing something like Ctrl + ArrowLeft, the keystroke event no longer answers true for #commandKeyPressed but for #optionKeyPressed instead. This makes a workaround in WindowAcrobatics [1] superfluous. The KeyboardExerciser is also a great tool. It gives a good overview of what is still left to do for the input mapping - that is (on Windows): * Ctrl + (Insert | Home | End | PageUp | PageDown) is mapped incorrectly to Ctrl + (A | D | L | ...) * Ctrl + Alt + is not recorded * Ctrl + Shift + Space is not recorded * In my image, Shift + Alt + U does not work - is this a strange bug or do I have an unknown global keyboard filter? [http://www.hpi.de/] And here is some - though minor - notes about the exerciser tool: * The "Move your mouse cursor" instruction message does not fit into the morph in my image and is not word-wrapped but misses a draw invalidation instead. Also, it is not multilanguage-safe, but since it is in the "Demo" system category, I guess this is okay. :D Best, Christoph [1] https://github.com/hpi-swa-teaching/WindowAcrobatics/blob/3398eb951d674360a37fe422710340e53a69bd84/packages/WindowAcrobatics-Core.package/WAHandler.class/instance/handle..st#L5 [https://github.com/hpi-swa-teaching/WindowAcrobatics/blob/3398eb951d674360a37fe422710340e53a69bd84/packages/WindowAcrobatics-Core.package/WAHandler.class/instance/handle..st#L5] Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Samstag, 24. April 2021 20:58 Uhr An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Please try it out | Fixing the input mapping for keystroke events   Hi Marcel, I tried it on macos and windows, no problem so far. I had some fun with the exercizer, some combinations are surprising indeed... Le ven. 23 avr. 2021 à 18:23, Marcel Taeumel a écrit : Hi all! Please find attached an updated changeset with a "KeyboardExerciser" to help you test and inspect the incoming keyboard events. You can find it also in the parts bin nearby the "ClickExerciser". The visuals are supposed to look platform-specific. However, the event data contains information to make your application work across platforms. See KeyboardEvent >> #checkCommandKey for more explanations. Try [CTRL]+[C] for keyStroke, keyDown, and keyUp. Note that the visuals might not look right for keyUp and keyDown events due to missing lookup tables for the raw, platform-specific key codes. On my machine, for example, [,] and [.] and [-] look odd: Nothing to worry about because all keyboard shortcuts in Squeak use keyStroke events at the moment. Best, Marcel Am 22.04.2021 10:41:15 schrieb Marcel Taeumel : Hi all! Please find attached a changeset that improves the cross-platform base for keystroke events. Please try it out and take a look at it. Report issues ASAP so that I can merge it into Trunk soon. Thanks to Tom (tobe), the new promising idea is to replace the existing attempt: Duplicate all control and alt keys Duplicate control and alt keys Swap control and alt keys With the following preferences: [X] Map ASCII control characters to printable characters  - Default is TRUE  - Only affects events that have the CONTROL modifier set (e.g. CTRL+J)  - Rather application-specific than platform-specific [X] Map CONTROL keys to COMMAND keys  - Checked at image start-up  - TRUE on Windows/Linux  - FALSE on macOS [X] Map ALT keys to OPTION keys  - Checked at image start-up  - TRUE on Windows/Linux  - FALSE on macOS (bc. ALT==CMD on recent Linux/Windows VMs) Please take a look at KeyboardEvent >> #checkCommandKey to learn about the fundamental trade-off we have solved. Please try out your preferred applications. Feel free to add logging to HandMorph >> #logEvent: for more convenient testing: (anEvent isKeyboard and: [anEvent isKeystroke])    ifTrue: [Transcript showln: anEvent]. Thanks! Best, Marcel (and Tom) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 37054 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 9239 bytes Desc: not available URL: From commits at source.squeak.org Mon Apr 26 07:10:08 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 07:10:08 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1760.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1760.mcz ==================== Summary ==================== Name: Morphic-mt.1760 Author: mt Time: 26 April 2021, 9:10:01.755065 am UUID: 78267d62-77c5-8c48-87c3-81525301c8b4 Ancestors: Morphic-mt.1759 Fixes a regression for "re-use windows" in smart search. Thanks Christoph (ct)! =============== Diff against Morphic-mt.1759 =============== Item was changed: ----- Method: SearchBar>>smartSearch:in: (in category 'searching') ----- smartSearch: text in: morph "Take the user input and perform an appropriate search" | input newContents | self removeResultsWidget. input := text asString ifEmpty:[^self]. self class useSmartSearch ifFalse: [^ ToolSet default browseMessageNames: input]. (Symbol lookup: input) ifNotNil: [:symbol| input := symbol]. "If it is a global or a full class name, browse that class." (Smalltalk bindingOf: input) ifNotNil: [:assoc| | class | class := (assoc value isBehavior ifTrue:[assoc value] ifFalse:[assoc value class]) theNonMetaClass. + ^ToolSet browseClass: class]. - Project current world submorphs do: - [:windowMorph| - (windowMorph isSystemWindow - and: [(windowMorph model isKindOf: Browser) - and: [windowMorph model isDisplayingClass: class]]) ifTrue: - [windowMorph beKeyWindow. - ^windowMorph model displayClass: class]]. - ^ToolSet browse: class selector: nil]. "If it is a symbol and there are implementors of it, browse those implementors." input isSymbol ifTrue: [(SystemNavigation new allImplementorsOf: input) ifNotEmpty: [:list| ^SystemNavigation new browseMessageList: list name: 'Implementors of ' , input]]. "If it starts uppercase, browse classes if any. Otherwise, just search for messages." input first isUppercase ifTrue: [(UIManager default classFromPattern: input withCaption: '') ifNotNil: [:aClass| ^ToolSet browse: aClass selector: nil]. newContents := input, ' -- not found.'. self searchTerm: newContents. self selection: (input size+1 to: newContents size). self currentHand newKeyboardFocus: morph textMorph. ^ self]. "Default to browse message names..." ToolSet default browseMessageNames: input! From commits at source.squeak.org Mon Apr 26 07:13:28 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 07:13:28 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1044.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1044.mcz ==================== Summary ==================== Name: Tools-mt.1044 Author: mt Time: 26 April 2021, 9:13:24.564065 am UUID: 7904f092-e7cf-b344-9ed9-e8802991c38e Ancestors: Tools-mt.1043 Complements Morphic-mt.1760. =============== Diff against Tools-mt.1043 =============== Item was added: + ----- Method: Browser>>representsSameBrowseeAs: (in category 'morphic ui') ----- + representsSameBrowseeAs: anotherBrowser + + ^ self hasUnacceptedEdits not + and: [self selectedClass == anotherBrowser selectedClass] + and: [self selectedMessage = anotherBrowser selectedMessage]! From commits at source.squeak.org Mon Apr 26 07:45:55 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 07:45:55 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1761.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1761.mcz ==================== Summary ==================== Name: Morphic-mt.1761 Author: mt Time: 26 April 2021, 9:45:48.321064 am UUID: b6da97e8-f5a5-ac41-9880-5a0c0e547913 Ancestors: Morphic-mt.1760 Avoid reusing a window if it is the requesting window. This is useful for the "browse" button in the system browser or even for the "hierarchy" button in the hierarchy browser if the hierarchy is the same. A common yet simple way to duplicate a window without using a halo. Since this is an explicit user interaction, it is not expected to interfere with the "re-use windows" preference. I suppose. :-) =============== Diff against Morphic-mt.1760 =============== Item was changed: ----- Method: SystemWindow>>anyOpenWindowLikeMeIn: (in category 'open/close') ----- anyOpenWindowLikeMeIn: aPasteUpMorph + + | requestor context | + self class reuseWindows ifFalse: [ ^ Array empty ]. + context := thisContext sender. + [ context notNil and: [ requestor isNil ] ] + whileTrue: "Search for the requesting window to ignore it later." + [ | receiver window | + ((receiver := context receiver) ~~ self + and: [ receiver isMorph + and: [ (window := receiver firstOwnerSuchThat: [ : m | m isSystemWindow ]) ~~ self + and: [ window notNil ] ] ]) + ifTrue: [ requestor := window ] + ifFalse: [ context := context sender ] ]. + ^ self class - self class reuseWindows ifFalse: [ ^Array empty ]. - ^ SystemWindow windowsIn: aPasteUpMorph satisfying: [ : each | + each ~~ requestor + and: [ each model class = self model class - each model class = self model class and: [ (each model respondsTo: #representsSameBrowseeAs:) + and: [ each model representsSameBrowseeAs: self model ] ] ] ] - and: [ each model representsSameBrowseeAs: self model ] ] ] ! From commits at source.squeak.org Mon Apr 26 07:56:44 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 07:56:44 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1045.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1045.mcz ==================== Summary ==================== Name: Tools-mt.1045 Author: mt Time: 26 April 2021, 9:56:40.676064 am UUID: c897bfda-a607-e64c-b3ad-b6fb989d38a3 Ancestors: Tools-mt.1044 Tweak browser re-use to only consider the current class if that new browser does not care, which is the case for ivoking browsers from the smart search. =============== Diff against Tools-mt.1044 =============== Item was changed: ----- Method: Browser>>representsSameBrowseeAs: (in category 'morphic ui') ----- representsSameBrowseeAs: anotherBrowser ^ self hasUnacceptedEdits not and: [self selectedClass == anotherBrowser selectedClass] + and: [anotherBrowser selectedMessageName isNil + or: [anotherBrowser selectedMessageName = self selectedMessageName]]! - and: [self selectedMessage = anotherBrowser selectedMessage]! From marcel.taeumel at hpi.de Mon Apr 26 08:03:32 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 10:03:32 +0200 Subject: [squeak-dev] The Trunk: Morphic-eem.1719.mcz In-Reply-To: References: <804594dd36de4be1b92d4dbecaaeb973@student.hpi.uni-potsdam.de> <,> Message-ID: Hi Christoph, I somewhat integrated your proposed changes into Trunk. :-) Browser >> #representsSameBrowseeAs: SearchBar >> #smartSearch:in: SystemWindow >> #anyOpenWindowLikeMeIn: Note that a tool's buttons can typically be used to duplicate the tool if desired. Thus, it is not an option to just remove the "hierarchy" button, for example, if it interferes with the "re-use windows" preference -- which you proposed. Also, by just hacking into #browseMethodFull for Browser, you omit all the other possible paths that might interfere with that preference. Well, preference settings might have other side effects, yet, if one would want to do that (e.g., in tests), you must put it into the ensure context: ^ [systemWindow reuseWindows: false. super browseMethodFull] ensure: [systemWindow reuseWindows: previous] Anyway -- instead -- I added the constraint that the requesting window should not be considered as a re-use candidate. With our current tool architecture, I had to resort to meta programming (i.e. context checking). I hope that you won't notice any performance glitches. (Took be about 1.5 hours.) Best, Marcel Am 25.04.2021 22:36:47 schrieb Thiede, Christoph : Hi all, please find the attached changeset which fixes the regression of the smart search bar not honoring the #reuseWindows preference. Also, I added a proper implementation of #reuseWindows for browsers. Please review and/or merge! :-) Best, Christoph PS: What is packages at lists.squeakfoundation.org and why is it being cc'ed in this conversation? Von: Squeak-dev im Auftrag von Chris Muller Gesendet: Freitag, 5. Februar 2021 22:19:13 An: The general-purpose Squeak developers list Cc: packages at lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Trunk: Morphic-eem.1719.mcz   Hi Christoph! I thought this feature seemed reminiscent of Reuse Windows as well.  The method to hook in each Model subclass (as needed) is #representsSameBrowseeAs:.  Looking at that, you can see that simply making your code pane temporarily dirty, an additional window will be spawned.  I mention that because Reuse Windows is fantastic and I hate to see your experience with it ruined over something so trivial.  :) You do also have the green duplicate halo.  People are happy to use "non-standard" UI features in other IDE's, but there seems to be an aversion to people using halos in Squeak.  I could be wrong about that, but I find the duplicate halo useful quite often.  - Chris On Thu, Feb 4, 2021 at 7:14 PM Thiede, Christoph wrote: Hi Eliot, could you please honor the "SystemWindow reuseWindows" here? I have turned that preference off in my image because I actually use to accept a class name multiple times in the search bar in order to open multiple windows - for instance, to view different protocols of the same class side-by-side. It would be great if this would work soon again ... :-) Best, Christoph Von: Squeak-dev im Auftrag von commits at source.squeak.org [mailto:commits at source.squeak.org] Gesendet: Donnerstag, 4. Februar 2021 03:38:15 An: squeak-dev at lists.squeakfoundation.org [mailto:squeak-dev at lists.squeakfoundation.org]; packages at lists.squeakfoundation.org [mailto:packages at lists.squeakfoundation.org] Betreff: [squeak-dev] The Trunk: Morphic-eem.1719.mcz   Eliot Miranda uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-eem.1719.mcz [http://source.squeak.org/trunk/Morphic-eem.1719.mcz] ==================== Summary ==================== Name: Morphic-eem.1719 Author: eem Time: 3 February 2021, 6:38:11.11355 pm UUID: ffb981b1-7c53-4fbe-b6f4-4c8f27c79f5a Ancestors: Morphic-mt.1718 Make SearchBar>>#smartSearch:in: search existing browsers for a class name being searched for, bringing the first such browser to the front and selecting the class.  This allows one to find classes in browsers either when one has very many, or when one is using multi-window browsers containing many many classes. =============== Diff against Morphic-mt.1718 =============== Item was added: + ----- Method: Browser>>displayClass: (in category '*Morphic-Menus-DockingBar-accessing') ----- + displayClass: aClass +        "Assuming the receiver has answered true to isDisplayingClass:, come to the front and select the given class." +        | index | +        index := self multiWindowIndexForClassName: aClass. +        index  ~= 0 ifTrue: +                [multiWindowState selectWindowIndex: index]. +        self selectClass: aClass! Item was added: + ----- Method: Browser>>isDisplayingClass: (in category '*Morphic-Menus-DockingBar-accessing') ----- + isDisplayingClass: aClass +        | className | +        className := aClass name. +        (self multiWindowIndexForClassName: className) ~= 0 ifTrue: [^true]. +        ^selectedClassName = className! Item was added: + ----- Method: Browser>>multiWindowIndexForClassName: (in category '*Morphic-Menus-DockingBar-accessing') ----- + multiWindowIndexForClassName: className +        "Answer the index of a browser displaying className in multiWindowState, if any. +         Otherwise answer zero." +        multiWindowState ifNil: [^0]. +        multiWindowState models withIndexDo: +                [:browser :index| +                browser selectedClassName = className ifTrue: [^index]]. +        ^0! Item was changed:   ----- Method: SearchBar>>smartSearch:in: (in category 'searching') -----   smartSearch: text in: morph          "Take the user input and perform an appropriate search"          | input newContents |          self removeResultsWidget.          input := text asString ifEmpty:[^self].          self class useSmartSearch ifFalse: [^ ToolSet default browseMessageNames: input].   +        (Symbol findInterned: input) ifNotNil: +                [:symbol| input := symbol].          "If it is a global or a full class name, browse that class." +        (Smalltalk bindingOf: input) ifNotNil: +                [:assoc| | class | +                class := (assoc value isBehavior ifTrue:[assoc value] ifFalse:[assoc value class]) theNonMetaClass. +                Project current world submorphs do: +                        [:windowMorph| +                         (windowMorph isSystemWindow +                          and: [(windowMorph model isKindOf: Browser) +                          and: [windowMorph model isDisplayingClass: class]]) ifTrue: +                                [windowMorph beKeyWindow. +                                 ^windowMorph model displayClass: class]]. +                ^ToolSet browse: class selector: nil]. -        (Smalltalk bindingOf: input) ifNotNil:[:assoc| | global | -                global := assoc value. -                ^ToolSet browse: (global isBehavior ifTrue:[global] ifFalse:[global class]) selector: nil].                   "If it is a symbol and there are implementors of it, browse those implementors."          Symbol hasInterned: input ifTrue: [:selector |                  (SystemNavigation new allImplementorsOf: selector) ifNotEmpty:[:list|                          ^SystemNavigation new                                  browseMessageList: list                                  name: 'Implementors of ' , input]].            "If it starts uppercase, browse classes if any. Otherwise, just search for messages." +        input first isUppercase ifTrue: +                [(UIManager default classFromPattern: input withCaption: '') +                        ifNotNil:[:aClass| ^ToolSet browse: aClass selector: nil]. +                newContents := input, ' -- not found.'. +                self searchTerm: newContents. +                self selection: (input size+1 to: newContents size). +                self currentHand newKeyboardFocus: morph textMorph. +                ^ self]. + +        "Default to browse message names..." +        ToolSet default browseMessageNames: input! -        input first isUppercase -                ifTrue: [ -                        (UIManager default classFromPattern: input withCaption: '') -                                ifNotNil:[:aClass| ^ToolSet browse: aClass selector: nil] -                                ifNil: [ -                                        newContents := input, ' -- not found.'. -                                        self searchTerm: newContents. -                                        self selection: (input size+1 to: newContents size). -                                        self currentHand newKeyboardFocus: morph textMorph. -                                        ^ self]] -                ifFalse: [ -                        ToolSet default browseMessageNames: input].! -------------- next part -------------- An HTML attachment was scrubbed... URL: From tonyg at leastfixedpoint.com Mon Apr 26 10:53:52 2021 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Mon, 26 Apr 2021 12:53:52 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <045abb52-2eed-408f-972b-88926f3bc5b4@email.android.com> References: <045abb52-2eed-408f-972b-88926f3bc5b4@email.android.com> Message-ID: <8d40b92d-8be3-7a4c-1037-01c8d7fcc9ac@leastfixedpoint.com> On 4/25/21 7:14 PM, Christoph Thiede wrote: > Cool stuff! I wish we could also use this on Android. :-) Me too. Smalltalk is (close to) what Android could have been... It just needs capability-security, better image management, nested VMs... a few minor details :-) From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 26 11:23:45 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 26 Apr 2021 11:23:45 +0000 Subject: [squeak-dev] Smalltalk Zoo not written in Smalltalk In-Reply-To: References: , Message-ID: Hi Marcel, mainly because of its speed, I guess. I don't think that we could simulate older Squeak VMs inside SqueakJS. In general, I think the idea is cool, but wouldn't webasm be significantly faster? Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 26. April 2021 08:34:56 An: squeak-dev Betreff: Re: [squeak-dev] Smalltalk Zoo not written in Smalltalk Hi Christoph. > Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Why is SqueakJS (https://squeak.js.org/) not what you are looking for? Best, Marcel Am 25.04.2021 20:41:17 schrieb Thiede, Christoph : Hi all, just a short and curious questions, but not guaranteed to be completely unprovoking. :-) Why is Smalltalk Zoo, the virtual exhibition which compares different milestones in the history of Squeak/Smalltalk, not implemented in Smalltalk itself but in JavaScript, a language which cannot compile itself, is quite the oppposite of Smalltalk in terms of clearness of expression, and escapes control of the actual application? While I love the idea in general, I think it's a shame that the zoo of a language that aims to be implemented in itself is not implemented in that language itself. :D Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Apr 26 13:08:07 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 13:08:07 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.294.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.294.mcz ==================== Summary ==================== Name: MorphicExtras-mt.294 Author: mt Time: 26 April 2021, 3:08:04.000131 pm UUID: c6d8ad6a-4132-bc46-95e0-57a6854b0ce6 Ancestors: MorphicExtras-eem.293 Adds missing example for moving-eye morph. =============== Diff against MorphicExtras-eem.293 =============== Item was added: + ----- Method: MovingEyeMorph class>>extraExampleSqueakGhostIsWatchingYou (in category 'examples') ----- + extraExampleSqueakGhostIsWatchingYou + "MovingEyeMorph extraExampleSqueakGhostIsWatchingYou openInHand" + + | logoMorph leftEye rightEye | + logoMorph := (Form squeakLogo "collectColors: #negated") asMorph. + leftEye := (self color: Color white irisColor: Color black) + extent: logoMorph extent * (0.1 @ 0.15); + center: (logoMorph pointAtFraction: 0.39 @ 0.55); + yourself. + rightEye := (self color: Color white irisColor: Color black) + extent: logoMorph extent * (0.1 @ 0.15); + center: (logoMorph pointAtFraction: 0.59 @ 0.56); + yourself. + logoMorph addAllMorphs: {leftEye. rightEye}. + ^ logoMorph.! From commits at source.squeak.org Mon Apr 26 13:08:48 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 26 Apr 2021 13:08:48 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.295.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.295.mcz ==================== Summary ==================== Name: MorphicExtras-mt.295 Author: mt Time: 26 April 2021, 3:08:44.455131 pm UUID: d6f2966e-08bb-3e4e-837c-213b25c346ed Ancestors: MorphicExtras-mt.294 Sorry for the noise. :-) =============== Diff against MorphicExtras-mt.294 =============== Item was changed: ----- Method: MovingEyeMorph class>>extraExampleSqueakGhostIsWatchingYou (in category 'examples') ----- extraExampleSqueakGhostIsWatchingYou "MovingEyeMorph extraExampleSqueakGhostIsWatchingYou openInHand" | logoMorph leftEye rightEye | + logoMorph := (Form squeakLogo collectColors: #negated) asMorph. - logoMorph := (Form squeakLogo "collectColors: #negated") asMorph. leftEye := (self color: Color white irisColor: Color black) extent: logoMorph extent * (0.1 @ 0.15); center: (logoMorph pointAtFraction: 0.39 @ 0.55); yourself. rightEye := (self color: Color white irisColor: Color black) extent: logoMorph extent * (0.1 @ 0.15); center: (logoMorph pointAtFraction: 0.59 @ 0.56); yourself. logoMorph addAllMorphs: {leftEye. rightEye}. ^ logoMorph.! From marcel.taeumel at hpi.de Mon Apr 26 15:05:05 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 17:05:05 +0200 Subject: [squeak-dev] Smalltalk Zoo not written in Smalltalk In-Reply-To: References: <,> Message-ID: > I don't think that we could simulate older Squeak VMs inside SqueakJS. Well, the Smalltalk Zoo is basically powered by SqueakJS. What do you mean? Maybe this helps: "SqueakJS: a modern and practical smalltalk that runs in any browser" (Freudenberg et al., 2014) https://dl.acm.org/doi/pdf/10.1145/2775052.2661100 [https://dl.acm.org/doi/pdf/10.1145/2775052.2661100] Best, Marcel Am 26.04.2021 13:24:00 schrieb Thiede, Christoph : Hi Marcel, mainly because of its speed, I guess. I don't think that we could simulate older Squeak VMs inside SqueakJS. In general, I think the idea is cool, but wouldn't webasm be significantly faster? Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 26. April 2021 08:34:56 An: squeak-dev Betreff: Re: [squeak-dev] Smalltalk Zoo not written in Smalltalk   Hi Christoph. > Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Why is SqueakJS (https://squeak.js.org/ [https://squeak.js.org/]) not what you are looking for? Best, Marcel Am 25.04.2021 20:41:17 schrieb Thiede, Christoph : Hi all, just a short and curious questions, but not guaranteed to be completely unprovoking. :-) Why is Smalltalk Zoo, the virtual exhibition which compares different milestones in the history of Squeak/Smalltalk, not implemented in Smalltalk itself but in JavaScript, a language which cannot compile itself, is quite the oppposite of Smalltalk in terms of clearness of expression, and escapes control of the actual application? While I love the idea in general, I think it's a shame that the zoo of a language that aims to be implemented in itself is not implemented in that language itself. :D Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 26 15:06:42 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 17:06:42 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: <8d40b92d-8be3-7a4c-1037-01c8d7fcc9ac@leastfixedpoint.com> References: <045abb52-2eed-408f-972b-88926f3bc5b4@email.android.com> <8d40b92d-8be3-7a4c-1037-01c8d7fcc9ac@leastfixedpoint.com> Message-ID: >  It just needs capability-security, better image management, > nested VMs... a few minor details :-) All these people with their feature requests ... ;-D Best, Marcel Am 26.04.2021 12:54:03 schrieb Tony Garnock-Jones : On 4/25/21 7:14 PM, Christoph Thiede wrote: > Cool stuff! I wish we could also use this on Android. :-) Me too. Smalltalk is (close to) what Android could have been... It just needs capability-security, better image management, nested VMs... a few minor details :-) -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 26 15:15:48 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 17:15:48 +0200 Subject: [squeak-dev] The Inbox: Kernel-mt.1390.mcz In-Reply-To: References: <79bc441b75b94ef1a116b5ba348940fd@student.hpi.uni-potsdam.de> Message-ID: Hi Jabob, hi Christoph, thanks for sharing your thoughts. As mentioned in the commit message, the primary example would be restarting the McmUpdater if it updated itself at some point. This is not possible at the moment, which renders it impossible to reliably change code in there for all images out there. If approved and polished, such a mechanism belongs into Kernel because it extends process/context management below the tool level. Or at least where Process, Context, and Exceptions are. :-D ... I think. If that would be too advanced for Kernel, then, I suppose Exceptions are, too. ;-) (Another perspective on this is a scriptable version of what the debugger can do with its buttons already.) Best, Marcel Am 25.04.2021 21:15:11 schrieb Jakob Reschke : Real world example use cases if we had the Common Lisp experience: Try to install something via Metacello. Metacello would register "retry" restarts before downloading a package. The download of the last of dozens of packages fails three times, so Metacello errs out, you get a debugger notifier. You would click on "retry" to restart the package download instead of seeking out the correct context for that (requires Metacello knowledge), or instead of restarting the whole installation, which would needlessly repeat the dependency resolution up to the failed package. Similar: when hitting the "Connection closed" error after pushing to GitHub from the Git Browser, retry the upload without computing the set of commits and compiling the pack file again... I guess with extra (domain-specific) message box programming, this would already be feasible now: 1. Register upload error handler that prompts for retrying (GUI layer). 2. Compute the file to be uploaded. (3. Register restart context for upload retry.) 4. Register handler for Connection closed error; the handler will signal upload error. 5. Attempt upload, which hits Connection closed. 6. Gets handled, signals upload error for the GUI. 7. Gets handled, GUI prompts whether to retry. 8. User chooses "Yes", GUI lets resume from upload error with that choice. 9. Connection closed handler receives this choice, restarts from the retry context. With the extra mile UI stuff in the debugger/notifier, one would not need to write domain code for the steps 1, 4, 6, 7, 8, 9. So the only additional code would be registering the restart context (with a nice description text). Am So., 25. Apr. 2021 um 20:05 Uhr schrieb Thiede, Christoph : Hi Marcel, these are interesting concepts though hard to evaluate without real-world examples, I guess. But it does seem to be a crucial core concept to me. Maybe this would better fit into the System package? I'd like to keep the Kernel package as small as possible and this one is rather advanced stuff ... 😊 Best, [http://www.hpi.de/] Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 19. April 2021 17:50:02 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Kernel-mt.1390.mcz   Here are the two options in an exapmle: Am 19.04.2021 17:48:03 schrieb commits at source.squeak.org [mailto:commits at source.squeak.org] : A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-mt.1390.mcz [http://source.squeak.org/inbox/Kernel-mt.1390.mcz] ==================== Summary ==================== Name: Kernel-mt.1390 Author: mt Time: 19 April 2021, 5:47:51.865053 pm UUID: c36ac126-16de-3d41-be90-6b7fd46bc0c7 Ancestors: Kernel-nice.1389 Proposal. Better support for hot code updates by restarting from a denoted (i.e. domain-specific) context (or active method). For example, this could be used to better update the McmUpdater as soon as a code change in itself is detected. Two options: either mark the restart context with an on:do: handler or process a query to look up that context such as by package name. =============== Diff against Kernel-nice.1389 =============== Item was added: + Notification subclass: #RestartContextRequest + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'Kernel-Exceptions'! Item was added: + ----- Method: RestartContextRequest class>>fromContextSuchThat: (in category 'as yet unclassified') ----- + fromContextSuchThat: block + "Use this to restart from an arbitrary context on the stack." + + | context | + context := thisContext sender. + [context notNil] whileTrue: [ + (block value: context) ifTrue: [ + ^ self new restartFrom: context]. + context := context sender]. + self error: 'No context found!!'.! Item was added: + ----- Method: RestartContextRequest>>restartFrom: (in category 'as yet unclassified') ----- + restartFrom: aContext + + | process actualContext unwindError | + aContext ifNil: [^ self error: 'No context to restart!!']. + + process := Processor activeProcess. + + [actualContext := process popTo: aContext. + unwindError := actualContext ~= aContext. + unwindError + ifTrue: [process resume] + ifFalse: [process restartTop; stepToSendOrReturn; resume] + ] fork. + + process suspend.! Item was added: + ----- Method: RestartContextRequest>>restartFromHere (in category 'as yet unclassified') ----- + restartFromHere + "Use this to restart from an exception handler." + self restartFrom: handlerContext.! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 158062 bytes Desc: not available URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 26 15:43:08 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 26 Apr 2021 15:43:08 +0000 Subject: [squeak-dev] The Inbox: Kernel-mt.1390.mcz In-Reply-To: References: <79bc441b75b94ef1a116b5ba348940fd@student.hpi.uni-potsdam.de> , Message-ID: Hi Marcel, EHS belongs into the Kernel, of course. But I'm not convinced yet that your proposal is an essential component of the EHS. :-) "Abort" is in System-Exceptions, too. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 26. April 2021 17:15:48 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Kernel-mt.1390.mcz Hi Jabob, hi Christoph, thanks for sharing your thoughts. As mentioned in the commit message, the primary example would be restarting the McmUpdater if it updated itself at some point. This is not possible at the moment, which renders it impossible to reliably change code in there for all images out there. If approved and polished, such a mechanism belongs into Kernel because it extends process/context management below the tool level. Or at least where Process, Context, and Exceptions are. :-D ... I think. If that would be too advanced for Kernel, then, I suppose Exceptions are, too. ;-) (Another perspective on this is a scriptable version of what the debugger can do with its buttons already.) Best, Marcel Am 25.04.2021 21:15:11 schrieb Jakob Reschke : Real world example use cases if we had the Common Lisp experience: Try to install something via Metacello. Metacello would register "retry" restarts before downloading a package. The download of the last of dozens of packages fails three times, so Metacello errs out, you get a debugger notifier. You would click on "retry" to restart the package download instead of seeking out the correct context for that (requires Metacello knowledge), or instead of restarting the whole installation, which would needlessly repeat the dependency resolution up to the failed package. Similar: when hitting the "Connection closed" error after pushing to GitHub from the Git Browser, retry the upload without computing the set of commits and compiling the pack file again... I guess with extra (domain-specific) message box programming, this would already be feasible now: 1. Register upload error handler that prompts for retrying (GUI layer). 2. Compute the file to be uploaded. (3. Register restart context for upload retry.) 4. Register handler for Connection closed error; the handler will signal upload error. 5. Attempt upload, which hits Connection closed. 6. Gets handled, signals upload error for the GUI. 7. Gets handled, GUI prompts whether to retry. 8. User chooses "Yes", GUI lets resume from upload error with that choice. 9. Connection closed handler receives this choice, restarts from the retry context. With the extra mile UI stuff in the debugger/notifier, one would not need to write domain code for the steps 1, 4, 6, 7, 8, 9. So the only additional code would be registering the restart context (with a nice description text). Am So., 25. Apr. 2021 um 20:05 Uhr schrieb Thiede, Christoph >: Hi Marcel, these are interesting concepts though hard to evaluate without real-world examples, I guess. But it does seem to be a crucial core concept to me. Maybe this would better fit into the System package? I'd like to keep the Kernel package as small as possible and this one is rather advanced stuff ... 😊 Best, Christoph ________________________________ Von: Squeak-dev > im Auftrag von Taeumel, Marcel Gesendet: Montag, 19. April 2021 17:50:02 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Kernel-mt.1390.mcz Here are the two options in an exapmle: [cid:1790a5b6615cb971f161] Am 19.04.2021 17:48:03 schrieb commits at source.squeak.org >: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-mt.1390.mcz ==================== Summary ==================== Name: Kernel-mt.1390 Author: mt Time: 19 April 2021, 5:47:51.865053 pm UUID: c36ac126-16de-3d41-be90-6b7fd46bc0c7 Ancestors: Kernel-nice.1389 Proposal. Better support for hot code updates by restarting from a denoted (i.e. domain-specific) context (or active method). For example, this could be used to better update the McmUpdater as soon as a code change in itself is detected. Two options: either mark the restart context with an on:do: handler or process a query to look up that context such as by package name. =============== Diff against Kernel-nice.1389 =============== Item was added: + Notification subclass: #RestartContextRequest + instanceVariableNames: '' + classVariableNames: '' + poolDictionaries: '' + category: 'Kernel-Exceptions'! Item was added: + ----- Method: RestartContextRequest class>>fromContextSuchThat: (in category 'as yet unclassified') ----- + fromContextSuchThat: block + "Use this to restart from an arbitrary context on the stack." + + | context | + context := thisContext sender. + [context notNil] whileTrue: [ + (block value: context) ifTrue: [ + ^ self new restartFrom: context]. + context := context sender]. + self error: 'No context found!!'.! Item was added: + ----- Method: RestartContextRequest>>restartFrom: (in category 'as yet unclassified') ----- + restartFrom: aContext + + | process actualContext unwindError | + aContext ifNil: [^ self error: 'No context to restart!!']. + + process := Processor activeProcess. + + [actualContext := process popTo: aContext. + unwindError := actualContext ~= aContext. + unwindError + ifTrue: [process resume] + ifFalse: [process restartTop; stepToSendOrReturn; resume] + ] fork. + + process suspend.! Item was added: + ----- Method: RestartContextRequest>>restartFromHere (in category 'as yet unclassified') ----- + restartFromHere + "Use this to restart from an exception handler." + self restartFrom: handlerContext.! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 158062 bytes Desc: image.png URL: From marcel.taeumel at hpi.de Mon Apr 26 16:07:23 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 18:07:23 +0200 Subject: [squeak-dev] Wrote a little about OnScreenKeyboardMorph In-Reply-To: References: <045abb52-2eed-408f-972b-88926f3bc5b4@email.android.com> <8d40b92d-8be3-7a4c-1037-01c8d7fcc9ac@leastfixedpoint.com> Message-ID: Hey Tony, here is a quick hack that shows how to add more space to fight that "fat finger problem". :-D Best, Marcel Am 26.04.2021 17:06:42 schrieb Marcel Taeumel : >  It just needs capability-security, better image management, > nested VMs... a few minor details :-) All these people with their feature requests ... ;-D Best, Marcel Am 26.04.2021 12:54:03 schrieb Tony Garnock-Jones : On 4/25/21 7:14 PM, Christoph Thiede wrote: > Cool stuff! I wish we could also use this on Android. :-) Me too. Smalltalk is (close to) what Android could have been... It just needs capability-security, better image management, nested VMs... a few minor details :-) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 179614 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: small-screen-hacks.1.cs Type: application/octet-stream Size: 9995 bytes Desc: not available URL: From marcel.taeumel at hpi.de Mon Apr 26 16:36:35 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 18:36:35 +0200 Subject: [squeak-dev] The Trunk: MorphicTests-nice.75.mcz In-Reply-To: <232ff796ffbc4528a61a3bdd3ecc88c8@student.hpi.uni-potsdam.de> References: <,> <232ff796ffbc4528a61a3bdd3ecc88c8@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph. > we already have #setPreference:toValue:during: on Preferences class Hmm... I think that I am reluctant to use the "Preferences" interface for pragma preferences, which have the benefit of directly showing the domain they are used for. The use of "Preferences" would add a dependency to System, for example. In this case, a "during:" mechanism would not work because #setUp and #tearDown are called by the SUnit "framework" :-) Maybe SUnit could provide some configurable way for this. In System-ct.1119, I do not like the overuse of symbols and meta-programming in client code (e.g. a test's #setUp). In preferences, the entire construction of a key for pragma preferences feels like an ugly hack. Hmm... actually, pragma preferences and other Preferences are easily accessible. SUnit could just snapshot all their values before the test and reset them after. The values are mostly primitive, immutable objects. An extra reference to them would suffice. A test's #setUp code could do what it wants to do and then rely on the implicit reset of all preferences in #tearDown. Hmm.... Best, Marcel Am 25.04.2021 20:23:27 schrieb Thiede, Christoph : Hi Marcel, we already have #setPreference:toValue:during: on Preferences class. I also had to remember this proposal + discussion: The Inbox: System-ct.1119.mcz [http://forum.world.st/The-Inbox-System-ct-1119-mcz-td5106025.html] Your counter-proposal with the preferences sandbox also sounds interesting, we could do this as well. (Just now, I am wondering whether preferences should be process-local ... But that's enough stuff for its own discussion. :-)) Best, Christoph [http://www.hpi.de/] Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Donnerstag, 15. April 2021 09:39:57 An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: MorphicTests-nice.75.mcz   Hi Nicolas. Thanks. We might want to think about a more generic way to specify system-wide preferences for tests. Maybe a new feature in TestCase (or SUnit). While I would never want to change such preferences in a specific test, I also see that the setUp-way (with that extra "reset" instVar) is quite cumbersome. Best, Marcel Am 14.04.2021 19:14:23 schrieb commits at source.squeak.org : Nicolas Cellier uploaded a new version of MorphicTests to project The Trunk: http://source.squeak.org/trunk/MorphicTests-nice.75.mcz ==================== Summary ==================== Name: MorphicTests-nice.75 Author: nice Time: 14 April 2021, 7:14:06.997889 pm UUID: d87c50dd-4e44-5242-9120-37e0452ca781 Ancestors: MorphicTests-eem.74 Fix loss of useRetractableScrollBars preference =============== Diff against MorphicTests-eem.74 =============== Item was changed: ----- Method: TableLayoutTest>>setUp (in category 'running') ----- setUp super setUp. - reset := { ([:enable | [self useRetractableScrollBars: enable]] value: self useRetractableScrollBars) + }. + self useRetractableScrollBars: false! - in: [:block | self useRetractableScrollBars: false]. - }.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 26 16:51:44 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 18:51:44 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: Hi Jakob. > What is your stance towards using inspectors to quickly check > identity, regarding ByteString? I guess that I usually don't do it. I normally do not work in domains where efficient string construction matters or individual bytes/characters might fail ... waiting to be inspected. If I would expect a larger payload from a web request, for example, I would normally do explore-it or inspect-it directly -- or have the WebResponse open in an explorer already. I only rely on symbols being identical. (I slightly recall a discussion where something in Squot relies on PackageInfo to never change its identity. ... which I still regard as a design smell bc. we have symbols for that and package names are symbols.) > To further motivate the question in 2., imagine that this ByteString > is big, say, a several hundred MB CLOB. :-) I would expect that, in such a scenario, print-it would rarely be used. Especially since that click would open a new tool and returning to that old one might destroy the text selection of "mouse over keyboard focus" is not enabled. Then you would have to remember how text undo works. Hmmm... we might want to remove that interactive print-it text after the user has clicked on it :-) Best, Marcel Am 25.04.2021 19:39:00 schrieb Jakob Reschke : Hi Marcel, What is your stance towards using inspectors to quickly check identity, regarding ByteString? Note: to make this practical, one needs to turn on the "Reuse windows" preference. Example workflow: 1. Expression print-it. 2. "Oh I have seen this string before, is it the same instance or another one?" 3. (Click on the result to open the inspector on the result object.) 4. Open an inspector on the other, previously encountered occurrence of the string (might be in another tool). If a second inspector appears, these are two distinct String instances. To further motivate the question in 2., imagine that this ByteString is big, say, a several hundred MB CLOB. :-) Kind regards, Jakob Am Sa., 24. Apr. 2021 um 17:43 Uhr schrieb Marcel Taeumel : > > Hi Jakob, > > thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. > > Hey Christoph, > > a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. > > I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. > > Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? > > Hi all, > > here is again the list of objects I think we should exclude from having a text action on their print-it result: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) > > Reducing visual clutter is worth a few lines of extra source code. > > Best, > Marcel > > Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : > > Hi Jakob, Hi Marcel, > > > thank you for reviving this discussion! :-) > > > > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") > > > Definitively also the latter. > > > While the type check might not be really necessary, avoiding visual clutter can be a good thing. > > -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > > > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. > > This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Jakob Reschke > Gesendet: Samstag, 24. April 2021 11:43:06 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > Hi Christoph, hi Marcel, > > Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > : > > > > Hi Christoph, > > > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > > > > I am struggling to understand how your arguments address each other > person's concerns. Did I understand your points correctly: > > - Christoph wants to get rid of the type check. He argues that > sometimes even for the objects with "primitive" structure you may want > to get the link. For example, MCVersionName loses its type information > when printed, so when you would inspect the result, you would get a > String instead of an MCVersionName. The other example is when you want > to track identity. Indeed, sometimes it is useful to check whether one > String is the same as another one retrieved (inspected) from somewhere > else. I do this regularly in Squot when debugging the capturing and > materialization (although seldom for Strings at this time because for > these it already works as expected). > > - Marcel says that the links are unnecessary for what are essentially > value objects that are not complex enough to need inspection beyond > just looking at the print string. Supposedly, one can just reevaluate > the result or the expression. Adding the links there produces visual > clutter and is distracting. Inspecting an MCVersionName would reveal > no further information about the object than the print string does > (that is, except for the type!). > > Christoph, when you inspect your MCVersionNames, do you already know > that these are version names or do you inspect them to find out what > they are? ("What is this, a String or an MCVersionName?") > > I fully agree with Marcel on the immediates and singletons (true, > false, nil, Symbols). While the type check might not be really > necessary, avoiding visual clutter can be a good thing. Tradeoff is > with having the special case in the code. > > Unfortunately(?), Strings in Squeak/Smalltalk are not quite value > objects, since they are mutable, can be used as buffers, etc. Depends > on the application. > > On the other hand, Points are mostly used as value objects, but did > not get the special case treatment. Though strictly, technically > speaking, they are not different from Strings in this regard. > > Inspecting the result string or the revaluating the original > expression to do so is only safe if it does not provoke side effects. > For Marcel's selection of classes, there are no side effects of > reevaluating the result string. But reevaluating the original > expression might not be free of side effects. I guess you would not > reevaluate the expression to inspect an immediate or singleton, but > for those objects that do have object identity, such as Strings, or > where the type of the result is not obvious, MCVersionName, you might > want to do that. > > How about allowing to turn off the highlighting of the result? I mean, > make it still clickable, but do not paint it blue. Then there would be > no visual clutter, and if you know that the feature is there (and you > have subsequently turned off the preference, for example), you would > also not easily forget that you can use it. > > Kind regards, > Jakob > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Apr 26 16:53:40 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 26 Apr 2021 18:53:40 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> Message-ID: Hi all, please note that "CMD+0" will immediately remove that text action after the print-it (CMD+P) if you want to use it for something else. :-) Best, Marcel Am 25.04.2021 19:43:40 schrieb Jakob Reschke : Hi all, So visual consistency for Christoph means: all results are highlighted(/click-inspectable). Whereas for Marcel it means: all complex/interesting results are highlighted/click-inspectable. What does everyone else think about this? I sometimes wish that the print-it results in the workspace would be treated differently than the text that I typed myself. Highlighting them (link or otherwise) could help to spot the frontier between expression and result after some more actions, but would otherwise not help me much. When I intended to use the printed result in my next expression, highlighting it as a result would be inappropriate, but I rarely ever want to do this. For most complex objects, this is not even possible because their print strings are not Smalltalk expressions. But I cannot use a non-Smalltalk expression with a link on it in my next expression either, so the feature does not help me in that case anyway. (What I would rather need is a "put this into a variable" command, kind of a refactoring operation for the Workspace.) If I wanted to send further messages to a returned 'String' I would most likely move it onto its own line for convenient Cmd-p/i first anyway, I would not keep it to the right of the expression that evaluated to the 'String'. With this reasoning, I would rather lean towards Christoph's interpretation now. (Also I believe it does not hurt so much if one can also inspect the primitive results.) But I have not used the feature in practice so far, so I will let some time pass for now. Kind regards, Jakob Am Sa., 24. Apr. 2021 um 17:43 Uhr schrieb Marcel Taeumel : > > Hi Jakob, > > thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. > > Hey Christoph, > > a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. > > I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. > > Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? > > Hi all, > > here is again the list of objects I think we should exclude from having a text action on their print-it result: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) > > Reducing visual clutter is worth a few lines of extra source code. > > Best, > Marcel > > Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : > > Hi Jakob, Hi Marcel, > > > thank you for reviving this discussion! :-) > > > > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") > > > Definitively also the latter. > > > While the type check might not be really necessary, avoiding visual clutter can be a good thing. > > -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > > > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. > > This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Jakob Reschke > Gesendet: Samstag, 24. April 2021 11:43:06 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > Hi Christoph, hi Marcel, > > Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > : > > > > Hi Christoph, > > > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > > > > I am struggling to understand how your arguments address each other > person's concerns. Did I understand your points correctly: > > - Christoph wants to get rid of the type check. He argues that > sometimes even for the objects with "primitive" structure you may want > to get the link. For example, MCVersionName loses its type information > when printed, so when you would inspect the result, you would get a > String instead of an MCVersionName. The other example is when you want > to track identity. Indeed, sometimes it is useful to check whether one > String is the same as another one retrieved (inspected) from somewhere > else. I do this regularly in Squot when debugging the capturing and > materialization (although seldom for Strings at this time because for > these it already works as expected). > > - Marcel says that the links are unnecessary for what are essentially > value objects that are not complex enough to need inspection beyond > just looking at the print string. Supposedly, one can just reevaluate > the result or the expression. Adding the links there produces visual > clutter and is distracting. Inspecting an MCVersionName would reveal > no further information about the object than the print string does > (that is, except for the type!). > > Christoph, when you inspect your MCVersionNames, do you already know > that these are version names or do you inspect them to find out what > they are? ("What is this, a String or an MCVersionName?") > > I fully agree with Marcel on the immediates and singletons (true, > false, nil, Symbols). While the type check might not be really > necessary, avoiding visual clutter can be a good thing. Tradeoff is > with having the special case in the code. > > Unfortunately(?), Strings in Squeak/Smalltalk are not quite value > objects, since they are mutable, can be used as buffers, etc. Depends > on the application. > > On the other hand, Points are mostly used as value objects, but did > not get the special case treatment. Though strictly, technically > speaking, they are not different from Strings in this regard. > > Inspecting the result string or the revaluating the original > expression to do so is only safe if it does not provoke side effects. > For Marcel's selection of classes, there are no side effects of > reevaluating the result string. But reevaluating the original > expression might not be free of side effects. I guess you would not > reevaluate the expression to inspect an immediate or singleton, but > for those objects that do have object identity, such as Strings, or > where the type of the result is not obvious, MCVersionName, you might > want to do that. > > How about allowing to turn off the highlighting of the result? I mean, > make it still clickable, but do not paint it blue. Then there would be > no visual clutter, and if you know that the feature is there (and you > have subsequently turned off the preference, for example), you would > also not easily forget that you can use it. > > Kind regards, > Jakob > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From asqueaker at gmail.com Mon Apr 26 18:17:23 2021 From: asqueaker at gmail.com (Chris Muller) Date: Mon, 26 Apr 2021 13:17:23 -0500 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: Okay, now that we have 7 candidates, there's no need for me to run anymore. Please remove me from the list of candidates. - Chris On Fri, Apr 23, 2021 at 12:48 PM Bruce O'Neel wrote: > > What!?!?! There is still time left? > > Ok, I'll throw my hat in the ring as well. > > I have used Squeak for 20 some years for fun projects. Before that for a > few glorious hours I had my hands on a Tex 4404 Smalltalk system and lusted > for a Smalltalk of my own ever since. > > My involvement has been to keep the planet Squeak site somewhat up to date > and to keep debug Linux VM build errors. > > cheers > > bruce > > > > *23 April 2021 19:31 tim Rowledge > > wrote:* > > I want to add emphasis to a few words from John-Reed > > > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: > > > > I encourage anyone who is interested in Squeak to consider becoming a > board member. It is a good way to learn more about Squeak as a project, and > help keep development moving forward. > > Please don't think there is some need to be a Soopa-Uber-Hacker of Squeak > in order to be a valuable Board member. If you love Squeak, if you have > some time and effort you can spare to help keep the community going, then > you'd be an asset. > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > Oxymorons: Resident alien > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 26 18:28:05 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 26 Apr 2021 18:28:05 +0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> , Message-ID: Hi Marcel, > I would expect that, in such a scenario, print-it would rarely be used. You are arguing from the status quo where printed-it (print-itted?) results are effectively lost for further observation. With the new attribute, a workflow no longer needs to make this assumption. I would rather think of these attributes as notebook-like cell outputs. Unless a user wants to reuse the result in another expression from within the same text field, he or she is not required to use any variables at all. In contexts without workspace bindings (such as inspectors), this is even the only way now to persist object results. Thus, speaking generally, users could indeed rely on print-its for costly operations as of now. :-) > Hmmm... we might want to remove that interactive print-it text after the user has clicked on it :-) Please don't introduce self-destroying objects in Squeak! :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 26. April 2021 18:53:40 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz Hi all, please note that "CMD+0" will immediately remove that text action after the print-it (CMD+P) if you want to use it for something else. :-) Best, Marcel Am 25.04.2021 19:43:40 schrieb Jakob Reschke : Hi all, So visual consistency for Christoph means: all results are highlighted(/click-inspectable). Whereas for Marcel it means: all complex/interesting results are highlighted/click-inspectable. What does everyone else think about this? I sometimes wish that the print-it results in the workspace would be treated differently than the text that I typed myself. Highlighting them (link or otherwise) could help to spot the frontier between expression and result after some more actions, but would otherwise not help me much. When I intended to use the printed result in my next expression, highlighting it as a result would be inappropriate, but I rarely ever want to do this. For most complex objects, this is not even possible because their print strings are not Smalltalk expressions. But I cannot use a non-Smalltalk expression with a link on it in my next expression either, so the feature does not help me in that case anyway. (What I would rather need is a "put this into a variable" command, kind of a refactoring operation for the Workspace.) If I wanted to send further messages to a returned 'String' I would most likely move it onto its own line for convenient Cmd-p/i first anyway, I would not keep it to the right of the expression that evaluated to the 'String'. With this reasoning, I would rather lean towards Christoph's interpretation now. (Also I believe it does not hurt so much if one can also inspect the primitive results.) But I have not used the feature in practice so far, so I will let some time pass for now. Kind regards, Jakob Am Sa., 24. Apr. 2021 um 17:43 Uhr schrieb Marcel Taeumel : > > Hi Jakob, > > thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. > > Hey Christoph, > > a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. > > I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. > > Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? > > Hi all, > > here is again the list of objects I think we should exclude from having a text action on their print-it result: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) > > Reducing visual clutter is worth a few lines of extra source code. > > Best, > Marcel > > Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : > > Hi Jakob, Hi Marcel, > > > thank you for reviving this discussion! :-) > > > > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") > > > Definitively also the latter. > > > While the type check might not be really necessary, avoiding visual clutter can be a good thing. > > -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > > > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. > > This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Jakob Reschke > Gesendet: Samstag, 24. April 2021 11:43:06 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > Hi Christoph, hi Marcel, > > Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > : > > > > Hi Christoph, > > > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > > > > I am struggling to understand how your arguments address each other > person's concerns. Did I understand your points correctly: > > - Christoph wants to get rid of the type check. He argues that > sometimes even for the objects with "primitive" structure you may want > to get the link. For example, MCVersionName loses its type information > when printed, so when you would inspect the result, you would get a > String instead of an MCVersionName. The other example is when you want > to track identity. Indeed, sometimes it is useful to check whether one > String is the same as another one retrieved (inspected) from somewhere > else. I do this regularly in Squot when debugging the capturing and > materialization (although seldom for Strings at this time because for > these it already works as expected). > > - Marcel says that the links are unnecessary for what are essentially > value objects that are not complex enough to need inspection beyond > just looking at the print string. Supposedly, one can just reevaluate > the result or the expression. Adding the links there produces visual > clutter and is distracting. Inspecting an MCVersionName would reveal > no further information about the object than the print string does > (that is, except for the type!). > > Christoph, when you inspect your MCVersionNames, do you already know > that these are version names or do you inspect them to find out what > they are? ("What is this, a String or an MCVersionName?") > > I fully agree with Marcel on the immediates and singletons (true, > false, nil, Symbols). While the type check might not be really > necessary, avoiding visual clutter can be a good thing. Tradeoff is > with having the special case in the code. > > Unfortunately(?), Strings in Squeak/Smalltalk are not quite value > objects, since they are mutable, can be used as buffers, etc. Depends > on the application. > > On the other hand, Points are mostly used as value objects, but did > not get the special case treatment. Though strictly, technically > speaking, they are not different from Strings in this regard. > > Inspecting the result string or the revaluating the original > expression to do so is only safe if it does not provoke side effects. > For Marcel's selection of classes, there are no side effects of > reevaluating the result string. But reevaluating the original > expression might not be free of side effects. I guess you would not > reevaluate the expression to inspect an immediate or singleton, but > for those objects that do have object identity, such as Strings, or > where the type of the result is not obvious, MCVersionName, you might > want to do that. > > How about allowing to turn off the highlighting of the result? I mean, > make it still clickable, but do not paint it blue. Then there would be > no visual clutter, and if you know that the feature is there (and you > have subsequently turned off the preference, for example), you would > also not easily forget that you can use it. > > Kind regards, > Jakob > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From asqueaker at gmail.com Mon Apr 26 18:32:09 2021 From: asqueaker at gmail.com (Chris Muller) Date: Mon, 26 Apr 2021 13:32:09 -0500 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <918474fbade74e00b8a33d1db2e089b3@hpi.de> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> Message-ID: > > > The schedule and process are as follows: > > Now until Friday 16th of April 2021, 18.00 UTC: Nominations of SOB members > and campaigning! > Friday 16th of April 2021, 18.00 UTC: Candidate list is finalized. > Friday 16th of April 2021, 19.00 UTC: Online election starts. > I had hurried to announce myself to make it in time for the above date so that we wouldn't have only 6 candidates, but now someone's candidacy was accepted a whole week later, I don't need to.. - Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Apr 26 18:45:38 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 26 Apr 2021 18:45:38 +0000 Subject: [squeak-dev] Smalltalk Zoo not written in Smalltalk In-Reply-To: References: <, > , Message-ID: <68931ba3427e49319625490fb3f73fb9@student.hpi.uni-potsdam.de> Hi Marcel, if the Smalltalk Zoo was running inside SqueakJS, I would imagine to run all the single image examples of former Squeak/Smalltalk versions inside SqueakJS in a nested fashion. At least this would be necessary if users should be able to inspect and play with the implementations of these historic VM versions. At the moment, this might be possible by browsing the JavaScript implementation using Lively, but for Smalltalk VMs, I would prefer to browse the original Smalltalk/Slang implementations of the VM! 🤓 If we did this in the regular OSVM, -- I guess -- we could simulate these VMs using VMMaker (but I did not try it out yet. Is it fast enough?). Given the current limitations of SqueakJS, I doubt that it would be able to support the VMMaker simulator in a satisfying speed. Thank you for the reference to the publication, I already had skimmed it a few months ago, interesting lecture. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 26. April 2021 17:05:05 An: squeak-dev Betreff: Re: [squeak-dev] Smalltalk Zoo not written in Smalltalk > I don't think that we could simulate older Squeak VMs inside SqueakJS. Well, the Smalltalk Zoo is basically powered by SqueakJS. What do you mean? Maybe this helps: "SqueakJS: a modern and practical smalltalk that runs in any browser" (Freudenberg et al., 2014) https://dl.acm.org/doi/pdf/10.1145/2775052.2661100 Best, Marcel Am 26.04.2021 13:24:00 schrieb Thiede, Christoph : Hi Marcel, mainly because of its speed, I guess. I don't think that we could simulate older Squeak VMs inside SqueakJS. In general, I think the idea is cool, but wouldn't webasm be significantly faster? Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 26. April 2021 08:34:56 An: squeak-dev Betreff: Re: [squeak-dev] Smalltalk Zoo not written in Smalltalk Hi Christoph. > Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Why is SqueakJS (https://squeak.js.org/) not what you are looking for? Best, Marcel Am 25.04.2021 20:41:17 schrieb Thiede, Christoph : Hi all, just a short and curious questions, but not guaranteed to be completely unprovoking. :-) Why is Smalltalk Zoo, the virtual exhibition which compares different milestones in the history of Squeak/Smalltalk, not implemented in Smalltalk itself but in JavaScript, a language which cannot compile itself, is quite the oppposite of Smalltalk in terms of clearness of expression, and escapes control of the actual application? While I love the idea in general, I think it's a shame that the zoo of a language that aims to be implemented in itself is not implemented in that language itself. :D Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron at usmedrec.com Mon Apr 26 18:57:54 2021 From: ron at usmedrec.com (Ron Teitelbaum) Date: Mon, 26 Apr 2021 14:57:54 -0400 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: Hi Chris, Now that voting has started there is no way to remove your name. Plus people have already voted and I'm sure some have already voted for you. You can suggest that people not vote for you but we don't have rules for this situation. The options are: 1. to exclude your name if you are elected and seat the 8th person on the list 2. You can resign after being elected and we would have 6 board members 3. We can seat the first 5 board members since our rules state that we should have an odd number. Board SeatsThe squeak community does its best to elect 7 board members each year. In the event that less than 7 board members run or less than 7 are elected (see Voting for None of the Below) the next largest ODD number of board members will be elected to the board. The requirement for an ODD number of seats is to ensure that tie votes can be broken. For example, if 7 candidates run and 6 are elected, the highest 5 ranking board members will serve on the board. I would prefer option 1 because it makes the most sense to me. It would be good to get feedback from the Squeak communities. If everyone agrees we can just ignore Chris's name on the ballot. All the best, Ron Teitelbaum On Mon, Apr 26, 2021, 2:17 PM Chris Muller wrote: > Okay, now that we have 7 candidates, there's no need for me to run > anymore. Please remove me from the list of candidates. > > - Chris > > On Fri, Apr 23, 2021 at 12:48 PM Bruce O'Neel > wrote: > >> >> What!?!?! There is still time left? >> >> Ok, I'll throw my hat in the ring as well. >> >> I have used Squeak for 20 some years for fun projects. Before that for a >> few glorious hours I had my hands on a Tex 4404 Smalltalk system and lusted >> for a Smalltalk of my own ever since. >> >> My involvement has been to keep the planet Squeak site somewhat up to >> date and to keep debug Linux VM build errors. >> >> cheers >> >> bruce >> >> >> >> *23 April 2021 19:31 tim Rowledge > >> wrote:* >> >> I want to add emphasis to a few words from John-Reed >> >> > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: >> > >> > I encourage anyone who is interested in Squeak to consider becoming a >> board member. It is a good way to learn more about Squeak as a project, and >> help keep development moving forward. >> >> Please don't think there is some need to be a Soopa-Uber-Hacker of Squeak >> in order to be a valuable Board member. If you love Squeak, if you have >> some time and effort you can spare to help keep the community going, then >> you'd be an asset. >> >> tim >> -- >> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim >> Oxymorons: Resident alien >> >> >> >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Mon Apr 26 19:00:29 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 26 Apr 2021 21:00:29 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: +1 for solution 1) 7 members is a good number Le lun. 26 avr. 2021 à 20:58, Ron Teitelbaum a écrit : > > Hi Chris, > > Now that voting has started there is no way to remove your name. Plus people have already voted and I'm sure some have already voted for you. You can suggest that people not vote for you but we don't have rules for this situation. The options are: > 1. to exclude your name if you are elected and seat the 8th person on the list > 2. You can resign after being elected and we would have 6 board members > 3. We can seat the first 5 board members since our rules state that we should have an odd number. > > Board Seats > > The squeak community does its best to elect 7 board members each year. In the event that less than 7 board members run or less than 7 are elected (see Voting for None of the Below) the next largest ODD number of board members will be elected to the board. The requirement for an ODD number of seats is to ensure that tie votes can be broken. For example, if 7 candidates run and 6 are elected, the highest 5 ranking board members will serve on the board. > > I would prefer option 1 because it makes the most sense to me. It would be good to get feedback from the Squeak communities. If everyone agrees we can just ignore Chris's name on the ballot. > > All the best, > > Ron Teitelbaum > > On Mon, Apr 26, 2021, 2:17 PM Chris Muller wrote: >> >> Okay, now that we have 7 candidates, there's no need for me to run anymore. Please remove me from the list of candidates. >> >> - Chris >> >> On Fri, Apr 23, 2021 at 12:48 PM Bruce O'Neel wrote: >>> >>> >>> What!?!?! There is still time left? >>> >>> Ok, I'll throw my hat in the ring as well. >>> >>> I have used Squeak for 20 some years for fun projects. Before that for a few glorious hours I had my hands on a Tex 4404 Smalltalk system and lusted for a Smalltalk of my own ever since. >>> >>> My involvement has been to keep the planet Squeak site somewhat up to date and to keep debug Linux VM build errors. >>> >>> cheers >>> >>> bruce >>> >>> >>> >>> 23 April 2021 19:31 tim Rowledge wrote: >>> >>> I want to add emphasis to a few words from John-Reed >>> >>> > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: >>> > >>> > I encourage anyone who is interested in Squeak to consider becoming a board member. It is a good way to learn more about Squeak as a project, and help keep development moving forward. >>> >>> Please don't think there is some need to be a Soopa-Uber-Hacker of Squeak in order to be a valuable Board member. If you love Squeak, if you have some time and effort you can spare to help keep the community going, then you'd be an asset. >>> >>> tim >>> -- >>> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim >>> Oxymorons: Resident alien >>> >>> >>> >>> >>> >> > From bruce.oneel at pckswarms.ch Mon Apr 26 19:00:56 2021 From: bruce.oneel at pckswarms.ch (Bruce O'Neel) Date: Mon, 26 Apr 2021 21:00:56 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: <1619463656-07618d1523e9725950bd3f72c51c4e53@pckswarms.ch> Hi all, Chris, please don't drop out because I signed up.  I'm sure you would make an excellent board member. Thanks. bruce -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Mon Apr 26 19:03:23 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Mon, 26 Apr 2021 12:03:23 -0700 Subject: [squeak-dev] Smalltalk Zoo not written in Smalltalk In-Reply-To: <68931ba3427e49319625490fb3f73fb9@student.hpi.uni-potsdam.de> References: <68931ba3427e49319625490fb3f73fb9@student.hpi.uni-potsdam.de> Message-ID: I bet Dan would love help from someone working on this! Some of the old Smalltalks indeed run on SqueakJS. Only -72 and -78 have their own Javascript VMs. And you could certainly make a VMMaker image to play with Squeak in SqueakJS. As for speed, I am hoping the new SqueakJS JIT will be competitive with the Stack VM speed. It is more memory hungry though. Then again, ImageSegments work so the different simulations would not all have to live in the same static image. –Vanessa– On Mon, Apr 26, 2021 at 11:45 AM Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de> wrote: > Hi Marcel, > > > if the Smalltalk Zoo was running inside SqueakJS, I would imagine to > run all the single image examples of former Squeak/Smalltalk versions > inside SqueakJS in a nested fashion. At least this would be necessary if > users should be able to inspect and play with the implementations of these > historic VM versions. At the moment, this might be possible by browsing the > JavaScript implementation using Lively, but for Smalltalk VMs, I would > prefer to browse the original Smalltalk/Slang implementations of the VM! 🤓 > > > If we did this in the regular OSVM, -- I guess -- we could simulate these > VMs using VMMaker (but I did not try it out yet. Is it fast enough?). Given > the current limitations of SqueakJS, I doubt that it would be able to > support the VMMaker simulator in a satisfying speed. > > > Thank you for the reference to the publication, I already had skimmed it a > few months ago, interesting lecture. :-) > > > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Taeumel, Marcel > *Gesendet:* Montag, 26. April 2021 17:05:05 > *An:* squeak-dev > *Betreff:* Re: [squeak-dev] Smalltalk Zoo not written in Smalltalk > > > I don't think that we could simulate older Squeak VMs inside SqueakJS. > > Well, the Smalltalk Zoo is basically powered by SqueakJS. What do you mean? > > Maybe this helps: > "SqueakJS: a modern and practical smalltalk that runs in any browser" > (Freudenberg et al., 2014) > https://dl.acm.org/doi/pdf/10.1145/2775052.2661100 > > Best, > Marcel > > Am 26.04.2021 13:24:00 schrieb Thiede, Christoph < > christoph.thiede at student.hpi.uni-potsdam.de>: > > Hi Marcel, > > > mainly because of its speed, I guess. I don't think that we could simulate > older Squeak VMs inside SqueakJS. In general, I think the idea is cool, but > wouldn't webasm be significantly faster? > > > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Taeumel, Marcel > *Gesendet:* Montag, 26. April 2021 08:34:56 > *An:* squeak-dev > *Betreff:* Re: [squeak-dev] Smalltalk Zoo not written in Smalltalk > > Hi Christoph. > > > Is it time to make OSVM ready for webasm? Excited to hear your thoughts > ... > > Why is SqueakJS (https://squeak.js.org/) not what you are looking for? > > Best, > Marcel > > Am 25.04.2021 20:41:17 schrieb Thiede, Christoph < > christoph.thiede at student.hpi.uni-potsdam.de>: > > Hi all, > > > just a short and curious questions, but not guaranteed to be completely > unprovoking. :-) Why is Smalltalk Zoo, the virtual exhibition which > compares different milestones in the history of Squeak/Smalltalk, not > implemented in Smalltalk itself but in JavaScript, a language which cannot > compile itself, is quite the oppposite of Smalltalk in terms of clearness > of expression, and escapes control of the actual application? While I love > the idea in general, I think it's a shame that the zoo of a language that > aims to be implemented in itself is not implemented in that language > itself. :D > > > Is it time to make OSVM ready for webasm? Excited to hear your thoughts ... > > > Best, > > Christoph > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ron at usmedrec.com Mon Apr 26 19:04:12 2021 From: ron at usmedrec.com (Ron Teitelbaum) Date: Mon, 26 Apr 2021 15:04:12 -0400 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: Hi Vannessa, Looks like we agree! Just to clarify the dates changed because at the last minute we were told that everyone that votes needed to first opt-in to receiving email from CIVS to vote. We discussed this and told the community and modified the dates to extend the election for 1 week to allow everyone that wanted to vote to opt-in. We also at that time did not have 7 candidates so we felt that it was reasonable to extend to allow people to opt-in and to give us more time to encourage participation. See: < http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-April/214952.html > We probably should have done that more and made it more visible. All the best, Ron Teitelbaum On Mon, Apr 26, 2021 at 2:57 PM Ron Teitelbaum wrote: > Hi Chris, > > Now that voting has started there is no way to remove your name. Plus > people have already voted and I'm sure some have already voted for you. > You can suggest that people not vote for you but we don't have rules for > this situation. The options are: > 1. to exclude your name if you are elected and seat the 8th person on the > list > 2. You can resign after being elected and we would have 6 board members > 3. We can seat the first 5 board members since our rules state that we > should have an odd number. > Board SeatsThe squeak community does its best to elect 7 board members > each year. In the event that less than 7 board members run or less than 7 > are elected (see Voting for None of the Below) the next largest ODD number > of board members will be elected to the board. The requirement for an ODD > number of seats is to ensure that tie votes can be broken. For example, if > 7 candidates run and 6 are elected, the highest 5 ranking board members > will serve on the board. > > I would prefer option 1 because it makes the most sense to me. It would > be good to get feedback from the Squeak communities. If everyone agrees we > can just ignore Chris's name on the ballot. > > All the best, > > Ron Teitelbaum > > On Mon, Apr 26, 2021, 2:17 PM Chris Muller wrote: > >> Okay, now that we have 7 candidates, there's no need for me to run >> anymore. Please remove me from the list of candidates. >> >> - Chris >> >> On Fri, Apr 23, 2021 at 12:48 PM Bruce O'Neel >> wrote: >> >>> >>> What!?!?! There is still time left? >>> >>> Ok, I'll throw my hat in the ring as well. >>> >>> I have used Squeak for 20 some years for fun projects. Before that for >>> a few glorious hours I had my hands on a Tex 4404 Smalltalk system and >>> lusted for a Smalltalk of my own ever since. >>> >>> My involvement has been to keep the planet Squeak site somewhat up to >>> date and to keep debug Linux VM build errors. >>> >>> cheers >>> >>> bruce >>> >>> >>> >>> *23 April 2021 19:31 tim Rowledge > >>> wrote:* >>> >>> I want to add emphasis to a few words from John-Reed >>> >>> > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: >>> > >>> > I encourage anyone who is interested in Squeak to consider becoming a >>> board member. It is a good way to learn more about Squeak as a project, and >>> help keep development moving forward. >>> >>> Please don't think there is some need to be a Soopa-Uber-Hacker of >>> Squeak in order to be a valuable Board member. If you love Squeak, if you >>> have some time and effort you can spare to help keep the community going, >>> then you'd be an asset. >>> >>> tim >>> -- >>> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim >>> Oxymorons: Resident alien >>> >>> >>> >>> >>> >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Mon Apr 26 19:05:56 2021 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Mon, 26 Apr 2021 12:05:56 -0700 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: Ah I remember now. All good :) Vanessa On Mon, Apr 26, 2021 at 12:04 PM Ron Teitelbaum wrote: > Hi Vannessa, > > Looks like we agree! > > Just to clarify the dates changed because at the last minute we were told > that everyone that votes needed to first opt-in to receiving email from > CIVS to vote. We discussed this and told the community and modified the > dates to extend the election for 1 week to allow everyone that wanted to > vote to opt-in. We also at that time did not have 7 candidates so we felt > that it was reasonable to extend to allow people to opt-in and to give us > more time to encourage participation. See: < > http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-April/214952.html > > > > We probably should have done that more and made it more visible. > > All the best, > > Ron Teitelbaum > > On Mon, Apr 26, 2021 at 2:57 PM Ron Teitelbaum wrote: > >> Hi Chris, >> >> Now that voting has started there is no way to remove your name. Plus >> people have already voted and I'm sure some have already voted for you. >> You can suggest that people not vote for you but we don't have rules for >> this situation. The options are: >> 1. to exclude your name if you are elected and seat the 8th person on the >> list >> 2. You can resign after being elected and we would have 6 board members >> 3. We can seat the first 5 board members since our rules state that we >> should have an odd number. >> Board SeatsThe squeak community does its best to elect 7 board members >> each year. In the event that less than 7 board members run or less than 7 >> are elected (see Voting for None of the Below) the next largest ODD number >> of board members will be elected to the board. The requirement for an ODD >> number of seats is to ensure that tie votes can be broken. For example, if >> 7 candidates run and 6 are elected, the highest 5 ranking board members >> will serve on the board. >> >> I would prefer option 1 because it makes the most sense to me. It would >> be good to get feedback from the Squeak communities. If everyone agrees we >> can just ignore Chris's name on the ballot. >> >> All the best, >> >> Ron Teitelbaum >> >> On Mon, Apr 26, 2021, 2:17 PM Chris Muller wrote: >> >>> Okay, now that we have 7 candidates, there's no need for me to run >>> anymore. Please remove me from the list of candidates. >>> >>> - Chris >>> >>> On Fri, Apr 23, 2021 at 12:48 PM Bruce O'Neel >>> wrote: >>> >>>> >>>> What!?!?! There is still time left? >>>> >>>> Ok, I'll throw my hat in the ring as well. >>>> >>>> I have used Squeak for 20 some years for fun projects. Before that for >>>> a few glorious hours I had my hands on a Tex 4404 Smalltalk system and >>>> lusted for a Smalltalk of my own ever since. >>>> >>>> My involvement has been to keep the planet Squeak site somewhat up to >>>> date and to keep debug Linux VM build errors. >>>> >>>> cheers >>>> >>>> bruce >>>> >>>> >>>> >>>> *23 April 2021 19:31 tim Rowledge > >>>> wrote:* >>>> >>>> I want to add emphasis to a few words from John-Reed >>>> >>>> > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: >>>> > >>>> > I encourage anyone who is interested in Squeak to consider becoming a >>>> board member. It is a good way to learn more about Squeak as a project, and >>>> help keep development moving forward. >>>> >>>> Please don't think there is some need to be a Soopa-Uber-Hacker of >>>> Squeak in order to be a valuable Board member. If you love Squeak, if you >>>> have some time and effort you can spare to help keep the community going, >>>> then you'd be an asset. >>>> >>>> tim >>>> -- >>>> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim >>>> Oxymorons: Resident alien >>>> >>>> >>>> >>>> >>>> >>>> >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ma.chris.m at gmail.com Mon Apr 26 19:08:30 2021 From: ma.chris.m at gmail.com (Chris Muller) Date: Mon, 26 Apr 2021 14:08:30 -0500 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: <1619463656-07618d1523e9725950bd3f72c51c4e53@pckswarms.ch> References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> <1619463656-07618d1523e9725950bd3f72c51c4e53@pckswarms.ch> Message-ID: :) Thanks Bruce. However, this year I want to focus 100% on getting my own stuff caught up with the rest of Squeak. I'm glad you decided to run. - Chris On Mon, Apr 26, 2021 at 2:01 PM Bruce O'Neel wrote: > Hi all, > > Chris, please don't drop out because I signed up. I'm sure you would make > an excellent board member. > > Thanks. > > bruce > > > > > *26 April 2021 20:57 Ron Teitelbaum > > wrote:* > > Hi Chris, > > Now that voting has started there is no way to remove your name. Plus > people have already voted and I'm sure some have already voted for you. > You can suggest that people not vote for you but we don't have rules for > this situation. The options are: > 1. to exclude your name if you are elected and seat the 8th person on the > list > 2. You can resign after being elected and we would have 6 board members > 3. We can seat the first 5 board members since our rules state that we > should have an odd number. > Board Seats > The squeak community does its best to elect 7 board members each year. In > the event that less than 7 board members run or less than 7 are elected > (see Voting for None of the Below) the next largest ODD number of board > members will be elected to the board. The requirement for an ODD number of > seats is to ensure that tie votes can be broken. For example, if 7 > candidates run and 6 are elected, the highest 5 ranking board members will > serve on the board. > > I would prefer option 1 because it makes the most sense to me. It would > be good to get feedback from the Squeak communities. If everyone agrees we > can just ignore Chris's name on the ballot. > > All the best, > > Ron Teitelbaum > > On Mon, Apr 26, 2021, 2:17 PM Chris Muller wrote: > >> Okay, now that we have 7 candidates, there's no need for me to run >> anymore. Please remove me from the list of candidates. >> >> - Chris >> >> On Fri, Apr 23, 2021 at 12:48 PM Bruce O'Neel >> wrote: >> >>> >>> What!?!?! There is still time left? >>> >>> Ok, I'll throw my hat in the ring as well. >>> >>> I have used Squeak for 20 some years for fun projects. Before that for >>> a few glorious hours I had my hands on a Tex 4404 Smalltalk system and >>> lusted for a Smalltalk of my own ever since. >>> >>> My involvement has been to keep the planet Squeak site somewhat up to >>> date and to keep debug Linux VM build errors. >>> >>> cheers >>> >>> bruce >>> >>> >>> >>> *23 April 2021 19:31 tim Rowledge > >>> wrote:* >>> >>> I want to add emphasis to a few words from John-Reed >>> >>> > On 2021-04-23, at 10:22 AM, John-Reed Maffeo wrote: >>> > >>> > I encourage anyone who is interested in Squeak to consider becoming a >>> board member. It is a good way to learn more about Squeak as a project, and >>> help keep development moving forward. >>> >>> Please don't think there is some need to be a Soopa-Uber-Hacker of >>> Squeak in order to be a valuable Board member. If you love Squeak, if you >>> have some time and effort you can spare to help keep the community going, >>> then you'd be an asset. >>> >>> tim >>> -- >>> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim >>> Oxymorons: Resident alien >>> >>> >>> >>> >>> <> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Mon Apr 26 19:44:03 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 26 Apr 2021 21:44:03 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: Hi Nicolas, Unfortunately, there are yet other things not working now: ['Foobar' displaySequentialProgress: [#(a b c) do: [:each | (Delay forSeconds: 1) wait] displayingProgress: [:each | 'item ', each]]] on: ProgressInitiationException do: [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] will end with a MNU because the handler in displaySequentialProgress: does not support the ProgressNotification signalled from the loop. I did not debug it until the end, but I guess the implicit handler in MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the loop) previously got the notification, but is now terminated away (by Context>>resumeEvaluating: in sendNotificationsTo:) before the workBlock is evaluated. So the loop progress notifications do not get there anymore, but to the handler in displaySequentialProgress:. If it is not terminated away, then I suppose the order of those two handlers on the stack is now swapped... Something like the above I use to test the progress suppressing during test cases, which was previously broken, but now works. Glad that I wrote these tests for the testing facility itself... It is quite messy how the progress stuff is coupled to the implementation details of exception handling. Kind regards, Jakob Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > ==================== Summary ==================== > > Name: ToolBuilder-Kernel-nice.143 > Author: nice > Time: 26 April 2021, 2:20:20.490026 am > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > Ancestors: ToolBuilder-Kernel-nice.141 > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > Item was changed: > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > sendNotificationsTo: aNewBlock > + self resumeEvaluating: [workBlock value: [ :barVal | > - > - self reactivateHandlers; resumeUnchecked: ( > - workBlock value: [ :barVal | > aNewBlock value: minVal value: maxVal value: barVal > + ]] > - ] > - ) > ! > > From tonyg at leastfixedpoint.com Mon Apr 26 20:52:40 2021 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Mon, 26 Apr 2021 22:52:40 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: On 4/26/21 8:57 PM, Ron Teitelbaum wrote: > The options are: > 1. to exclude your name if you are elected and seat the 8th person on > the list > I would prefer option 1 because it makes the most sense to me. Me too. +1 to option 1. Tony From nicolas.cellier.aka.nice at gmail.com Mon Apr 26 21:17:27 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 26 Apr 2021 23:17:27 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: Ah yes, tight coupling is not ideal... It's pretty long to debug. I see a (ProgressNotification signal: '' extra: (oldLabel := newLabel)) sent from inner do:displayProgress: (do:displayProgress:every:) This is indeed caught by outer displaySequentialProgress: which interprets the messageText '' asNumber and fails... It appears like the enclosing on: ProgressInitiationException do: ... sendNotificationsTo: ... is catching both initiations instead of only the first one... This is because the resumeEvaluating: rearmed the handler before evaluating the block. It does so while unwinding the ensure: [self reactivateHandler] in handleSignal:... So, in normal case, the 2nd ProgressInitiationException is not caught... It thus performs its default action, which is opening the progress bar, and catching ProgressNotification to feed the progress bar... In normal case, this is this second (on: ProgressNotification do:) which is on top of stack of handlers... Somehow, my proposed solution is equivalent to evaluating this in older image, which equally fails... ['Foobar' displaySequentialProgress: [#(a b c) do: [:each | (Delay forSeconds: 1) wait] displayingProgress: [:each | 'item ', each]]] on: ProgressInitiationException do: [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min :max :val | "nothing"]]] If I change implementation with ugly: sendNotificationsTo: aNewBlock self resumeEvaluating: [self privHandlerContext deactivateHandler. [workBlock value: [ :barVal | aNewBlock value: minVal value: maxVal value: barVal]] ensure: [self privHandlerContext reactivateHandler]] then this snippet pass... Le lun. 26 avr. 2021 à 21:44, Jakob Reschke a écrit : > > Hi Nicolas, > > Unfortunately, there are yet other things not working now: > > ['Foobar' displaySequentialProgress: > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > displayingProgress: [:each | 'item ', each]]] > on: ProgressInitiationException do: > [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] > > will end with a MNU because the handler in displaySequentialProgress: > does not support the ProgressNotification signalled from the loop. > I did not debug it until the end, but I guess the implicit handler in > MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the > loop) previously got the notification, but is now terminated away (by > Context>>resumeEvaluating: in sendNotificationsTo:) before the > workBlock is evaluated. So the loop progress notifications do not get > there anymore, but to the handler in displaySequentialProgress:. If it > is not terminated away, then I suppose the order of those two handlers > on the stack is now swapped... > > Something like the above I use to test the progress suppressing during > test cases, which was previously broken, but now works. Glad that I > wrote these tests for the testing facility itself... > > It is quite messy how the progress stuff is coupled to the > implementation details of exception handling. > > Kind regards, > Jakob > > Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > > > ==================== Summary ==================== > > > > Name: ToolBuilder-Kernel-nice.143 > > Author: nice > > Time: 26 April 2021, 2:20:20.490026 am > > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > > Ancestors: ToolBuilder-Kernel-nice.141 > > > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > > > Item was changed: > > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > > sendNotificationsTo: aNewBlock > > + self resumeEvaluating: [workBlock value: [ :barVal | > > - > > - self reactivateHandlers; resumeUnchecked: ( > > - workBlock value: [ :barVal | > > aNewBlock value: minVal value: maxVal value: barVal > > + ]] > > - ] > > - ) > > ! > > > > > From jakres+squeak at gmail.com Mon Apr 26 21:22:13 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 26 Apr 2021 23:22:13 +0200 Subject: [squeak-dev] Squeak Oversight Board Election 2021 In-Reply-To: References: <918474fbade74e00b8a33d1db2e089b3@hpi.de> <1619200075-34ae0136bde94ebae51dd92da9d2e57b@pckswarms.ch> Message-ID: Option 1 please. Am Mo., 26. Apr. 2021 um 22:52 Uhr schrieb Tony Garnock-Jones : > > On 4/26/21 8:57 PM, Ron Teitelbaum wrote: > > The options are: > > 1. to exclude your name if you are elected and seat the 8th person on > > the list > > > I would prefer option 1 because it makes the most sense to me. > > Me too. +1 to option 1. > > Tony > From nicolas.cellier.aka.nice at gmail.com Mon Apr 26 21:29:56 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 26 Apr 2021 23:29:56 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: Le lun. 26 avr. 2021 à 23:17, Nicolas Cellier a écrit : > > Ah yes, tight coupling is not ideal... > It's pretty long to debug. > I see a (ProgressNotification signal: '' extra: (oldLabel := > newLabel)) sent from inner do:displayProgress: > (do:displayProgress:every:) > This is indeed caught by outer displaySequentialProgress: which > interprets the messageText '' asNumber and fails... > > It appears like the enclosing on: ProgressInitiationException do: ... > sendNotificationsTo: ... is catching both initiations instead of only > the first one... > This is because the resumeEvaluating: rearmed the handler before > evaluating the block. > It does so while unwinding the ensure: [self reactivateHandler] in > handleSignal:... > > So, in normal case, the 2nd ProgressInitiationException is not caught... > It thus performs its default action, which is opening the progress > bar, and catching ProgressNotification to feed the progress bar... > In normal case, this is this second (on: ProgressNotification do:) > which is on top of stack of handlers... > > Somehow, my proposed solution is equivalent to evaluating this in > older image, which equally fails... > > ['Foobar' displaySequentialProgress: > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > displayingProgress: [:each | 'item ', each]]] > on: ProgressInitiationException do: > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > :max :val | "nothing"]]] > > If I change implementation with ugly: > > sendNotificationsTo: aNewBlock > self resumeEvaluating: > [self privHandlerContext deactivateHandler. > [workBlock value: [ :barVal | > aNewBlock value: minVal value: maxVal value: barVal]] > ensure: [self privHandlerContext reactivateHandler]] > > then this snippet pass... > sent too soon, sorry... The snippet you gave pass with horrific hack proposed above. But if we deactivateHandler inside sendNotificationsTo:, then we're not able to rearm anymore: on: ProgressInitiationException do: [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min :max :val | "nothing"]]] will now fail to properly rearm... Horrible. sendNotificationsTo: is really tightly coupled to the fact that inner handlers remain active... > > Le lun. 26 avr. 2021 à 21:44, Jakob Reschke a écrit : > > > > Hi Nicolas, > > > > Unfortunately, there are yet other things not working now: > > > > ['Foobar' displaySequentialProgress: > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > displayingProgress: [:each | 'item ', each]]] > > on: ProgressInitiationException do: > > [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] > > > > will end with a MNU because the handler in displaySequentialProgress: > > does not support the ProgressNotification signalled from the loop. > > I did not debug it until the end, but I guess the implicit handler in > > MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the > > loop) previously got the notification, but is now terminated away (by > > Context>>resumeEvaluating: in sendNotificationsTo:) before the > > workBlock is evaluated. So the loop progress notifications do not get > > there anymore, but to the handler in displaySequentialProgress:. If it > > is not terminated away, then I suppose the order of those two handlers > > on the stack is now swapped... > > > > Something like the above I use to test the progress suppressing during > > test cases, which was previously broken, but now works. Glad that I > > wrote these tests for the testing facility itself... > > > > It is quite messy how the progress stuff is coupled to the > > implementation details of exception handling. > > > > Kind regards, > > Jakob > > > > Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > > > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > > > > > ==================== Summary ==================== > > > > > > Name: ToolBuilder-Kernel-nice.143 > > > Author: nice > > > Time: 26 April 2021, 2:20:20.490026 am > > > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > > > Ancestors: ToolBuilder-Kernel-nice.141 > > > > > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > > > > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > > > > > Item was changed: > > > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > > > sendNotificationsTo: aNewBlock > > > + self resumeEvaluating: [workBlock value: [ :barVal | > > > - > > > - self reactivateHandlers; resumeUnchecked: ( > > > - workBlock value: [ :barVal | > > > aNewBlock value: minVal value: maxVal value: barVal > > > + ]] > > > - ] > > > - ) > > > ! > > > > > > > > From tim at rowledge.org Mon Apr 26 21:48:54 2021 From: tim at rowledge.org (tim Rowledge) Date: Mon, 26 Apr 2021 14:48:54 -0700 Subject: [squeak-dev] Squeak VM & image package/bundle building? Message-ID: <047E8F66-343F-403F-9EEB-D6EB3168C74F@rowledge.org> We obviously have some system in place that produces the downloadable packages containing the vm & image etc. I haven't so far successfully googled anything that usefully helps me understand *how*. What is the current build setup for these things? Do we have to run platform specific jobs or is it practical to have a single system? I'm interested in how one might build a Mac bundle, for example, that might have a custom name, icons, image file, other resources. I recall some quite long threads about the joy of signing Mac application bundles too. And can Mac & Windows applications run without open windows these days? Again, I recall interesting issues with this years ago but nothing from more recent times. Imagine I want to run a Seaside server; no open windows, write errors to a suitable log, stuff like that. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful Latin Phrases:- Furnulum pani nolo = I don't want a toaster. From commits at source.squeak.org Tue Apr 27 11:51:34 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 27 Apr 2021 11:51:34 0000 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.144.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.144.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-nice.144 Author: nice Time: 27 April 2021, 1:51:16.980651 pm UUID: 89bbcc07-c286-4b42-b938-3ccee798d5fb Ancestors: ToolBuilder-Kernel-nice.141 Fix ProgressInitiationException>>sendNotificationsTo: so that: - the ProgressInitiationException remains inactive during workBlock evaluation - unlesse explicitely rearmed - active inner handlers remain active during workBlock evaluation For the last goal, it is necessary to first resume, then evaluate the workBlock, hence usage of #resumeEvaluating: This goes with Kernel-nice.1394 which implements this method as well as upgraded signal handling. But if we resume, then we also reactivate current handler. Generally, we do not want to reactivate current handler, unless explicit rearmHandlerDuring:, thus the intricated activate/deactivate dance. =============== Diff against ToolBuilder-Kernel-nice.141 =============== Item was changed: + ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'handling') ----- - ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- sendNotificationsTo: aNewBlock + "Resume execution using aNewBlock as workBlock value. + Note that the execution is resumed in signalContext (or outerContext). + This is done so that inner exception handlers be active during workBlock execution. + However, our own handlerContext should be deactivated, unless explicitely rearmed." + | mustDeactivateHandler | + mustDeactivateHandler := handlerContext notNil and: [handlerContext isHandlerActive not]. + mustDeactivateHandler + ifTrue: + ["The handlerContext is de-activated during handleSignal: + But it will be reactivated during unwinding when we will resumeEvaluating: + That's unwanted, we don't generally want to rearm the handler during workBlock evaluation. + Hence we have to deactivate it again inside the deferred block." + self resumeEvaluating: + [handlerContext deactivateHandler. + [workBlock value: [ :barVal | + aNewBlock value: minVal value: maxVal value: barVal]] + ensure: [handlerContext reactivateHandler]]] + ifFalse: + ["If the handler is active at this step, then it must have been rearmed + with a #rearmHandlerDuring: + It's thus intentional to keep the handler active during workBlock evaluation" + self resumeEvaluating: + [workBlock value: [ :barVal | + aNewBlock value: minVal value: maxVal value: barVal]]]! - - self reactivateHandlers; resumeUnchecked: ( - workBlock value: [ :barVal | - aNewBlock value: minVal value: maxVal value: barVal - ] - ) - ! From nicolas.cellier.aka.nice at gmail.com Tue Apr 27 11:57:03 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 27 Apr 2021 13:57:03 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: Hi Jakob, So far, you're my greatest brainstorming provider! See my next solution in ToolBuilder-Kernel-nice.144. I don't feel like I can omit the comments, which is a smell. But that's the price for maintaining backward compatibility with contradictory rules/features. Le lun. 26 avr. 2021 à 23:29, Nicolas Cellier a écrit : > > Le lun. 26 avr. 2021 à 23:17, Nicolas Cellier > a écrit : > > > > Ah yes, tight coupling is not ideal... > > It's pretty long to debug. > > I see a (ProgressNotification signal: '' extra: (oldLabel := > > newLabel)) sent from inner do:displayProgress: > > (do:displayProgress:every:) > > This is indeed caught by outer displaySequentialProgress: which > > interprets the messageText '' asNumber and fails... > > > > It appears like the enclosing on: ProgressInitiationException do: ... > > sendNotificationsTo: ... is catching both initiations instead of only > > the first one... > > This is because the resumeEvaluating: rearmed the handler before > > evaluating the block. > > It does so while unwinding the ensure: [self reactivateHandler] in > > handleSignal:... > > > > So, in normal case, the 2nd ProgressInitiationException is not caught... > > It thus performs its default action, which is opening the progress > > bar, and catching ProgressNotification to feed the progress bar... > > In normal case, this is this second (on: ProgressNotification do:) > > which is on top of stack of handlers... > > > > Somehow, my proposed solution is equivalent to evaluating this in > > older image, which equally fails... > > > > ['Foobar' displaySequentialProgress: > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > displayingProgress: [:each | 'item ', each]]] > > on: ProgressInitiationException do: > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > :max :val | "nothing"]]] > > > > If I change implementation with ugly: > > > > sendNotificationsTo: aNewBlock > > self resumeEvaluating: > > [self privHandlerContext deactivateHandler. > > [workBlock value: [ :barVal | > > aNewBlock value: minVal value: maxVal value: barVal]] > > ensure: [self privHandlerContext reactivateHandler]] > > > > then this snippet pass... > > > > sent too soon, sorry... > The snippet you gave pass with horrific hack proposed above. > > But if we deactivateHandler inside sendNotificationsTo:, then we're > not able to rearm anymore: > > on: ProgressInitiationException do: > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > :max :val | "nothing"]]] > > will now fail to properly rearm... Horrible. > > sendNotificationsTo: is really tightly coupled to the fact that inner > handlers remain active... > > > > > Le lun. 26 avr. 2021 à 21:44, Jakob Reschke a écrit : > > > > > > Hi Nicolas, > > > > > > Unfortunately, there are yet other things not working now: > > > > > > ['Foobar' displaySequentialProgress: > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > displayingProgress: [:each | 'item ', each]]] > > > on: ProgressInitiationException do: > > > [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] > > > > > > will end with a MNU because the handler in displaySequentialProgress: > > > does not support the ProgressNotification signalled from the loop. > > > I did not debug it until the end, but I guess the implicit handler in > > > MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the > > > loop) previously got the notification, but is now terminated away (by > > > Context>>resumeEvaluating: in sendNotificationsTo:) before the > > > workBlock is evaluated. So the loop progress notifications do not get > > > there anymore, but to the handler in displaySequentialProgress:. If it > > > is not terminated away, then I suppose the order of those two handlers > > > on the stack is now swapped... > > > > > > Something like the above I use to test the progress suppressing during > > > test cases, which was previously broken, but now works. Glad that I > > > wrote these tests for the testing facility itself... > > > > > > It is quite messy how the progress stuff is coupled to the > > > implementation details of exception handling. > > > > > > Kind regards, > > > Jakob > > > > > > Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > > > > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > > > > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > > > > > > > ==================== Summary ==================== > > > > > > > > Name: ToolBuilder-Kernel-nice.143 > > > > Author: nice > > > > Time: 26 April 2021, 2:20:20.490026 am > > > > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > > > > Ancestors: ToolBuilder-Kernel-nice.141 > > > > > > > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > > > > > > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > > > > > > > Item was changed: > > > > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > > > > sendNotificationsTo: aNewBlock > > > > + self resumeEvaluating: [workBlock value: [ :barVal | > > > > - > > > > - self reactivateHandlers; resumeUnchecked: ( > > > > - workBlock value: [ :barVal | > > > > aNewBlock value: minVal value: maxVal value: barVal > > > > + ]] > > > > - ] > > > > - ) > > > > ! > > > > > > > > > > > From marcel.taeumel at hpi.de Tue Apr 27 14:40:56 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 27 Apr 2021 16:40:56 +0200 Subject: [squeak-dev] Please try out | Cross-platform mapping for virtual key codes :-) Message-ID: Hi all! Please find attached a changeset that adds mapping tables for virtual keys (or scan codes) for macOS, X11, and Windows. You can find them in EventSensor class >> #virtualKeysOn* You can try out if they work through the KeyboardExerciser. Please take a look at the balloon text (i.e. tool tip) to better understand the data. There is also a new preference: [x] Simplify Virtual-key codes ... because of Windows who dares to couple codes to the input language (e.g. US vs. DE), which Squeak knows nothing about. macOS is better in this regard. :-) Biggest mess is on Linux/X11. For key-down/up events, the Linux VM delivers actual character codes instead of scan codes, which makes a basic mapping to physical keys almost impossible. See EventSensor class >> #virtualKeysOnX11. We MUST fix that! Please. Somebody. Can I haz scan codes? ^__^ *** *** The good news: KeyboardEvent >> #key (and UserInputEvent >> #modifiers) now gives you cross-platform stable information about physical keys to be used in keyboard handlers. Yes, for both key-stroke and key-down/up events. Or at least, that is the plan. That's why it would be great if you could help testing! :-) Why key-stroke events too? Aren't they for typing text only? 1. Almost all keyboard shortcuts in current Squeak are based on key-stroke events. 2. Using the #keyCharacter is tricky because SHIFT changes lower-case to upper-case, which makes "anEvent shiftPressed" hard to understand. 3. CTRL combinations might not do the expected thing. How would you handle CTRL+C? The #keyCharacter could arrive as $c or Character enter. See the preference "Map non-printable characters to printable characters. Now, #key will always answer $C in such a case. Regardless of that preference. Can't we just use #keyCharacter in key-down/up events? No. Those are undefined. Never do that. key-down/up events carry virtual-key codes in their #keyValue. We might want to change #keyCharacter to answer "nil" for those events. *** Q: What is a "physical key" or "physical modifier"? A: The label that can be presented to the user so that he or she feels at home when using Squeak. Thus, looks platform-specific. Q: What is a "virtual key" or "virtual modifier"? A: The information to be processed in your application's key handlers. Thus, looks platform-independent. If you have still no clue how to talk to keyboard events, please read the commentary in KeyboardEvent >> #checkCommandKey. *** Happy testing! :-) And thank you all in advance! Best, Marcel P.S.: You might want to disable the preference "synthesize mouse-wheel events from keyboard-events" to get CTRL+ArrowUp and CTRL+ArrowDown ;-) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 57922 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: virtual-keys.11.cs Type: application/octet-stream Size: 33673 bytes Desc: not available URL: From marcel.taeumel at hpi.de Tue Apr 27 14:59:12 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 27 Apr 2021 16:59:12 +0200 Subject: [squeak-dev] The Inbox: Morphic-ct.1586.mcz In-Reply-To: References: <96876dfbbb014187a83bee99f8819c5a@student.hpi.uni-potsdam.de> <84a83a66744e4fbd83de179f73b10b1f@student.hpi.uni-potsdam.de> <2b963e0e1d1c4eedaf2639846a3ef32a@student.hpi.uni-potsdam.de> <6b97ba33768846ebbf0544950bc570e4@student.hpi.uni-potsdam.de> <,> Message-ID: Hi Christoph. > With the new attribute, a workflow no longer needs to make this assumption. I am not talking about changing people. I hypothesized existing workflows. :-) What are people doing now and how can we avoid disrupting existing knowledge and expectations. Well, I am trying to treat this as a new feature, knowing that you have been using it for quite some time now. Any statistics on clicking on ByteStrings? > Please don't introduce self-destroying objects in Squeak! :-) Who would ever want to keep the browser open after saving that source code? What's done is done. :-D Best, Marcel Am 26.04.2021 20:28:21 schrieb Thiede, Christoph : Hi Marcel, > I would expect that, in such a scenario, print-it would rarely be used. [http://www.hpi.de/] You are arguing from the status quo where printed-it (print-itted?) results are effectively lost for further observation. With the new attribute, a workflow no longer needs to make this assumption. I would rather think of these attributes as notebook-like cell outputs. Unless a user wants to reuse the result in another expression from within the same text field, he or she is not required to use any variables at all. In contexts without workspace bindings (such as inspectors), this is even the only way now to persist object results. Thus, speaking generally, users could indeed rely on print-its for costly operations as of now. :-) > Hmmm... we might want to remove that interactive print-it text after the user has clicked on it :-) Please don't introduce self-destroying objects in Squeak! :-) Best, Christoph Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 26. April 2021 18:53:40 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz   Hi all, please note that "CMD+0" will immediately remove that text action after the print-it (CMD+P) if you want to use it for something else. :-) Best, Marcel Am 25.04.2021 19:43:40 schrieb Jakob Reschke : Hi all, So visual consistency for Christoph means: all results are highlighted(/click-inspectable). Whereas for Marcel it means: all complex/interesting results are highlighted/click-inspectable. What does everyone else think about this? I sometimes wish that the print-it results in the workspace would be treated differently than the text that I typed myself. Highlighting them (link or otherwise) could help to spot the frontier between expression and result after some more actions, but would otherwise not help me much. When I intended to use the printed result in my next expression, highlighting it as a result would be inappropriate, but I rarely ever want to do this. For most complex objects, this is not even possible because their print strings are not Smalltalk expressions. But I cannot use a non-Smalltalk expression with a link on it in my next expression either, so the feature does not help me in that case anyway. (What I would rather need is a "put this into a variable" command, kind of a refactoring operation for the Workspace.) If I wanted to send further messages to a returned 'String' I would most likely move it onto its own line for convenient Cmd-p/i first anyway, I would not keep it to the right of the expression that evaluated to the 'String'. With this reasoning, I would rather lean towards Christoph's interpretation now. (Also I believe it does not hurt so much if one can also inspect the primitive results.) But I have not used the feature in practice so far, so I will let some time pass for now. Kind regards, Jakob Am Sa., 24. Apr. 2021 um 17:43 Uhr schrieb Marcel Taeumel : > > Hi Jakob, > > thanks for summarizing our arguments. :-) I would rather try to avoid another preference just to configure this preference. ;-) Maybe we can keep the uniform appearance for clickable text actions. I am surprised that DoItActions look different. > > Hey Christoph, > > a simple list of exclusions is not complex. Especially since it reflects stable language (and system) properties. I do appreciate your onward pursue of "perfect consistency." However, the system is full of trade-offs because it serves a rather broad audience. > > I am also in favor of visual consistency for this feature. By only showing it for actually interesting object structures, we actually achieve consistency for those structures. Having it also for primitives would spoil the usefulness of this feature. People might think they found something interesting -- to then be disappointed that it is just a flat string. > > Optimizing this feature for MCVersionName?! A domain-specific subclass of String? Well, I consider this design rather unfortunate. In such a case, on might be better of to favor composition over inheritance. That's an anti-pattern. Please do not do that in your projects. :-) ... I suspect an optimization for a database ... not sure. Chris? > > Hi all, > > here is again the list of objects I think we should exclude from having a text action on their print-it result: > > ByteString > ByteSymbol > Number > Boolean > UndefinedObject > > If you find concrete arguments (and examples) against elements on this list, please step forward and name them. :-) > > Reducing visual clutter is worth a few lines of extra source code. > > Best, > Marcel > > Am 24.04.2021 15:42:08 schrieb Thiede, Christoph : > > Hi Jakob, Hi Marcel, > > > thank you for reviving this discussion! :-) > > > > Christoph, when you inspect your MCVersionNames, do you already know that these are version names or do you inspect them to find out what they are? ("What is this, a String or an MCVersionName?") > > > Definitively also the latter. > > > While the type check might not be really necessary, avoiding visual clutter can be a good thing. > > -1 from my side here. :-) I see little value in adding complexity - and possibly confusion - in order to "simplify" the appearance - in my opinion, the clutter would become even larger if in some cases, the result is blue, and in other cases, it isn't. I would rank (visual) consistency the highest here. We are introducing an additional classification here ("is primitive/is literal/is non-sense?") that is non-trivial as we can see from this discussion, and such heuristics feels a little bit like "too much AI" for a general-purpose system like Squeak/Smalltalk, at least to me. > > > How about allowing to turn off the highlighting of the result? I mean, make it still clickable, but do not paint it blue. > > This might be a trade-off for me, but on the other hand, the logic is still cluttered. And the explorability is impeded ... > > Best, > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von Jakob Reschke > Gesendet: Samstag, 24. April 2021 11:43:06 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Inbox: Morphic-ct.1586.mcz > > Hi Christoph, hi Marcel, > > Am Di., 20. Apr. 2021 um 08:58 Uhr schrieb Marcel Taeumel > : > > > > Hi Christoph, > > > > > [...] subclasses of ByteString can be indeed non-trivial. This applies to MCVersionName, for example > > > > You are mixing up object structure with structured information. The latter needs interpretation by some other means. Squeak's inspector cannot provide such means of interpretation such as for URLs in strings. > > > > I am struggling to understand how your arguments address each other > person's concerns. Did I understand your points correctly: > > - Christoph wants to get rid of the type check. He argues that > sometimes even for the objects with "primitive" structure you may want > to get the link. For example, MCVersionName loses its type information > when printed, so when you would inspect the result, you would get a > String instead of an MCVersionName. The other example is when you want > to track identity. Indeed, sometimes it is useful to check whether one > String is the same as another one retrieved (inspected) from somewhere > else. I do this regularly in Squot when debugging the capturing and > materialization (although seldom for Strings at this time because for > these it already works as expected). > > - Marcel says that the links are unnecessary for what are essentially > value objects that are not complex enough to need inspection beyond > just looking at the print string. Supposedly, one can just reevaluate > the result or the expression. Adding the links there produces visual > clutter and is distracting. Inspecting an MCVersionName would reveal > no further information about the object than the print string does > (that is, except for the type!). > > Christoph, when you inspect your MCVersionNames, do you already know > that these are version names or do you inspect them to find out what > they are? ("What is this, a String or an MCVersionName?") > > I fully agree with Marcel on the immediates and singletons (true, > false, nil, Symbols). While the type check might not be really > necessary, avoiding visual clutter can be a good thing. Tradeoff is > with having the special case in the code. > > Unfortunately(?), Strings in Squeak/Smalltalk are not quite value > objects, since they are mutable, can be used as buffers, etc. Depends > on the application. > > On the other hand, Points are mostly used as value objects, but did > not get the special case treatment. Though strictly, technically > speaking, they are not different from Strings in this regard. > > Inspecting the result string or the revaluating the original > expression to do so is only safe if it does not provoke side effects. > For Marcel's selection of classes, there are no side effects of > reevaluating the result string. But reevaluating the original > expression might not be free of side effects. I guess you would not > reevaluate the expression to inspect an immediate or singleton, but > for those objects that do have object identity, such as Strings, or > where the type of the result is not obvious, MCVersionName, you might > want to do that. > > How about allowing to turn off the highlighting of the result? I mean, > make it still clickable, but do not paint it blue. Then there would be > no visual clutter, and if you know that the feature is there (and you > have subsequently turned off the preference, for example), you would > also not easily forget that you can use it. > > Kind regards, > Jakob > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Apr 27 15:07:18 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 27 Apr 2021 17:07:18 +0200 Subject: [squeak-dev] The Inbox: Collections-ul.933.mcz In-Reply-To: References: Message-ID: +1 I suppose =) It's faster then: [OrderedCollection streamContents: [:s | s nextPut: #apple]] bench   BEFORE: '2,630,000 per second. 380 nanoseconds per run. 16.13677 % GC time.' AFTER: '3,990,000 per second. 251 nanoseconds per run. 15.89682 % GC time.' Best, Marcel Am 31.03.2021 02:19:03 schrieb commits at source.squeak.org : Levente Uzonyi uploaded a new version of Collections to project The Inbox: http://source.squeak.org/inbox/Collections-ul.933.mcz ==================== Summary ==================== Name: Collections-ul.933 Author: ul Time: 31 March 2021, 2:17:52.141067 am UUID: b290ad2c-2ed0-4d46-b2fe-12545bf5f31c Ancestors: Collections-ul.932 - use #ofSize: instead of #new: in SequenceableCollection class >> new:streamContents:, so that it creates a stream on a non-empty collection even if the receiver is OrderedCollection. =============== Diff against Collections-ul.932 =============== Item was changed: ----- Method: SequenceableCollection class>>new:streamContents: (in category 'stream creation') ----- new: newSize streamContents: blockWithArg | stream originalContents | + stream := WriteStream on: (self ofSize: newSize). - stream := WriteStream on: (self new: newSize). blockWithArg value: stream. originalContents := stream originalContents. + ^originalContents size = stream position + ifTrue: [ originalContents ] + ifFalse: [ stream contents ]! - originalContents size = stream position - ifTrue: [ ^originalContents ] - ifFalse: [ ^stream contents ]! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Apr 28 07:04:40 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 28 Apr 2021 07:04:40 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1762.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1762.mcz ==================== Summary ==================== Name: Morphic-mt.1762 Author: mt Time: 28 April 2021, 9:04:35.649168 am UUID: 19ccb34e-5e3b-0e4d-a61f-bc953107aaf2 Ancestors: Morphic-mt.1761 Until the discussion is resolved, do not apply a list of exceptions for the "interactive print-it" feature/preference. See http://forum.world.st/The-Inbox-Morphic-ct-1586-mcz-tp5106774p5129065.html =============== Diff against Morphic-mt.1761 =============== Item was changed: ----- Method: TextEditor>>printItTextFor: (in category 'do-its') ----- printItTextFor: anObject + self flag: #todo. "mt: Maybe reserve highlights for non-primitive structures only? Maybe skip ByteString, ByteSymbol, Number, Boolean, UndefinedObject? See discussion here: http://forum.world.st/The-Inbox-Morphic-ct-1586-mcz-tp5106774p5129065.html" + + ^ self class interactivePrintIt - ^ (self class interactivePrintIt and: [(anObject isString or: [anObject isNumber]) not]) ifFalse: [anObject printString] ifTrue: [Text string: anObject printString attribute: (TextInspectIt on: anObject)]! From commits at source.squeak.org Wed Apr 28 07:31:18 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 28 Apr 2021 07:31:18 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1763.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1763.mcz ==================== Summary ==================== Name: Morphic-mt.1763 Author: mt Time: 28 April 2021, 9:31:14.313168 am UUID: 33370f53-b3b0-0b4a-8333-fe869808b435 Ancestors: Morphic-mt.1762 Fixes hpi-dpi bug for windows opened via #openModal: such as the FontChooserTool. The windows had the wrong extent. =============== Diff against Morphic-mt.1762 =============== Item was changed: ----- Method: Morph>>openModal: (in category 'polymorph') ----- openModal: aSystemWindow "Open the given window locking the receiver until it is dismissed. Answer the system window. Restore the original keyboard focus when closed." + | hand priorFocus mySysWin | + mySysWin := self isSystemWindow + ifTrue: [ self ] + ifFalse: [ (self ownerThatIsA: SystemWindow) ifNil: [ self ] ]. + hand := self currentHand. + priorFocus := hand keyboardFocus. + [ mySysWin modalLockTo: aSystemWindow. + ToolBuilder default runModal: aSystemWindow openAsIs ] + ensure: + [ mySysWin modalUnlockFrom: aSystemWindow. + hand newKeyboardFocus: priorFocus ]. - |area mySysWin keyboardFocus| - keyboardFocus := self activeHand keyboardFocus. - mySysWin := self isSystemWindow ifTrue: [self] ifFalse: [self ownerThatIsA: SystemWindow]. - mySysWin ifNil: [mySysWin := self]. - mySysWin modalLockTo: aSystemWindow. - area := RealEstateAgent maximumUsableArea. - aSystemWindow extent: aSystemWindow initialExtent. - aSystemWindow position = (0 at 0) - ifTrue: [aSystemWindow - position: self activeHand position - (aSystemWindow extent // 2)]. - aSystemWindow - bounds: (aSystemWindow bounds translatedToBeWithin: area). - [ToolBuilder default runModal: aSystemWindow openAsIs] - ensure: [mySysWin modalUnlockFrom: aSystemWindow. - self activeHand newKeyboardFocus: keyboardFocus]. ^aSystemWindow! From marcel.taeumel at hpi.de Wed Apr 28 10:02:44 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 28 Apr 2021 12:02:44 +0200 Subject: [squeak-dev] Please try out | Cross-platform mapping for virtual key codes :-) In-Reply-To: References: Message-ID: Hi all! Here is a small update. Please find attached the changeset. Updates: - Adds KeyboardEvent >> #keyCode (via new inst-var) - Logs the last key-down event to attach virtual-key codes to key-stroke events; see HandMorph >> #generateKeyboardEvent: - Simplifies KeyboardEvent >> #key - Show event repetition in KeyboardExecizer Major questions: 1. Does it work on your machine? 2. What are your thoughts on KeyboardEvent >> #key? 3. What are your thoughts on KeyboardEvent >> #keyCode? 4. Do you understand KeyboardEvent >> #physicalKey #virtualKey #physicalModifiers #virtualModifiers ? Happy testing! Best, Marcel P.S.: Don't forget about the X11 key (scan?) codes. ^__^ I haven't had the time to look into the VM plugin yet. Am 27.04.2021 16:40:56 schrieb Marcel Taeumel : Hi all! Please find attached a changeset that adds mapping tables for virtual keys (or scan codes) for macOS, X11, and Windows. You can find them in EventSensor class >> #virtualKeysOn* You can try out if they work through the KeyboardExerciser. Please take a look at the balloon text (i.e. tool tip) to better understand the data. There is also a new preference: [x] Simplify Virtual-key codes ... because of Windows who dares to couple codes to the input language (e.g. US vs. DE), which Squeak knows nothing about. macOS is better in this regard. :-) Biggest mess is on Linux/X11. For key-down/up events, the Linux VM delivers actual character codes instead of scan codes, which makes a basic mapping to physical keys almost impossible. See EventSensor class >> #virtualKeysOnX11. We MUST fix that! Please. Somebody. Can I haz scan codes? ^__^ *** *** The good news: KeyboardEvent >> #key (and UserInputEvent >> #modifiers) now gives you cross-platform stable information about physical keys to be used in keyboard handlers. Yes, for both key-stroke and key-down/up events. Or at least, that is the plan. That's why it would be great if you could help testing! :-) Why key-stroke events too? Aren't they for typing text only? 1. Almost all keyboard shortcuts in current Squeak are based on key-stroke events. 2. Using the #keyCharacter is tricky because SHIFT changes lower-case to upper-case, which makes "anEvent shiftPressed" hard to understand. 3. CTRL combinations might not do the expected thing. How would you handle CTRL+C? The #keyCharacter could arrive as $c or Character enter. See the preference "Map non-printable characters to printable characters. Now, #key will always answer $C in such a case. Regardless of that preference. Can't we just use #keyCharacter in key-down/up events? No. Those are undefined. Never do that. key-down/up events carry virtual-key codes in their #keyValue. We might want to change #keyCharacter to answer "nil" for those events. *** Q: What is a "physical key" or "physical modifier"? A: The label that can be presented to the user so that he or she feels at home when using Squeak. Thus, looks platform-specific. Q: What is a "virtual key" or "virtual modifier"? A: The information to be processed in your application's key handlers. Thus, looks platform-independent. If you have still no clue how to talk to keyboard events, please read the commentary in KeyboardEvent >> #checkCommandKey. *** Happy testing! :-) And thank you all in advance! Best, Marcel P.S.: You might want to disable the preference "synthesize mouse-wheel events from keyboard-events" to get CTRL+ArrowUp and CTRL+ArrowDown ;-) -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 57922 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: image.png Type: image/png Size: 62612 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: virtual-keys.13.cs Type: application/octet-stream Size: 43949 bytes Desc: not available URL: From commits at source.squeak.org Wed Apr 28 13:41:47 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 28 Apr 2021 13:41:47 0000 Subject: [squeak-dev] The Inbox: Tests-jar.454.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-jar.454.mcz ==================== Summary ==================== Name: Tests-jar.454 Author: jar Time: 28 April 2021, 3:41:45.571949 pm UUID: 63612592-7650-d04d-868a-b0a216708d6b Ancestors: Tests-nice.453 Fix: simpleOuterTest fails to detect an incorrect #outer behavior After resuming to #outer the execution has to continue right after the ex outer handler block; presently the test only checks whether the execution resumes inside the block but fails to check where it goes next. I proposed a change in #handleSignal that passed the current test but would lead to an incorrect #outer semantics :| The fix I'm proposing would reveal my error. See the counterexample here: http://forum.world.st/The-Inbox-Kernel-nice-1391-mcz-tp5129040p5129084.html Simple do-it example demonstrating the issue: resumedCorrectly := false. [ [ Warning signal ] on: Warning do: [ :ex | ex outer ]. resumedCorrectly := true. "after ex outer continue here" ] on: Warning do: [ :ex | ex resume ]. resumedCorrectly =============== Diff against Tests-nice.453 =============== Item was changed: ----- Method: ExceptionTester>>simpleOuterTest (in category 'signaledException tests') ----- simpleOuterTest "uses #resume" [[self doSomething. MyTestNotification signal. "self doSomethingElse" self doSomethingExceptional] on: MyTestNotification + do: [:ex | ex outer]. self doSomethingElse] - do: [:ex | ex outer. self doSomethingElse]] on: MyTestNotification do: [:ex | self doYetAnotherThing. ex resume]! From m at jaromir.net Wed Apr 28 13:48:22 2021 From: m at jaromir.net (Jaromir Matas) Date: Wed, 28 Apr 2021 08:48:22 -0500 (CDT) Subject: [squeak-dev] The Inbox: Kernel-nice.1391.mcz In-Reply-To: <1619292720661-0.post@n4.nabble.com> References: <1619292720661-0.post@n4.nabble.com> Message-ID: <1619617702062-0.post@n4.nabble.com> Hi All, Jaromir Matas wrote > I'd like to suggest the following change to really make handling `return` > the same whether it's called explicitly or not: The last line should send > `return: val` to exception instead of self - the `exception return` calls > `handlerContext return` and at the moment it's true the `self` is the > handlerContext. But in theory someone can e.g. change `return` definition > and then the two returns won't be the same... Plus I think this is more > consistent and readable. Thanks, > > handleSignal: exception > "Sent to handler (on:do:) contexts only. If my exception class (first > arg) > handles exception > and the handler is active then execute my handle block (second arg), > otherwise forward > this message to the next handler context. If none left, execute > exception's defaultAction > (see nil>>handleSignal:)." > > | val | > (self willHandleSignal: exception) ifFalse: > [self deactivateHandler. > ^self nextHandlerContext handleSignal: exception]. > > exception privHandlerContext: self contextTag. > self deactivateHandler. "disable self while executing handle block" > val := self fireHandlerActionWith: exception. > + exception return: val "return as default action if not otherwise > directed > in handle block" > - self return: val "return from self if not otherwise directed in handle > block" Please disregard the above proposal - it leads to an incorrect #outer behavior. Unfortunately it passes all the tests which shouldn't happen and I sent a fix to the Inbox to update the outer test: http://forum.world.st/The-Inbox-Tests-jar-454-mcz-td5129221.html best, ----- ^[^ Jaromir -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From commits at source.squeak.org Wed Apr 28 16:12:10 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 28 Apr 2021 16:12:10 0000 Subject: [squeak-dev] The Trunk: Tests-nice.458.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.458.mcz ==================== Summary ==================== Name: Tests-nice.458 Author: nice Time: 28 April 2021, 6:11:51.033213 pm UUID: 13fec56a-805e-754e-bd02-8cbaa015e102 Ancestors: Tests-jr.457 Document the fact that becomeForward: does NOT forward identityHash of receiver anymore (since Collections-eem.885 April 2020) See #elementsForwardIdentityTo: vs #elementsForwardIdentityAndHashTo: See also http://forum.world.st/How-to-become-immediate-objects-td5114931.html =============== Diff against Tests-jr.457 =============== Item was changed: ----- Method: BecomeTest>>testBecomeForward (in category 'tests') ----- testBecomeForward "Test the forward become." | a b c d | a := 'ab' copy. b := 'cd' copy. + c := Array with: a. - c := a. d := b. a becomeForward: b. self assert: a = 'cd'; assert: b = 'cd'; + assert: a == b; + assert: c first == b; + assert: d == b. - assert: c = 'cd'; - assert: d = 'cd'. - ! Item was added: + ----- Method: BecomeTest>>testBecomeForwardCopyIdentityHash (in category 'tests') ----- + testBecomeForwardCopyIdentityHash + "Check that + 1. the argument to becomeForward: is modified to have the receiver's identity hash. + 2. the receiver's identity hash is unchanged." + + | a b ha | + + a := 'ab' copy. + b := 'cd' copy. + ha := a identityHash. + + a becomeForward: b copyHash: true. + + self + assert: a identityHash = ha; + assert: b identityHash = ha. + + ! Item was changed: ----- Method: BecomeTest>>testBecomeForwardDontCopyIdentityHash (in category 'tests') ----- testBecomeForwardDontCopyIdentityHash "Check that 1. the argument to becomeForward: is NOT modified to have the receiver's identity hash. + 2. the receiver's identity hash is changed." - 2. the receiver's identity hash is unchanged." | a b hb | a := 'ab' copy. b := 'cd' copy. hb := b identityHash. a becomeForward: b copyHash: false. self assert: a identityHash = hb; assert: b identityHash = hb. ! Item was changed: ----- Method: BecomeTest>>testBecomeForwardIdentityHash (in category 'tests') ----- testBecomeForwardIdentityHash + "Document that the receiver hash is changed, but the argument hash is unchanged. + (a becomeForward: b) has thus same effect as (a becomeForward: b copyHash: false)" - "Check that - 1. the argument to becomeForward: is modified to have the receiver's identity hash. - 2. the receiver's identity hash is unchanged." + | a b hb | - | a b ha | a := 'ab' copy. b := 'cd' copy. + hb := b identityHash. - ha := a identityHash. a becomeForward: b. self + assert: a identityHash = hb; + assert: b identityHash = hb. - assert: a identityHash = ha; - assert: b identityHash = ha. ! From jakres+squeak at gmail.com Wed Apr 28 17:35:19 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Wed, 28 Apr 2021 19:35:19 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: Hi Nicolas, Sorry, tests are still failing. Please install the Git Browser/Squot, then you will have a TestCaseSuppressingProgressDisplayTraitTest in your image. With ToolBuilder-Kernel-nice.144 and Kernel-nice.1394, it contains two failing tests. Those tests assert that the progress suppressing does not affect test results. But the supposedly-passing or -failing tests currently signal errors. Those errors are still the MNU asNumber as in my previous message, so the handlers are still not on the stack as the progress implementation expects it. You can also directly run the underlying tests with: (TestCaseSuppressingProgressDisplayTraitTestSubject selector: #testThatPasses) debug. (TestCaseSuppressingProgressDisplayTraitTestSubject selector: #testThatFails) debug. For practical purposes, I can see that my Squot tests do display some progress (below the TestRunner's progress bar) even though that should have been suppressed. Kind regards, Jakob Am Di., 27. Apr. 2021 um 13:57 Uhr schrieb Nicolas Cellier : > > Hi Jakob, > So far, you're my greatest brainstorming provider! > See my next solution in ToolBuilder-Kernel-nice.144. > > I don't feel like I can omit the comments, which is a smell. > But that's the price for maintaining backward compatibility with > contradictory rules/features. > > > Le lun. 26 avr. 2021 à 23:29, Nicolas Cellier > a écrit : > > > > Le lun. 26 avr. 2021 à 23:17, Nicolas Cellier > > a écrit : > > > > > > Ah yes, tight coupling is not ideal... > > > It's pretty long to debug. > > > I see a (ProgressNotification signal: '' extra: (oldLabel := > > > newLabel)) sent from inner do:displayProgress: > > > (do:displayProgress:every:) > > > This is indeed caught by outer displaySequentialProgress: which > > > interprets the messageText '' asNumber and fails... > > > > > > It appears like the enclosing on: ProgressInitiationException do: ... > > > sendNotificationsTo: ... is catching both initiations instead of only > > > the first one... > > > This is because the resumeEvaluating: rearmed the handler before > > > evaluating the block. > > > It does so while unwinding the ensure: [self reactivateHandler] in > > > handleSignal:... > > > > > > So, in normal case, the 2nd ProgressInitiationException is not caught... > > > It thus performs its default action, which is opening the progress > > > bar, and catching ProgressNotification to feed the progress bar... > > > In normal case, this is this second (on: ProgressNotification do:) > > > which is on top of stack of handlers... > > > > > > Somehow, my proposed solution is equivalent to evaluating this in > > > older image, which equally fails... > > > > > > ['Foobar' displaySequentialProgress: > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > displayingProgress: [:each | 'item ', each]]] > > > on: ProgressInitiationException do: > > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > > :max :val | "nothing"]]] > > > > > > If I change implementation with ugly: > > > > > > sendNotificationsTo: aNewBlock > > > self resumeEvaluating: > > > [self privHandlerContext deactivateHandler. > > > [workBlock value: [ :barVal | > > > aNewBlock value: minVal value: maxVal value: barVal]] > > > ensure: [self privHandlerContext reactivateHandler]] > > > > > > then this snippet pass... > > > > > > > sent too soon, sorry... > > The snippet you gave pass with horrific hack proposed above. > > > > But if we deactivateHandler inside sendNotificationsTo:, then we're > > not able to rearm anymore: > > > > on: ProgressInitiationException do: > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > :max :val | "nothing"]]] > > > > will now fail to properly rearm... Horrible. > > > > sendNotificationsTo: is really tightly coupled to the fact that inner > > handlers remain active... > > > > > > > > Le lun. 26 avr. 2021 à 21:44, Jakob Reschke a écrit : > > > > > > > > Hi Nicolas, > > > > > > > > Unfortunately, there are yet other things not working now: > > > > > > > > ['Foobar' displaySequentialProgress: > > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > > displayingProgress: [:each | 'item ', each]]] > > > > on: ProgressInitiationException do: > > > > [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] > > > > > > > > will end with a MNU because the handler in displaySequentialProgress: > > > > does not support the ProgressNotification signalled from the loop. > > > > I did not debug it until the end, but I guess the implicit handler in > > > > MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the > > > > loop) previously got the notification, but is now terminated away (by > > > > Context>>resumeEvaluating: in sendNotificationsTo:) before the > > > > workBlock is evaluated. So the loop progress notifications do not get > > > > there anymore, but to the handler in displaySequentialProgress:. If it > > > > is not terminated away, then I suppose the order of those two handlers > > > > on the stack is now swapped... > > > > > > > > Something like the above I use to test the progress suppressing during > > > > test cases, which was previously broken, but now works. Glad that I > > > > wrote these tests for the testing facility itself... > > > > > > > > It is quite messy how the progress stuff is coupled to the > > > > implementation details of exception handling. > > > > > > > > Kind regards, > > > > Jakob > > > > > > > > Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > > > > > > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > > > > > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > > > > > > > > > ==================== Summary ==================== > > > > > > > > > > Name: ToolBuilder-Kernel-nice.143 > > > > > Author: nice > > > > > Time: 26 April 2021, 2:20:20.490026 am > > > > > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > > > > > Ancestors: ToolBuilder-Kernel-nice.141 > > > > > > > > > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > > > > > > > > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > > > > > > > > > Item was changed: > > > > > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > > > > > sendNotificationsTo: aNewBlock > > > > > + self resumeEvaluating: [workBlock value: [ :barVal | > > > > > - > > > > > - self reactivateHandlers; resumeUnchecked: ( > > > > > - workBlock value: [ :barVal | > > > > > aNewBlock value: minVal value: maxVal value: barVal > > > > > + ]] > > > > > - ] > > > > > - ) > > > > > ! > > > > > > > > > > > > > > > From asqueaker at gmail.com Wed Apr 28 19:03:34 2021 From: asqueaker at gmail.com (Chris Muller) Date: Wed, 28 Apr 2021 14:03:34 -0500 Subject: [squeak-dev] The Trunk: Tools-mt.1029.mcz In-Reply-To: References: Message-ID: If I understand this correctly, it'll probably conflict with Maui's equivalent gesture, and only for the equivalent of dragging a splitter bar all the way up to the top..? (really, is it just substituting that one DnD operation for another?) Except it opens a new window, too (which I'll have to later close?). Maybe I'm missing something, but it seems heavy and laborious for only what it does. Hopefully the hook can be customized.. On Thu, Mar 4, 2021 at 8:47 AM Marcel Taeumel wrote: > > Here is an example: > > > Am 04.03.2021 15:38:47 schrieb commits at source.squeak.org : > > Marcel Taeumel uploaded a new version of Tools to project The Trunk: > http://source.squeak.org/trunk/Tools-mt.1029.mcz > > ==================== Summary ==================== > > Name: Tools-mt.1029 > Author: mt > Time: 4 March 2021, 3:38:36.350661 pm > UUID: bef0c471-6ff1-774d-860e-8958e1aa508b > Ancestors: Tools-mt.1028 > > Enable source-code dragging through a browser's message list to be dropped into the world to open a compact code editor. > > Complements Tools-mt.1028, ToolBuilder-Kernel-mt.139, ToolBuilder-Morphic-mt.274, and Morphic-mt.1733. > > =============== Diff against Tools-mt.1028 =============== > > Item was changed: > ----- Method: Browser>>buildMessageListWith: (in category 'toolbuilder') ----- > buildMessageListWith: builder > | listSpec | > listSpec := builder pluggableListSpec new. > listSpec > model: self; > list: #messageList; > getIndex: #messageListIndex; > setIndex: #messageListIndex:; > icon: #messageIconAt:; > helpItem: #messageHelpAt:; > menu: #messageListMenu:shifted:; > keyPress: #messageListKey:from:. > + SystemBrowser browseWithDragNDrop ifTrue: [ > + listSpec > + dragItem: #dragFromMessageList:; > + dragType: #dragTypeForMessageListAt:]. > - SystemBrowser browseWithDragNDrop > - ifTrue:[listSpec dragItem: #dragFromMessageList:]. > ^listSpec > ! > > Item was added: > + ----- Method: Browser>>dragTypeForMessageListAt: (in category 'drag and drop') ----- > + dragTypeForMessageListAt: index > + > + ^ #sourceCode! > > > From asqueaker at gmail.com Wed Apr 28 19:18:50 2021 From: asqueaker at gmail.com (Chris Muller) Date: Wed, 28 Apr 2021 14:18:50 -0500 Subject: [squeak-dev] Browser flash (was Re: The Trunk: Tools-mt.1029.mcz) In-Reply-To: <12B8A259-39EC-453F-9CA2-D0F1E1BEB990@rowledge.org> References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> <12B8A259-39EC-453F-9CA2-D0F1E1BEB990@rowledge.org> Message-ID: Hi Tim, > - all the other browsers ought to support the drag stuff too. I see some do, but the messagetrace doesn't appear to. "The drag stuff" tells me you don't have a firm grip on the purpose and scope of the use-cases. MessageTrace uses swipe to select multiple methods. It's rightly confined to what you trace, DnD outside its browser doesn't make sense for tracing. > - drag a method into a MessageTrace browser and thus add implementors of that message to the stack. That would result in multiple, unrelated Trace's all in the one window. I don't understand why you'd want to do that. > - Nothing to do with d&d, but how about a very simple way to add notes to methods in a browser? I'm thinking here of using a messagetrace browser and wanting to add little (pop-up?) notes to remind me of any points I notice as I follow the messages up and down. Why was I looking at this? What is it related to? All that stuff it is so easy to forget a week later when you start climbing back up the rabbit hole you fell into. Why not simply send Object>>#todo, and include a comment next to it? No little pop-ups please! From commits at source.squeak.org Wed Apr 28 19:24:06 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 28 Apr 2021 19:24:06 0000 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.145.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.145.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-nice.145 Author: nice Time: 28 April 2021, 9:23:48.35444 pm UUID: f27e3b02-2905-d94b-97f3-93e95bd58880 Ancestors: ToolBuilder-Kernel-nice.141 Fix ProgressInitiationException>>sendNotificationsTo: so that: - the ProgressInitiationException remains inactive during workBlock evaluation - unless explicitely rearmed - active inner handlers remain active during workBlock evaluation For the last goal, it is necessary to first resume, then evaluate the workBlock, hence usage of #resumeEvaluating: This goes with Kernel-nice.1394 which implements this method as well as upgraded signal handling. But if we resume, then we also unwind the stack and evaluate all the ensure: blocks... This will reactivate current handler, and desarm it if we rearmed, in other words, the exact contrary of what was requested! Hence the intricated activate/deactivate dance. If the purpose is to completely suppress Progress bars and progress notifications, then provide an appropriate handling action that will do so: #resumeSuppressingProgress =============== Diff against ToolBuilder-Kernel-nice.141 =============== Item was added: + ----- Method: ProgressInitiationException>>resumeSuppressingProgress (in category 'handling') ----- + resumeSuppressingProgress + "Catch and suppress every ProgressInitiationException and ProgressNotification + during the evaluation of workBlock" + + ^self resumeEvaluating: + [self rearmHandlerDuring: + [[workBlock value: [ :barVal | "do nothing"]] + on: ProgressNotification do: [:e | e resume]]]! Item was changed: + ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'handling') ----- - ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- sendNotificationsTo: aNewBlock + "Resume execution using aNewBlock as workBlock value. + Note that the execution is resumed in signalContext (or outerContext). + This is done so that inner exception handlers be active during workBlock execution. + However, our own handlerContext should be deactivated, unless explicitely rearmed." + | mustDeactivateHandler | + mustDeactivateHandler := handlerContext notNil and: [handlerContext isHandlerActive not]. + mustDeactivateHandler + ifTrue: + ["The handlerContext is de-activated during handleSignal: + But it will be reactivated during unwinding when we will resumeEvaluating: + That's unwanted, we don't generally want to rearm the handler during workBlock evaluation. + Hence we have to deactivate it again inside the deferred block." + self resumeEvaluating: + [handlerContext deactivateHandler. + [workBlock value: [ :barVal | + aNewBlock value: minVal value: maxVal value: barVal]] + ensure: [handlerContext reactivateHandler]]] + ifFalse: + ["If the handler is active at this step, then it must have been rearmed + with a #rearmHandlerDuring: + It's thus intentional to keep the handler active during workBlock evaluation + But the ensure: [self desarmHandler] will be evaluated during unwinding when we will resumeEvaluating: + It is thus necessary to rearm again inside the evaluated block" + self resumeEvaluating: + [self rearmHandlerDuring: + [workBlock value: [ :barVal | + aNewBlock value: minVal value: maxVal value: barVal]]]]! - - self reactivateHandlers; resumeUnchecked: ( - workBlock value: [ :barVal | - aNewBlock value: minVal value: maxVal value: barVal - ] - ) - ! From nicolas.cellier.aka.nice at gmail.com Wed Apr 28 19:24:02 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed, 28 Apr 2021 21:24:02 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: Hi Jakob, yes, an even more brainstorming example... what happens is that this ProgressInitiationException handler action: e rearmHandlerDuring: [[e sendNotificationsTo: [:min :max :current | "silence"]] on: ProgressNotification do: [:notification | notification resume]] is unwound by the resumeEvaluating: inside sendNotificationsTo: thus, the ( on: ProgressNotification do: ) is no more on the stack, so no more active... The handler is not even rearmed because of the unwinding, but it is still active. I suggest that we simply equip the ProgressInitiationException with appropriate protocol, like: resumeSuppressingProgress "Catch and suppress every ProgressInitiationException and ProgressNotification during the evaluation of workBlock" ^self resumeEvaluating: [self rearmHandlerDuring: [[workBlock value: [ :barVal | "do nothing"]] on: ProgressNotification do: [:e | e resume]]] If I use this resumeSuppressingProgress in the tests, they pass. It's unfortunate that you would have to change the client code, as it will complicate the configuration for ensuring compatibility with various versions of Squeak, but I think that it's the most reasonable solution. Beside, the new message is clearly expressing the intention... See ToolBuilder-Kernel-nice.145 Le mer. 28 avr. 2021 à 19:35, Jakob Reschke a écrit : > > Hi Nicolas, > > Sorry, tests are still failing. > > Please install the Git Browser/Squot, then you will have a > TestCaseSuppressingProgressDisplayTraitTest in your image. With > ToolBuilder-Kernel-nice.144 and Kernel-nice.1394, it contains two > failing tests. Those tests assert that the progress suppressing does > not affect test results. But the supposedly-passing or -failing tests > currently signal errors. Those errors are still the MNU asNumber as in > my previous message, so the handlers are still not on the stack as the > progress implementation expects it. > > You can also directly run the underlying tests with: > (TestCaseSuppressingProgressDisplayTraitTestSubject selector: > #testThatPasses) debug. > (TestCaseSuppressingProgressDisplayTraitTestSubject selector: > #testThatFails) debug. > > For practical purposes, I can see that my Squot tests do display some > progress (below the TestRunner's progress bar) even though that should > have been suppressed. > > Kind regards, > Jakob > > Am Di., 27. Apr. 2021 um 13:57 Uhr schrieb Nicolas Cellier > : > > > > Hi Jakob, > > So far, you're my greatest brainstorming provider! > > See my next solution in ToolBuilder-Kernel-nice.144. > > > > I don't feel like I can omit the comments, which is a smell. > > But that's the price for maintaining backward compatibility with > > contradictory rules/features. > > > > > > Le lun. 26 avr. 2021 à 23:29, Nicolas Cellier > > a écrit : > > > > > > Le lun. 26 avr. 2021 à 23:17, Nicolas Cellier > > > a écrit : > > > > > > > > Ah yes, tight coupling is not ideal... > > > > It's pretty long to debug. > > > > I see a (ProgressNotification signal: '' extra: (oldLabel := > > > > newLabel)) sent from inner do:displayProgress: > > > > (do:displayProgress:every:) > > > > This is indeed caught by outer displaySequentialProgress: which > > > > interprets the messageText '' asNumber and fails... > > > > > > > > It appears like the enclosing on: ProgressInitiationException do: ... > > > > sendNotificationsTo: ... is catching both initiations instead of only > > > > the first one... > > > > This is because the resumeEvaluating: rearmed the handler before > > > > evaluating the block. > > > > It does so while unwinding the ensure: [self reactivateHandler] in > > > > handleSignal:... > > > > > > > > So, in normal case, the 2nd ProgressInitiationException is not caught... > > > > It thus performs its default action, which is opening the progress > > > > bar, and catching ProgressNotification to feed the progress bar... > > > > In normal case, this is this second (on: ProgressNotification do:) > > > > which is on top of stack of handlers... > > > > > > > > Somehow, my proposed solution is equivalent to evaluating this in > > > > older image, which equally fails... > > > > > > > > ['Foobar' displaySequentialProgress: > > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > > displayingProgress: [:each | 'item ', each]]] > > > > on: ProgressInitiationException do: > > > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > > > :max :val | "nothing"]]] > > > > > > > > If I change implementation with ugly: > > > > > > > > sendNotificationsTo: aNewBlock > > > > self resumeEvaluating: > > > > [self privHandlerContext deactivateHandler. > > > > [workBlock value: [ :barVal | > > > > aNewBlock value: minVal value: maxVal value: barVal]] > > > > ensure: [self privHandlerContext reactivateHandler]] > > > > > > > > then this snippet pass... > > > > > > > > > > sent too soon, sorry... > > > The snippet you gave pass with horrific hack proposed above. > > > > > > But if we deactivateHandler inside sendNotificationsTo:, then we're > > > not able to rearm anymore: > > > > > > on: ProgressInitiationException do: > > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > > :max :val | "nothing"]]] > > > > > > will now fail to properly rearm... Horrible. > > > > > > sendNotificationsTo: is really tightly coupled to the fact that inner > > > handlers remain active... > > > > > > > > > > > Le lun. 26 avr. 2021 à 21:44, Jakob Reschke a écrit : > > > > > > > > > > Hi Nicolas, > > > > > > > > > > Unfortunately, there are yet other things not working now: > > > > > > > > > > ['Foobar' displaySequentialProgress: > > > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > > > displayingProgress: [:each | 'item ', each]]] > > > > > on: ProgressInitiationException do: > > > > > [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] > > > > > > > > > > will end with a MNU because the handler in displaySequentialProgress: > > > > > does not support the ProgressNotification signalled from the loop. > > > > > I did not debug it until the end, but I guess the implicit handler in > > > > > MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the > > > > > loop) previously got the notification, but is now terminated away (by > > > > > Context>>resumeEvaluating: in sendNotificationsTo:) before the > > > > > workBlock is evaluated. So the loop progress notifications do not get > > > > > there anymore, but to the handler in displaySequentialProgress:. If it > > > > > is not terminated away, then I suppose the order of those two handlers > > > > > on the stack is now swapped... > > > > > > > > > > Something like the above I use to test the progress suppressing during > > > > > test cases, which was previously broken, but now works. Glad that I > > > > > wrote these tests for the testing facility itself... > > > > > > > > > > It is quite messy how the progress stuff is coupled to the > > > > > implementation details of exception handling. > > > > > > > > > > Kind regards, > > > > > Jakob > > > > > > > > > > Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > > > > > > > > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > > > > > > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > > > > > > > > > > > ==================== Summary ==================== > > > > > > > > > > > > Name: ToolBuilder-Kernel-nice.143 > > > > > > Author: nice > > > > > > Time: 26 April 2021, 2:20:20.490026 am > > > > > > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > > > > > > Ancestors: ToolBuilder-Kernel-nice.141 > > > > > > > > > > > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > > > > > > > > > > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > > > > > > > > > > > Item was changed: > > > > > > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > > > > > > sendNotificationsTo: aNewBlock > > > > > > + self resumeEvaluating: [workBlock value: [ :barVal | > > > > > > - > > > > > > - self reactivateHandlers; resumeUnchecked: ( > > > > > > - workBlock value: [ :barVal | > > > > > > aNewBlock value: minVal value: maxVal value: barVal > > > > > > + ]] > > > > > > - ] > > > > > > - ) > > > > > > ! > > > > > > > > > > > > > > > > > > > > From nicolas.cellier.aka.nice at gmail.com Wed Apr 28 19:42:58 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed, 28 Apr 2021 21:42:58 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: For compatibility, you can implement this: resumeEvaluating: aBlock (self class superclass canUnderstand: #resumeEvaluating:) ifTrue: [^super resumeEvaluating: aBlock]. "compatibility with squeak < 6.0" ^self resume: aBlock value Le mer. 28 avr. 2021 à 21:24, Nicolas Cellier a écrit : > > Hi Jakob, > yes, an even more brainstorming example... > what happens is that this ProgressInitiationException handler action: > > e rearmHandlerDuring: > [[e sendNotificationsTo: [:min :max :current | > "silence"]] > on: ProgressNotification do: > [:notification | notification resume]] > > is unwound by the resumeEvaluating: inside sendNotificationsTo: > thus, the ( on: ProgressNotification do: ) is no more on the stack, so > no more active... > The handler is not even rearmed because of the unwinding, but it is > still active. > > I suggest that we simply equip the ProgressInitiationException with > appropriate protocol, like: > > resumeSuppressingProgress > "Catch and suppress every ProgressInitiationException and > ProgressNotification > during the evaluation of workBlock" > > ^self resumeEvaluating: > [self rearmHandlerDuring: > [[workBlock value: [ :barVal | "do nothing"]] > on: ProgressNotification do: [:e | e resume]]] > > If I use this resumeSuppressingProgress in the tests, they pass. > It's unfortunate that you would have to change the client code, as it > will complicate the configuration for ensuring compatibility with > various versions of Squeak, but I think that it's the most reasonable > solution. Beside, the new message is clearly expressing the > intention... > > See ToolBuilder-Kernel-nice.145 > > Le mer. 28 avr. 2021 à 19:35, Jakob Reschke a écrit : > > > > Hi Nicolas, > > > > Sorry, tests are still failing. > > > > Please install the Git Browser/Squot, then you will have a > > TestCaseSuppressingProgressDisplayTraitTest in your image. With > > ToolBuilder-Kernel-nice.144 and Kernel-nice.1394, it contains two > > failing tests. Those tests assert that the progress suppressing does > > not affect test results. But the supposedly-passing or -failing tests > > currently signal errors. Those errors are still the MNU asNumber as in > > my previous message, so the handlers are still not on the stack as the > > progress implementation expects it. > > > > You can also directly run the underlying tests with: > > (TestCaseSuppressingProgressDisplayTraitTestSubject selector: > > #testThatPasses) debug. > > (TestCaseSuppressingProgressDisplayTraitTestSubject selector: > > #testThatFails) debug. > > > > For practical purposes, I can see that my Squot tests do display some > > progress (below the TestRunner's progress bar) even though that should > > have been suppressed. > > > > Kind regards, > > Jakob > > > > Am Di., 27. Apr. 2021 um 13:57 Uhr schrieb Nicolas Cellier > > : > > > > > > Hi Jakob, > > > So far, you're my greatest brainstorming provider! > > > See my next solution in ToolBuilder-Kernel-nice.144. > > > > > > I don't feel like I can omit the comments, which is a smell. > > > But that's the price for maintaining backward compatibility with > > > contradictory rules/features. > > > > > > > > > Le lun. 26 avr. 2021 à 23:29, Nicolas Cellier > > > a écrit : > > > > > > > > Le lun. 26 avr. 2021 à 23:17, Nicolas Cellier > > > > a écrit : > > > > > > > > > > Ah yes, tight coupling is not ideal... > > > > > It's pretty long to debug. > > > > > I see a (ProgressNotification signal: '' extra: (oldLabel := > > > > > newLabel)) sent from inner do:displayProgress: > > > > > (do:displayProgress:every:) > > > > > This is indeed caught by outer displaySequentialProgress: which > > > > > interprets the messageText '' asNumber and fails... > > > > > > > > > > It appears like the enclosing on: ProgressInitiationException do: ... > > > > > sendNotificationsTo: ... is catching both initiations instead of only > > > > > the first one... > > > > > This is because the resumeEvaluating: rearmed the handler before > > > > > evaluating the block. > > > > > It does so while unwinding the ensure: [self reactivateHandler] in > > > > > handleSignal:... > > > > > > > > > > So, in normal case, the 2nd ProgressInitiationException is not caught... > > > > > It thus performs its default action, which is opening the progress > > > > > bar, and catching ProgressNotification to feed the progress bar... > > > > > In normal case, this is this second (on: ProgressNotification do:) > > > > > which is on top of stack of handlers... > > > > > > > > > > Somehow, my proposed solution is equivalent to evaluating this in > > > > > older image, which equally fails... > > > > > > > > > > ['Foobar' displaySequentialProgress: > > > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > > > displayingProgress: [:each | 'item ', each]]] > > > > > on: ProgressInitiationException do: > > > > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > > > > :max :val | "nothing"]]] > > > > > > > > > > If I change implementation with ugly: > > > > > > > > > > sendNotificationsTo: aNewBlock > > > > > self resumeEvaluating: > > > > > [self privHandlerContext deactivateHandler. > > > > > [workBlock value: [ :barVal | > > > > > aNewBlock value: minVal value: maxVal value: barVal]] > > > > > ensure: [self privHandlerContext reactivateHandler]] > > > > > > > > > > then this snippet pass... > > > > > > > > > > > > > sent too soon, sorry... > > > > The snippet you gave pass with horrific hack proposed above. > > > > > > > > But if we deactivateHandler inside sendNotificationsTo:, then we're > > > > not able to rearm anymore: > > > > > > > > on: ProgressInitiationException do: > > > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > > > :max :val | "nothing"]]] > > > > > > > > will now fail to properly rearm... Horrible. > > > > > > > > sendNotificationsTo: is really tightly coupled to the fact that inner > > > > handlers remain active... > > > > > > > > > > > > > > Le lun. 26 avr. 2021 à 21:44, Jakob Reschke a écrit : > > > > > > > > > > > > Hi Nicolas, > > > > > > > > > > > > Unfortunately, there are yet other things not working now: > > > > > > > > > > > > ['Foobar' displaySequentialProgress: > > > > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > > > > displayingProgress: [:each | 'item ', each]]] > > > > > > on: ProgressInitiationException do: > > > > > > [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] > > > > > > > > > > > > will end with a MNU because the handler in displaySequentialProgress: > > > > > > does not support the ProgressNotification signalled from the loop. > > > > > > I did not debug it until the end, but I guess the implicit handler in > > > > > > MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the > > > > > > loop) previously got the notification, but is now terminated away (by > > > > > > Context>>resumeEvaluating: in sendNotificationsTo:) before the > > > > > > workBlock is evaluated. So the loop progress notifications do not get > > > > > > there anymore, but to the handler in displaySequentialProgress:. If it > > > > > > is not terminated away, then I suppose the order of those two handlers > > > > > > on the stack is now swapped... > > > > > > > > > > > > Something like the above I use to test the progress suppressing during > > > > > > test cases, which was previously broken, but now works. Glad that I > > > > > > wrote these tests for the testing facility itself... > > > > > > > > > > > > It is quite messy how the progress stuff is coupled to the > > > > > > implementation details of exception handling. > > > > > > > > > > > > Kind regards, > > > > > > Jakob > > > > > > > > > > > > Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > > > > > > > > > > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > > > > > > > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > > > > > > > > > > > > > ==================== Summary ==================== > > > > > > > > > > > > > > Name: ToolBuilder-Kernel-nice.143 > > > > > > > Author: nice > > > > > > > Time: 26 April 2021, 2:20:20.490026 am > > > > > > > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > > > > > > > Ancestors: ToolBuilder-Kernel-nice.141 > > > > > > > > > > > > > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > > > > > > > > > > > > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > > > > > > > > > > > > > Item was changed: > > > > > > > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > > > > > > > sendNotificationsTo: aNewBlock > > > > > > > + self resumeEvaluating: [workBlock value: [ :barVal | > > > > > > > - > > > > > > > - self reactivateHandlers; resumeUnchecked: ( > > > > > > > - workBlock value: [ :barVal | > > > > > > > aNewBlock value: minVal value: maxVal value: barVal > > > > > > > + ]] > > > > > > > - ] > > > > > > > - ) > > > > > > > ! > > > > > > > > > > > > > > > > > > > > > > > > > From nicolas.cellier.aka.nice at gmail.com Wed Apr 28 20:02:38 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Wed, 28 Apr 2021 22:02:38 +0200 Subject: [squeak-dev] The Inbox: ToolBuilder-Kernel-nice.143.mcz In-Reply-To: References: Message-ID: Le mer. 28 avr. 2021 à 21:42, Nicolas Cellier a écrit : > > For compatibility, you can implement this: > > resumeEvaluating: aBlock > (self class superclass canUnderstand: #resumeEvaluating:) ifTrue: > [^super resumeEvaluating: aBlock]. > "compatibility with squeak < 6.0" > ^self resume: aBlock value > > Le mer. 28 avr. 2021 à 21:24, Nicolas Cellier > a écrit : > > > > Hi Jakob, > > yes, an even more brainstorming example... > > what happens is that this ProgressInitiationException handler action: > > > > e rearmHandlerDuring: > > [[e sendNotificationsTo: [:min :max :current | > > "silence"]] > > on: ProgressNotification do: > > [:notification | notification resume]] > > > > is unwound by the resumeEvaluating: inside sendNotificationsTo: > > thus, the ( on: ProgressNotification do: ) is no more on the stack, so > > no more active... > > The handler is not even rearmed because of the unwinding, but it is > > still active. > > > > I suggest that we simply equip the ProgressInitiationException with > > appropriate protocol, like: > > > > resumeSuppressingProgress > > "Catch and suppress every ProgressInitiationException and > > ProgressNotification > > during the evaluation of workBlock" > > > > ^self resumeEvaluating: > > [self rearmHandlerDuring: > > [[workBlock value: [ :barVal | "do nothing"]] > > on: ProgressNotification do: [:e | e resume]]] > > and note that rearmHandlerDuring: above is only necessary if we want to catch the ProgressInitiationException signalled by an outer handler action... It's not everyday/everyone use case... resuming will already make the handler reentrant, no need to rearm. I think that we shall better omit it here. > > If I use this resumeSuppressingProgress in the tests, they pass. > > It's unfortunate that you would have to change the client code, as it > > will complicate the configuration for ensuring compatibility with > > various versions of Squeak, but I think that it's the most reasonable > > solution. Beside, the new message is clearly expressing the > > intention... > > > > See ToolBuilder-Kernel-nice.145 > > > > Le mer. 28 avr. 2021 à 19:35, Jakob Reschke a écrit : > > > > > > Hi Nicolas, > > > > > > Sorry, tests are still failing. > > > > > > Please install the Git Browser/Squot, then you will have a > > > TestCaseSuppressingProgressDisplayTraitTest in your image. With > > > ToolBuilder-Kernel-nice.144 and Kernel-nice.1394, it contains two > > > failing tests. Those tests assert that the progress suppressing does > > > not affect test results. But the supposedly-passing or -failing tests > > > currently signal errors. Those errors are still the MNU asNumber as in > > > my previous message, so the handlers are still not on the stack as the > > > progress implementation expects it. > > > > > > You can also directly run the underlying tests with: > > > (TestCaseSuppressingProgressDisplayTraitTestSubject selector: > > > #testThatPasses) debug. > > > (TestCaseSuppressingProgressDisplayTraitTestSubject selector: > > > #testThatFails) debug. > > > > > > For practical purposes, I can see that my Squot tests do display some > > > progress (below the TestRunner's progress bar) even though that should > > > have been suppressed. > > > > > > Kind regards, > > > Jakob > > > > > > Am Di., 27. Apr. 2021 um 13:57 Uhr schrieb Nicolas Cellier > > > : > > > > > > > > Hi Jakob, > > > > So far, you're my greatest brainstorming provider! > > > > See my next solution in ToolBuilder-Kernel-nice.144. > > > > > > > > I don't feel like I can omit the comments, which is a smell. > > > > But that's the price for maintaining backward compatibility with > > > > contradictory rules/features. > > > > > > > > > > > > Le lun. 26 avr. 2021 à 23:29, Nicolas Cellier > > > > a écrit : > > > > > > > > > > Le lun. 26 avr. 2021 à 23:17, Nicolas Cellier > > > > > a écrit : > > > > > > > > > > > > Ah yes, tight coupling is not ideal... > > > > > > It's pretty long to debug. > > > > > > I see a (ProgressNotification signal: '' extra: (oldLabel := > > > > > > newLabel)) sent from inner do:displayProgress: > > > > > > (do:displayProgress:every:) > > > > > > This is indeed caught by outer displaySequentialProgress: which > > > > > > interprets the messageText '' asNumber and fails... > > > > > > > > > > > > It appears like the enclosing on: ProgressInitiationException do: ... > > > > > > sendNotificationsTo: ... is catching both initiations instead of only > > > > > > the first one... > > > > > > This is because the resumeEvaluating: rearmed the handler before > > > > > > evaluating the block. > > > > > > It does so while unwinding the ensure: [self reactivateHandler] in > > > > > > handleSignal:... > > > > > > > > > > > > So, in normal case, the 2nd ProgressInitiationException is not caught... > > > > > > It thus performs its default action, which is opening the progress > > > > > > bar, and catching ProgressNotification to feed the progress bar... > > > > > > In normal case, this is this second (on: ProgressNotification do:) > > > > > > which is on top of stack of handlers... > > > > > > > > > > > > Somehow, my proposed solution is equivalent to evaluating this in > > > > > > older image, which equally fails... > > > > > > > > > > > > ['Foobar' displaySequentialProgress: > > > > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > > > > displayingProgress: [:each | 'item ', each]]] > > > > > > on: ProgressInitiationException do: > > > > > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > > > > > :max :val | "nothing"]]] > > > > > > > > > > > > If I change implementation with ugly: > > > > > > > > > > > > sendNotificationsTo: aNewBlock > > > > > > self resumeEvaluating: > > > > > > [self privHandlerContext deactivateHandler. > > > > > > [workBlock value: [ :barVal | > > > > > > aNewBlock value: minVal value: maxVal value: barVal]] > > > > > > ensure: [self privHandlerContext reactivateHandler]] > > > > > > > > > > > > then this snippet pass... > > > > > > > > > > > > > > > > sent too soon, sorry... > > > > > The snippet you gave pass with horrific hack proposed above. > > > > > > > > > > But if we deactivateHandler inside sendNotificationsTo:, then we're > > > > > not able to rearm anymore: > > > > > > > > > > on: ProgressInitiationException do: > > > > > [:e | e rearmHandlerDuring: [ e sendNotificationsTo: [:min > > > > > :max :val | "nothing"]]] > > > > > > > > > > will now fail to properly rearm... Horrible. > > > > > > > > > > sendNotificationsTo: is really tightly coupled to the fact that inner > > > > > handlers remain active... > > > > > > > > > > > > > > > > > Le lun. 26 avr. 2021 à 21:44, Jakob Reschke a écrit : > > > > > > > > > > > > > > Hi Nicolas, > > > > > > > > > > > > > > Unfortunately, there are yet other things not working now: > > > > > > > > > > > > > > ['Foobar' displaySequentialProgress: > > > > > > > [#(a b c) do: [:each | (Delay forSeconds: 1) wait] > > > > > > > displayingProgress: [:each | 'item ', each]]] > > > > > > > on: ProgressInitiationException do: > > > > > > > [:e | e sendNotificationsTo: [:min :max :val | "nothing"]] > > > > > > > > > > > > > > will end with a MNU because the handler in displaySequentialProgress: > > > > > > > does not support the ProgressNotification signalled from the loop. > > > > > > > I did not debug it until the end, but I guess the implicit handler in > > > > > > > MorphicUIManager>>#displayProgress:at:from:to:during: (emplaced by the > > > > > > > loop) previously got the notification, but is now terminated away (by > > > > > > > Context>>resumeEvaluating: in sendNotificationsTo:) before the > > > > > > > workBlock is evaluated. So the loop progress notifications do not get > > > > > > > there anymore, but to the handler in displaySequentialProgress:. If it > > > > > > > is not terminated away, then I suppose the order of those two handlers > > > > > > > on the stack is now swapped... > > > > > > > > > > > > > > Something like the above I use to test the progress suppressing during > > > > > > > test cases, which was previously broken, but now works. Glad that I > > > > > > > wrote these tests for the testing facility itself... > > > > > > > > > > > > > > It is quite messy how the progress stuff is coupled to the > > > > > > > implementation details of exception handling. > > > > > > > > > > > > > > Kind regards, > > > > > > > Jakob > > > > > > > > > > > > > > Am Mo., 26. Apr. 2021 um 02:20 Uhr schrieb : > > > > > > > > > > > > > > > > Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Inbox: > > > > > > > > http://source.squeak.org/inbox/ToolBuilder-Kernel-nice.143.mcz > > > > > > > > > > > > > > > > ==================== Summary ==================== > > > > > > > > > > > > > > > > Name: ToolBuilder-Kernel-nice.143 > > > > > > > > Author: nice > > > > > > > > Time: 26 April 2021, 2:20:20.490026 am > > > > > > > > UUID: fc579454-b15f-4d7e-bd7b-adfc3a1ad863 > > > > > > > > Ancestors: ToolBuilder-Kernel-nice.141 > > > > > > > > > > > > > > > > Evaluate the new work block upon #sendNotificationsTo: in the context that sent the ProgressInitiationException signal > > > > > > > > > > > > > > > > =============== Diff against ToolBuilder-Kernel-nice.141 =============== > > > > > > > > > > > > > > > > Item was changed: > > > > > > > > ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- > > > > > > > > sendNotificationsTo: aNewBlock > > > > > > > > + self resumeEvaluating: [workBlock value: [ :barVal | > > > > > > > > - > > > > > > > > - self reactivateHandlers; resumeUnchecked: ( > > > > > > > > - workBlock value: [ :barVal | > > > > > > > > aNewBlock value: minVal value: maxVal value: barVal > > > > > > > > + ]] > > > > > > > > - ] > > > > > > > > - ) > > > > > > > > ! > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > From tim at rowledge.org Wed Apr 28 21:47:11 2021 From: tim at rowledge.org (tim Rowledge) Date: Wed, 28 Apr 2021 14:47:11 -0700 Subject: [squeak-dev] Browser flash (was Re: The Trunk: Tools-mt.1029.mcz) In-Reply-To: References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> <12B8A259-39EC-453F-9CA2-D0F1E1BEB990@rowledge.org> Message-ID: <814A4BBC-8CAF-45BC-80D9-A6B97C85A5D6@rowledge.org> > On 2021-04-28, at 12:18 PM, Chris Muller wrote: > > Hi Tim, > >> - all the other browsers ought to support the drag stuff too. I see some do, but the messagetrace doesn't appear to. > > "The drag stuff" tells me you don't have a firm grip on the purpose > and scope of the use-cases. MessageTrace uses swipe to select > multiple methods. It's rightly confined to what you trace, DnD > outside its browser doesn't make sense for tracing. I mildly disagree. Dragging *out* would make sense in various ways. To open another browser, for example. To drop into a text view (where I'd quite like to get the method's reference pasted, perhaps with shift held the method source. Right now we get a not very useful 'compiledMethodBunchOfDigits') or a FileBrowser. > >> - drag a method into a MessageTrace browser and thus add implementors of that message to the stack. > > That would result in multiple, unrelated Trace's all in the one > window. I don't understand why you'd want to do that. I can imagine having a use for a message trace open on several related methods that do not specifically tie together. Maybe #at: & #at:put: would be an example. This would be using a message tracer as a way of gathering methods together as part of thinking about refactorings or extensions. > >> - Nothing to do with d&d, but how about a very simple way to add notes to methods in a browser? I'm thinking here of using a messagetrace browser and wanting to add little (pop-up?) notes to remind me of any points I notice as I follow the messages up and down. Why was I looking at this? What is it related to? All that stuff it is so easy to forget a week later when you start climbing back up the rabbit hole you fell into. > > Why not simply send Object>>#todo, and include a comment next to it? > No little pop-ups please! I don't want to *edit* the code for this, I want to *annotate* it in the context of the tool I am using. One might make a plausible argument that this is not a message tracer anymore; whatever. I suggest that it would be a useful tool. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim "Bother" said Pooh, as he realised Piglet was undercooked. From Marcel.Taeumel at hpi.de Thu Apr 29 05:01:46 2021 From: Marcel.Taeumel at hpi.de (Taeumel, Marcel) Date: Thu, 29 Apr 2021 05:01:46 +0000 Subject: [squeak-dev] The Trunk: Tools-mt.1029.mcz In-Reply-To: References: , Message-ID: Hi Chris, for custom projects such as Maui, you should change the world's drop handler to fit your needs. It is very easy and avoids any conflict. Of course you can replicate some of the standard features if you want. For example, I did this for Vivide to open custom tools. See PasteUpMorph >> #transferMorphConverter: Just call it with a selector when Maui starts. Best, Marcel ________________________________ From: Squeak-dev on behalf of Chris Muller Sent: Wednesday, April 28, 2021 9:03:34 PM To: The general-purpose Squeak developers list Subject: Re: [squeak-dev] The Trunk: Tools-mt.1029.mcz If I understand this correctly, it'll probably conflict with Maui's equivalent gesture, and only for the equivalent of dragging a splitter bar all the way up to the top..? (really, is it just substituting that one DnD operation for another?) Except it opens a new window, too (which I'll have to later close?). Maybe I'm missing something, but it seems heavy and laborious for only what it does. Hopefully the hook can be customized.. On Thu, Mar 4, 2021 at 8:47 AM Marcel Taeumel wrote: > > Here is an example: > > > Am 04.03.2021 15:38:47 schrieb commits at source.squeak.org : > > Marcel Taeumel uploaded a new version of Tools to project The Trunk: > http://source.squeak.org/trunk/Tools-mt.1029.mcz > > ==================== Summary ==================== > > Name: Tools-mt.1029 > Author: mt > Time: 4 March 2021, 3:38:36.350661 pm > UUID: bef0c471-6ff1-774d-860e-8958e1aa508b > Ancestors: Tools-mt.1028 > > Enable source-code dragging through a browser's message list to be dropped into the world to open a compact code editor. > > Complements Tools-mt.1028, ToolBuilder-Kernel-mt.139, ToolBuilder-Morphic-mt.274, and Morphic-mt.1733. > > =============== Diff against Tools-mt.1028 =============== > > Item was changed: > ----- Method: Browser>>buildMessageListWith: (in category 'toolbuilder') ----- > buildMessageListWith: builder > | listSpec | > listSpec := builder pluggableListSpec new. > listSpec > model: self; > list: #messageList; > getIndex: #messageListIndex; > setIndex: #messageListIndex:; > icon: #messageIconAt:; > helpItem: #messageHelpAt:; > menu: #messageListMenu:shifted:; > keyPress: #messageListKey:from:. > + SystemBrowser browseWithDragNDrop ifTrue: [ > + listSpec > + dragItem: #dragFromMessageList:; > + dragType: #dragTypeForMessageListAt:]. > - SystemBrowser browseWithDragNDrop > - ifTrue:[listSpec dragItem: #dragFromMessageList:]. > ^listSpec > ! > > Item was added: > + ----- Method: Browser>>dragTypeForMessageListAt: (in category 'drag and drop') ----- > + dragTypeForMessageListAt: index > + > + ^ #sourceCode! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Thu Apr 29 07:35:05 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 29 Apr 2021 09:35:05 +0200 Subject: [squeak-dev] The Trunk: Tools-mt.1029.mcz In-Reply-To: References: <,CANzdToEv5PXU26vJDY3PgBa+cNuSLsMMsW7AN4jQynpd2QffNA@mail.gmail.com> Message-ID: Hi Chris, I wanted to check Maui but its latest version does not load in Squeak Trunk because its installer scripts depend on some local magma-index SqueakSource server. More specifically, it wants to load "Compiler" from #local->'squeak', which ends up in Installer class >> #defaultLocalRepository, which answers just a local file-based repository on "mc/squeak" ... which does not exist ony my machine. :-) What is the expected setup here? Is there a fall-back? Why not just load the code from source.squeak.org/trunk? Best, Marcel Am 29.04.2021 07:01:47 schrieb Taeumel, Marcel : Hi Chris, for custom projects such as Maui, you should change the world's drop handler to fit your needs. It is very easy and avoids any conflict. Of course you can replicate some of the standard features if you want. For example, I did this for Vivide to open custom tools. See PasteUpMorph >> #transferMorphConverter: Just call it with a selector when Maui starts. Best, Marcel From: Squeak-dev on behalf of Chris Muller Sent: Wednesday, April 28, 2021 9:03:34 PM To: The general-purpose Squeak developers list Subject: Re: [squeak-dev] The Trunk: Tools-mt.1029.mcz   If I understand this correctly, it'll probably conflict with Maui's equivalent gesture, and only for the equivalent of dragging a splitter bar all the way up to the top..?  (really, is it just substituting that one DnD operation for another?)  Except it opens a new window, too (which I'll have to later close?).  Maybe I'm missing something, but it seems heavy and laborious for only what it does.  Hopefully the hook can be customized.. On Thu, Mar 4, 2021 at 8:47 AM Marcel Taeumel wrote: > > Here is an example: > > > Am 04.03.2021 15:38:47 schrieb commits at source.squeak.org : > > Marcel Taeumel uploaded a new version of Tools to project The Trunk: > http://source.squeak.org/trunk/Tools-mt.1029.mcz [http://source.squeak.org/trunk/Tools-mt.1029.mcz] > > ==================== Summary ==================== > > Name: Tools-mt.1029 > Author: mt > Time: 4 March 2021, 3:38:36.350661 pm > UUID: bef0c471-6ff1-774d-860e-8958e1aa508b > Ancestors: Tools-mt.1028 > > Enable source-code dragging through a browser's message list to be dropped into the world to open a compact code editor. > > Complements Tools-mt.1028, ToolBuilder-Kernel-mt.139, ToolBuilder-Morphic-mt.274, and Morphic-mt.1733. > > =============== Diff against Tools-mt.1028 =============== > > Item was changed: > ----- Method: Browser>>buildMessageListWith: (in category 'toolbuilder') ----- > buildMessageListWith: builder > | listSpec | > listSpec := builder pluggableListSpec new. > listSpec > model: self; > list: #messageList; > getIndex: #messageListIndex; > setIndex: #messageListIndex:; > icon: #messageIconAt:; > helpItem: #messageHelpAt:; > menu: #messageListMenu:shifted:; > keyPress: #messageListKey:from:. > + SystemBrowser browseWithDragNDrop ifTrue: [ > + listSpec > + dragItem: #dragFromMessageList:; > + dragType: #dragTypeForMessageListAt:]. > - SystemBrowser browseWithDragNDrop > - ifTrue:[listSpec dragItem: #dragFromMessageList:]. > ^listSpec > ! > > Item was added: > + ----- Method: Browser>>dragTypeForMessageListAt: (in category 'drag and drop') ----- > + dragTypeForMessageListAt: index > + > + ^ #sourceCode! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Apr 29 08:25:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 08:25:12 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1764.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1764.mcz ==================== Summary ==================== Name: Morphic-mt.1764 Author: mt Time: 29 April 2021, 10:25:06.452338 am UUID: 0d4946b3-9ccb-1740-a7b1-e7baf16e42bf Ancestors: Morphic-mt.1763 For better compatibility between the projects "Connectors" and "Etoys", extract the #isButton classification. See comment in Morph >> #isButton. =============== Diff against Morphic-mt.1763 =============== Item was added: + ----- Method: Morph>>isButton (in category 'classification') ----- + isButton + "Answers whether this morph acts like a button, which usually entails a mouse-click handler. Originally used in the projects 'Connectors' and 'Etoys', receivers that claim to be a button need to answer to #actionSelector as well." + + ^ false! Item was added: + ----- Method: PluggableButtonMorph>>isButton (in category 'classification') ----- + isButton + + ^ true! Item was added: + ----- Method: SimpleButtonMorph>>isButton (in category 'classification') ----- + isButton + + ^ true! Item was added: + ----- Method: ThreePhaseButtonMorph>>isButton (in category 'classification') ----- + isButton + + ^ true + ! From commits at source.squeak.org Thu Apr 29 08:27:14 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 08:27:14 0000 Subject: [squeak-dev] The Trunk: ToolBuilder-Morphic-mt.275.mcz Message-ID: Marcel Taeumel uploaded a new version of ToolBuilder-Morphic to project The Trunk: http://source.squeak.org/trunk/ToolBuilder-Morphic-mt.275.mcz ==================== Summary ==================== Name: ToolBuilder-Morphic-mt.275 Author: mt Time: 29 April 2021, 10:27:13.467338 am UUID: 31457269-9d9d-8d45-a393-882acbe56fc4 Ancestors: ToolBuilder-Morphic-mt.274 Complements Morphic-mt.1764 =============== Diff against ToolBuilder-Morphic-mt.274 =============== Item was added: + ----- Method: PluggableCheckBoxMorph>>isButton (in category 'classification') ----- + isButton + + ^ true! From commits at source.squeak.org Thu Apr 29 08:28:01 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 08:28:01 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.296.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.296.mcz ==================== Summary ==================== Name: MorphicExtras-mt.296 Author: mt Time: 29 April 2021, 10:27:58.055338 am UUID: a00d87c2-20a9-6041-9829-8600de5c06a7 Ancestors: MorphicExtras-mt.295 Complements Morphic-mt.1764 =============== Diff against MorphicExtras-mt.295 =============== Item was added: + ----- Method: StringButtonMorph>>isButton (in category 'classification') ----- + isButton + + ^ true! From commits at source.squeak.org Thu Apr 29 08:33:58 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 08:33:58 0000 Subject: [squeak-dev] The Trunk: EToys-mt.443.mcz Message-ID: Marcel Taeumel uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-mt.443.mcz ==================== Summary ==================== Name: EToys-mt.443 Author: mt Time: 29 April 2021, 10:33:50.941891 am UUID: f09386ec-8bb6-4f4b-b3f7-72760b3f6e78 Ancestors: EToys-mt.442 Complements Morphic-mt.1764 =============== Diff against EToys-mt.442 =============== Item was removed: - ----- Method: Morph>>isButton (in category '*Etoys-Squeakland-testing') ----- - isButton - - ^ false! Item was removed: - ----- Method: SimpleButtonMorph>>isButton (in category '*Etoys-Squeakland-testing') ----- - isButton - - ^ true! Item was removed: - ----- Method: ThreePhaseButtonMorph>>isButton (in category '*Etoys-Squeakland-testing') ----- - isButton - - ^ true. - ! From commits at source.squeak.org Thu Apr 29 08:44:04 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 08:44:04 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1765.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1765.mcz ==================== Summary ==================== Name: Morphic-mt.1765 Author: mt Time: 29 April 2021, 10:43:58.612891 am UUID: 33804a11-9924-af48-a156-b2796a328878 Ancestors: Morphic-mt.1764 Extract #boundsSignatureHash to "Connectors" project. Etoys does not really need it. =============== Diff against Morphic-mt.1764 =============== Item was removed: - ----- Method: PolygonMorph>>boundsSignatureHash (in category 'attachments') ----- - boundsSignatureHash - ^(vertices - (self positionInWorld)) hash - ! From commits at source.squeak.org Thu Apr 29 08:46:18 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 08:46:18 0000 Subject: [squeak-dev] The Trunk: EToys-mt.444.mcz Message-ID: Marcel Taeumel uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-mt.444.mcz ==================== Summary ==================== Name: EToys-mt.444 Author: mt Time: 29 April 2021, 10:46:11.228891 am UUID: d8b044dd-8964-a049-996c-dd8018ecc043 Ancestors: EToys-mt.443 Moves some Connectors preferences and #boundsSignatureHash to "Connectors" project. Not needed in eToys. Complements Morphic-mt.1765 =============== Diff against EToys-mt.443 =============== Item was changed: ----- Method: HighlightMorph>>step (in category 'stepping') ----- step + (target isNil or: [lastHash = (lastHash := target boundsInWorld hash)]) - (target isNil or: [lastHash = (lastHash := target boundsSignatureHash)]) ifTrue: [self incrementStepTime] ifFalse: [stepTime := self minimumStepTime]. target notNil ifTrue: [ target isInWorld ifFalse: [^self delete]. self bounds: target bounds]! Item was removed: - ----- Method: Morph>>boundsSignatureHash (in category '*Etoys') ----- - boundsSignatureHash - "Answer a hash value that can be used to see if I've moved or been changed significantly" - ^self boundsInWorld hash - ! Item was removed: - ----- Method: Preferences class>>chooseConnectorsLabelFont (in category '*Etoys-Squeakland-fonts') ----- - chooseConnectorsLabelFont - "present a menu with the possible fonts for etoy textual code" - - self - chooseFontWithPrompt: 'Choose the connectors label font' translated - andSendTo: self - withSelector: #setConnectorsLabelFont: - highlight: self connectorsLabelFont! Item was removed: - ----- Method: Preferences class>>connectorsLabelFont (in category '*Etoys-Squeakland-fonts') ----- - connectorsLabelFont - "Answer the font to use in the etoy environment to view textual code." - - ^ (UserInterfaceTheme current get: #connectorsLabelFont) - ifNil: [TextStyle defaultFont]! Item was changed: ----- Method: SpeechBubbleMorph>>step (in category 'stepping') ----- step + (target isNil or: [lastHash = (lastHash := target boundsInWorld hash)]) - (target isNil or: [lastHash = (lastHash := target boundsSignatureHash)]) ifTrue: [self incrementStepTime] ifFalse: [stepTime := self minimumStepTime]. target notNil ifTrue: [ target isInWorld ifFalse: [^self delete]. self positionMyselfAccordingToTarget]. "This will keep the correct extent if the graphic changed" self msgMorph notNil ifTrue: [ (self balloon fullBounds containsRect: self msgMorph fullBounds) ifFalse: [self extent: 1 at 1]] ! From commits at source.squeak.org Thu Apr 29 09:00:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 09:00:20 0000 Subject: [squeak-dev] The Trunk: EToys-mt.445.mcz Message-ID: Marcel Taeumel uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-mt.445.mcz ==================== Summary ==================== Name: EToys-mt.445 Author: mt Time: 29 April 2021, 11:00:13.160891 am UUID: 52e9dd0f-9312-b14c-9c5e-e70fe689d457 Ancestors: EToys-mt.444 Move BroomMorphs to the "Connectors" project ... where they already are! :-O So, resolve conflicts between Connectors and Etoys when loading Connectors into Squeak. =============== Diff against EToys-mt.444 =============== Item was removed: - Morph subclass: #BroomMorph - instanceVariableNames: 'centered drawBroomIcon filter hotspot lastHotspot moved span start transient unmoved width' - classVariableNames: 'BroomIcon' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! - - !BroomMorph commentStamp: 'nk 7/24/2003 15:15' prior: 0! - This is a Morph (actually a family of Morphs) that do alignment of other morphs. - - BroomMorphs become: an object of one of their subclasses when dragged far enough. - - Drag a BroomMorph in some direction and it becomes a broom that can align the Morphs it touches. - - This idea is borrowed from the GEF framework (http://gef.tigris.org) - - If you want to pick up a BroomMorph, you can use the Shift key. - - Hitting the ESC key will re-position all moved Morphs to their original position. - - BroomMorph newTransient will give you a BroomMorph that will delete itself on mouse up. - - unmoved the set of Morphs that I won't move - moved the set of Morphs that I might move - start my first hotspot - span how wide to make (each half of) my bar initially - width the width of the main lines - hotspot my active position - lastHotspot my last active position - drawBroomIcon true if I look like a broom while idle (false=look like a +) - transient if true, then I delete myself on mouse-up - ! Item was removed: - ----- Method: BroomMorph class>>broomIcon (in category 'icons') ----- - broomIcon - "BroomMorph broomIcon openAsMorph" - ^BroomIcon ifNil: [ BroomIcon := ((ColorForm - extent: 48 at 48 - depth: 8 - fromArray: #( 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294965235 2123104255 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294289468 792571391 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4250474910 4268775935 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4281003980 4040445339 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 3558577510 3456013868 3305111551 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4119016581 1223753318 1509949439 4294967295 429 4967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294325096 1601695446 905969663 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294953525 2688143356 2354708479 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967163 1386041086 3779953919 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967294 730230149 4272828159 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4280259150 3556661084 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4284369021 1626460469 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294927207 1420492426 1308622847 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4 294967295 4294967295 4294937190 2120285430 1165885439 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294957119 1936237296 3090939903 4294967295 4294967295 4294967295 1314410239 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 980114393 4199311359 4294967295 4294967295 4294922751 3468260930 1409286143 4294967295 4294967295 4294967295 4294967295 4294967295 1985634676 4278069247 4294967295 4294967295 822072038 4259577561 1764753407 4294967295 4294967295 4294967295 4294967295 4294967295 3629150295 2650507588 4294967295 4294915958 3355115262 4143841013 4272170751 4294967295 4294967295 4294967295 4294967295 4294967295 4294926694 1526660645 2147418111 811775466 4278123248 4110024186 4209802495 4294967295 4294967295 4294967295 4294967295 4294967295 4291518587 1401683663 331415327 2949970174 4142920702 4261016571 4278113279 4294967295 4294967295 4294967295 4294967295 4294967295 4294967126 2521018110 1564595145 4177130745 4 177394940 4226481918 3875468850 4294967295 4294967295 4294967295 4294967295 4294967295 4294966641 1818781950 4128018932 4227464691 4260888054 4193844470 4278022746 4294967295 4294967295 4294967295 4294967295 4294967295 4294957251 1082604973 4103079930 4227659000 4260949757 4260625918 4151583689 4294967295 4294967295 4294967295 4294967295 4294967295 4294966523 2254399056 4275306750 4259969533 4126735860 4160027632 1714067961 4294967295 4294967295 4294967295 4294967295 4294967295 3774129236 3427224966 2232244218 4009623029 4143840757 4227709222 1704204739 4294967295 4294967295 4294967295 4294967295 4294967281 3329305219 4274147615 459535614 4261278453 4260753150 4270732152 2132872703 4294967295 4294967295 4294967295 4294967295 4294966951 995344887 3891984632 4244567550 4260690427 4076796361 1799391336 17564460 4294967295 4294967295 4294967295 4294967295 4274153014 2180382453 4261084157 4175822318 4059954686 4277316954 1602381320 643309831 4294967295 4294967295 4294967295 4294967282 28 23377603 3942511613 4142661107 4260624381 4261016062 4052699741 2049901056 391839597 4294967295 4294967295 4294967295 4294894196 747109878 4260689915 4210947065 4260953586 4177395136 1851158651 553648145 1599406079 4294967295 4294967295 4294967295 4256715083 3203923193 4177133041 4210883322 4244305914 4244547905 1487161345 330496 2227240959 4294967295 4294967295 4294967295 4280716212 4160615158 4244110584 4261214970 4261280247 4135604607 2017591306 728003705 1908998143 4294967295 4294967295 4294967257 2301731170 4093376766 4277467390 4259968509 3959291337 1415802972 571015178 360829128 4294967295 4294967295 4294967295 4294967254 1790591001 4244501995 4093310961 4160159230 4126914352 2004436244 50331652 659736575 4294967295 4294967295 4294967295 4294967238 1761476611 2144730878 4160683517 4143772670 4203101036 1849950720 34150400 1526726655 4294967295 4294967295 4294967295 4294967245 1806603524 512422141 4177326578 4261346478 1567853403 419430418 27790 2499805183 4294967295 429496729 5 4294967295 4294967295 2251944828 416179 4143369424 4142962521 2121937418 218103943 3075177727 4294967295 4294967295 4294967295 4294967295 4294967295 4030225866 2973499918 708410107 3394655628 1595344640 292229396 3218276351 4294967295 4294967295 4294967295 4294967295 3741319167 4292174133 2024384681 2646072943 1099787826 335808768 24831321 1996488703 4294967295 4294967295 4294967295 4294967295 4294967295 4294960585 1731939648 1162880122 2488537608 262165 842649087 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967246 4257768094 2930289509 420675584 173165056 1442840575 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4291847681 17632000 100663398 1027537151 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4290903836 152109071 5575935 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294954239 1392579628 436207615 4294967295 4294967295 42949672 95 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295 4294967295) - offset: 0 at 0) - colorsFromArray: #(#(0.0 0.0 0.0) #(0.004 0.004 0.004) #(0.008 0.008 0.008) #(0.012 0.012 0.012) #(0.016 0.016 0.016) #(0.02 0.02 0.02) #(0.023 0.023 0.023) #(0.027 0.027 0.027) #(0.031 0.031 0.031) #(0.035 0.035 0.035) #(0.039 0.039 0.039) #(0.043 0.043 0.043) #(0.047 0.047 0.047) #(0.051 0.051 0.051) #(0.055 0.055 0.055) #(0.059 0.059 0.059) #(0.063 0.063 0.063) #(0.066 0.066 0.066) #(0.07 0.07 0.07) #(0.074 0.074 0.074) #(0.078 0.078 0.078) #(0.082 0.082 0.082) #(0.086 0.086 0.086) #(0.09 0.09 0.09) #(0.094 0.094 0.094) #(0.098 0.098 0.098) #(0.102 0.102 0.102) #(0.106 0.106 0.106) #(0.109 0.109 0.109) #(0.113 0.113 0.113) #(0.117 0.117 0.117) #(0.121 0.121 0.121) #(0.125 0.125 0.125) #(0.129 0.129 0.129) #(0.133 0.133 0.133) #(0.137 0.137 0.137) #(0.141 0.141 0.141) #(0.145 0.145 0.145) #(0.149 0.149 0.149) #(0.152 0.152 0.152) #(0.156 0.156 0.156) #(0.16 0.16 0.16) #(0.164 0.164 0.164) #(0.168 0.168 0.168) #(0.172 0.172 0.172) #(0.176 0.176 0.176) #(0.18 0.18 0.18) #(0.184 0. 184 0.184) #(0.188 0.188 0.188) #(0.192 0.192 0.192) #(0.196 0.196 0.196) #(0.199 0.199 0.199) #(0.203 0.203 0.203) #(0.207 0.207 0.207) #(0.211 0.211 0.211) #(0.215 0.215 0.215) #(0.219 0.219 0.219) #(0.223 0.223 0.223) #(0.227 0.227 0.227) #(0.231 0.231 0.231) #(0.235 0.235 0.235) #(0.239 0.239 0.239) #(0.242 0.242 0.242) #(0.246 0.246 0.246) #(0.25 0.25 0.25) #(0.254 0.254 0.254) #(0.258 0.258 0.258) #(0.262 0.262 0.262) #(0.266 0.266 0.266) #(0.27 0.27 0.27) #(0.274 0.274 0.274) #(0.278 0.278 0.278) #(0.282 0.282 0.282) #(0.285 0.285 0.285) #(0.289 0.289 0.289) #(0.293 0.293 0.293) #(0.297 0.297 0.297) #(0.301 0.301 0.301) #(0.305 0.305 0.305) #(0.309 0.309 0.309) #(0.313 0.313 0.313) #(0.317 0.317 0.317) #(0.321 0.321 0.321) #(0.325 0.325 0.325) #(0.328 0.328 0.328) #(0.333 0.333 0.333) #(0.337 0.337 0.337) #(0.341 0.341 0.341) #(0.345 0.345 0.345) #(0.349 0.349 0.349) #(0.353 0.353 0.353) #(0.357 0.357 0.357) #(0.361 0.361 0.361) #(0.365 0.365 0.365) #(0.369 0.369 0.369) #(0.3 72 0.372 0.372) #(0.376 0.376 0.376) #(0.38 0.38 0.38) #(0.384 0.384 0.384) #(0.388 0.388 0.388) #(0.392 0.392 0.392) #(0.396 0.396 0.396) #(0.4 0.4 0.4) #(0.404 0.404 0.404) #(0.408 0.408 0.408) #(0.412 0.412 0.412) #(0.415 0.415 0.415) #(0.419 0.419 0.419) #(0.423 0.423 0.423) #(0.427 0.427 0.427) #(0.431 0.431 0.431) #(0.435 0.435 0.435) #(0.439 0.439 0.439) #(0.443 0.443 0.443) #(0.447 0.447 0.447) #(0.451 0.451 0.451) #(0.455 0.455 0.455) #(0.458 0.458 0.458) #(0.462 0.462 0.462) #(0.466 0.466 0.466) #(0.47 0.47 0.47) #(0.474 0.474 0.474) #(0.478 0.478 0.478) #(0.482 0.482 0.482) #(0.486 0.486 0.486) #(0.49 0.49 0.49) #(0.494 0.494 0.494) #(0.498 0.498 0.498) #(0.501 0.501 0.501) #(0.505 0.505 0.505) #(0.509 0.509 0.509) #(0.513 0.513 0.513) #(0.517 0.517 0.517) #(0.521 0.521 0.521) #(0.525 0.525 0.525) #(0.529 0.529 0.529) #(0.533 0.533 0.533) #(0.537 0.537 0.537) #(0.541 0.541 0.541) #(0.544 0.544 0.544) #(0.548 0.548 0.548) #(0.552 0.552 0.552) #(0.556 0.556 0.556) #(0.56 0. 56 0.56) #(0.564 0.564 0.564) #(0.568 0.568 0.568) #(0.572 0.572 0.572) #(0.576 0.576 0.576) #(0.58 0.58 0.58) #(0.584 0.584 0.584) #(0.587 0.587 0.587) #(0.591 0.591 0.591) #(0.595 0.595 0.595) #(0.599 0.599 0.599) #(0.603 0.603 0.603) #(0.607 0.607 0.607) #(0.611 0.611 0.611) #(0.615 0.615 0.615) #(0.619 0.619 0.619) #(0.623 0.623 0.623) #(0.627 0.627 0.627) #(0.63 0.63 0.63) #(0.634 0.634 0.634) #(0.638 0.638 0.638) #(0.642 0.642 0.642) #(0.646 0.646 0.646) #(0.65 0.65 0.65) #(0.654 0.654 0.654) #(0.658 0.658 0.658) #(0.662 0.662 0.662) #(0.667 0.667 0.667) #(0.671 0.671 0.671) #(0.674 0.674 0.674) #(0.678 0.678 0.678) #(0.682 0.682 0.682) #(0.686 0.686 0.686) #(0.69 0.69 0.69) #(0.694 0.694 0.694) #(0.698 0.698 0.698) #(0.702 0.702 0.702) #(0.706 0.706 0.706) #(0.71 0.71 0.71) #(0.714 0.714 0.714) #(0.717 0.717 0.717) #(0.721 0.721 0.721) #(0.725 0.725 0.725) #(0.729 0.729 0.729) #(0.733 0.733 0.733) #(0.737 0.737 0.737) #(0.741 0.741 0.741) #(0.745 0.745 0.745) #(0.749 0.749 0. 749) #(0.753 0.753 0.753) #(0.757 0.757 0.757) #(0.761 0.761 0.761) #(0.764 0.764 0.764) #(0.768 0.768 0.768) #(0.772 0.772 0.772) #(0.776 0.776 0.776) #(0.78 0.78 0.78) #(0.784 0.784 0.784) #(0.788 0.788 0.788) #(0.792 0.792 0.792) #(0.796 0.796 0.796) #(0.8 0.8 0.8) #(0.804 0.804 0.804) #(0.807 0.807 0.807) #(0.811 0.811 0.811) #(0.815 0.815 0.815) #(0.819 0.819 0.819) #(0.823 0.823 0.823) #(0.827 0.827 0.827) #(0.831 0.831 0.831) #(0.835 0.835 0.835) #(0.839 0.839 0.839) #(0.843 0.843 0.843) #(0.847 0.847 0.847) #(0.85 0.85 0.85) #(0.854 0.854 0.854) #(0.858 0.858 0.858) #(0.862 0.862 0.862) #(0.866 0.866 0.866) #(0.87 0.87 0.87) #(0.874 0.874 0.874) #(0.878 0.878 0.878) #(0.882 0.882 0.882) #(0.886 0.886 0.886) #(0.89 0.89 0.89) #(0.893 0.893 0.893) #(0.897 0.897 0.897) #(0.901 0.901 0.901) #(0.905 0.905 0.905) #(0.909 0.909 0.909) #(0.913 0.913 0.913) #(0.917 0.917 0.917) #(0.921 0.921 0.921) #(0.925 0.925 0.925) #(0.929 0.929 0.929) #(0.933 0.933 0.933) #(0.936 0.936 0.936) #( 0.94 0.94 0.94) #(0.944 0.944 0.944) #(0.948 0.948 0.948) #(0.952 0.952 0.952) #(0.956 0.956 0.956) #(0.96 0.96 0.96) #(0.964 0.964 0.964) #(0.968 0.968 0.968) #(0.972 0.972 0.972) #(0.976 0.976 0.976) #(0.979 0.979 0.979) #(0.983 0.983 0.983) #(0.987 0.987 0.987) #(0.991 0.991 0.991) #(0.995 0.995 0.995) #( ) )) ]! Item was removed: - ----- Method: BroomMorph class>>descriptionForPartsBin (in category 'parts bin') ----- - descriptionForPartsBin - ^ self partName: 'Broom' translatedNoop - categories: {'Graphics' translatedNoop} - documentation: 'A broom to align Morphs with' translatedNoop! Item was removed: - ----- Method: BroomMorph class>>newCentered (in category 'instance creation') ----- - newCentered - "return a BroomMorph that will align Morph centers" - "BroomMorph newCentered openInHand" - ^(self new) centered: true! Item was removed: - ----- Method: BroomMorph class>>newTransient (in category 'instance creation') ----- - newTransient - "return a BroomMorph that will delete itself on mouse-up" - - "BroomMorph newTransient openInHand" - - ^self new transient: true! Item was removed: - ----- Method: BroomMorph class>>newTransientInHand (in category 'instance creation') ----- - newTransientInHand - - "return a BroomMorph that will delete itself on mouse-up" - - "BroomMorph newTransientInHand" - - ^self newTransient openInHand! Item was removed: - ----- Method: BroomMorph>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - ^ #()! Item was removed: - ----- Method: BroomMorph>>basicClass (in category 'private') ----- - basicClass - ^BroomMorph! Item was removed: - ----- Method: BroomMorph>>centered: (in category 'accessing') ----- - centered: aBoolean - "If aBoolean is true, I align morphs on their H or V centerlines" - centered := aBoolean.! Item was removed: - ----- Method: BroomMorph>>drawBroomIcon: (in category 'accessing') ----- - drawBroomIcon: aBoolean - "If aBoolean is true, then I draw a cute broom icon; otherwise I draw a cross" - drawBroomIcon := aBoolean. - self changed.! Item was removed: - ----- Method: BroomMorph>>drawOn: (in category 'drawing') ----- - drawOn: aCanvas - drawBroomIcon - ifTrue: [ aCanvas paintImage: self class broomIcon at: self position ] - ifFalse: [ self drawPlusOn: aCanvas ]. - ! Item was removed: - ----- Method: BroomMorph>>drawPlusOn: (in category 'drawing') ----- - drawPlusOn: aCanvas - | halfWidth | - halfWidth := width + 1 // 2. - aCanvas line: bounds leftCenter + (halfWidth at 0) to: bounds rightCenter + (halfWidth negated at 0) width: width color: self color. - aCanvas line: bounds topCenter + (0 at halfWidth) to: bounds bottomCenter + (0 at halfWidth negated) width: width color: self color. - ! Item was removed: - ----- Method: BroomMorph>>filter: (in category 'accessing') ----- - filter: aBlock - "Set my acceptance filter. aBlock should return true for all Morphs to be moved" - filter := aBlock! Item was removed: - ----- Method: BroomMorph>>handlesKeyboard: (in category 'event handling') ----- - handlesKeyboard: evt - ^true! Item was removed: - ----- Method: BroomMorph>>handlesMouseDown: (in category 'event handling') ----- - handlesMouseDown: evt - ^evt shiftPressed not! Item was removed: - ----- Method: BroomMorph>>handlesMouseStillDown: (in category 'event handling') ----- - handlesMouseStillDown: evt - ^true.! Item was removed: - ----- Method: BroomMorph>>hotspot (in category 'accessing') ----- - hotspot - ^hotspot! Item was removed: - ----- Method: BroomMorph>>hotspot: (in category 'private') ----- - hotspot: aPoint - lastHotspot := hotspot. - hotspot := aPoint. - ^self center: aPoint! Item was removed: - ----- Method: BroomMorph>>initialize (in category 'initialization') ----- - initialize - super initialize. - width := 5. - span := 100. - hotspot := self center. - self reset. - self color: Color blue muchDarker. - self setBalloonText: 'Drag me to align other Morphs. Drag with the Shift key to move me without affecting other Morphs. Drag me with the second mouse button to align centers.' translated. - drawBroomIcon := true. - transient := false. - centered := false. - ! Item was removed: - ----- Method: BroomMorph>>justDroppedInto:event: (in category 'dropping/grabbing') ----- - justDroppedInto: aMorph event: anEvent - super justDroppedInto: aMorph event: anEvent. - aMorph isPlayfieldLike ifFalse: [ ^self delete ]. - self centered: anEvent hand lastEvent yellowButtonPressed. - self transient ifFalse: [ ^self ]. - self reset. - self hotspot: (start := anEvent position). - anEvent hand newMouseFocus: self. - anEvent hand newKeyboardFocus: self. - "Cursor blank show."! Item was removed: - ----- Method: BroomMorph>>keyStroke: (in category 'event handling') ----- - keyStroke: evt - evt keyCharacter ~= Character escape ifTrue: [ ^self ]. - evt hand releaseMouseFocus: self. - evt hand releaseKeyboardFocus: self. - Cursor normal show. - moved keysAndValuesDo: [ :m :b | m bounds: b ]. - transient ifTrue: [ ^self delete ]. - self resetClass. - self reset. - self hotspot: start. - ! Item was removed: - ----- Method: BroomMorph>>lineWidth (in category 'accessing') ----- - lineWidth - ^width! Item was removed: - ----- Method: BroomMorph>>lineWidth: (in category 'accessing') ----- - lineWidth: aNumber - width := aNumber. - self changed! Item was removed: - ----- Method: BroomMorph>>morphIfNecessary: (in category 'stepping and presenter') ----- - morphIfNecessary: yellowButtonPressed - | pt delta threshold cls center | - center := yellowButtonPressed | centered. - pt := self center. - threshold := self width / 2. - delta := pt - start. - cls := delta x > threshold - ifTrue: [center - ifTrue: [CenterBroomMorphRight] - ifFalse: [BroomMorphRight]] - ifFalse: [delta x < threshold negated - ifTrue: [center - ifTrue: [CenterBroomMorphLeft] - ifFalse: [BroomMorphLeft]] - ifFalse: [delta y > threshold - ifTrue: [center - ifTrue: [CenterBroomMorphDown] - ifFalse: [BroomMorphDown]] - ifFalse: [delta y < threshold negated - ifTrue: [center - ifTrue: [CenterBroomMorphUp] - ifFalse: [BroomMorphUp]]]]]. - cls - ifNotNil: [self - become: (self as: cls). - self reset. - self resetFilter. - unmoved addAll: self affectedMorphs]! Item was removed: - ----- Method: BroomMorph>>mouseDown: (in category 'event handling') ----- - mouseDown: evt - self reset. - self resetFilter. - self hotspot: (start := evt position). - evt hand newMouseFocus: self. - evt hand newKeyboardFocus: self. - "Cursor blank show."! Item was removed: - ----- Method: BroomMorph>>mouseMove: (in category 'event handling') ----- - mouseMove: evt - self hotspot: evt position. - self moveMorphs: evt yellowButtonPressed! Item was removed: - ----- Method: BroomMorph>>mouseStillDown: (in category 'event handling') ----- - mouseStillDown: evt - self hotspot: evt position. - self moveMorphs: evt yellowButtonPressed! Item was removed: - ----- Method: BroomMorph>>mouseUp: (in category 'event handling') ----- - mouseUp: evt - evt hand releaseMouseFocus: self. - Cursor normal show. - self rememberCommand: self undoCommand. - transient ifTrue: [ ^self delete ]. - self resetClass. - self reset. - self hotspot: start.! Item was removed: - ----- Method: BroomMorph>>moveMorphs: (in category 'stepping and presenter') ----- - moveMorphs: yellowButtonPressed - "Move all the newly affected morphs and the ones I'm already moving." - self class == self basicClass - ifTrue: [^ self morphIfNecessary: yellowButtonPressed ]. - (((self affectedMorphs - reject: [:m | unmoved includes: m]) - reject: [:m | moved includesKey: m]) - select: filter) - do: [:m | moved at: m put: m bounds]. - moved - keysAndValuesDo: [:m :b | self positionMorph: m originalBounds: b]! Item was removed: - ----- Method: BroomMorph>>openCenteredInHand (in category 'initialization') ----- - openCenteredInHand - "BroomMorph new openCenteredInHand" - "NCBroomMorph new openCenteredInHand" - self centered: true. - self openInHand.! Item was removed: - ----- Method: BroomMorph>>openTransientCenteredInHand (in category 'initialization') ----- - openTransientCenteredInHand - "BroomMorph new openTransientCenteredInHand" - self transient: true. - self centered: true. - self openInHand.! Item was removed: - ----- Method: BroomMorph>>openTransientInHand (in category 'initialization') ----- - openTransientInHand - "BroomMorph new openTransientInHand" - self transient: true. - self openInHand.! Item was removed: - ----- Method: BroomMorph>>reset (in category 'initialization') ----- - reset - moved := IdentityDictionary new. "morph -> original bounds" - unmoved := IdentitySet new. - self resetExtent. - filter := nil. - ! Item was removed: - ----- Method: BroomMorph>>resetClass (in category 'initialization') ----- - resetClass - self become: (self as: self basicClass)! Item was removed: - ----- Method: BroomMorph>>resetExtent (in category 'initialization') ----- - resetExtent - super extent: self class broomIcon extent. - hotspot := lastHotspot := self center.! Item was removed: - ----- Method: BroomMorph>>resetFilter (in category 'initialization') ----- - resetFilter - - self filter: [ :m | true ]. - ! Item was removed: - ----- Method: BroomMorph>>span (in category 'accessing') ----- - span - ^span! Item was removed: - ----- Method: BroomMorph>>span: (in category 'accessing') ----- - span: aNumber - span := aNumber. - self hotspot: self hotspot. - self changed.! Item was removed: - ----- Method: BroomMorph>>transient (in category 'accessing') ----- - transient - ^transient! Item was removed: - ----- Method: BroomMorph>>transient: (in category 'accessing') ----- - transient: aBoolean - "if aBoolean is true, then I delete myself on mouse-up" - transient := aBoolean! Item was removed: - ----- Method: BroomMorph>>undoCommand (in category 'undo') ----- - undoCommand - | cmd args | - cmd := Command new cmdWording: 'align morphs'. - args := OrderedCollection new. - moved keysAndValuesDo: [ :m :b | - args add: { m. b. m bounds. m owner. m owner morphPreceding: m } - ]. - cmd undoTarget: self selector: #undoMove:redo:args: arguments: { cmd. false. args }. - ^cmd! Item was removed: - ----- Method: BroomMorph>>undoMove:redo:args: (in category 'undo') ----- - undoMove: cmd redo: redo args: args - "morph oldbounds newbounds oldowner oldpredecessor" - cmd redoTarget: self selector: #undoMove:redo:args: arguments: { cmd. true. args }. - args do: [ :a | | morph oldbounds newbounds oldowner oldpredecessor | - morph := a at: 1. - oldbounds := a at: 2. - newbounds := a at: 3. - oldowner := a at: 4. - oldpredecessor := a at: 5. - oldowner ifNotNil: [ oldpredecessor ifNil: [ oldowner addMorphFront: morph ] - ifNotNil: [ oldowner addMorph: morph after: oldpredecessor ]]. - morph bounds: (redo ifTrue: [ newbounds ] ifFalse: [ oldbounds ]). - (morph isKindOf: SystemWindow) ifTrue: [ morph activate ]. - ].! Item was removed: - BroomMorph subclass: #BroomMorphDown - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! - - !BroomMorphDown commentStamp: '' prior: 0! - I am a BroomMorph that pushes morphs down.! Item was removed: - ----- Method: BroomMorphDown>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: hotspot x @ lastHotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds left - right: m bounds right - top: m bounds top - bottom: m bounds top + 1)]! Item was removed: - ----- Method: BroomMorphDown>>drawOn: (in category 'drawing') ----- - drawOn: aCanvas - | halfWidth | - halfWidth := width + 1 // 2. - aCanvas line: bounds topCenter + (0 at halfWidth) to: bounds bottomCenter + (0 at halfWidth negated) width: width color: self color. - aCanvas line: bounds bottomLeft + (halfWidth @ halfWidth negated) to: bounds bottomRight + (halfWidth negated at halfWidth negated) width: width color: self color. - aCanvas line: self hotspot + (span negated @ (width * -2)) to: self hotspot + (span negated @ -1) color: self color. - aCanvas line: self hotspot + (span -1 @ (width * -2)) to: self hotspot + (span-1 @ -1) color: self color. - ! Item was removed: - ----- Method: BroomMorphDown>>hotspot: (in category 'accessing') ----- - hotspot: aPoint - | left right bottom newBounds | - left := aPoint x - span min: bounds left. - right := aPoint x + span max: bounds right. - bottom := aPoint y max: start y. - lastHotspot := hotspot. - hotspot := aPoint x @ bottom. - newBounds := Rectangle - left: left - right: right - top: bottom - bounds height - bottom: bottom. - self bounds: newBounds. - ! Item was removed: - ----- Method: BroomMorphDown>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m top: (self bottom max: b top)! Item was removed: - ----- Method: BroomMorphDown>>resetExtent (in category 'drawing') ----- - resetExtent - | newBounds | - newBounds := 0 at 0 extent: (2*span) @ (12 + width). - self bounds: (newBounds align: newBounds bottomCenter with: hotspot)! Item was removed: - BroomMorphRight subclass: #BroomMorphLeft - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! - - !BroomMorphLeft commentStamp: '' prior: 0! - I am a BroomMorph that pushes morphs left.! Item was removed: - ----- Method: BroomMorphLeft>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: lastHotspot x @ hotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds right - 1 - right: m bounds right - top: m bounds top - bottom: m bounds bottom)]! Item was removed: - ----- Method: BroomMorphLeft>>drawOn: (in category 'drawing') ----- - drawOn: aCanvas - | halfWidth | - halfWidth := (width + 1 // 2). - aCanvas line: bounds leftCenter + (halfWidth at 0) to: bounds rightCenter + (halfWidth negated @0) width: width color: self color. - aCanvas line: bounds topLeft + (halfWidth @ halfWidth) to: bounds bottomLeft + (halfWidth @halfWidth negated) width: width color: self color. - aCanvas line: self hotspot + (width * 2 @ (span negated)) to: self hotspot + (1 @ (span negated)) color: self color. - aCanvas line: self hotspot + (width * 2 @ (span-1)) to: self hotspot + (1 @ (span-1)) color: self color. - ! Item was removed: - ----- Method: BroomMorphLeft>>hotspot: (in category 'accessing') ----- - hotspot: aPoint - | newBounds top bottom left | - top := aPoint y - span min: bounds top. - bottom := aPoint y + span max: bounds bottom. - left := aPoint x min: start x. - lastHotspot := hotspot. - hotspot := left @ aPoint y. - newBounds := Rectangle - left: left - right: left + bounds width - top: top - bottom: bottom. - self bounds: newBounds! Item was removed: - ----- Method: BroomMorphLeft>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m right: (self left min: b right)! Item was removed: - ----- Method: BroomMorphLeft>>resetExtent (in category 'drawing') ----- - resetExtent - | newBounds | - newBounds := 0 at 0 extent: (12 + width) @ (2*span). - self bounds: (newBounds align: newBounds leftCenter with: hotspot)! Item was removed: - BroomMorph subclass: #BroomMorphRight - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! - - !BroomMorphRight commentStamp: '' prior: 0! - I am a BroomMorph that pushes morphs right.! Item was removed: - ----- Method: BroomMorphRight>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: lastHotspot x @ hotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds left - right: m bounds left + 1 - top: m bounds top - bottom: m bounds bottom)]! Item was removed: - ----- Method: BroomMorphRight>>drawOn: (in category 'drawing') ----- - drawOn: aCanvas - | halfWidth | - halfWidth := width + 1 // 2. - aCanvas line: bounds leftCenter + (halfWidth at 0) to: bounds rightCenter + (halfWidth negated @0) width: width color: self color. - aCanvas line: bounds topRight + (halfWidth negated @ halfWidth) to: bounds bottomRight + (halfWidth negated at halfWidth negated) width: width color: self color. - aCanvas line: self hotspot + (width * -2 @ (span negated)) to: self hotspot + (-1 @ (span negated)) color: self color. - aCanvas line: self hotspot + (width * -2 @ (span-1)) to: self hotspot + (-1 @ (span-1)) color: self color. - ! Item was removed: - ----- Method: BroomMorphRight>>hotspot: (in category 'accessing') ----- - hotspot: aPoint - | newBounds top bottom right | - top := aPoint y - span min: bounds top. - bottom := aPoint y + span max: bounds bottom. - right := aPoint x max: start x. - lastHotspot := hotspot. - hotspot := right @ aPoint y. - newBounds := Rectangle - left: right - bounds width - right: right - top: top - bottom: bottom. - self bounds: newBounds! Item was removed: - ----- Method: BroomMorphRight>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m left: (self right max: b left)! Item was removed: - ----- Method: BroomMorphRight>>resetExtent (in category 'accessing') ----- - resetExtent - | newBounds | - newBounds := 0 at 0 extent: (12 + width) @ (2*span). - self bounds: (newBounds align: newBounds rightCenter with: hotspot)! Item was removed: - BroomMorphDown subclass: #BroomMorphUp - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! - - !BroomMorphUp commentStamp: '' prior: 0! - I am a BroomMorph that pushes morphs up.! Item was removed: - ----- Method: BroomMorphUp>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: hotspot x @ lastHotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds left - right: m bounds right - top: m bounds bottom - 1 - bottom: m bounds bottom)]! Item was removed: - ----- Method: BroomMorphUp>>drawOn: (in category 'drawing') ----- - drawOn: aCanvas - | halfWidth | - halfWidth := width + 1 // 2. - aCanvas line: bounds topCenter + (0 at halfWidth) to: bounds bottomCenter + (0 at halfWidth negated) width: width color: self color. - aCanvas line: bounds topLeft + (halfWidth @ halfWidth) to: bounds topRight + ((halfWidth) negated at halfWidth) width: width color: self color. - aCanvas line: self hotspot + (span negated @ (width * 2)) to: self hotspot + (span negated @ 1) color: self color. - aCanvas line: self hotspot + (span -1 @ (width * 2)) to: self hotspot + (span -1 @ 1) color: self color. - ! Item was removed: - ----- Method: BroomMorphUp>>hotspot: (in category 'accessing') ----- - hotspot: aPoint - | left right newBounds top | - left := aPoint x - span min: bounds left. - right := aPoint x + span max: bounds right. - top := aPoint y min: start y. - lastHotspot := hotspot. - hotspot := aPoint x @ top. - newBounds := Rectangle - left: left - right: right - top: top - bottom: top + bounds height. - self bounds: newBounds! Item was removed: - ----- Method: BroomMorphUp>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m bottom: (self top min: b bottom)! Item was removed: - ----- Method: BroomMorphUp>>resetExtent (in category 'drawing') ----- - resetExtent - | newBounds | - newBounds := 0 at 0 extent: (2*span) @ (12 + width). - self bounds: (newBounds align: newBounds topCenter with: hotspot)! Item was removed: - BroomMorphDown subclass: #CenterBroomMorphDown - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! Item was removed: - ----- Method: CenterBroomMorphDown>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: hotspot x @ lastHotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds left - right: m bounds right - top: m bounds center y - 1 - bottom: m bounds center y + 1)]! Item was removed: - ----- Method: CenterBroomMorphDown>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m center: m center x @ (self bottom max: b center y)! Item was removed: - BroomMorphLeft subclass: #CenterBroomMorphLeft - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! Item was removed: - ----- Method: CenterBroomMorphLeft>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: lastHotspot x @ hotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds center x - 1 - right: m bounds center x + 1 - top: m bounds top - bottom: m bounds bottom)]! Item was removed: - ----- Method: CenterBroomMorphLeft>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m center: (self left min: b center x) @ m center y! Item was removed: - BroomMorphRight subclass: #CenterBroomMorphRight - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! Item was removed: - ----- Method: CenterBroomMorphRight>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: lastHotspot x @ hotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds center x - 1 - right: m bounds center x + 1 - top: m bounds top - bottom: m bounds bottom)]! Item was removed: - ----- Method: CenterBroomMorphRight>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m center: (self right max: b center x) @ m center y! Item was removed: - BroomMorphUp subclass: #CenterBroomMorphUp - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Base'! Item was removed: - ----- Method: CenterBroomMorphUp>>affectedMorphs (in category 'private') ----- - affectedMorphs - "Answer all the morphs that I should be moving" - | movedRect | - movedRect := self bounds encompass: hotspot x @ lastHotspot y. - ^ owner submorphs - select: [:m | movedRect - intersects: (Rectangle - left: m bounds left - right: m bounds right - top: m bounds center y - 1 - bottom: m bounds center y + 1)]! Item was removed: - ----- Method: CenterBroomMorphUp>>positionMorph:originalBounds: (in category 'private') ----- - positionMorph: m originalBounds: b - m center: m center x @ (self top min: b center y)! Item was removed: - BroomMorph subclass: #NCBroomMorph - instanceVariableNames: '' - classVariableNames: '' - poolDictionaries: '' - category: 'Etoys-Squeakland-BroomMorphs-Connectors'! - - !NCBroomMorph commentStamp: '' prior: 0! - This is a BroomMorph that won't move labels or connectors.! Item was removed: - ----- Method: NCBroomMorph class>>descriptionForPartsBin (in category 'parts bin') ----- - descriptionForPartsBin - ^ self partName: 'Connector Broom' translatedNoop - categories: {'Connectors' translatedNoop} - documentation: 'A broom to align shapes with' translatedNoop! Item was removed: - ----- Method: NCBroomMorph class>>newInHand (in category 'instance creation') ----- - newInHand - self new openInHand! Item was removed: - ----- Method: NCBroomMorph>>basicClass (in category 'initialization') ----- - basicClass - ^NCBroomMorph! Item was removed: - ----- Method: NCBroomMorph>>resetFilter (in category 'initialization') ----- - resetFilter - - self filter: [ :m | m isConnector not and: [ m isConstraint not ] ].! From commits at source.squeak.org Thu Apr 29 09:03:47 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 09:03:47 0000 Subject: [squeak-dev] The Trunk: System-mt.1231.mcz Message-ID: Marcel Taeumel uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-mt.1231.mcz ==================== Summary ==================== Name: System-mt.1231 Author: mt Time: 29 April 2021, 11:03:42.969891 am UUID: af06a9e1-6280-0649-820c-f6c89ef25640 Ancestors: System-mt.1230 Removes autogenerated pref accessors, which are now under "*autogenerated - ...". =============== Diff against System-mt.1230 =============== Item was removed: - ----- Method: Preferences class>>alwaysShowConnectionVocabulary (in category 'standard queries') ----- - alwaysShowConnectionVocabulary - ^ self - valueOfFlag: #alwaysShowConnectionVocabulary - ifAbsent: [false]! Item was removed: - ----- Method: Preferences class>>useSmartLabels (in category 'standard queries') ----- - useSmartLabels - ^ self - valueOfFlag: #useSmartLabels - ifAbsent: [false]! From commits at source.squeak.org Thu Apr 29 12:02:58 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 12:02:58 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1394.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1394.mcz ==================== Summary ==================== Name: Kernel-nice.1394 Author: nice Time: 26 April 2021, 1:50:12.861556 am UUID: 3a981b94-0213-44f3-8263-838dda062f8a Ancestors: Kernel-bp.1393 Revise exception handling so as to - inactivate inner handler blocks when the exception is signalled in an outer handler - except when the inner handler has been explicitely rearmed (see rearmHandlerDuring:) Implementation notes: add a marker to handleSignal:, so as to detect the case when an exception is signalled within the execution of a handler block. This induces a subtle difference: - findNextHandlerContext might now return a handleSignal: context, - while nextHandlerContext will only return a on:do: context (or nil). The new workhorse for finding the proper handler is now #nextHandlerContextForSignal: It finds and answers the (handler) context that will handle the exception, but if it finds a handleSignal: during the scan, it will restrict the search to rearmed handlers, until it reaches the handler of prior exception, at which step it continues to search normally. Due to the scanning of inner blocks, we still need a marker for blocking re-entrancy (handlerActive temp in on:do:), but also a marker for rearmed blocks (handlerRearmed in on:do:). This can't be the same marker: an example is testHandlerReentrancy: when the rearmed inner handler pass the exception to its outer handler, the outer handler must still be inactive if it raised the Exception. Borrow resumeEvaluating: to Cuis and use it in resignalAs: Use many small methods in order to make the intention more explicit than with those mysterious tempAt: tempAt:put: =============== Diff against Kernel-bp.1393 =============== Item was changed: ----- Method: BlockClosure>>on:do: (in category 'exceptions') ----- on: exceptionOrExceptionSet do: handlerAction "Evaluate the receiver in the scope of an exception handler." + | handlerActive handlerRearmed | - | handlerActive | "just a marker, fail and execute the following" handlerActive := true. + handlerRearmed := false. ^ self value! Item was changed: ----- Method: Context>>canHandleSignal: (in category 'private-exceptions') ----- canHandleSignal: exception "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception then return true, otherwise forward this message to the next handler context. If none left, return false (see nil>>canHandleSignal:)" + ^ (self willHandleSignal: exception) - ^ (((self tempAt: 1) handles: exception) and: [self tempAt: 3]) or: [self nextHandlerContext canHandleSignal: exception]. ! Item was added: + ----- Method: Context>>deactivateHandler (in category 'private-exceptions') ----- + deactivateHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 3 ifTrue: [self tempAt: 3 put: false] "this is temporary handlerActive in #on:do:"! Item was added: + ----- Method: Context>>desarmHandler (in category 'private-exceptions') ----- + desarmHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 4 ifTrue: [self tempAt: 4 put: false] "this is temporary handlerRearmed in #on:do:"! Item was added: + ----- Method: Context>>findNextHandlerContext (in category 'private-exceptions') ----- + findNextHandlerContext + "find next context marked with . + This can be either a handler context (on:do:), + or a handling context (handleSignal:)" + + ^ self sender findNextHandlerContextStarting! Item was added: + ----- Method: Context>>fireHandlerActionForSignal: (in category 'private-exceptions') ----- + fireHandlerActionForSignal: exception + "Sent to handler (on:do:) contexts only. + Perform the second argument, which is the handler action" + + ^(self tempAt: 2) cull: exception! Item was changed: ----- Method: Context>>handleSignal: (in category 'private-exceptions') ----- handleSignal: exception + "Sent to handler (on:do:) contexts only. + Execute the handler action block" - "Sent to handler (on:do:) contexts only. If my exception class (first arg) handles exception - and the handler is active then execute my handle block (second arg), otherwise forward - this message to the next handler context. If none left, execute exception's defaultAction - (see nil>>handleSignal:)." + | val | + "just a marker, fail and execute the following" - | handlerActive val | - "If the context has been returned from the handlerActive temp var may not be accessible." - handlerActive := stackp >= 3 and: [(self tempAt: 3) == true]. - (((self tempAt: 1) handles: exception) and: [handlerActive]) ifFalse: - [stackp >= 3 ifTrue: [self tempAt: 3 put: false]. - ^self nextHandlerContext handleSignal: exception]. - exception privHandlerContext: self contextTag. + self deactivateHandler. "Prevent re-entering the action block, unless it is explicitely rearmed" + val := [self fireHandlerActionForSignal: exception] ensure: [self reactivateHandler]. + self return: val "return from self if not otherwise directed in handle block"! - self tempAt: 3 put: false. "disable self while executing handle block" - val := [(self tempAt: 2) cull: exception] - ifCurtailed: [self tempAt: 3 put: true]. - self return: val "return from self if not otherwise directed in handle block" - ! Item was added: + ----- Method: Context>>isHandlerActive (in category 'private-exceptions') ----- + isHandlerActive + "Private - sent to exception handler context only (on:do:)" + + ^stackp >= 3 and: [(self tempAt: 3) == true] "this is temporary handlerActive in #on:do:"! Item was added: + ----- Method: Context>>isHandlerRearmed (in category 'private-exceptions') ----- + isHandlerRearmed + "Private - sent to exception handler context only (on:do:)" + + ^stackp >= 4 and: [(self tempAt: 4) == true] "this is temporary handlerRearmed in #on:do:"! Item was changed: ----- Method: Context>>nextHandlerContext (in category 'private-exceptions') ----- nextHandlerContext + "Answer the next handler context (on:do:) in the call chain. + Answer nil if none found" + + | handler | + handler := self findNextHandlerContext. + [handler ifNil: [^nil]. + handler selector == #handleSignal:] + whileTrue: [handler := handler findNextHandlerContext]. + ^handler! - - ^ self sender findNextHandlerContextStarting! Item was added: + ----- Method: Context>>nextHandlerContextForSignal: (in category 'private-exceptions') ----- + nextHandlerContextForSignal: exception + "Answer the handler context (on:do:) for this exception + Answer nil if none found" + + | handler priorHandler | + handler := self. + [(handler := handler findNextHandlerContext) ifNil: [^nil]. + handler selector == #handleSignal:] + whileFalse: [(handler willHandleSignal: exception) ifTrue: [^handler]]. + + "exception has been signalled in the scope of another signal handler (while #handleSignal:) + Check for a rearmed inner handler. If none, jump to outer handler context." + priorHandler := (handler tempAt: 1) "the exception argument to handleSignal:" + privHandlerContext. + + [(handler := handler nextHandlerContext) ifNil: [^nil]. + (handler isHandlerRearmed and: [handler willHandleSignal: exception]) ifTrue: [^handler]. + handler == priorHandler] whileFalse. + + ^priorHandler nextHandlerContextForSignal: exception! Item was added: + ----- Method: Context>>reactivateHandler (in category 'private-exceptions') ----- + reactivateHandler + "Private - sent to exception handler context only (on:do:)" + + stackp >= 3 ifTrue: [self tempAt: 3 put: true] "this is temporary handlerActive in #on:do:"! Item was changed: ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- reactivateHandlers + "Private - exception handling + do nothing, this method is only here for smooth transition. + It shall be removed at next update map." - "Private - sent to exception handler context only (on:do:). - Reactivate all the handlers into the chain" + ^self! - self tempAt: 3 put: true. "this is temporary handlerActive in #on:do:" - self nextHandlerContext reactivateHandlers! Item was added: + ----- Method: Context>>rearmHandler (in category 'private-exceptions') ----- + rearmHandler + "Private - sent to exception handler context only (on:do:)" + + self reactivateHandler. + stackp >= 4 ifTrue: [self tempAt: 4 put: true] "this is temporary handlerRearmed in #on:do:"! Item was changed: ----- Method: Context>>rearmHandlerDuring: (in category 'private-exceptions') ----- rearmHandlerDuring: aBlock "Sent to handler (on:do:) contexts only. Makes me re-entrant for the duration of aBlock. Only works in a closure-enabled image" + ^ [self rearmHandler. aBlock value] + ensure: [self desarmHandler]! - ^ [self tempAt: 3 put: true. aBlock value] - ensure: [self tempAt: 3 put: false]! Item was added: + ----- Method: Context>>rearmHandlersWhich:upTo: (in category 'private-exceptions') ----- + rearmHandlersWhich: selectBlock upTo: aHandlerContext + "Private - sent to exception handler context only (on:do:). + Rearm the inner handlers into the chain, up to, but not including, aHandlerContext, that satisfy the selectBlock predicate" + + self == aHandlerContext ifTrue: [^self]. + (selectBlock value: self) ifTrue: [self rearmHandler]. + self nextHandlerContext rearmHandlersWhich: selectBlock upTo: aHandlerContext! Item was changed: ----- Method: Context>>resume: (in category 'controlling') ----- resume: value "Unwind thisContext to self and resume with value as result of last send. Execute unwind blocks when unwinding. ASSUMES self is a sender of thisContext" + ^self resumeEvaluating: [value] - | ctxt unwindBlock | - self isDead ifTrue: [self cannotReturn: value to: self]. - ctxt := thisContext. - [ ctxt := ctxt findNextUnwindContextUpTo: self. - ctxt isNil - ] whileFalse: [ - (ctxt tempAt: 2) ifNil:[ - ctxt tempAt: 2 put: true. - unwindBlock := ctxt tempAt: 1. - thisContext terminateTo: ctxt. - unwindBlock value]. - ]. - thisContext terminateTo: self. - ^ value ! Item was added: + ----- Method: Context>>resumeEvaluating: (in category 'controlling') ----- + resumeEvaluating: aBlock + "Unwind thisContext to self and resume with value as result of last send. + Execute unwind blocks when unwinding. + ASSUMES self is a sender of thisContext" + + | ctxt unwindBlock | + self isDead ifTrue: [self cannotReturn: aBlock value to: self]. + ctxt := thisContext. + [ ctxt := ctxt findNextUnwindContextUpTo: self. + ctxt isNil + ] whileFalse: [ + (ctxt tempAt: 2) ifNil:[ + ctxt tempAt: 2 put: true. + unwindBlock := ctxt tempAt: 1. + thisContext terminateTo: ctxt. + unwindBlock value]. + ]. + thisContext terminateTo: self. + ^ aBlock value + ! Item was added: + ----- Method: Context>>returnEvaluating: (in category 'controlling') ----- + returnEvaluating: aBlock + "Unwind thisContext to self and return aBlock value to self's sender. + Execute any unwind blocks while unwinding. + ASSUMES self is a sender of thisContext" + + sender ifNil: [self cannotReturn: aBlock value to: sender]. + sender resumeEvaluating: aBlock! Item was added: + ----- Method: Context>>willHandleSignal: (in category 'private-exceptions') ----- + willHandleSignal: exception + "Sent to handler (on:do:) contexts only." + + ^self isHandlerActive and: [(self tempAt: 1) handles: exception] + ! Item was changed: ----- Method: Exception>>pass (in category 'handling') ----- pass "Yield control to the enclosing exception action for the receiver." + (handlerContext nextHandlerContextForSignal: self) handleSignal: self! - handlerContext nextHandlerContext handleSignal: self! Item was added: + ----- Method: Exception>>privHandlerContext (in category 'priv handling') ----- + privHandlerContext + ^handlerContext! Item was changed: ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- reactivateHandlers + "Private - exception handling + do nothing, this method is only here for smooth transition. + It shall be removed at next update map." + + ^self! - "reactivate all the exception handlers in the context chain" - self canSearchForSignalerContext - ifTrue: [signalContext nextHandlerContext reactivateHandlers]! Item was changed: ----- Method: Exception>>resignalAs: (in category 'handling') ----- resignalAs: replacementException "Signal an alternative exception in place of the receiver." + self resumeEvaluating: [replacementException signal]! - self reactivateHandlers. - self resumeUnchecked: replacementException signal! Item was changed: ----- Method: Exception>>resume: (in category 'handling') ----- resume: resumptionValue "Return resumptionValue as the value of the signal message." self isResumable ifFalse: [IllegalResumeAttempt signal]. - self reactivateHandlers. self resumeUnchecked: resumptionValue! Item was added: + ----- Method: Exception>>resumeEvaluating: (in category 'handling') ----- + resumeEvaluating: aBlock + "Return result of evaluating aBlock as the value of #signal, unless this was called after an #outer message, then return resumptionValue as the value of #outer. + The block is only evaluated after unwinding the stack." + + | ctxt | + outerContext ifNil: [ + signalContext returnEvaluating: aBlock + ] ifNotNil: [ + ctxt := outerContext. + outerContext := ctxt tempAt: 1. "prevOuterContext in #outer" + ctxt returnEvaluating: aBlock + ]. + ! Item was changed: ----- Method: Exception>>signal (in category 'signaling') ----- signal "Ask ContextHandlers in the sender chain to handle this signal. The default is to execute and return my defaultAction." signalContext := thisContext contextTag. + ^(thisContext nextHandlerContextForSignal: self) handleSignal: self! - ^ thisContext nextHandlerContext handleSignal: self! Item was changed: ----- Method: UndefinedObject>>handleSignal: (in category 'bottom context') ----- handleSignal: exception + "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action." - "When no more handler (on:do:) context left in sender chain this gets called. Return from signal with default action. - Before doing that, reactivate the handlers so that they can catch eventual secondary exceptions raised by defaultAction." + ^ exception resumeUnchecked: exception defaultAction! - ^ exception reactivateHandlers; resumeUnchecked: exception defaultAction! Item was removed: - ----- Method: UndefinedObject>>reactivateHandlers (in category 'bottom context') ----- - reactivateHandlers - "nothing to do for bottom context" - - ^ self! Item was added: + ----- Method: UndefinedObject>>rearmHandlersWhich:upTo: (in category 'bottom context') ----- + rearmHandlersWhich: selectBlock upTo: aHandlerContext + + ^ self! From commits at source.squeak.org Thu Apr 29 12:04:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 12:04:46 0000 Subject: [squeak-dev] The Trunk: ToolBuilder-Kernel-nice.145.mcz Message-ID: Nicolas Cellier uploaded a new version of ToolBuilder-Kernel to project The Trunk: http://source.squeak.org/trunk/ToolBuilder-Kernel-nice.145.mcz ==================== Summary ==================== Name: ToolBuilder-Kernel-nice.145 Author: nice Time: 28 April 2021, 9:23:48.35444 pm UUID: f27e3b02-2905-d94b-97f3-93e95bd58880 Ancestors: ToolBuilder-Kernel-nice.141 Fix ProgressInitiationException>>sendNotificationsTo: so that: - the ProgressInitiationException remains inactive during workBlock evaluation - unless explicitely rearmed - active inner handlers remain active during workBlock evaluation For the last goal, it is necessary to first resume, then evaluate the workBlock, hence usage of #resumeEvaluating: This goes with Kernel-nice.1394 which implements this method as well as upgraded signal handling. But if we resume, then we also unwind the stack and evaluate all the ensure: blocks... This will reactivate current handler, and desarm it if we rearmed, in other words, the exact contrary of what was requested! Hence the intricated activate/deactivate dance. If the purpose is to completely suppress Progress bars and progress notifications, then provide an appropriate handling action that will do so: #resumeSuppressingProgress =============== Diff against ToolBuilder-Kernel-nice.141 =============== Item was added: + ----- Method: ProgressInitiationException>>resumeSuppressingProgress (in category 'handling') ----- + resumeSuppressingProgress + "Catch and suppress every ProgressInitiationException and ProgressNotification + during the evaluation of workBlock" + + ^self resumeEvaluating: + [self rearmHandlerDuring: + [[workBlock value: [ :barVal | "do nothing"]] + on: ProgressNotification do: [:e | e resume]]]! Item was changed: + ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'handling') ----- - ----- Method: ProgressInitiationException>>sendNotificationsTo: (in category 'initialize-release') ----- sendNotificationsTo: aNewBlock + "Resume execution using aNewBlock as workBlock value. + Note that the execution is resumed in signalContext (or outerContext). + This is done so that inner exception handlers be active during workBlock execution. + However, our own handlerContext should be deactivated, unless explicitely rearmed." + | mustDeactivateHandler | + mustDeactivateHandler := handlerContext notNil and: [handlerContext isHandlerActive not]. + mustDeactivateHandler + ifTrue: + ["The handlerContext is de-activated during handleSignal: + But it will be reactivated during unwinding when we will resumeEvaluating: + That's unwanted, we don't generally want to rearm the handler during workBlock evaluation. + Hence we have to deactivate it again inside the deferred block." + self resumeEvaluating: + [handlerContext deactivateHandler. + [workBlock value: [ :barVal | + aNewBlock value: minVal value: maxVal value: barVal]] + ensure: [handlerContext reactivateHandler]]] + ifFalse: + ["If the handler is active at this step, then it must have been rearmed + with a #rearmHandlerDuring: + It's thus intentional to keep the handler active during workBlock evaluation + But the ensure: [self desarmHandler] will be evaluated during unwinding when we will resumeEvaluating: + It is thus necessary to rearm again inside the evaluated block" + self resumeEvaluating: + [self rearmHandlerDuring: + [workBlock value: [ :barVal | + aNewBlock value: minVal value: maxVal value: barVal]]]]! - - self reactivateHandlers; resumeUnchecked: ( - workBlock value: [ :barVal | - aNewBlock value: minVal value: maxVal value: barVal - ] - ) - ! From commits at source.squeak.org Thu Apr 29 12:59:19 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 12:59:19 0000 Subject: [squeak-dev] The Inbox: Monticello-ct.744.mcz Message-ID: A new version of Monticello was added to project The Inbox: http://source.squeak.org/inbox/Monticello-ct.744.mcz ==================== Summary ==================== Name: Monticello-ct.744 Author: ct Time: 29 April 2021, 2:59:16.605035 pm UUID: b1e2068c-07c6-624b-8da3-098968e9364c Ancestors: Monticello-mt.743 Fixes invalid category of MCPostscriptDefinition>>#wantsToBeOutermost =============== Diff against Monticello-mt.743 =============== Item was changed: + ----- Method: MCPostscriptDefinition>>wantsToBeOutermost (in category 'testing') ----- - ----- Method: MCPostscriptDefinition>>wantsToBeOutermost (in category 'nil') ----- wantsToBeOutermost ^ true! From commits at source.squeak.org Thu Apr 29 13:16:34 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 13:16:34 0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1760.mcz Message-ID: A new version of Morphic was added to project The Inbox: http://source.squeak.org/inbox/Morphic-ct.1760.mcz ==================== Summary ==================== Name: Morphic-ct.1760 Author: ct Time: 29 April 2021, 3:16:27.408422 pm UUID: e0169b48-fe90-7f45-bcb5-5d4dcfb14aa3 Ancestors: Morphic-mt.1759 Make editors' #spawn feature more robust against missing models. A short scan of all references to the model variable reveals that this was the only method that could not handle nil models correctly. =============== Diff against Morphic-mt.1759 =============== Item was changed: ----- Method: TextEditor>>spawn (in category 'menu messages') ----- spawn "Create and schedule a message browser for the code of the model's selected message. Retain any edits that have not yet been accepted." | code | code := paragraph text string. self cancel. + model + ifNotNil: [model spawn: code] + ifNil: [UIManager default edit: code].! - model spawn: code.! From commits at source.squeak.org Thu Apr 29 13:17:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 13:17:20 0000 Subject: [squeak-dev] The Inbox: ST80-ct.270.mcz Message-ID: A new version of ST80 was added to project The Inbox: http://source.squeak.org/inbox/ST80-ct.270.mcz ==================== Summary ==================== Name: ST80-ct.270 Author: ct Time: 29 April 2021, 3:17:17.120422 pm UUID: 4bc7c665-0739-2c4c-8b46-75e840ae3bfb Ancestors: ST80-ct.269 Complements Morphic-ct.1760. If an MVC editor does not have a model, ask the UIManager to open the text to spawn. =============== Diff against ST80-ct.269 =============== Item was changed: ----- Method: ParagraphEditor>>spawn (in category 'menu messages') ----- spawn "Create and schedule a message browser for the code of the model's selected message. Retain any edits that have not yet been accepted." | code | code := paragraph text string. self cancel. + model + ifNotNil: [model spawn: code] + ifNil: [UIManager default edit: code]. - model notNil ifTrue:[model spawn: code]. ! From christoph.thiede at student.hpi.uni-potsdam.de Thu Apr 29 13:25:46 2021 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Thu, 29 Apr 2021 08:25:46 -0500 (CDT) Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz In-Reply-To: References: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de> Message-ID: <1619702746050-0.post@n4.nabble.com> Hi Nicolas, your removal of #newSource broke the handling of syntax errors in Monticello, see MethodAddition >> #createCompiledMethod. Would you mind restoring them if you cannot find another solution? :-) Best, Christoph ----- Carpe Squeak! -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html From commits at source.squeak.org Thu Apr 29 14:11:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 14:11:26 0000 Subject: [squeak-dev] The Inbox: Tools-ct.1044.mcz Message-ID: A new version of Tools was added to project The Inbox: http://source.squeak.org/inbox/Tools-ct.1044.mcz ==================== Summary ==================== Name: Tools-ct.1044 Author: ct Time: 29 April 2021, 4:11:22.748797 pm UUID: c5dcb710-6784-bf4e-a9e6-52ce7385bf32 Ancestors: Tools-mt.1043 Fixes styling in MessageSets when prettyPrint is turned on. =============== Diff against Tools-mt.1043 =============== Item was changed: ----- Method: MessageSet>>aboutToStyle: (in category 'code pane') ----- aboutToStyle: aPluggableShoutMorphOrView "This is a notification that aPluggableShoutMorphOrView is about to re-style its text. Set the classOrMetaClass in aPluggableShoutMorphOrView, so that identifiers will be resolved correctly. Answer true to allow styling to proceed, or false to veto the styling" | selectedMessageName showingMethod | + self isModeStyleable ifFalse: [^false]. - self showingSource ifFalse: [^false]. selectedMessageName := self selectedMessageName. showingMethod := (#(Comment Definition Hierarchy) includes: selectedMessageName) not. "Hack!! setting classOrMetaClass: to nil allows doit or class definition colouring." aPluggableShoutMorphOrView classOrMetaClass: (showingMethod ifTrue: [self selectedClassOrMetaClass]). ^(#(Comment Hierarchy) includes: selectedMessageName) not! From commits at source.squeak.org Thu Apr 29 14:11:46 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 14:11:46 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1766.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1766.mcz ==================== Summary ==================== Name: Morphic-mt.1766 Author: mt Time: 29 April 2021, 4:11:40.190356 pm UUID: 4cb3ac38-5af3-0045-925d-ea4a97fd68aa Ancestors: Morphic-mt.1765 Fixes a hick-up with the grid layout for morphs that do not #spaceFill the grid cells such as any "Morph new" (Note that I think that #cellPositioning should be part of any LayoutProperties, not just the TableLayoutProperties. So, this fix is more like a temporary workaround.) =============== Diff against Morphic-mt.1765 =============== Item was added: + ----- Method: GridLayoutProperties>>cellPositioning (in category 'accessing') ----- + cellPositioning + + ^ #topLeft! From commits at source.squeak.org Thu Apr 29 14:27:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 14:27:12 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1046.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1046.mcz ==================== Summary ==================== Name: Tools-mt.1046 Author: mt Time: 29 April 2021, 4:27:09.983356 pm UUID: 103a7fea-3c92-f94f-a5f5-0568d1b1d8c2 Ancestors: Tools-mt.1045 Auto-select the first entry when browsing change sets. This is similar to the dependency browser, where we often work with smaller lists. There it is cumbersome to have to make extra clicks just to show the contents of the first entry. =============== Diff against Tools-mt.1045 =============== Item was changed: ----- Method: ChangeSorter>>currentClassName: (in category 'class list') ----- currentClassName: aString currentClassName := aString. - currentSelector := nil. "fix by wod" self changed: #currentClassName. self changed: #messageList. + + self currentSelector: (self messageList ifNotEmpty: [:list | list first]). + ! - self setContents. - self contentsChanged.! Item was changed: ----- Method: ChangeSorter>>showChangeSet: (in category 'access') ----- showChangeSet: chgSet myChangeSet == chgSet ifFalse: [ myChangeSet := chgSet. currentClassName := nil. currentSelector := nil]. self changed: #relabel. self changed: #currentCngSet. "new -- list of sets" self changed: #mainButtonName. "old, button" self changed: #classList. + + self currentClassName: (self classList ifNotEmpty: [:list | list first]).! - self changed: #messageList. - self setContents. - self contentsChanged.! From commits at source.squeak.org Thu Apr 29 14:31:30 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 14:31:30 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1047.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1047.mcz ==================== Summary ==================== Name: Tools-mt.1047 Author: mt Time: 29 April 2021, 4:31:27.714356 pm UUID: 46c05c05-171e-294b-bbcb-1eb3472044b5 Ancestors: Tools-mt.1046 Sorry for the noise. I was mistaken in that I thought that #ifNotEmpty: answers "nil" if the collection is indeed empty. =============== Diff against Tools-mt.1046 =============== Item was changed: ----- Method: ChangeSorter>>currentClassName: (in category 'class list') ----- currentClassName: aString currentClassName := aString. self changed: #currentClassName. self changed: #messageList. + self currentSelector: (self messageList ifEmpty: [nil] ifNotEmpty: [:list | list first]). - self currentSelector: (self messageList ifNotEmpty: [:list | list first]). ! Item was changed: ----- Method: ChangeSorter>>showChangeSet: (in category 'access') ----- showChangeSet: chgSet myChangeSet == chgSet ifFalse: [ myChangeSet := chgSet. currentClassName := nil. currentSelector := nil]. self changed: #relabel. self changed: #currentCngSet. "new -- list of sets" self changed: #mainButtonName. "old, button" self changed: #classList. + self currentClassName: (self classList ifEmpty: [nil] ifNotEmpty: [:list | list first]).! - self currentClassName: (self classList ifNotEmpty: [:list | list first]).! From commits at source.squeak.org Thu Apr 29 16:03:26 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 16:03:26 0000 Subject: [squeak-dev] The Trunk: MorphicExtras-mt.297.mcz Message-ID: Marcel Taeumel uploaded a new version of MorphicExtras to project The Trunk: http://source.squeak.org/trunk/MorphicExtras-mt.297.mcz ==================== Summary ==================== Name: MorphicExtras-mt.297 Author: mt Time: 29 April 2021, 6:03:23.320356 pm UUID: 90db92d6-2b46-7741-a2bd-147dbc644da9 Ancestors: MorphicExtras-mt.296 Avoid using ActiveWorld, ActiveHand, ActiveEvent. =============== Diff against MorphicExtras-mt.296 =============== Item was changed: ----- Method: Workspace class>>extraExampleContents2 (in category '*MorphicExtras-examples') ----- extraExampleContents2 "This is example code for #extraExample2" "Inspect any (sub)expression result by pressing i" (20 to: 40 by: 2) asOrderedCollection addFirst: 16; addLast: 42; sort: [:x | x \\ 3] descending; yourself. "Explore any (sub)expression result by pressing I" Project current world. "Debug any (sub)expression using D" (1 to: 9) join asNumber sqrt truncateTo: 1e-3. + (SystemWindow windowsIn: self currentWorld) - (SystemWindow windowsIn: ActiveWorld) select: [:window | window bounds isWide] thenDo: [:window | window color: window color negated].! From commits at source.squeak.org Thu Apr 29 16:04:25 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 16:04:25 0000 Subject: [squeak-dev] The Trunk: EToys-mt.446.mcz Message-ID: Marcel Taeumel uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-mt.446.mcz ==================== Summary ==================== Name: EToys-mt.446 Author: mt Time: 29 April 2021, 6:04:17.914356 pm UUID: a152d734-d85e-934d-95e1-713756d0e0fe Ancestors: EToys-mt.445 Avoid using ActiveWorld, ActiveHand, ActiveEvent. =============== Diff against EToys-mt.445 =============== Item was changed: ----- Method: ScriptEditorMorph>>offerScriptorMenu (in category 'other') ----- offerScriptorMenu "Put up a menu in response to the user's clicking in the menu-request area of the scriptor's heaer" | aMenu count | self modernize. self currentHand showTemporaryCursor: nil. Preferences eToyFriendly ifTrue: [^ self offerSimplerScriptorMenu]. aMenu := MenuMorph new defaultTarget: self. aMenu addTitle: scriptName asString. aMenu addStayUpItem. "NB: the kids version in #offerSimplerScriptorMenu does not deploy the stay-up item" aMenu addList: (self hasParameter ifTrue: [{ {'remove parameter' translated. #ceaseHavingAParameter}}] ifFalse: [{ {'add parameter' translated. #addParameter}}]). self hasParameter ifFalse: [aMenu addTranslatedList: { {'button to fire this script' translatedNoop. #tearOfButtonToFireScript}. {'fires per tick...' translatedNoop. #chooseFrequency}. #- }]. aMenu addUpdating: #showingCaretsString target: self action: #toggleShowingCarets. aMenu addLine. aMenu addList: { {'edit balloon help for this script' translated. #editMethodDescription}. {'explain status alternatives' translated. #explainStatusAlternatives}. {'button to show/hide this script' translated. #buttonToOpenOrCloseThisScript}. #- }. Preferences universalTiles ifFalse: [ count := self savedTileVersionsCount. self showingMethodPane ifFalse: [ "currently showing tiles" aMenu add: 'show code textually' translated action: #showSourceInScriptor. count > 0 ifTrue: [ aMenu add: 'revert to tile version...' translated action: #revertScriptVersion]. aMenu add: 'save this version' translated action: #saveScriptVersion ] ifTrue: [ "current showing textual source" aMenu add: 'convert to tile version' translated action: #toggleWhetherShowingTiles. count > 0 ifTrue: [aMenu add: 'revert to tile version...' translated action: #revertScriptVersion]] ]. "aMenu addLine. self addGoldBoxItemsTo: aMenu." aMenu addLine. + aMenu add: 'grab this object' translated target: playerScripted selector: #grabPlayerIn: argument: self currentWorld. - aMenu add: 'grab this object' translated target: playerScripted selector: #grabPlayerIn: argument: ActiveWorld. aMenu balloonTextForLastItem: 'This will actually pick up the object bearing this script and hand it to you. Click the (left) button to drop it' translated. + aMenu add: 'reveal this object' translated target: playerScripted selector: #revealPlayerIn: argument: self currentWorld. - aMenu add: 'reveal this object' translated target: playerScripted selector: #revealPlayerIn: argument: ActiveWorld. aMenu balloonTextForLastItem: 'If you have misplaced the object bearing this script, use this item to (try to) make it visible' translated. aMenu add: 'tile representing this object' translated target: playerScripted action: #tearOffTileForSelf. aMenu balloonTextForLastItem: 'choose this to obtain a tile which represents the object associated with this script' translated. aMenu addTranslatedList: { #-. {'open viewer' translatedNoop. #openObjectsViewer. 'open the viewer of the object to which this script belongs' translatedNoop}. {'detached method pane' translatedNoop. #makeIsolatedCodePane. 'open a little window that shows the Smalltalk code underlying this script.' translatedNoop}. #-. {'destroy this script' translatedNoop. #destroyScript} }. aMenu popUpInWorld: self currentWorld.! From commits at source.squeak.org Thu Apr 29 16:14:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 16:14:15 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1048.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1048.mcz ==================== Summary ==================== Name: Tools-mt.1048 Author: mt Time: 29 April 2021, 6:14:12.930356 pm UUID: 14815123-219f-0b41-a441-c56e1392000f Ancestors: Tools-mt.1047 Fixes selection update after removing a whole class from the current change-set. =============== Diff against Tools-mt.1047 =============== Item was changed: ----- Method: ChangeSorter>>forgetClass (in category 'class list') ----- forgetClass "Remove all mention of this class from the changeSet. After forgetting, select at the same point in the class list, which helps if e.g. doing something repetitive such as moving a number of classes to the other side." | index classList | self okToChange ifFalse: [^ self]. currentClassName ifNil: [^self]. index := self classList indexOf: currentClassName. myChangeSet removeClassChanges: (self withoutItemAnnotation: currentClassName). + self changed: #classList. - currentSelector := nil. classList := self classList. + self currentClassName: (classList isEmpty ifFalse: + [classList at: (index min: classList size)]).! - currentClassName := classList isEmpty ifFalse: - [classList at: (index min: classList size)]. - self showChangeSet: myChangeSet! From commits at source.squeak.org Thu Apr 29 17:18:36 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 17:18:36 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1049.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1049.mcz ==================== Summary ==================== Name: Tools-mt.1049 Author: mt Time: 29 April 2021, 7:18:34.478575 pm UUID: 65b976d3-5eaf-9247-8c06-675a97ef6890 Ancestors: Tools-mt.1048 In the ChangeSorter, don't be too harsh on the selection update when removing s selector from the change-set. Try to match the implementation-style of #forgetClass nearby. =============== Diff against Tools-mt.1048 =============== Item was changed: ----- Method: ChangeSorter>>forget (in category 'message list') ----- forget "Drop this method from the changeSet" + | className index messageList | self okToChange ifFalse: [^ self]. + currentSelector ifNil: [^ self]. + className := self currentClassName. + index := self messageList indexOf: currentSelector. + myChangeSet + removeSelectorChanges: self selectedMessageName + class: self selectedClassOrMetaClass. + self changed: #classList. + self changed: #messageList. + (self classList includes: className) + ifFalse: ["Last entry removed" + self currentClassName: nil] + ifTrue: [ + messageList := self messageList. + self currentSelector: (messageList isEmpty ifFalse: + [messageList at: (index min: messageList size)])].! - currentSelector ifNotNil: [ - myChangeSet removeSelectorChanges: self selectedMessageName - class: self selectedClassOrMetaClass. - currentSelector := nil. - self showChangeSet: myChangeSet]! From commits at source.squeak.org Thu Apr 29 17:49:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 17:49:12 0000 Subject: [squeak-dev] The Trunk: Compiler-nice.458.mcz Message-ID: Nicolas Cellier uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-nice.458.mcz ==================== Summary ==================== Name: Compiler-nice.458 Author: nice Time: 29 April 2021, 7:48:52.29844 pm UUID: 354afee1-3aba-4d40-b36c-0000b2e10a93 Ancestors: Compiler-nice.457 Restore newSource which is still used by MethodAddition >> #createCompiledMethod. No need to resume: from within defaultAction. The sender of defaultAction will resume: See UndefinedObject>>handleSignal: =============== Diff against Compiler-nice.457 =============== Item was changed: ----- Method: OutOfScopeNotification>>defaultAction (in category 'as yet unclassified') ----- defaultAction + ^false! - self resume: false! Item was added: + ----- Method: SyntaxErrorNotification>>newSource (in category 'accessing') ----- + newSource + ^newSource! From nicolas.cellier.aka.nice at gmail.com Thu Apr 29 17:49:13 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 29 Apr 2021 19:49:13 +0200 Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz In-Reply-To: <1619702746050-0.post@n4.nabble.com> References: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de> <1619702746050-0.post@n4.nabble.com> Message-ID: Hi Christoph, Done! I missed this usage indeed, case of blindness... Le jeu. 29 avr. 2021 à 15:25, Christoph Thiede a écrit : > > Hi Nicolas, > > your removal of #newSource broke the handling of syntax errors in > Monticello, see MethodAddition >> #createCompiledMethod. Would you mind > restoring them if you cannot find another solution? :-) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > From commits at source.squeak.org Thu Apr 29 17:53:10 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 17:53:10 0000 Subject: [squeak-dev] The Trunk: Monticello-ct.744.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-ct.744.mcz ==================== Summary ==================== Name: Monticello-ct.744 Author: ct Time: 29 April 2021, 2:59:16.605035 pm UUID: b1e2068c-07c6-624b-8da3-098968e9364c Ancestors: Monticello-mt.743 Fixes invalid category of MCPostscriptDefinition>>#wantsToBeOutermost =============== Diff against Monticello-mt.743 =============== Item was changed: + ----- Method: MCPostscriptDefinition>>wantsToBeOutermost (in category 'testing') ----- - ----- Method: MCPostscriptDefinition>>wantsToBeOutermost (in category 'nil') ----- wantsToBeOutermost ^ true! From commits at source.squeak.org Thu Apr 29 18:13:25 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 18:13:25 0000 Subject: [squeak-dev] The Trunk: System-nice.1232.mcz Message-ID: Nicolas Cellier uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-nice.1232.mcz ==================== Summary ==================== Name: System-nice.1232 Author: nice Time: 29 April 2021, 8:13:00.64144 pm UUID: 9bba2398-62e1-bd4f-90ba-5960a05f6ec8 Ancestors: System-mt.1231 No need to resume: from within defaultAction. The sender of defaultAction will resume: See UndefinedObject>>handleSignal: =============== Diff against System-mt.1231 =============== Item was removed: - ----- Method: ProgressTargetRequestNotification>>defaultAction (in category 'handling') ----- - defaultAction - - self resume: nil! Item was changed: ----- Method: ProjectEntryNotification>>defaultAction (in category 'handling') ----- defaultAction + ^projectToEnter enter! - self resume: projectToEnter enter! Item was changed: ----- Method: ProjectPasswordNotification>>defaultAction (in category 'handling') ----- defaultAction + ^''! - self resume: ''! Item was changed: ----- Method: ProjectViewOpenNotification>>defaultAction (in category 'handling') ----- defaultAction + ^true! - self resume: true! From commits at source.squeak.org Thu Apr 29 18:15:10 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 18:15:10 0000 Subject: [squeak-dev] The Trunk: Monticello-nice.745.mcz Message-ID: Nicolas Cellier uploaded a new version of Monticello to project The Trunk: http://source.squeak.org/trunk/Monticello-nice.745.mcz ==================== Summary ==================== Name: Monticello-nice.745 Author: nice Time: 29 April 2021, 8:14:50.06744 pm UUID: b9fd885b-31b0-fe4b-b0da-da4b02c9e580 Ancestors: Monticello-ct.744 No need to resume: from within defaultAction. The sender of defaultAction will resume: See UndefinedObject>>handleSignal: =============== Diff against Monticello-ct.744 =============== Item was changed: ----- Method: MCProxyMaterialization>>defaultAction (in category 'handling') ----- defaultAction + ^proxy materializeInfo! - self resume: proxy materializeInfo! From commits at source.squeak.org Thu Apr 29 18:15:58 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 18:15:58 0000 Subject: [squeak-dev] The Trunk: EToys-nice.447.mcz Message-ID: Nicolas Cellier uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-nice.447.mcz ==================== Summary ==================== Name: EToys-nice.447 Author: nice Time: 29 April 2021, 8:15:33.42044 pm UUID: f9ab3ef1-aa15-5f44-819c-cb04b18577f0 Ancestors: EToys-mt.446 No need to resume: from within defaultAction. The sender of defaultAction will resume: See UndefinedObject>>handleSignal: =============== Diff against EToys-mt.446 =============== Item was changed: ----- Method: RequestAlternateSyntaxSetting>>defaultAction (in category 'as yet unclassified') ----- defaultAction + ^ Preferences printAlternateSyntax! - self resume: Preferences printAlternateSyntax! From commits at source.squeak.org Thu Apr 29 18:19:12 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 18:19:12 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1395.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1395.mcz ==================== Summary ==================== Name: Kernel-nice.1395 Author: nice Time: 29 April 2021, 8:18:50.78844 pm UUID: f62a6682-e4e0-404a-8b5a-f25b60cad832 Ancestors: Kernel-nice.1394 Clean-up scories from previous fix for nested exception handling. No need to resume from within defaultAction. If anySatisfy: does the job, don't you inline it! =============== Diff against Kernel-nice.1394 =============== Item was removed: - ----- Method: Context>>reactivateHandlers (in category 'private-exceptions') ----- - reactivateHandlers - "Private - exception handling - do nothing, this method is only here for smooth transition. - It shall be removed at next update map." - - ^self! Item was removed: - ----- Method: Context>>rearmHandlersWhich:upTo: (in category 'private-exceptions') ----- - rearmHandlersWhich: selectBlock upTo: aHandlerContext - "Private - sent to exception handler context only (on:do:). - Rearm the inner handlers into the chain, up to, but not including, aHandlerContext, that satisfy the selectBlock predicate" - - self == aHandlerContext ifTrue: [^self]. - (selectBlock value: self) ifTrue: [self rearmHandler]. - self nextHandlerContext rearmHandlersWhich: selectBlock upTo: aHandlerContext! Item was removed: - ----- Method: Exception>>reactivateHandlers (in category 'priv handling') ----- - reactivateHandlers - "Private - exception handling - do nothing, this method is only here for smooth transition. - It shall be removed at next update map." - - ^self! Item was changed: ----- Method: ExceptionSet>>handles: (in category 'exceptionSelector') ----- handles: anException "Determine whether an exception handler will accept a signaled exception." + ^exceptions anySatisfy: [:ex | ex handles: anException]! - exceptions do: - [:ex | - (ex handles: anException) - ifTrue: [^true]]. - ^false! Item was changed: ----- Method: InMidstOfFileinNotification>>defaultAction (in category 'handling') ----- defaultAction + ^false! - self resume: false! Item was removed: - ----- Method: UndefinedObject>>rearmHandlersWhich:upTo: (in category 'bottom context') ----- - rearmHandlersWhich: selectBlock upTo: aHandlerContext - - ^ self! From commits at source.squeak.org Thu Apr 29 20:30:23 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 20:30:23 0000 Subject: [squeak-dev] The Trunk: Tests-nice.459.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.459.mcz ==================== Summary ==================== Name: Tests-nice.459 Author: nice Time: 29 April 2021, 10:30:03.551961 pm UUID: 67799656-9640-e447-b665-6f74573e3716 Ancestors: Tests-nice.458 For some reason, ImageSegmentTest>>testContextsShouldBeWritableToaFile interact badly with progress bar, resulting in a context that cannotReturn: Workaround by temporarily suppressing progress. =============== Diff against Tests-nice.458 =============== Item was changed: ----- Method: ImageSegmentTest>>testContextsShouldBeWritableToaFile (in category 'tests') ----- testContextsShouldBeWritableToaFile "This should not throw an exception" + [NativeImageSegment new - NativeImageSegment new copyFromRoots: {thisContext. thisContext copyStack} sizeHint: 100; extract; writeToFile: 'ContextChain'; + yourself] on: ProgressInitiationException do: [:e | e resumeSuppressingProgress] - yourself "TODO: write assertions showing that something meaningful actually happened." "TODO: bring them back in again"! From nicolas.cellier.aka.nice at gmail.com Thu Apr 29 20:53:49 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Thu, 29 Apr 2021 22:53:49 +0200 Subject: [squeak-dev] The Trunk: Tests-nice.459.mcz In-Reply-To: References: Message-ID: Hmm no, this does not solve anything. It happened to work once or twice, but no more... It's impossible to debug, some doesNotUnderstand: occurs that install and set state to #inactive, but debugger interacts and is causing more doesNotUnderstand: Le jeu. 29 avr. 2021 à 22:30, a écrit : > > Nicolas Cellier uploaded a new version of Tests to project The Trunk: > http://source.squeak.org/trunk/Tests-nice.459.mcz > > ==================== Summary ==================== > > Name: Tests-nice.459 > Author: nice > Time: 29 April 2021, 10:30:03.551961 pm > UUID: 67799656-9640-e447-b665-6f74573e3716 > Ancestors: Tests-nice.458 > > For some reason, ImageSegmentTest>>testContextsShouldBeWritableToaFile interact badly with progress bar, resulting in a context that cannotReturn: > Workaround by temporarily suppressing progress. > > =============== Diff against Tests-nice.458 =============== > > Item was changed: > ----- Method: ImageSegmentTest>>testContextsShouldBeWritableToaFile (in category 'tests') ----- > testContextsShouldBeWritableToaFile > "This should not throw an exception" > + [NativeImageSegment new > - NativeImageSegment new > copyFromRoots: {thisContext. thisContext copyStack} sizeHint: 100; > extract; > writeToFile: 'ContextChain'; > + yourself] on: ProgressInitiationException do: [:e | e resumeSuppressingProgress] > - yourself > > "TODO: write assertions showing that something meaningful actually happened." > > "TODO: bring them back in again"! > > From commits at source.squeak.org Thu Apr 29 22:25:22 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 22:25:22 0000 Subject: [squeak-dev] The Inbox: Kernel-jar.1395.mcz Message-ID: A new version of Kernel was added to project The Inbox: http://source.squeak.org/inbox/Kernel-jar.1395.mcz ==================== Summary ==================== Name: Kernel-jar.1395 Author: jar Time: 30 April 2021, 12:25:17.561362 am UUID: 0f589a20-6b8e-a94b-9dbc-9b3f91c84ce8 Ancestors: Kernel-nice.1394 Fix a bug in Exception>>#outer causing a return to an incorrect handler context. Explanation in: http://forum.world.st/A-bug-in-Exception-gt-gt-outer-causing-a-return-to-an-incorrect-handler-context-td5129273.html =============== Diff against Kernel-nice.1394 =============== Item was changed: ----- Method: Exception>>outer (in category 'handling') ----- outer "Evaluate the enclosing exception action and return to here instead of signal if it resumes (see #resumeUnchecked:)." + | prevOuterContext currHandlerContext | - | prevOuterContext | self isResumable ifTrue: [ + currHandlerContext := handlerContext. prevOuterContext := outerContext. outerContext := thisContext contextTag. ]. self pass. ! Item was changed: ----- Method: Exception>>resumeUnchecked: (in category 'handling') ----- resumeUnchecked: resumptionValue "Return resumptionValue as the value of #signal, unless this was called after an #outer message, then return resumptionValue as the value of #outer." | ctxt | outerContext ifNil: [ signalContext return: resumptionValue ] ifNotNil: [ ctxt := outerContext. outerContext := ctxt tempAt: 1. "prevOuterContext in #outer" + handlerContext := ctxt tempAt: 2. "currHandlerContext in #outer" ctxt return: resumptionValue ]. ! From commits at source.squeak.org Thu Apr 29 22:34:09 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 29 Apr 2021 22:34:09 0000 Subject: [squeak-dev] The Inbox: Tests-jar.455.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-jar.455.mcz ==================== Summary ==================== Name: Tests-jar.455 Author: jar Time: 30 April 2021, 12:34:05.935949 am UUID: 689cd0f4-1fe4-4e46-8e75-c94cd3753f91 Ancestors: Tests-jar.454 Supersedes The Inbox: Tests-jar.454 (reversed the previous change and added new tests instead; activated DoubleOuterTest with correct results) Complements The Inbox: Kernel-jar.1395.mcz ( A bug in Exception>>#outer causing a return to an incorrect handler context) =============== Diff against Tests-jar.454 =============== Item was added: + ----- Method: ExceptionTester>>doubleOuterTestResults (in category 'signaledException results') ----- + doubleOuterTestResults + + ^OrderedCollection new + add: self doSomethingString; + add: self doYetAnotherThingString; + add: self doSomethingElseString; + yourself! Item was added: + ----- Method: ExceptionTester>>simpleOuterDefaultReturnTest (in category 'signaledException tests') ----- + simpleOuterDefaultReturnTest + "uses #resume" + + [[self doSomething. + MyTestNotification signal. + "self doSomethingElse" + self doSomethingExceptional] + on: MyTestNotification + do: [:ex | ex outer]. self doSomethingElse] + on: MyTestNotification + do: [:ex | self doYetAnotherThing. ex resume]! Item was added: + ----- Method: ExceptionTester>>simpleOuterDefaultReturnTestResults (in category 'signaledException results') ----- + simpleOuterDefaultReturnTestResults + + ^OrderedCollection new + add: self doSomethingString; + add: self doYetAnotherThingString; + add: self doSomethingElseString; + yourself! Item was added: + ----- Method: ExceptionTester>>simpleOuterReturnTest (in category 'signaledException tests') ----- + simpleOuterReturnTest + "uses #resume" + + [[self doSomething. + MyTestNotification signal. + "self doSomethingElse" + self doSomethingExceptional] + on: MyTestNotification + do: [:ex | ex outer. ex return]. self doSomethingElse] + on: MyTestNotification + do: [:ex | self doYetAnotherThing. ex resume]! Item was added: + ----- Method: ExceptionTester>>simpleOuterReturnTestResults (in category 'signaledException results') ----- + simpleOuterReturnTestResults + + ^OrderedCollection new + add: self doSomethingString; + add: self doYetAnotherThingString; + add: self doSomethingElseString; + yourself! Item was changed: ----- Method: ExceptionTester>>simpleOuterTest (in category 'signaledException tests') ----- simpleOuterTest "uses #resume" [[self doSomething. MyTestNotification signal. "self doSomethingElse" self doSomethingExceptional] on: MyTestNotification + do: [:ex | ex outer. self doSomethingElse]] - do: [:ex | ex outer]. self doSomethingElse] on: MyTestNotification do: [:ex | self doYetAnotherThing. ex resume]! Item was added: + ----- Method: ExceptionTests>>testDoubleOuterTest (in category 'tests - ExceptionTester') ----- + testDoubleOuterTest + self assertSuccess: (ExceptionTester new runTest: #doubleOuterTest ) ! Item was added: + ----- Method: ExceptionTests>>testSimpleOuterReturn (in category 'tests - ExceptionTester') ----- + testSimpleOuterReturn + self assertSuccess: (ExceptionTester new runTest: #simpleOuterReturnTest ) ! From commits at source.squeak.org Fri Apr 30 06:48:27 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 06:48:27 0000 Subject: [squeak-dev] The Inbox: Tests-jar.456.mcz Message-ID: A new version of Tests was added to project The Inbox: http://source.squeak.org/inbox/Tests-jar.456.mcz ==================== Summary ==================== Name: Tests-jar.456 Author: jar Time: 30 April 2021, 8:48:23.469949 am UUID: 4aaf1b2d-d027-3c49-be9f-873b73d4c92a Ancestors: Tests-jar.455 one more test illustrating the whole execution path of a nested resumed outer exception. Complements Tests-jar.455 =============== Diff against Tests-jar.455 =============== Item was added: + ----- Method: ExceptionTests>>testDoubleOuterDoubleResumeTest (in category 'tests - ExceptionTester') ----- + testDoubleOuterDoubleResumeTest + + | path | + path := ''. + [path := path, '1'. + [path := path, '2'. + [1/0] on: ZeroDivide do: [:ex | ex outer. path := path, '5'. ex return]. + path := path, '6' + ] on: ZeroDivide do: [:ex | ex outer. path := path, '4'. ex resume]. + path := path, '7' + ] on: ZeroDivide do: [:ex | path := path, '3'. ex resume]. + self assert: path = '1234567'! From commits at source.squeak.org Fri Apr 30 07:16:47 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 07:16:47 0000 Subject: [squeak-dev] The Trunk: Kernel-mt.1396.mcz Message-ID: Marcel Taeumel uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-mt.1396.mcz ==================== Summary ==================== Name: Kernel-mt.1396 Author: mt Time: 30 April 2021, 9:16:44.415936 am UUID: d1ca8229-01e5-b548-9660-5018841eea20 Ancestors: Kernel-nice.1395 Adds support for composition of tool-builder specs such as through DualChangeSorter. There, we need to share the windowSpec. =============== Diff against Kernel-nice.1395 =============== Item was added: + ----- Method: Model>>buildWindow:with:specs: (in category 'toolbuilder') ----- + buildWindow: windowSpec with: builder specs: specs + + specs do:[:assoc| + | rect action widgetSpec | + rect := assoc key. + action := assoc value. + widgetSpec := action value. + widgetSpec ifNotNil:[ + widgetSpec frame: rect. + windowSpec children add: widgetSpec]]. + ^ windowSpec! Item was changed: ----- Method: Model>>buildWindowWith:specs: (in category 'toolbuilder') ----- buildWindowWith: builder specs: specs + + ^ self + buildWindow: (self buildWindowWith: builder) + with: builder + specs: specs! - | windowSpec | - windowSpec := self buildWindowWith: builder. - specs do:[:assoc| - | rect action widgetSpec | - rect := assoc key. - action := assoc value. - widgetSpec := action value. - widgetSpec ifNotNil:[ - widgetSpec frame: rect. - windowSpec children add: widgetSpec]]. - ^windowSpec! From commits at source.squeak.org Fri Apr 30 07:19:17 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 07:19:17 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1050.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1050.mcz ==================== Summary ==================== Name: Tools-mt.1050 Author: mt Time: 30 April 2021, 9:19:14.010936 am UUID: c1a1da37-9117-f548-b3a3-f910d6ae2c4c Ancestors: Tools-mt.1049 Refactors buildWith: in ChangeSorter to match the implementation in other tools (such as MessageSet and Browser). Complements Kernel-mt.1396 =============== Diff against Tools-mt.1049 =============== Item was added: + ----- Method: ChangeSorter>>buildChangeSetListWith: (in category 'toolbuilder') ----- + buildChangeSetListWith: builder + + | listSpec | + listSpec := builder pluggableListSpec new. + listSpec + model: self; + list: #changeSetList; + getSelected: #currentCngSet; + setSelected: #showChangeSetNamed:; + menu: #changeSetMenu:shifted:; + keyPress: #changeSetListKey:from:; + dragItem: #dragChangeSet:; + autoDeselect: false. + ^ listSpec! Item was added: + ----- Method: ChangeSorter>>buildClassListWith: (in category 'toolbuilder') ----- + buildClassListWith: builder + + | listSpec | + listSpec := builder pluggableListSpec new. + listSpec + model: self; + list: #classList; + getSelected: #currentClassName; + setSelected: #currentClassName:; + menu: #classListMenu:shifted:; + keyPress: #classListKey:from:; + dragItem: #dragClass:. + ^ listSpec! Item was added: + ----- Method: ChangeSorter>>buildCodePaneWith: (in category 'toolbuilder') ----- + buildCodePaneWith: builder + + | textSpec | + textSpec := builder pluggableCodePaneSpec new. + textSpec + model: self; + getText: #contents; + setText: #contents:notifying:; + selection: #contentsSelection; + menu: #codePaneMenu:shifted:. + ^ textSpec! Item was added: + ----- Method: ChangeSorter>>buildMessageListWith: (in category 'toolbuilder') ----- + buildMessageListWith: builder + + | listSpec | + listSpec := builder pluggableListSpec new. + listSpec + model: self; + list: #messageList; + getSelected: #currentSelector; + setSelected: #currentSelector:; + menu: #messageMenu:shifted:; + keyPress: #messageListKey:from:; + dragItem: #dragMessage:. + ^ listSpec! Item was changed: ----- Method: ChangeSorter>>buildWith: (in category 'toolbuilder') ----- buildWith: builder + + ^ builder build: + (self + buildWith: builder + in: (self buildWindowWith: builder) + rect: (0 at 0 extent: 1 at 1))! - " - ToolBuilder open: ChangeSorter. - " - | windowSpec | - windowSpec := builder pluggableWindowSpec new. - windowSpec label: 'Change Sorter'. - windowSpec model: self. - windowSpec children: OrderedCollection new. - windowSpec label: #labelString. - self buildWith: builder in: windowSpec rect: (0 at 0 extent: 1 at 1). - ^builder build: windowSpec! Item was changed: ----- Method: ChangeSorter>>buildWith:in:rect: (in category 'toolbuilder') ----- buildWith: builder in: window rect: rect - | csListHeight msgListHeight csMsgListHeight listSpec textSpec | - contents := ''. - csListHeight := 0.25. - msgListHeight := 0.25. - csMsgListHeight := csListHeight + msgListHeight. + | windowSpec offset factor | + offset := rect origin. + factor := rect extent. + windowSpec := self buildWindow: window with: builder specs: (({ + (0.0 at 0.0 corner: 0.5 at 0.25) -> [self buildChangeSetListWith: builder]. + (0.5 at 0.0 corner: 1.0 at 0.25) -> [self buildClassListWith: builder]. + (0.0 at 0.25 corner: 1.0 at 0.5) -> [self buildMessageListWith: builder]. + (0.0 at 0.5 corner: 1.0 at 1.0) -> [self buildCodePaneWith: builder] }) + collect: [:spec | ((spec key scaleBy: factor) translateBy: offset) -> spec value]). + ^ builder build: windowSpec! - listSpec := builder pluggableListSpec new. - listSpec - model: self; - list: #changeSetList; - getSelected: #currentCngSet; - setSelected: #showChangeSetNamed:; - menu: #changeSetMenu:shifted:; - keyPress: #changeSetListKey:from:; - dragItem: #dragChangeSet:; - autoDeselect: false; - frame: (((0 at 0 extent: 0.5 at csListHeight) - scaleBy: rect extent) translateBy: rect origin). - window children add: listSpec. - - listSpec := builder pluggableListSpec new. - listSpec - model: self; - list: #classList; - getSelected: #currentClassName; - setSelected: #currentClassName:; - menu: #classListMenu:shifted:; - keyPress: #classListKey:from:; - dragItem: #dragClass:; - frame: (((0.5 at 0 extent: 0.5 at csListHeight) - scaleBy: rect extent) translateBy: rect origin). - window children add: listSpec. - - listSpec := builder pluggableListSpec new. - listSpec - model: self; - list: #messageList; - getSelected: #currentSelector; - setSelected: #currentSelector:; - menu: #messageMenu:shifted:; - keyPress: #messageListKey:from:; - dragItem: #dragMessage:; - frame: (((0 at csListHeight extent: 1 at msgListHeight) - scaleBy: rect extent) translateBy: rect origin). - window children add: listSpec. - - textSpec := builder pluggableCodePaneSpec new. - textSpec - model: self; - getText: #contents; - setText: #contents:notifying:; - selection: #contentsSelection; - menu: #codePaneMenu:shifted:; - frame: (((0 at csMsgListHeight corner: 1 at 1) scaleBy: rect extent) translateBy: rect origin). - window children add: textSpec. - ^window! Item was changed: ----- Method: DualChangeSorter>>buildWith: (in category 'toolbuilder') ----- buildWith: builder | windowSpec window | leftCngSorter := ChangeSorter new myChangeSet: ChangeSet current. leftCngSorter parent: self. rightCngSorter := ChangeSorter new myChangeSet: ChangeSet secondaryChangeSet. rightCngSorter parent: self. + windowSpec := self buildWindowWith: builder. - windowSpec := builder pluggableWindowSpec new. - windowSpec model: self. - windowSpec label: 'Change Sorter'. - windowSpec children: OrderedCollection new. - windowSpec label: #labelString. leftCngSorter buildWith: builder in: windowSpec rect: (0 at 0 extent: 0.5 at 1). rightCngSorter buildWith: builder in: windowSpec rect: (0.5 at 0 extent: 0.5 at 1). window := builder build: windowSpec. leftCngSorter addDependent: window. "so it will get changed: #relabel" rightCngSorter addDependent: window. "so it will get changed: #relabel" ^window! From commits at source.squeak.org Fri Apr 30 07:31:34 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 07:31:34 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1051.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1051.mcz ==================== Summary ==================== Name: Tools-mt.1051 Author: mt Time: 30 April 2021, 9:31:31.368936 am UUID: 732ccab4-19fe-3e4d-aebd-ee970b44661b Ancestors: Tools-mt.1050 Removes unnecessary codes duplication. (I am not sure why ChangeSetBrowser exists. It just has a different window menu and some different context menus...) =============== Diff against Tools-mt.1050 =============== Item was removed: - ----- Method: ChangeSorter>>buildCodePaneWith: (in category 'toolbuilder') ----- - buildCodePaneWith: builder - - | textSpec | - textSpec := builder pluggableCodePaneSpec new. - textSpec - model: self; - getText: #contents; - setText: #contents:notifying:; - selection: #contentsSelection; - menu: #codePaneMenu:shifted:. - ^ textSpec! Item was added: + ----- Method: ChangeSorter>>wantsAnnotationPane (in category 'code pane') ----- + wantsAnnotationPane + + ^ false! From commits at source.squeak.org Fri Apr 30 07:43:04 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 07:43:04 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1052.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1052.mcz ==================== Summary ==================== Name: Tools-mt.1052 Author: mt Time: 30 April 2021, 9:42:59.802936 am UUID: 7051fe94-6d06-724b-a1db-f1e369ab228e Ancestors: Tools-mt.1051 After taking a look at Squeak 3.9, I figured out what ChangeSetBrowser is supposed to look like. :-D (You can invoke it from the regular ChangeSorter via CMD+SHIFT+B in the list of change sets. Or the context menu there.) =============== Diff against Tools-mt.1051 =============== Item was added: + ----- Method: ChangeSetBrowser>>buildWith: (in category 'toolbuilder') ----- + buildWith: builder + + | max windowSpec | + max := self wantsOptionalButtons ifTrue:[0.42] ifFalse:[0.5]. + windowSpec := self buildWindowWith: builder specs: { + (0.0 at 0.0 corner: 0.5 at max) -> [self buildClassListWith: builder]. + (0.5 at 0.0 corner: 1.0 at max) -> [self buildMessageListWith: builder]. + (0.0 at max corner: 1.0 at 1.0) -> [self buildCodePaneWith: builder] }. + ^ builder build: windowSpec! From commits at source.squeak.org Fri Apr 30 08:06:27 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 08:06:27 0000 Subject: [squeak-dev] The Trunk: Tools-mt.1053.mcz Message-ID: Marcel Taeumel uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-mt.1053.mcz ==================== Summary ==================== Name: Tools-mt.1053 Author: mt Time: 30 April 2021, 10:06:23.164936 am UUID: 5f61f12c-2895-c046-a679-a626a257a6d7 Ancestors: Tools-mt.1052 Adds our common interface for tools to ChangeSetBrowser. =============== Diff against Tools-mt.1052 =============== Item was added: + ----- Method: ChangeSetBrowser class>>on: (in category 'instance creation') ----- + on: aChangeSet + + ^ self new + myChangeSet: aChangeSet; + yourself! Item was added: + ----- Method: ChangeSetBrowser class>>openOn: (in category 'instance creation') ----- + openOn: aChangeSet + + ^ ToolBuilder open: (self on: aChangeSet)! Item was added: + ----- Method: ChangeSetBrowser class>>openOnCurrent (in category 'instance creation') ----- + openOnCurrent + + ^ self openOn: ChangeSet current! From commits at source.squeak.org Fri Apr 30 08:11:15 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 08:11:15 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.1767.mcz Message-ID: Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.1767.mcz ==================== Summary ==================== Name: Morphic-mt.1767 Author: mt Time: 30 April 2021, 10:11:09.230936 am UUID: ebeb7f55-0ca6-a04c-8b5c-87008f09c697 Ancestors: Morphic-mt.1766 Now that I recently discovered the various ways to browse changes ... make the (rather new) changes menu in the docking bar feel more complete. Note that I have no real clue on the actual uses of browsing single change sets or sets of changed methods. Maybe you can help me with some experience reports so that we might remove one or the other menu item again. =============== Diff against Morphic-mt.1766 =============== Item was added: + ----- Method: TheWorldMainDockingBar>>browseChangeSet (in category 'submenu - changes') ----- + browseChangeSet + + ChangeSetBrowser openOnCurrent.! Item was added: + ----- Method: TheWorldMainDockingBar>>browseChangedMethods (in category 'submenu - changes') ----- + browseChangedMethods + + ChangedMessageSet openFor: ChangeSet current.! Item was added: + ----- Method: TheWorldMainDockingBar>>browseChangesDual (in category 'submenu - changes') ----- + browseChangesDual + + DualChangeSorter open.! Item was changed: ----- Method: TheWorldMainDockingBar>>listChangesOn: (in category 'submenu - changes') ----- listChangesOn: menu | latestMethodChanges latestClassChanges| latestMethodChanges := (Array streamContents: [:s | ChangeSet current changedMethodsDo: [:method :changeType :dateAndTime :category | s nextPut: { dateAndTime. method. changeType. category }]]) sorted: [:a :b | a first >= b first]. 1 to: (10 min: latestMethodChanges size) do: [:index | | spec method | spec := latestMethodChanges at: index. method := spec second. menu addItem: [:item | item contents: ('{1} {2} \{{3}\} \{{4}\}' format: {method methodClass. method selector. spec fourth. method methodClass category}) ; target: ToolSet; balloonText: spec third asString; icon: ((#(remove addedThenRemoved) includes: spec third) ifTrue: [MenuIcons smallDeleteIcon] ifFalse: [ spec third = #add ifTrue: [MenuIcons smallNewIcon] ifFalse: [MenuIcons blankIcon]]); selector: (method isInstalled ifTrue: [#browseMethod:] ifFalse: [#browseMethodVersion:]); arguments: {method}]]. latestClassChanges := (Array streamContents: [:s | ChangeSet current changedClassesDo: [:class :changeTypes :dateAndTime :category | "We are not interested in classes whose method's did only change." changeTypes ifNotEmpty: [s nextPut: { dateAndTime. class. changeTypes. category }]]]) sorted: [:a :b | a first >= b first]. latestClassChanges ifNotEmpty: [menu addLine]. 1 to: (10 min: latestClassChanges size) do: [:index | | spec class | spec := latestClassChanges at: index. class := spec second. menu addItem: [:item | item contents: ('{1} \{{2}\}' format: {class name. spec fourth }) ; target: ToolSet; balloonText: (spec third sorted joinSeparatedBy: Character space); icon: ((spec third includesAnyOf: #(remove addedThenRemoved)) ifTrue: [MenuIcons smallDeleteIcon] ifFalse: [ (spec third includes: #add) ifTrue: [MenuIcons smallNewIcon] ifFalse: [MenuIcons blankIcon]]); selector: ((spec third includes: #remove) ifTrue: [#inspect:] ifFalse: [#browseClass:]); arguments: {class}]]. + + menu defaultTarget: self. + menu addTranslatedList: #( + - + ('Browse current change set' browseChangeSet) + ('Browse changed methods' browseChangedMethods) + - + ('Simple Change Sorter' browseChanges) + ('Dual Change Sorter' browseChangesDual)). + + + ! - - menu addLine; addItem: [:item | - item - contents: 'Browse current change set...' translated; - target: self; - selector: #browseChanges].! Item was changed: + (PackageInfo named: 'Morphic') postscript: 'TheWorldMainDockingBar updateInstances..'! - (PackageInfo named: 'Morphic') postscript: 'TheWorldMainDockingBar updateInstances.'! From marcel.taeumel at hpi.de Fri Apr 30 08:19:51 2021 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 30 Apr 2021 10:19:51 +0200 Subject: [squeak-dev] Browser flash (was Re: The Trunk: Tools-mt.1029.mcz) In-Reply-To: <814A4BBC-8CAF-45BC-80D9-A6B97C85A5D6@rowledge.org> References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> <12B8A259-39EC-453F-9CA2-D0F1E1BEB990@rowledge.org> <814A4BBC-8CAF-45BC-80D9-A6B97C85A5D6@rowledge.org> Message-ID: Hmm... it is unusual that a normal click can also select a range. Usually, one would expect to use SHIFT+CLICK to do so, which you can actually do too. :-D I suppose that behavior originates from that older multi-selection list, where a simple click changes the selection state of a single element.... which is also quite unusual given today's widgets in other GUI frameworks. Here is what I would expect from a multi-selection list: - simple click clears and sets the entire selection to a single element - shift+click adds a range to the selection starting from the current element to the clicked one - ctrl+click toggles the selection state of a single element - click-drag drags whatever is currently selected Best, Marcel Am 28.04.2021 23:47:24 schrieb tim Rowledge : > On 2021-04-28, at 12:18 PM, Chris Muller wrote: > > Hi Tim, > >> - all the other browsers ought to support the drag stuff too. I see some do, but the messagetrace doesn't appear to. > > "The drag stuff" tells me you don't have a firm grip on the purpose > and scope of the use-cases. MessageTrace uses swipe to select > multiple methods. It's rightly confined to what you trace, DnD > outside its browser doesn't make sense for tracing. I mildly disagree. Dragging *out* would make sense in various ways. To open another browser, for example. To drop into a text view (where I'd quite like to get the method's reference pasted, perhaps with shift held the method source. Right now we get a not very useful 'compiledMethodBunchOfDigits') or a FileBrowser. > >> - drag a method into a MessageTrace browser and thus add implementors of that message to the stack. > > That would result in multiple, unrelated Trace's all in the one > window. I don't understand why you'd want to do that. I can imagine having a use for a message trace open on several related methods that do not specifically tie together. Maybe #at: & #at:put: would be an example. This would be using a message tracer as a way of gathering methods together as part of thinking about refactorings or extensions. > >> - Nothing to do with d&d, but how about a very simple way to add notes to methods in a browser? I'm thinking here of using a messagetrace browser and wanting to add little (pop-up?) notes to remind me of any points I notice as I follow the messages up and down. Why was I looking at this? What is it related to? All that stuff it is so easy to forget a week later when you start climbing back up the rabbit hole you fell into. > > Why not simply send Object>>#todo, and include a comment next to it? > No little pop-ups please! I don't want to *edit* the code for this, I want to *annotate* it in the context of the tool I am using. One might make a plausible argument that this is not a message tracer anymore; whatever. I suggest that it would be a useful tool. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim "Bother" said Pooh, as he realised Piglet was undercooked. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Fri Apr 30 09:37:51 2021 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Fri, 30 Apr 2021 11:37:51 +0200 Subject: [squeak-dev] Browser flash (was Re: The Trunk: Tools-mt.1029.mcz) In-Reply-To: References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> <12B8A259-39EC-453F-9CA2-D0F1E1BEB990@rowledge.org> <814A4BBC-8CAF-45BC-80D9-A6B97C85A5D6@rowledge.org> Message-ID: Outside of Squeak that would be my expectations as well. Ctrl click may open the halo instead... I can also understand that Chris would be sad to see range selection without the need for touching the keyboard go away. I often use that in the TestRunner to select some but not all test case classes of a package. Marcel Taeumel schrieb am Fr., 30. Apr. 2021, 10:20: > Hmm... it is unusual that a normal click can also select a range. Usually, > one would expect to use SHIFT+CLICK to do so, which you can actually do > too. :-D I suppose that behavior originates from that older multi-selection > list, where a simple click changes the selection state of a single > element.... which is also quite unusual given today's widgets in other GUI > frameworks. > > Here is what I would expect from a multi-selection list: > - simple click clears and sets the entire selection to a single element > - shift+click adds a range to the selection starting from the current > element to the clicked one > - ctrl+click toggles the selection state of a single element > - click-drag drags whatever is currently selected > > Best, > Marcel > > Am 28.04.2021 23:47:24 schrieb tim Rowledge : > > > > On 2021-04-28, at 12:18 PM, Chris Muller wrote: > > > > Hi Tim, > > > >> - all the other browsers ought to support the drag stuff too. I see > some do, but the messagetrace doesn't appear to. > > > > "The drag stuff" tells me you don't have a firm grip on the purpose > > and scope of the use-cases. MessageTrace uses swipe to select > > multiple methods. It's rightly confined to what you trace, DnD > > outside its browser doesn't make sense for tracing. > > I mildly disagree. Dragging *out* would make sense in various ways. To > open another browser, for example. To drop into a text view (where I'd > quite like to get the method's reference pasted, perhaps with shift held > the method source. Right now we get a not very useful > 'compiledMethodBunchOfDigits') or a FileBrowser. > > > > >> - drag a method into a MessageTrace browser and thus add implementors > of that message to the stack. > > > > That would result in multiple, unrelated Trace's all in the one > > window. I don't understand why you'd want to do that. > > I can imagine having a use for a message trace open on several related > methods that do not specifically tie together. Maybe #at: & #at:put: would > be an example. This would be using a message tracer as a way of gathering > methods together as part of thinking about refactorings or extensions. > > > > >> - Nothing to do with d&d, but how about a very simple way to add notes > to methods in a browser? I'm thinking here of using a messagetrace browser > and wanting to add little (pop-up?) notes to remind me of any points I > notice as I follow the messages up and down. Why was I looking at this? > What is it related to? All that stuff it is so easy to forget a week later > when you start climbing back up the rabbit hole you fell into. > > > > Why not simply send Object>>#todo, and include a comment next to it? > > No little pop-ups please! > > I don't want to *edit* the code for this, I want to *annotate* it in the > context of the tool I am using. > > One might make a plausible argument that this is not a message tracer > anymore; whatever. I suggest that it would be a useful tool. > > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > "Bother" said Pooh, as he realised Piglet was undercooked. > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Fri Apr 30 14:02:18 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 14:02:18 0000 Subject: [squeak-dev] FFI: FFI-Kernel-mt.121.mcz Message-ID: Marcel Taeumel uploaded a new version of FFI-Kernel to project FFI: http://source.squeak.org/FFI/FFI-Kernel-mt.121.mcz ==================== Summary ==================== Name: FFI-Kernel-mt.121 Author: mt Time: 30 April 2021, 4:02:17.500442 pm UUID: d2b4689e-ac74-5843-9526-b4e752914eb5 Ancestors: FFI-Kernel-mt.120 Fixes off-by-one regression. =============== Diff against FFI-Kernel-mt.120 =============== Item was changed: ----- Method: ExternalData>>from:to: (in category 'accessing') ----- from: firstIndex to: lastIndex "Only copy data if already in object memory, that is, as byte array. Only check size if configured." | byteOffset numElements byteSize newType | ((1 > firstIndex) or: [size notNil and: [lastIndex > size]]) ifTrue: [^ self errorSubscriptBounds: lastIndex]. byteOffset := ((firstIndex-1) * self contentType byteSize)+1. numElements := lastIndex - firstIndex + 1. byteSize := numElements * self contentType byteSize. "For portions of a null-terminated C string, change the type from char* to byte* to avoid confusion." newType := self containerType = ExternalType string ifTrue: [ExternalType byte asPointerType] ifFalse: [self containerType "No change"]. ^ lastIndex < firstIndex ifTrue: [ handle isExternalAddress ifTrue: [(ExternalData fromHandle: handle + (byteOffset - 1) "Keep pointer." type: newType) size: 0; yourself] ifFalse: [(ExternalData fromHandle: #[] "Empty memory" type: newType) size: 0; yourself]] ifFalse: [ handle isExternalAddress ifTrue: [(ExternalData fromHandle: handle + (byteOffset - 1) type: newType) size: numElements; yourself] ifFalse: [(ExternalData + fromHandle: (handle copyFrom: byteOffset to: byteOffset+byteSize-1) - fromHandle: (handle copyFrom: byteOffset to: byteOffset+byteSize) type: newType) size: numElements; yourself]]! From commits at source.squeak.org Fri Apr 30 14:06:13 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 14:06:13 0000 Subject: [squeak-dev] FFI: FFI-Callbacks-mt.4.mcz Message-ID: Marcel Taeumel uploaded a new version of FFI-Callbacks to project FFI: http://source.squeak.org/FFI/FFI-Callbacks-mt.4.mcz ==================== Summary ==================== Name: FFI-Callbacks-mt.4 Author: mt Time: 30 April 2021, 4:06:12.828442 pm UUID: 549fb596-a536-c944-a48c-646844ddd6ac Ancestors: FFI-Callbacks-mt.3 Continues work on callback evaluation: - Lets ABI be a symbol, not a string. - Adds pool for callback constants. - Adds stub for ARM64 ABI - Adds more docs in #primTrunkEntryAddress - Minor change in callback setup - Clarify argument types and result types - Adds stubs for word64 and struct results - Adds #endianness message to platform description =============== Diff against FFI-Callbacks-mt.3 =============== Item was changed: ExternalObject subclass: #FFICallback + instanceVariableNames: 'abi type evaluableObject thunk argumentTypes resultType' - instanceVariableNames: 'abi type evaluableObject thunk argTypes' classVariableNames: 'ThunkToCallbackMap' poolDictionaries: '' category: 'FFI-Callbacks'! Item was removed: - ----- Method: FFICallback class>>maxThunkSize (in category 'constants') ----- - maxThunkSize - "see FFICallbackThunk initialize & initializeStdcall:; must be big enough for the largest thunk created" - ^ 40! Item was changed: ----- Method: FFICallback>>evaluateDynamic: (in category 'callback - evaluators') ----- evaluateDynamic: callbackContext "Read all arguments and make the call(back). Assume that 'handle' and 'type' are set correctly. Only watch out for the sign. See field definition in FFICallbackContext to explore alternative ways to read the arguments." | offset args | offset := 1. + args := Array new: argumentTypes size. - args := Array new: argTypes size - 1. "Skip return type" 1 to: args size do: [:argIndex | | argType data | + argType := argumentTypes at: argIndex. - argType := argTypes at: argIndex + 1. "Skip return type" argType isPointerType ifTrue: [ data := (type handle: handle at: offset). argType referentClass "pointer to atomic" ifNil: [data := data asType: argType] ifNotNil: [:structClass | "pointer to external structure or union" argType isTypeAliasToPointer ifTrue: [data := structClass fromHandle: data getHandle asByteArrayPointer] ifFalse: [data := structClass fromHandle: data getHandle]] ] ifFalse: [ "non-pointer type" self flag: #floats. "mt: When should we switch to callbackContext floatRegArgs?" data := argType handle: handle at: offset. argType isAtomic ifFalse: ["structure type, most likely type alias to pointer" data := argType referentClass fromHandle: (ExternalAddress fromInteger: data) asByteArrayPointer] ifTrue: [ argType isTypeAlias ifTrue: [ "alias to atomic type" data := argType referentClass fromHandle: data] ifFalse: [ "atomic, non-pointer type" data := data ";-)"]] ]. args at: argIndex put: data. offset := offset + ((type byteSize max: argType byteSize) roundUpTo: type byteSize)]. ^ self setResult: (evaluableObject valueWithArguments: args) inContext: callbackContext.! Item was changed: ----- Method: FFICallback>>evaluateDynamic_ARM32: (in category 'callback - evaluators') ----- evaluateDynamic_ARM32: callbackContext "Set handle to access arguments as most appropriate for the ABI. For ''RISCs'' it is the pointer to the integer register." + - self setArgData: callbackContext intRegArgs. ^ self evaluateDynamic: callbackContext! Item was changed: ----- Method: FFICallback>>evaluateDynamic_IA32: (in category 'callback - evaluators') ----- evaluateDynamic_IA32: callbackContext "Set handle to access arguments as most appropriate for the ABI. For x86 (i.e. IA32) it is the stack pointer." + - + | stackPtr offset args | + stackPtr := callbackContext stackPtr. "For IA32, all arguments are on the stack." + + handle := stackPtr getHandle. + type := stackPtr contentType. "intptr_t" + + offset := 1. + args := Array new: argumentTypes size. + + 1 to: args size do: [:argIndex | + | argType data | + argType := argumentTypes at: argIndex. + data := argType handle: handle at: offset. + args at: argIndex put: data. + + "Move the offset. Consider the byte-alignment?" + offset := offset + ((type byteSize max: argType byteSize) roundUpTo: type byteSize)]. + + ^ self + setResult: (evaluableObject valueWithArguments: args) + inContext: callbackContext! - self setArgData: callbackContext stackPtr. - ^ self evaluateDynamic: callbackContext! Item was changed: ----- Method: FFICallback>>evaluateDynamic_X64: (in category 'callback - evaluators') ----- evaluateDynamic_X64: callbackContext "Set handle to access arguments as most appropriate for the ABI. For ''RISCs'' it is the pointer to the integer register." + - self setArgData: callbackContext intRegArgs. ^ self evaluateDynamic: callbackContext! Item was changed: ----- Method: FFICallback>>evaluateDynamic_X64Win64: (in category 'callback - evaluators') ----- evaluateDynamic_X64Win64: callbackContext "Set handle to access arguments as most appropriate for the ABI. For ''RISCs'' it is the pointer to the integer register." + - self setArgData: callbackContext intRegArgs. ^ self evaluateDynamic: callbackContext! Item was changed: ----- Method: FFICallback>>init__ccall_ARM32 (in category 'initialization - thunk prepare') ----- init__ccall_ARM32 + - "Initialize the receiver with a __ccall thunk. The thunk calls thunkEntry in the IA32ABI plugin, whose source is in platforms/Cross/plugins/IA32ABI/arm32abicc.c. thunkEntry is the entry point for Callbacks. The objective of the thunk is to call thunkEntry with all arguments to the call of the thunk (registers and stack) as well as a pointer to the thunk itself. thunkEntry is as follows: long long thunkEntry(long r0, long r1, long r2, long r3, double d0, double d1, double d2, double d3, double d4, double d5, double d6, double d7, void *thunkpPlus16, sqIntptr_t *stackp) thunkEntry then collects the various arguments (thunk, integer register arguments, floating-point register arguments, stack pointer) in a VMCallbackContext and invokes the callback via invokeCallbackContext:." "0x0 : mov r12, sp ; 0xe1a0c00d 0x4 : sub sp, sp, #16 ; 0xe24dd010 0x8 : str pc, [sp, #0] ; 0xe58df000 N.B. passes thunk+16; thunkEntry compensates 0xc : str r12, [sp,#4] ; 0xe58dc004 0x10 : str lr, [sp, #12] ; 0xe58de00c 0x14 : ldr r12, [pc, #8] ; 0xe59fc008 0x18 : blx r12 ; 0xe12fff3c 0x1c : add sp, sp, #12 ; 0xe28dd00c 0x20 : ldr pc, [sp], #4!! ; 0xe49df004 ; pop {pc} 0x24 : .word thunkEntry" self flag: #hidden. "mt: How is the thunk's handle stored to lookup this instance upon callback later?" thunk getHandle unsignedLongAt: 1 put: 16re1a0c00d; unsignedLongAt: 5 put: 16re24dd010; unsignedLongAt: 9 put: 16re58df000; unsignedLongAt: 13 put: 16re58dc004; unsignedLongAt: 17 put: 16re58de00c; unsignedLongAt: 21 put: 16re59fc008; unsignedLongAt: 25 put: 16re12fff3c; unsignedLongAt: 29 put: 16re28dd00c; unsignedLongAt: 33 put: 16re49df004; shortPointerAt: 37 put: self thunkEntryAddress.! Item was added: + ----- Method: FFICallback>>init__ccall_ARM64 (in category 'initialization - thunk prepare') ----- + init__ccall_ARM64 + + "Initialize the receiver with a __ccall thunk. The thunk calls thunkEntry in the Alien/IA32ABI plugin, + whose source is in platforms/Cross/plugins/IA32ABI/arm64abicc.c. thunkEntry is the entry point + for Callbacks. The objective of the thunk is to call thunkEntry with all arguments to the call of the + thunk (registers and stack) as well as a pointer to the thunk itself. thunkEntry is as follows: + + long long + thunkEntry(long x0, long x1, long x2, long x3, + long x4, long x5, long x6, long x7, + double d0, double d1, double d2, double d3, + double d4, double d5, double d6, double d7, + void *thunkpPlus16, sqIntptr_t *stackp) + + thunkEntry then collects the various arguments (thunk, integer register arguments, floating-point + register arguments, stack pointer) in a VMCallbackContext and invokes the callback via invokeCallbackContext:." + + self shouldBeImplemented + + "self newCCall"! Item was changed: ----- Method: FFICallback>>init__ccall_IA32 (in category 'initialization - thunk prepare') ----- init__ccall_IA32 + - "Initialize the receiver with a __ccall thunk. The thunk calls thunkEntry in the IA32ABI plugin, whose source is in platforms/Cross/plugins/IA32ABI/x64win64abicc.c. thunkEntry is the entry point for Callbacks. The objective of the thunk is to call thunkEntry with all arguments to the call of the thunk (registers and stack) as well as a pointer to the thunk itself. thunkEntry is as follows: long thunkEntry(void *thunkp, sqIntptr_t *stackp) thunkEntry then collects the various arguments (thunk, stack pointer) in a VMCallbackContext and invokes the callback via invokeCallbackContext:." "thunk: push %esp 0x54 0xa1905454 thunk+01: push %esp 0x54 thunk+02: nop 0x90 thunk+03: mov $thunkEntry,%eax 0xb8 0x00 0x00 0x00 0x00 0x00000000 - entry thunk+08: nop 0x90 0x68909090 thunk+09: nop 0x90 thunk+10: nop 0x90 thunk+11: push $thunk 0x68 0x00 0x00 0x00 0x00 0x00000000 - thunk thunk+16: call *%eax 0xff 0xd0 0xc483d0ff thunk+18: add $0xC,%esp 0x83 0xc4 0x0C 0x9090c30C thunk+21: ret 0xc3 thunk+22: nop 0x90 thunk+23: nop 0x90" thunk getHandle unsignedLongAt: 1 put: 16rB8905454; shortPointerAt: 5 put: self thunkEntryAddress; unsignedLongAt: 9 put: 16r68909090; shortPointerAt: 13 put: thunk getHandle; unsignedLongAt: 17 put: 16rC483D0FF; unsignedLongAt: 21 put: 16r9090C30C! Item was changed: ----- Method: FFICallback>>init__ccall_X64 (in category 'initialization - thunk prepare') ----- init__ccall_X64 + - "Initialize the receiver with a __ccall thunk. The thunk calls thunkEntry in the IA32ABI plugin, whose source is in platforms/Cross/plugins/IA32ABI/x64sysvabicc.c. thunkEntry is the entry point for Callbacks. The objective of the thunk is to call thunkEntry with all arguments to the call of the thunk (registers and stack) as well as a pointer to the thunk itself. thunkEntry is as follows: long thunkEntry(long a0, long a1, long a2, long a3, long a4, long a5, double d0, double d1, double d2, double d3, double d4, double d5, double d6, double d7, void *thunkp, sqIntptr_t *stackp) thunkEntry then collects the various arguments (thunk, integer register arguments, floating-point register arguments, stack pointer) in a VMCallbackContext and invokes the callback via invokeCallbackContext:." "thunk+0x0: pushq %rsp 54 thunk+0x1: pushq %rsp 54 thunk+0x4: movabsq $thunk, %rax 48 b8 b0..b7 eight bytes of thunk address a.k.a. handle thunk+0xc: pushq %rax 50 thunk+0xd: movabsq $thunkEntry, %rax 48 b8 b0..b7 eight bytes of the thunkEntry address thunk+0x17: callq *%rax ff d0 thunk+0x19: addq $0x18, %rsp 48 83 c4 18 thunk+0x1d: retq c3 thunk+0x1e: nop 90 thunk+0x1f: nop 90" thunk getHandle unsignedLongAt: 1 put: 16rb8485454; longPointerAt: 5 put: thunk getHandle; unsignedLongAt: 13 put: 16r00b84850; "00 is the first byte of the 64-bit constant the movabsq/0x48 opcode moves" longPointerAt: 16 put: self thunkEntryAddress; unsignedByteAt: 24 put: 16rff; unsignedLongAt: 25 put: 16rc48348d0; unsignedLongAt: 29 put: 16r9090c318.! Item was changed: ----- Method: FFICallback>>init__ccall_X64Win64 (in category 'initialization - thunk prepare') ----- init__ccall_X64Win64 + - "Initialize the receiver with a __ccall thunk. The thunk calls thunkEntry in the IA32ABI plugin, whose source is in platforms/Cross/plugins/IA32ABI/x64win64abicc.c. thunkEntry is the entry point for Callbacks. The objective of the thunk is to call thunkEntry with all arguments to the call of the thunk (registers and stack) as well as a pointer to the thunk itself. thunkEntry is as follows: long long thunkEntry(long long rcx, long long rdx, long long r8, long long r9, void *thunkp, sqIntptr_t *stackp) thunkEntry then collects the various arguments (thunk, integer register arguments, stack pointer) in a VMCallbackContext and invokes the callback via invokeCallbackContext:." "thunk+0x0: pushq %rsp 54 thunk+0x1: pushq %rsp 54 thunk+0x4: movabsq $thunk, %rax 48 b8 b0..b7 eight bytes of thunk address a.k.a. addressField thunk+0xc: pushq %rax 50 thunk+0xd: subq $0x20, %rsp 48 83 c4 e0 (this is addq -20 since the immediate is signed extended) thunk+0x11: movabsq $thunkEntry, %rax 48 b8 b0..b7 eight bytes of the thunkEntry address thunk+0x1b: callq *%rax ff d0 thunk+0x1d: addq $0x38, %rsp 48 83 c4 38 thunk+0x21: retq c3 thunk+0x22: nop 90 thunk+0x23: nop 90" thunk getHandle unsignedLongAt: 1 put: 16rb8485454; longPointerAt: 5 put: thunk getHandle; unsignedLongAt: 13 put: 16rc4834850; unsignedLongAt: 17 put: 16r00b848e0; "00 is the first byte of the 64-bit constant the movabsq/0x48 opcode moves" longPointerAt: 20 put: self thunkEntryAddress; unsignedByteAt: 28 put: 16rff; unsignedLongAt: 29 put: 16rc48348d0; unsignedLongAt: 33 put: 16r9090c338.! Item was changed: ----- Method: FFICallback>>init__stdcall_IA32: (in category 'initialization - thunk prepare') ----- init__stdcall_IA32: numBytes + - "Initialize the receiver with a __stdcall thunk with numBytes argument bytes. (See #init__ccall_IA32 for more info)" "thunk: push %esp 0x54 0xa1905454 thunk+01: push %esp 0x54 thunk+02: nop 0x90 thunk+03: mov $thunkEntry,%eax 0xb8 0x00 0x00 0x00 0x00 0x00000000 - entry thunk+08: nop 0x90 0x68909090 thunk+09: nop 0x90 thunk+10: nop 0x90 thunk+11: push $thunk 0x68 0x00 0x00 0x00 0x00 0x00000000 - thunk thunk+16: call *%eax 0xff 0xd0 0xc483d0ff thunk+18: add $0xC,%esp 0x83 0xc4 0x0C 0xBYTSc20C thunk+21: ret $bytes 0xc2 0xBY 0xTS" thunk getHandle unsignedLongAt: 1 put: 16rB8905454; shortPointerAt: 5 put: self thunkEntryAddress; unsignedLongAt: 9 put: 16r68909090; shortPointerAt: 13 put: thunk getHandle; unsignedLongAt: 17 put: 16rC483D0FF; unsignedShortAt: 21 put: 16rC20C; unsignedShortAt: 23 put: numBytes.! Item was changed: ----- Method: FFICallback>>primThunkEntryAddress (in category 'initialization - thunk prepare') ----- primThunkEntryAddress "^" "Answer the address of the entry-point for thunk callbacks: + IA32: long + thunkEntry(void *thunkp, long *stackp); + X64: long + thunkEntry(long a0, long a1, long a2, long a3, long a4, long a5, + double d0, double d1, double d2, double d3, + double d4, double d5, double d6, double d7, + void *thunkp, sqIntptr_t *stackp); + X64Win64 long long + thunkEntry(long long rcx, long long rdx, + long long r8, long long r9, + void *thunkp, sqIntptr_t *stackp); + ARM32: long long + thunkEntry(long r0, long r1, long r2, long r3, + double d0, double d1, double d2, double d3, + double d4, double d5, double d6, double d7, + void *thunkpPlus16, sqIntptr_t *stackp); + ARM64: long long + thunkEntry(long x0, long x1, long x2, long x3, + long x4, long x5, long x6, long x7, + double d0, double d1, double d2, double d3, + double d4, double d5, double d6, double d7, + void *thunkpPlus16, sqIntptr_t *stackp); - x86: long thunkEntry(void *thunkp, long *stackp); - x64: long thunkEntry(long a, long b, long c, long d, long, e, long f, - double d0, double d1, double d2, double d3, - double d4, double d5, double d6, double d7, - void *thunkp, long *stackp); - ARM: long thunkEntry(long a, long b, long c, long d, - double d0, double d1, double d2, double d3, - double d4, double d5, double d6, double d7, - void *thunkp, long *stackp); etc. This is the function a callback thunk/trampoline should call to initiate a callback." ^self primitiveFailed! Item was removed: - ----- Method: FFICallback>>setArgTypes:evaluableObject: (in category 'initialization') ----- - setArgTypes: externalTypes evaluableObject: blockOrMessage - - - abi := FFIPlatformDescription current abi. - handle := nil. - type := nil. - - evaluableObject := blockOrMessage. - argTypes := externalTypes. - - - - - - "Support for callee pop callbacks (Pascal calling convention such as the Win32 stdcall: convention) are supported using the pragma which specifies how many bytes to pop. See http://forum.world.st/Pharo-FFI-on-aarch64-arm64-td5096777.html#a5096786." - thunk := FFICallbackMemory allocateExecutableBlock. - self init__ccall. - "self init__stdcall: 0." - "(method pragmaAt: #calleepops:) - ifNil: [self init__ccall] - ifNotNil: [:pragma | self init__stdcall: (pragma argumentAt: 1)]." - - "numEvaluatorArgs := (evaluator := method selector) numArgs. - self addToThunkTable" - ThunkToCallbackMap at: thunk getHandle put: self! Item was changed: ----- Method: FFICallback>>setBlock:signature: (in category 'initialization') ----- setBlock: aBlock "" signature: signature "" self + setTypes: (ExternalType lookupTypes: signature) - setArgTypes: (ExternalType lookupTypes: signature) evaluableObject: aBlock.! Item was changed: ----- Method: FFICallback>>setMessage: (in category 'initialization') ----- setMessage: aMessageSend "Fetch the argTypes from pragma in method." | method | self assert: [aMessageSend receiver notNil]. method := aMessageSend receiver class lookupSelector: aMessageSend selector. self + setTypes: ((method pragmaAt: #callback:) argumentAt: 1) - setArgTypes: ((method pragmaAt: #callback:) argumentAt: 1) evaluableObject: aMessageSend.! Item was changed: ----- Method: FFICallback>>setMessage:signature: (in category 'initialization') ----- setMessage: aMessageSend signature: signature "Override the argTypes from pragma in method." self assert: [aMessageSend receiver notNil]. self + setTypes: (ExternalType lookupTypes: signature) - setArgTypes: (ExternalType lookupTypes: signature) evaluableObject: aMessageSend.! Item was changed: ----- Method: FFICallback>>setResult:inContext: (in category 'callback') ----- setResult: anObject inContext: aCallbackContext "Set the result in the callback context. Add some fast checks to detect errors." + resultType isPointerType + ifTrue: [ + "an ExternalStructure, an ExternalUnion, an ExternalData, ..." + ^ aCallbackContext externalObjectResult: anObject]. + + resultType atomicType = 0 "void" + ifTrue: ["Quick exit for void return type." - argTypes first atomicType = 0 "void" - ifTrue: [ - "Quick exit for void return type." ^ aCallbackContext voidResult]. anObject isInteger ifTrue: [ + self assert: [resultType isIntegerType]. + self flag: #todo. "mt: ABI #X64Win64 has special treatment for word64, too. But maybe it is not needed." + ^ (anObject isLarge and: [FFIPlatformDescription current abi = #IA32]) + ifTrue: [aCallbackContext word64Result: anObject] + ifFalse: [aCallbackContext wordResult: anObject]]. - self assert: [argTypes first isIntegerType]. - ^ aCallbackContext wordResult: anObject]. anObject isBoolean ifTrue: [ + self assert: [resultType atomicType = 1 "bool"]. - self assert: [argTypes first atomicType = 1 "bool"]. ^ aCallbackContext wordResult: anObject]. anObject isFloat ifTrue: [ + self assert: [resultType atomicType >= 12 "float/double"]. - self assert: [argTypes first atomicType >= 12 "float/double"]. ^ aCallbackContext floatResult: anObject]. + self notify: 'Unkown result type.'. + ^ aCallbackContext errorResult! - "Try to push pointer for external object." - ^ aCallbackContext externalObjectResult: anObject! Item was added: + ----- Method: FFICallback>>setResultType:argumentTypes:evaluableObject: (in category 'initialization') ----- + setResultType: anExternalType argumentTypes: moreExternalTypes evaluableObject: blockOrMessage + + + abi := FFIPlatformDescription current abi. + handle := nil. + type := nil. + + evaluableObject := blockOrMessage. + argumentTypes := moreExternalTypes. + resultType := anExternalType. + + + + + "Support for callee pop callbacks (Pascal calling convention such as the Win32 stdcall: convention) are supported using the pragma which specifies how many bytes to pop. See http://forum.world.st/Pharo-FFI-on-aarch64-arm64-td5096777.html#a5096786." + thunk := FFICallbackMemory allocateExecutableBlock. + self init__ccall. + "self init__stdcall: 0." + "(method pragmaAt: #calleepops:) + ifNil: [self init__ccall] + ifNotNil: [:pragma | self init__stdcall: (pragma argumentAt: 1)]." + + "numEvaluatorArgs := (evaluator := method selector) numArgs. + self addToThunkTable" + ThunkToCallbackMap at: thunk getHandle put: self! Item was added: + ----- Method: FFICallback>>setTypes:evaluableObject: (in category 'initialization') ----- + setTypes: externalTypes evaluableObject: blockOrMessage + + self + setResultType: externalTypes first + argumentTypes: externalTypes allButFirst + evaluableObject: blockOrMessage.! Item was added: + SharedPool subclass: #FFICallbackConstants + instanceVariableNames: '' + classVariableNames: 'MaxThunkSize ResultTypeDouble ResultTypeStruct ResultTypeWord ResultTypeWord64' + poolDictionaries: '' + category: 'FFI-Callbacks'! Item was added: + ----- Method: FFICallbackConstants class>>initialize (in category 'class initialization') ----- + initialize + " + self initialize. + " + + "Callback return types. See vmCallback.h" + ResultTypeWord := 1. + ResultTypeWord64 := 2. + ResultTypeDouble := 3. + ResultTypeStruct := 4. + + "See FFICallbackThunk initialize & initializeStdcall:; must be big enough for the largest thunk created" + MaxThunkSize := 40.! Item was changed: ExternalStructure subclass: #FFICallbackContext instanceVariableNames: '' classVariableNames: '' + poolDictionaries: 'FFICallbackConstants' - poolDictionaries: '' category: 'FFI-Callbacks'! + + !FFICallbackContext commentStamp: 'mt 4/30/2021 11:32' prior: 0! + A callback context is a data structure prepared from the VM for accessing the callback's arguments. See FFICallback >> #thunkEntryAddress. + + !!!!!! BE AWARE that the actual location of argument values in this structure depend on the current ABI (i.e. 'Application Binary Interface'). See FFIPlatformDescription to access the current ABI.! Item was changed: + ----- Method: FFICallbackContext>>errorResult (in category 'callback result - convenience') ----- - ----- Method: FFICallbackContext>>errorResult (in category 'callback result') ----- errorResult ^ self wordResult: -1! Item was changed: + ----- Method: FFICallbackContext>>externalObjectResult: (in category 'callback result - convenience') ----- - ----- Method: FFICallbackContext>>externalObjectResult: (in category 'callback result') ----- externalObjectResult: anExternalObject "ExternalStructure, ExternalUnion, ExternalData ... handle MUST BE an ExternalAddress" ^ self pointerResult: anExternalObject getHandle! Item was changed: ----- Method: FFICallbackContext>>floatResult: (in category 'callback result') ----- floatResult: aFloat + self flag: #floatVsDouble. "mt: What about result types that expect single-precision floats?" self rvs floatResult: aFloat. + ^ ResultTypeDouble! - ^ 3! Item was changed: + ----- Method: FFICallbackContext>>pointerResult: (in category 'callback result - convenience') ----- - ----- Method: FFICallbackContext>>pointerResult: (in category 'callback result') ----- pointerResult: anExternalAddress ^ self wordResult: anExternalAddress asInteger! Item was added: + ----- Method: FFICallbackContext>>structResult: (in category 'callback result') ----- + structResult: anObject + + self shouldBeImplemented. + ^ ResultTypeStruct! Item was changed: + ----- Method: FFICallbackContext>>voidResult (in category 'callback result - convenience') ----- - ----- Method: FFICallbackContext>>voidResult (in category 'callback result') ----- voidResult self flag: #discuss. "mt: Is this the expected answer in the IA32ABI plugin?" ^ self wordResult: 0! Item was added: + ----- Method: FFICallbackContext>>word64Result: (in category 'callback result') ----- + word64Result: anInteger + "Separate the integer into high-and-low (big endian) or low-and-high (little endian)." + + self shouldBeImplemented. "mt: See platforms\Cross\plugins\IA32ABI" + + self assert: [anInteger isLarge]. + self assert: [FFIPlatformDescription current wordSize = 4 + or: [FFIPlatformDescription current abi = 'X64Win64']]. + + FFIPlatformDescription current endianness caseOf: { + [ #little ] -> []. + [ #big ] -> []. + }. + + + ^ ResultTypeWord64! Item was changed: ----- Method: FFICallbackContext>>wordResult: (in category 'callback result') ----- wordResult: aValue - "Accept any value in the -2^31 to 2^32-1 range or booleans." aValue isBoolean ifTrue: [self rvs booleanResult: aValue]. aValue isInteger ifTrue: [aValue >= 0 ifTrue: [self rvs positiveIntegerResult: aValue] ifFalse: [self rvs integerResult: aValue]]. + ^ ResultTypeWord! - ^1! Item was changed: ByteArray variableByteSubclass: #FFICallbackMemory instanceVariableNames: '' classVariableNames: 'AccessProtect AllocatedThunks ExecutablePages LifoCallbackSemaphore' + poolDictionaries: 'FFICallbackConstants' - poolDictionaries: '' category: 'FFI-Callbacks'! !FFICallbackMemory commentStamp: 'mt 6/17/2020 12:24' prior: 0! Interface for memory allocation using the IA32ABI plugin. Also used as a compatibility layer for Alien. *** An instance of FFICallbackThunk is a reference to a machine-code thunk/trampoline that calls-back into the VM. The reference can be passed to C code which can use it as a function pointer through which to call-back into Smalltalk. The machine-code thunk/trampoline is different for each instance, hence its address is a unique key that can be used to assocuate the Smalltalk side of the call-back (e.g. a block) with the thunk. Since thunks must be executable and some OSs may not provide default execute permission on memory returned by malloc we may not be able to use malloc directly. Instead we rely on a primitive to provide memory that is guaranteed to be executable. ExternalAddress class>>allocateExecutablePage answers an instance of ExternalData that references an executable piece of memory that is some (possiby unitary) multiple of the pagesize. Class-side code then parcels out pieces of a page to individual thunks. These pieces are recycled when thunks are reclaimed. Sinc e the first byte of a thunk is non-zero we can use it as a flag indicating if the piece is in use or not. See FFICallback for the higher-level construct that represents a Smalltalk block to be run in response to a callback. Callbacks wrap instances of FFICallbackThunk and FFICallbackContext instances that describe the stack layout and register contents for receiving callback arguments. Class Variables AccessProtect critical section for ExecutablePages (de)allocation AllocatedThunks Integer>> - weak collection of thunks, used to return thunk storage to the executable page pool. ExecutablePages - collection of pages with execute permissions used to provide executable thunks! Item was changed: ----- Method: FFICallbackMemory class>>allocateExecutableBlock (in category 'executable pages') ----- allocateExecutableBlock | blockSize | + blockSize := MaxThunkSize. - blockSize := FFICallback maxThunkSize. AccessProtect critical: [ExecutablePages do: [:page | 1 to: page size - blockSize by: blockSize do: [:i| (page at: i) = 0 ifTrue: [page at: i put: 1. ^ page blockAt: i byteSize: blockSize]]]]. AccessProtect critical: [ | newPage | newPage := ExecutablePages add: self allocateExecutablePage. ^ (newPage blockAt: 1 byteSize: blockSize) at: 1 put: 1; yourself]! Item was changed: ----- Method: FFIPlatformDescription>>abi (in category '*FFI-Callbacks') ----- abi | processor | processor := self subtype asLowercase. (processor = 'arm' or: [(processor beginsWith: 'armv') and: [processor fifth <= $7]]) + ifTrue: [^ #'ARM32']. - ifTrue: [^ 'ARM32']. (processor first = $i and: [processor = 'intel' or: ['i#86' match: processor]]) + ifTrue: [^ #'IA32']. - ifTrue: [^ 'IA32']. (processor first = $x and: [processor = 'x64' or: [('x86#64*' match: processor)]]) + ifTrue: [^ self isWindows ifTrue: [#'X64Win64'] ifFalse: [#'X64']]. - ifTrue: [^ self isWindows ifTrue: ['X64Win64'] ifFalse: ['X64']]. + ^ #'UNKNOWN_ABI'! - ^ 'UNKNOWN'! Item was added: + ----- Method: FFIPlatformDescription>>endianness (in category '*FFI-Callbacks') ----- + endianness + + ^ Smalltalk endianness! From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 30 16:36:20 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 30 Apr 2021 16:36:20 +0000 Subject: [squeak-dev] Dictionary >> #at:ifAbsentPut:ifPresentPut: Message-ID: <8d6d63a2257344c7853cbf45603de7cb@student.hpi.uni-potsdam.de> Hi all, recently I stumbled upon an extension method for Dictionary which *might* fit well into the Trunk: Dictionary >> #at: key ifAbsentPut: startBlock ifPresentPut: nextBlock "(c) 2020 Basti Kruck und Marcel Taeumel. :-)" (self includesKey: key) ifFalse: [ ^ self at: key put: startBlock value]. ^ self at: key put: (nextBlock value: (self at: key)) See https://github.com/hpi-swa/vivide/blob/c4ac5ea562bd563358d52ee41c149a3fbcffd90e/repository/Vivide.package/Dictionary.extension/instance/at.ifAbsentPut.ifPresentPut..st. Usage: counter := counters at: key ifAbsentPut: [0] ifPresentPut: [:i | i + 1] What do you think, should we copy this into the Trunk? Or is it just fine to do something like this instead at the sender side: counter := counters at: key put: (counters at: key ifAbsent: [0] ifPresent: [:i | i + 1]) Also, I'm not sure about the order of arguments. Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 30 17:01:47 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 30 Apr 2021 17:01:47 +0000 Subject: [squeak-dev] The Trunk: Tests-nice.458.mcz In-Reply-To: References: Message-ID: Hi Nicolas, I appreciate all your work, but it would be great if you could also check the inbox before. I already had implemented equivalent tests in Tests-ct.447 three months ago. Now I feel a tiny little bit nihilistic. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 28. April 2021 18:12:10 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Tests-nice.458.mcz Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.458.mcz ==================== Summary ==================== Name: Tests-nice.458 Author: nice Time: 28 April 2021, 6:11:51.033213 pm UUID: 13fec56a-805e-754e-bd02-8cbaa015e102 Ancestors: Tests-jr.457 Document the fact that becomeForward: does NOT forward identityHash of receiver anymore (since Collections-eem.885 April 2020) See #elementsForwardIdentityTo: vs #elementsForwardIdentityAndHashTo: See also http://forum.world.st/How-to-become-immediate-objects-td5114931.html =============== Diff against Tests-jr.457 =============== Item was changed: ----- Method: BecomeTest>>testBecomeForward (in category 'tests') ----- testBecomeForward "Test the forward become." | a b c d | a := 'ab' copy. b := 'cd' copy. + c := Array with: a. - c := a. d := b. a becomeForward: b. self assert: a = 'cd'; assert: b = 'cd'; + assert: a == b; + assert: c first == b; + assert: d == b. - assert: c = 'cd'; - assert: d = 'cd'. - ! Item was added: + ----- Method: BecomeTest>>testBecomeForwardCopyIdentityHash (in category 'tests') ----- + testBecomeForwardCopyIdentityHash + "Check that + 1. the argument to becomeForward: is modified to have the receiver's identity hash. + 2. the receiver's identity hash is unchanged." + + | a b ha | + + a := 'ab' copy. + b := 'cd' copy. + ha := a identityHash. + + a becomeForward: b copyHash: true. + + self + assert: a identityHash = ha; + assert: b identityHash = ha. + + ! Item was changed: ----- Method: BecomeTest>>testBecomeForwardDontCopyIdentityHash (in category 'tests') ----- testBecomeForwardDontCopyIdentityHash "Check that 1. the argument to becomeForward: is NOT modified to have the receiver's identity hash. + 2. the receiver's identity hash is changed." - 2. the receiver's identity hash is unchanged." | a b hb | a := 'ab' copy. b := 'cd' copy. hb := b identityHash. a becomeForward: b copyHash: false. self assert: a identityHash = hb; assert: b identityHash = hb. ! Item was changed: ----- Method: BecomeTest>>testBecomeForwardIdentityHash (in category 'tests') ----- testBecomeForwardIdentityHash + "Document that the receiver hash is changed, but the argument hash is unchanged. + (a becomeForward: b) has thus same effect as (a becomeForward: b copyHash: false)" - "Check that - 1. the argument to becomeForward: is modified to have the receiver's identity hash. - 2. the receiver's identity hash is unchanged." + | a b hb | - | a b ha | a := 'ab' copy. b := 'cd' copy. + hb := b identityHash. - ha := a identityHash. a becomeForward: b. self + assert: a identityHash = hb; + assert: b identityHash = hb. - assert: a identityHash = ha; - assert: b identityHash = ha. ! -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Fri Apr 30 17:02:14 2021 From: tim at rowledge.org (tim Rowledge) Date: Fri, 30 Apr 2021 10:02:14 -0700 Subject: [squeak-dev] Browser flash (was Re: The Trunk: Tools-mt.1029.mcz) In-Reply-To: References: <9574ca2682be4bb78fe4664b0f7155d9@student.hpi.uni-potsdam.de> <12B8A259-39EC-453F-9CA2-D0F1E1BEB990@rowledge.org> <814A4BBC-8CAF-45BC-80D9-A6B97C85A5D6@rowledge.org> Message-ID: <9A701758-83CA-46E0-81C9-A9E04C05DDDF@rowledge.org> > On 2021-04-30, at 1:19 AM, Marcel Taeumel wrote: > > Hmm... it is unusual that a normal click can also select a range. Usually, one would expect to use SHIFT+CLICK to do so, which you can actually do too. :-D I suppose that behavior originates from that older multi-selection list, where a simple click changes the selection state of a single element.... which is also quite unusual given today's widgets in other GUI frameworks. > > Here is what I would expect from a multi-selection list: > - simple click clears and sets the entire selection to a single element > - shift+click adds a range to the selection starting from the current element to the clicked one > - ctrl+click toggles the selection state of a single element > - click-drag drags whatever is currently selected Pretty much what I'd prefer too. I accept there are plausible 'better' approaches but the daily reality is that having a system reasonably close to (what passes for) normal would be simpler to work with. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: SEXI: Sign EXtend Integer From Das.Linux at gmx.de Fri Apr 30 17:05:54 2021 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri, 30 Apr 2021 19:05:54 +0200 Subject: [squeak-dev] Dictionary >> #at:ifAbsentPut:ifPresentPut: In-Reply-To: <8d6d63a2257344c7853cbf45603de7cb@student.hpi.uni-potsdam.de> References: <8d6d63a2257344c7853cbf45603de7cb@student.hpi.uni-potsdam.de> Message-ID: Hi > On 30. Apr 2021, at 18:36, Thiede, Christoph wrote: > > Hi all, > > recently I stumbled upon an extension method for Dictionary which *might* fit well into the Trunk: > > Dictionary >> #at: key ifAbsentPut: startBlock ifPresentPut: nextBlock > "(c) 2020 Basti Kruck und Marcel Taeumel. :-)" > (self includesKey: key) ifFalse: [ > ^ self at: key put: startBlock value]. > ^ self > at: key > put: (nextBlock value: (self at: key)) > > See https://github.com/hpi-swa/vivide/blob/c4ac5ea562bd563358d52ee41c149a3fbcffd90e/repository/Vivide.package/Dictionary.extension/instance/at.ifAbsentPut.ifPresentPut..st. > > Usage: > counter := counters at: key ifAbsentPut: [0] ifPresentPut: [:i | i + 1] > > What do you think, should we copy this into the Trunk? Or is it just fine to do something like this instead at the sender side: > counter := counters at: key put: (counters at: key ifAbsent: [0] ifPresent: [:i | i + 1]) > > Also, I'm not sure about the order of arguments. I find it a bit too specific for trunk. It's quite an edge case... -t From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 30 17:09:46 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 30 Apr 2021 17:09:46 +0000 Subject: [squeak-dev] WG: The Trunk: Tests-nice.458.mcz In-Reply-To: References: , Message-ID: <8c3676cc5b4f43b390ea6f67ae7087aa@student.hpi.uni-potsdam.de> But let's take this as something positive and inspirative instead. :-) Do we maybe need a new tool for this? When editing a class/method, automatically display a small "under construction" icon/hint if there is already a pending patch for it in the inbox? This might also help us to avoid future merge conflicts in a workflow that is not aligned at fast integration cycles. Just brainstorming ... :-) Best, Christoph ________________________________ Von: Thiede, Christoph Gesendet: Freitag, 30. April 2021 19:01 Uhr An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: AW: [squeak-dev] The Trunk: Tests-nice.458.mcz Hi Nicolas, I appreciate all your work, but it would be great if you could also check the inbox before. I already had implemented equivalent tests in Tests-ct.447 three months ago. Now I feel a tiny little bit nihilistic. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 28. April 2021 18:12:10 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Tests-nice.458.mcz Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.458.mcz ==================== Summary ==================== Name: Tests-nice.458 Author: nice Time: 28 April 2021, 6:11:51.033213 pm UUID: 13fec56a-805e-754e-bd02-8cbaa015e102 Ancestors: Tests-jr.457 Document the fact that becomeForward: does NOT forward identityHash of receiver anymore (since Collections-eem.885 April 2020) See #elementsForwardIdentityTo: vs #elementsForwardIdentityAndHashTo: See also http://forum.world.st/How-to-become-immediate-objects-td5114931.html Squeak - Dev - How to become immediate objects? :-) forum.world.st How to become immediate objects? :-). Hi, all! I suppose that since ModificationForbidden and read-only objects, the following is no longer possible: MyExternalResource allInstancesDo: [:resource... =============== Diff against Tests-jr.457 =============== Item was changed: ----- Method: BecomeTest>>testBecomeForward (in category 'tests') ----- testBecomeForward "Test the forward become." | a b c d | a := 'ab' copy. b := 'cd' copy. + c := Array with: a. - c := a. d := b. a becomeForward: b. self assert: a = 'cd'; assert: b = 'cd'; + assert: a == b; + assert: c first == b; + assert: d == b. - assert: c = 'cd'; - assert: d = 'cd'. - ! Item was added: + ----- Method: BecomeTest>>testBecomeForwardCopyIdentityHash (in category 'tests') ----- + testBecomeForwardCopyIdentityHash + "Check that + 1. the argument to becomeForward: is modified to have the receiver's identity hash. + 2. the receiver's identity hash is unchanged." + + | a b ha | + + a := 'ab' copy. + b := 'cd' copy. + ha := a identityHash. + + a becomeForward: b copyHash: true. + + self + assert: a identityHash = ha; + assert: b identityHash = ha. + + ! Item was changed: ----- Method: BecomeTest>>testBecomeForwardDontCopyIdentityHash (in category 'tests') ----- testBecomeForwardDontCopyIdentityHash "Check that 1. the argument to becomeForward: is NOT modified to have the receiver's identity hash. + 2. the receiver's identity hash is changed." - 2. the receiver's identity hash is unchanged." | a b hb | a := 'ab' copy. b := 'cd' copy. hb := b identityHash. a becomeForward: b copyHash: false. self assert: a identityHash = hb; assert: b identityHash = hb. ! Item was changed: ----- Method: BecomeTest>>testBecomeForwardIdentityHash (in category 'tests') ----- testBecomeForwardIdentityHash + "Document that the receiver hash is changed, but the argument hash is unchanged. + (a becomeForward: b) has thus same effect as (a becomeForward: b copyHash: false)" - "Check that - 1. the argument to becomeForward: is modified to have the receiver's identity hash. - 2. the receiver's identity hash is unchanged." + | a b hb | - | a b ha | a := 'ab' copy. b := 'cd' copy. + hb := b identityHash. - ha := a identityHash. a becomeForward: b. self + assert: a identityHash = hb; + assert: b identityHash = hb. - assert: a identityHash = ha; - assert: b identityHash = ha. ! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Fri Apr 30 17:10:07 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 17:10:07 0000 Subject: [squeak-dev] FFI: FFI-Callbacks-mt.5.mcz Message-ID: Marcel Taeumel uploaded a new version of FFI-Callbacks to project FFI: http://source.squeak.org/FFI/FFI-Callbacks-mt.5.mcz ==================== Summary ==================== Name: FFI-Callbacks-mt.5 Author: mt Time: 30 April 2021, 7:10:05.967986 pm UUID: 32dde9ab-5acb-384f-bade-83c10c63ecec Ancestors: FFI-Callbacks-mt.4 Merges 2020/21 updates from VMMaker/Alien plugin: - #voidResult - #oopAt:put: (not yet compatible with SqueakFFI) - #mostRecentCallbackContext + field "outerContext" for debugging - better comments - detect new ABI #ARM64 And simplify the existing #evaluateDynamic again. There is still logic missing when to switch between registers. =============== Diff against FFI-Callbacks-mt.4 =============== Item was changed: ----- Method: FFICallback class>>initialize (in category 'class initialization') ----- initialize + Smalltalk addToStartUpList: self after: FFIPlatformDescription. ThunkToCallbackMap := WeakValueDictionary new.! Item was added: + ----- Method: FFICallback class>>startUp: (in category 'system startup') ----- + startUp: resuming + "Any thunks in the finalization registry at the time the image comes up in a new session MUST NOT be finalized and should immediately be discarded. Their thunk pointers are no longer valid." + + resuming ifTrue: + [ThunkToCallbackMap := WeakValueDictionary new]! Item was changed: ----- Method: FFICallback>>evaluateDynamic: (in category 'callback - evaluators') ----- evaluateDynamic: callbackContext "Read all arguments and make the call(back). Assume that 'handle' and 'type' are set correctly. Only watch out for the sign. See field definition in FFICallbackContext to explore alternative ways to read the arguments." | offset args | offset := 1. args := Array new: argumentTypes size. 1 to: args size do: [:argIndex | | argType data | argType := argumentTypes at: argIndex. + data := argType handle: handle at: offset. - - argType isPointerType - ifTrue: [ - data := (type handle: handle at: offset). - - argType referentClass "pointer to atomic" - ifNil: [data := data asType: argType] - ifNotNil: [:structClass | "pointer to external structure or union" - argType isTypeAliasToPointer - ifTrue: [data := structClass fromHandle: data getHandle asByteArrayPointer] - ifFalse: [data := structClass fromHandle: data getHandle]] ] - ifFalse: [ "non-pointer type" - self flag: #floats. "mt: When should we switch to callbackContext floatRegArgs?" - data := argType handle: handle at: offset. - - argType isAtomic - ifFalse: ["structure type, most likely type alias to pointer" - data := argType referentClass - fromHandle: (ExternalAddress fromInteger: data) asByteArrayPointer] - ifTrue: [ argType isTypeAlias - ifTrue: [ "alias to atomic type" - data := argType referentClass fromHandle: data] - ifFalse: [ "atomic, non-pointer type" - data := data ";-)"]] ]. - args at: argIndex put: data. + + "Move the offset. Consider the byte-alignment?" offset := offset + ((type byteSize max: argType byteSize) roundUpTo: type byteSize)]. ^ self setResult: (evaluableObject valueWithArguments: args) + inContext: callbackContext! - inContext: callbackContext.! Item was changed: ----- Method: FFICallback>>evaluateDynamic_ARM32: (in category 'callback - evaluators') ----- evaluateDynamic_ARM32: callbackContext "Set handle to access arguments as most appropriate for the ABI. For ''RISCs'' it is the pointer to the integer register." + | intRegArgs floatRegArgs stackPtr | + intRegArgs := callbackContext intRegArgs. + intRegArgs size: 4. + floatRegArgs := callbackContext floatRegArgs. + floatRegArgs size: 8. + + stackPtr := callbackContext stackPtr. + + self assert: [argumentTypes size <= intRegArgs size]. + + self setArgData: intRegArgs. - self setArgData: callbackContext intRegArgs. ^ self evaluateDynamic: callbackContext! Item was added: + ----- Method: FFICallback>>evaluateDynamic_ARM64: (in category 'callback - evaluators') ----- + evaluateDynamic_ARM64: callbackContext + "Set handle to access arguments as most appropriate for the ABI. ARMv8 with AArch64." + + + | intRegArgs floatRegArgs stackPtr | + intRegArgs := callbackContext intRegArgs. + intRegArgs size: 8. + floatRegArgs := callbackContext floatRegArgs. + floatRegArgs size: 8. + + stackPtr := callbackContext stackPtr. + + self assert: [argumentTypes size <= intRegArgs size]. + + self setArgData: intRegArgs. + ^ self evaluateDynamic: callbackContext! Item was changed: ----- Method: FFICallback>>evaluateDynamic_IA32: (in category 'callback - evaluators') ----- evaluateDynamic_IA32: callbackContext "Set handle to access arguments as most appropriate for the ABI. For x86 (i.e. IA32) it is the stack pointer." + - + self setArgData: callbackContext stackPtr. + ^ self evaluateDynamic: callbackContext! - | stackPtr offset args | - stackPtr := callbackContext stackPtr. "For IA32, all arguments are on the stack." - - handle := stackPtr getHandle. - type := stackPtr contentType. "intptr_t" - - offset := 1. - args := Array new: argumentTypes size. - - 1 to: args size do: [:argIndex | - | argType data | - argType := argumentTypes at: argIndex. - data := argType handle: handle at: offset. - args at: argIndex put: data. - - "Move the offset. Consider the byte-alignment?" - offset := offset + ((type byteSize max: argType byteSize) roundUpTo: type byteSize)]. - - ^ self - setResult: (evaluableObject valueWithArguments: args) - inContext: callbackContext! Item was changed: ----- Method: FFICallback>>evaluateDynamic_X64: (in category 'callback - evaluators') ----- evaluateDynamic_X64: callbackContext "Set handle to access arguments as most appropriate for the ABI. For ''RISCs'' it is the pointer to the integer register." + | intRegArgs floatRegArgs stackPtr | + intRegArgs := callbackContext intRegArgs. + intRegArgs size: 6. + floatRegArgs := callbackContext floatRegArgs. + floatRegArgs size: 8. + + stackPtr := callbackContext stackPtr. + + self assert: [argumentTypes size <= intRegArgs size]. + + self setArgData: intRegArgs. - self setArgData: callbackContext intRegArgs. ^ self evaluateDynamic: callbackContext! Item was changed: ----- Method: FFICallback>>evaluateDynamic_X64Win64: (in category 'callback - evaluators') ----- evaluateDynamic_X64Win64: callbackContext "Set handle to access arguments as most appropriate for the ABI. For ''RISCs'' it is the pointer to the integer register." + + | intRegArgs floatRegArgs stackPtr | + intRegArgs := callbackContext intRegArgs. + intRegArgs size: 4. + floatRegArgs := callbackContext floatRegArgs. + floatRegArgs size: 4. + stackPtr := callbackContext stackPtr. + + self assert: [argumentTypes size <= intRegArgs size]. + + self setArgData: intRegArgs. - self setArgData: callbackContext intRegArgs. ^ self evaluateDynamic: callbackContext! Item was changed: ----- Method: FFICallback>>setArgData: (in category 'callback') ----- setArgData: externalData handle := externalData getHandle. + type := externalData contentType. ! - type := externalData externalType. ! Item was changed: ----- Method: FFICallbackContext class>>fields (in category 'field definition') ----- fields " self defineFields. " ^ #( (thunkp 'void*') (stackPtr 'intptr_t*') "was: char*" (intRegArgs 'intptr_t*') "was: long* or int*" (floatRegArgs 'double*') (nil 'void*') "was: savedCStackPointer" (nil 'void*') "was: savedCFramePointer" (rvs 'FFICallbackResult') + (nil 'void*') "was: savedPrimFunctionPointer" + (outerContext 'FFICallbackContext*') "jmp_buf trampoline --- for debugging only?" ) " typedef struct { void *thunkp; char *stackptr; long *intRegArgs; double *floatRegArgs; void *savedCStackPointer; void *savedCFramePointer; union { intptr_t vallong; struct { int low, high; } valleint64; struct { int high, low; } valbeint64; double valflt64; struct { void *addr; intptr_t size; } valstruct; } rvs; void *savedPrimFunctionPointer; jmp_buf trampoline; jmp_buf savedReenterInterpreter; } VMCallbackContext; "! Item was changed: + ----- Method: FFICallbackContext>>voidResult (in category 'callback result') ----- - ----- Method: FFICallbackContext>>voidResult (in category 'callback result - convenience') ----- voidResult + "Actually return garbage." + ^ ResultTypeWord! - self flag: #discuss. "mt: Is this the expected answer in the IA32ABI plugin?" - ^ self wordResult: 0! Item was added: + ----- Method: FFICallbackMemory class>>forOop (in category 'instance creation') ----- + forOop + " DANGEROUS!! Use during callbacks only or oop will be come invalid!! + object := Morph new. + handle := FFICallbackMemory forOop. + handle oopAt: 1 put: object. + handle oopAt: 1. + " + + ^ self new + sizeFieldPut: ExternalAddress wordSize; + yourself ! Item was changed: ----- Method: FFICallbackMemory class>>invokeCallbackContext: (in category 'callbacks') ----- + invokeCallbackContext: vmCallbackContextAddress "" - invokeCallbackContext: vmCallbackContextAddress "" "^" "The low-level entry-point for callbacks sent from the VM/IA32ABI plugin. Evaluate the callback corresponding to the thunk referenced by vmCallbackContextAddress, + a pointer to a VMCallbackContext32 or VMCallbackContext64, set up by the VM's thunkEntry + routine. Return from the Callback via primSignal:andReturnAs:fromContext:. thisContext's + sender is typically an FFI call-out context and is restored as the Process's top context on return. + Therefore callbacks run on the process that did the call-out in which the callback occurred." + - a pointer to a FFICallbackContext, set up by the VM's thunkEntry - routine. Return to C via primSignal:andReturnAs:fromContext:. thisContext's sender is the - call-out context." | callbackContext typeCode helper | callbackContext := FFICallbackContext fromHandle: vmCallbackContextAddress. helper := self fromInteger: vmCallbackContextAddress. [typeCode := FFICallback evaluateCallbackForContext: callbackContext] ifCurtailed: [self error: 'attempt to non-local return across a callback']. typeCode ifNil: [typeCode := callbackContext errorResult]. + + "Now attempt to return from a Callback. This must be done in LIFO order. The IA32ABI + plugin maintains a linked list of vmCallbackContextAddresses to record this order. If + vmCallbackContextAddress *is* that of the most recent Callback then the return will + occur and the primitive will not return here. If vmCallbackContextAddress *is not* that + of the most recent Callback the primitive will answer false, in which case this process + waits on the lifoCallbackSemaphore which will be signalled by some other attempted + Callback return. In any case (successful return from callback or answering false here), + the primtive signals the first process waiting on the semaphore (which is after this one + if this one was waiting), allowing the next process to attempt to return, and so on. + Hence all nested callbacks should eventually return, and in the right order." + [helper primSignal: LifoCallbackSemaphore andReturnAs: typeCode fromContext: thisContext] + whileFalse: + [LifoCallbackSemaphore wait]! - "Now attempt to return to C. The primitive will answer false if this is not the most recent Callback, - in which case we should wait on the lifoCallbackSemaphore which will be signalled when the most - recent callback successfully returns. If this is the most recent callback the primitive will signal all - the processes waiting on the lifoCallbackSemaphore, one of which will be the next most recent. - Hence all nested callbacks will end up returning in the right order." - [helper primSignal: LifoCallbackSemaphore andReturnAs: typeCode fromContext: thisContext] whileFalse: - [LifoCallbackSemaphore wait]! Item was added: + ----- Method: FFICallbackMemory class>>mostRecentCallbackContext (in category 'callbacks') ----- + mostRecentCallbackContext + + ^ FFICallbackContext fromHandle: self primMostRecentCallbackContextAddress! Item was added: + ----- Method: FFICallbackMemory class>>primMostRecentCallbackContextAddress (in category 'callbacks') ----- + primMostRecentCallbackContextAddress + "Answer the address of the mostRecentCallbackContext, which will be 0 if no callback is running. + Does not fail (if the plugin is present and implements the primitive)." + + self primitiveFailed.! Item was changed: ----- Method: FFICallbackMemory class>>startUp: (in category 'system startup') ----- startUp: resuming + - "Any thunks in the finalization registry at the time the image comes up in a new session MUST NOT be finalized and should immediately be discarded. Their thunk pointers are no longer valid." resuming ifTrue: + [ ExecutablePages := Set new. + LifoCallbackSemaphore := Semaphore new ]! - ["AllocatedThunks removeAll." - ExecutablePages := Set new]! Item was added: + ----- Method: FFICallbackMemory>>oopAt: (in category 'alien compatibility') ----- + oopAt: byteOffset + "Access for callbacks that want to exchange Smalltalk objects." + + ^self primitiveFailed! Item was added: + ----- Method: FFICallbackMemory>>oopAt:put: (in category 'alien compatibility') ----- + oopAt: byteOffset put: value + "Access for callbacks that want to exchange Smalltalk objects." + + ^self primitiveFailed! Item was changed: ----- Method: FFICallbackMemory>>primSignal:andReturnAs:fromContext: (in category 'callbacks') ----- + primSignal: aSemaphore andReturnAs: typeCode fromContext: context + "Attempt to return from a callback. This must be done in LIFO order. The IA32ABI + plugin maintains a linked list of vmCallbackContextAddresses to record this order. + If vmCallbackContextAddress *is* that of the most recent Callback then return from + the callback and do not return here. If vmCallbackContextAddress *is not* that of + the most recent Callback then succeed but answer false. In either case, signal the + first process waiting on aSemaphore. See Alien class>> invokeCallbackContext: + for a full explanation. Fail if the arguments are not of the expected type." - primSignal: aSemaphore "" andReturnAs: typeCode "" fromContext: context "" ^ self primitiveFailed! Item was changed: ----- Method: FFICallbackResult class>>fields (in category 'field definition') ----- fields " self defineFields. " ^ #( (booleanResult 'bool') (floatResult 'double') (positiveIntegerResult 'uintptr_t') (integerResult 'intptr_t') + "(oopResult 'oop')" "Not yet working. Needs new atomic oop type to then call #oopAt:put: on ByteArray or ExternalAddress. See AtomicSelectors. Still, the IA32ABI plugin needs the Alien-form of a byte array. See FFICallbackMemory and its #oopAt:(put:) implementation. Maybe in the future Squeak FFI supports this interface on its regular handles, too." )! Item was changed: ----- Method: FFIPlatformDescription>>abi (in category '*FFI-Callbacks') ----- abi | processor | processor := self subtype asLowercase. + (#('aarch64' 'arm64') includes: processor) + ifTrue: [^ #ARM64 "#ARMv8 ???"]. (processor = 'arm' or: [(processor beginsWith: 'armv') and: [processor fifth <= $7]]) + ifTrue: [^ #ARM32]. - ifTrue: [^ #'ARM32']. (processor first = $i and: [processor = 'intel' or: ['i#86' match: processor]]) + ifTrue: [^ #IA32]. - ifTrue: [^ #'IA32']. (processor first = $x and: [processor = 'x64' or: [('x86#64*' match: processor)]]) + ifTrue: [^ self isWindows ifTrue: [#X64Win64] ifFalse: [#X64]]. - ifTrue: [^ self isWindows ifTrue: [#'X64Win64'] ifFalse: [#'X64']]. ^ #'UNKNOWN_ABI'! From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 30 17:10:23 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 30 Apr 2021 17:10:23 +0000 Subject: [squeak-dev] The Trunk: Compiler-nice.457.mcz In-Reply-To: References: <6573207aa94b43118cb57b1bb8fcfbb2@student.hpi.uni-potsdam.de> <1619702746050-0.post@n4.nabble.com>, Message-ID: Great, thank you! :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Nicolas Cellier Gesendet: Donnerstag, 29. April 2021 19:49:13 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Compiler-nice.457.mcz Hi Christoph, Done! I missed this usage indeed, case of blindness... Le jeu. 29 avr. 2021 à 15:25, Christoph Thiede a écrit : > > Hi Nicolas, > > your removal of #newSource broke the handling of syntax errors in > Monticello, see MethodAddition >> #createCompiledMethod. Would you mind > restoring them if you cannot find another solution? :-) > > Best, > Christoph > > > > ----- > Carpe Squeak! > -- > Sent from: http://forum.world.st/Squeak-Dev-f45488.html > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 30 17:14:25 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 30 Apr 2021 17:14:25 +0000 Subject: [squeak-dev] False merge conflicts Message-ID: <4d76345a822b417187517284683875f7@student.hpi.uni-potsdam.de> Hi all, this is not the first time I am receiving a merge conflict resolution window while updating my image even though there is not a real merge conflict: [cid:cdf93b35-01eb-4934-8ba1-bfc8bef8a86d] Did anyone else of you experience similar issues in the past? Is there something wrong with the detection of merge conflicts? Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: pastedImage.png Type: image/png Size: 28429 bytes Desc: pastedImage.png URL: From tim at rowledge.org Fri Apr 30 17:15:56 2021 From: tim at rowledge.org (tim Rowledge) Date: Fri, 30 Apr 2021 10:15:56 -0700 Subject: [squeak-dev] The Trunk: Tests-nice.458.mcz In-Reply-To: <8c3676cc5b4f43b390ea6f67ae7087aa@student.hpi.uni-potsdam.de> References: <8c3676cc5b4f43b390ea6f67ae7087aa@student.hpi.uni-potsdam.de> Message-ID: <985F8BA7-BDE9-4BD3-8A9C-9F1883E5FDFC@rowledge.org> > On 2021-04-30, at 10:09 AM, Thiede, Christoph wrote: > > But let's take this as something positive and inspirative instead. :-) Do we maybe need a new tool for this? Tools to help workflow are always welcome; lack of them almost always results in potentially good ideas getting lost in the mire. (Think traits, for example) tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: DPN: Double Precision No-op From commits at source.squeak.org Fri Apr 30 18:02:32 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 18:02:32 0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1768.mcz Message-ID: A new version of Morphic was added to project The Inbox: http://source.squeak.org/inbox/Morphic-ct.1768.mcz ==================== Summary ==================== Name: Morphic-ct.1768 Author: ct Time: 30 April 2021, 8:02:20.035293 pm UUID: 2c143938-6557-0b42-973c-6453d49680cf Ancestors: Morphic-mt.1767 Fixes a GrafPort bug when drawing round rectangle frames. In the past, the horizontal segments were too wide. Original snippet to reproduce (provided by Marcel, mt): morph := Morph new. morph extent: 500 at 500; borderWidth: 50; borderColor: Color red; cornerStyle: #rounded; cornerRadius: 20; yourself. morph openInHand. =============== Diff against Morphic-mt.1767 =============== Item was changed: ----- Method: GrafPort>>frameRoundRect:radius:borderWidth: (in category 'drawing support') ----- frameRoundRect: aRectangle radius: radius borderWidth: borderWidth | nextY outer nextOuterX ovalDiameter rectExtent rectOffset rectX rectY rectWidth rectHeight ovalRadius ovalRect innerRadius innerDiameter innerRect inner nextInnerX wp | aRectangle area <= 0 ifTrue: [^ self]. ovalDiameter := (radius * 2) asPoint min: aRectangle extent. (ovalDiameter x <= 0 or:[ovalDiameter y <= 0]) ifTrue:[ ^self fillRect: aRectangle offset: 0 at 0. ]. "force diameter to be even - this simplifies lots of stuff" ovalRadius := (ovalDiameter x // 2) @ (ovalDiameter y // 2). (ovalRadius x <= 0 or:[ovalRadius y <= 0]) ifTrue:[ ^self fillRect: aRectangle offset: 0 at 0. ]. wp := borderWidth asPoint. ovalDiameter := ovalRadius * 2. innerRadius := ovalRadius - borderWidth max: 0 at 0. innerDiameter := innerRadius * 2. rectExtent := aRectangle extent - ovalDiameter. rectWidth := rectExtent x. rectHeight := rectExtent y. rectOffset := aRectangle origin + ovalRadius. rectX := rectOffset x. rectY := rectOffset y. ovalRect := 0 at 0 extent: ovalDiameter. innerRect := 0 at 0 extent: innerDiameter. height := 1. outer := EllipseMidpointTracer new on: ovalRect. inner := EllipseMidpointTracer new on: innerRect. nextY := ovalRadius y. 1 to: (wp y min: nextY) do:[:i| nextOuterX := outer stepInY. width := nextOuterX * 2 + rectWidth. destX := rectX - nextOuterX. destY := rectY - nextY. self copyBits. destY := rectY + nextY + rectHeight - 1. self copyBits. nextY := nextY - 1. ]. [nextY > 0] whileTrue:[ nextOuterX := outer stepInY. nextInnerX := inner stepInY. destX := rectX - nextOuterX. destY := rectY - nextY. width := nextOuterX - nextInnerX. self copyBits. destX := rectX + nextInnerX + rectWidth. self copyBits. destX := rectX - nextOuterX. destY := rectY + nextY + rectHeight-1. self copyBits. destX := rectX + nextInnerX + rectWidth. self copyBits. nextY := nextY - 1. ]. destX := aRectangle left. destY := rectOffset y. height := rectHeight. width := wp x. self copyBits. destX := aRectangle right - width. self copyBits. innerRadius y = 0 ifTrue:[ destX := aRectangle left + wp x. destY := rectY. + width := aRectangle width - (wp x * 2). - width := rectWidth. height := wp y - ovalRadius y. self copyBits. destY := aRectangle bottom - wp y. self copyBits. ].! From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 30 18:03:28 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 30 Apr 2021 18:03:28 +0000 Subject: [squeak-dev] The Inbox: Morphic-ct.1768.mcz In-Reply-To: References: Message-ID: <6cd7be20ce9e48cdb993b57d56f3ce26@student.hpi.uni-potsdam.de> > Original snippet to reproduce (provided by Marcel, mt): > > morph := Morph new. > morph > extent: 500 at 500; > borderWidth: 50; > borderColor: Color red; > cornerStyle: #rounded; > cornerRadius: 20; > yourself. > morph openInHand. Before: [cid:500b569a-552b-4c5b-a194-e777c4b6170c] After: [cid:befc4681-cf79-4410-beb2-9a94ab9e9c19] :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Freitag, 30. April 2021 20:02:32 An: squeak-dev at lists.squeakfoundation.org Betreff: [squeak-dev] The Inbox: Morphic-ct.1768.mcz A new version of Morphic was added to project The Inbox: http://source.squeak.org/inbox/Morphic-ct.1768.mcz ==================== Summary ==================== Name: Morphic-ct.1768 Author: ct Time: 30 April 2021, 8:02:20.035293 pm UUID: 2c143938-6557-0b42-973c-6453d49680cf Ancestors: Morphic-mt.1767 Fixes a GrafPort bug when drawing round rectangle frames. In the past, the horizontal segments were too wide. Original snippet to reproduce (provided by Marcel, mt): morph := Morph new. morph extent: 500 at 500; borderWidth: 50; borderColor: Color red; cornerStyle: #rounded; cornerRadius: 20; yourself. morph openInHand. =============== Diff against Morphic-mt.1767 =============== Item was changed: ----- Method: GrafPort>>frameRoundRect:radius:borderWidth: (in category 'drawing support') ----- frameRoundRect: aRectangle radius: radius borderWidth: borderWidth | nextY outer nextOuterX ovalDiameter rectExtent rectOffset rectX rectY rectWidth rectHeight ovalRadius ovalRect innerRadius innerDiameter innerRect inner nextInnerX wp | aRectangle area <= 0 ifTrue: [^ self]. ovalDiameter := (radius * 2) asPoint min: aRectangle extent. (ovalDiameter x <= 0 or:[ovalDiameter y <= 0]) ifTrue:[ ^self fillRect: aRectangle offset: 0 at 0. ]. "force diameter to be even - this simplifies lots of stuff" ovalRadius := (ovalDiameter x // 2) @ (ovalDiameter y // 2). (ovalRadius x <= 0 or:[ovalRadius y <= 0]) ifTrue:[ ^self fillRect: aRectangle offset: 0 at 0. ]. wp := borderWidth asPoint. ovalDiameter := ovalRadius * 2. innerRadius := ovalRadius - borderWidth max: 0 at 0. innerDiameter := innerRadius * 2. rectExtent := aRectangle extent - ovalDiameter. rectWidth := rectExtent x. rectHeight := rectExtent y. rectOffset := aRectangle origin + ovalRadius. rectX := rectOffset x. rectY := rectOffset y. ovalRect := 0 at 0 extent: ovalDiameter. innerRect := 0 at 0 extent: innerDiameter. height := 1. outer := EllipseMidpointTracer new on: ovalRect. inner := EllipseMidpointTracer new on: innerRect. nextY := ovalRadius y. 1 to: (wp y min: nextY) do:[:i| nextOuterX := outer stepInY. width := nextOuterX * 2 + rectWidth. destX := rectX - nextOuterX. destY := rectY - nextY. self copyBits. destY := rectY + nextY + rectHeight - 1. self copyBits. nextY := nextY - 1. ]. [nextY > 0] whileTrue:[ nextOuterX := outer stepInY. nextInnerX := inner stepInY. destX := rectX - nextOuterX. destY := rectY - nextY. width := nextOuterX - nextInnerX. self copyBits. destX := rectX + nextInnerX + rectWidth. self copyBits. destX := rectX - nextOuterX. destY := rectY + nextY + rectHeight-1. self copyBits. destX := rectX + nextInnerX + rectWidth. self copyBits. nextY := nextY - 1. ]. destX := aRectangle left. destY := rectOffset y. height := rectHeight. width := wp x. self copyBits. destX := aRectangle right - width. self copyBits. innerRadius y = 0 ifTrue:[ destX := aRectangle left + wp x. destY := rectY. + width := aRectangle width - (wp x * 2). - width := rectWidth. height := wp y - ovalRadius y. self copyBits. destY := aRectangle bottom - wp y. self copyBits. ].! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: pastedImage.png Type: image/png Size: 32965 bytes Desc: pastedImage.png URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: pastedImage.png Type: image/png Size: 31298 bytes Desc: pastedImage.png URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Fri Apr 30 18:06:34 2021 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Fri, 30 Apr 2021 18:06:34 +0000 Subject: [squeak-dev] The Trunk: Tests-nice.458.mcz In-Reply-To: <985F8BA7-BDE9-4BD3-8A9C-9F1883E5FDFC@rowledge.org> References: <8c3676cc5b4f43b390ea6f67ae7087aa@student.hpi.uni-potsdam.de>, <985F8BA7-BDE9-4BD3-8A9C-9F1883E5FDFC@rowledge.org> Message-ID: > Tools to help workflow are always welcome; lack of them almost always results in potentially good ideas getting lost in the mire. (Think traits, for example) And how can we fight this development? Better visibility/PR? :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von tim Rowledge Gesendet: Freitag, 30. April 2021 19:15:56 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Tests-nice.458.mcz > On 2021-04-30, at 10:09 AM, Thiede, Christoph wrote: > > But let's take this as something positive and inspirative instead. :-) Do we maybe need a new tool for this? Tools to help workflow are always welcome; lack of them almost always results in potentially good ideas getting lost in the mire. (Think traits, for example) tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Strange OpCodes: DPN: Double Precision No-op -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Fri Apr 30 18:58:46 2021 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 30 Apr 2021 20:58:46 +0200 Subject: [squeak-dev] The Trunk: Tests-nice.458.mcz In-Reply-To: References: <8c3676cc5b4f43b390ea6f67ae7087aa@student.hpi.uni-potsdam.de> <985F8BA7-BDE9-4BD3-8A9C-9F1883E5FDFC@rowledge.org> Message-ID: Hi Christoph, sorry, i forgot to check the inbox. The change itself was easy. I spent time searching the origin of the change, if it was a VM change or an image change (or both), and the reason for it. Le ven. 30 avr. 2021 à 20:06, Thiede, Christoph a écrit : > > > Tools to help workflow are always welcome; lack of them almost always results in potentially good ideas getting lost in the mire. (Think traits, for example) > > > And how can we fight this development? Better visibility/PR? :-) > > > Best, > > Christoph > > ________________________________ > Von: Squeak-dev im Auftrag von tim Rowledge > Gesendet: Freitag, 30. April 2021 19:15:56 > An: The general-purpose Squeak developers list > Betreff: Re: [squeak-dev] The Trunk: Tests-nice.458.mcz > > > > > On 2021-04-30, at 10:09 AM, Thiede, Christoph wrote: > > > > But let's take this as something positive and inspirative instead. :-) Do we maybe need a new tool for this? > > Tools to help workflow are always welcome; lack of them almost always results in potentially good ideas getting lost in the mire. (Think traits, for example) > > tim > -- > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim > Strange OpCodes: DPN: Double Precision No-op > > > > From commits at source.squeak.org Fri Apr 30 19:36:52 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 19:36:52 0000 Subject: [squeak-dev] The Trunk: Tests-nice.460.mcz Message-ID: Nicolas Cellier uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-nice.460.mcz ==================== Summary ==================== Name: Tests-nice.460 Author: nice Time: 30 April 2021, 9:36:50.260749 pm UUID: 2996ccbb-9955-4399-ace4-4a61c14fc0d0 Ancestors: Tests-nice.459 Integrate test from Jaromir showing the expected behavior of outer. Thanks Jaromir. See https://source.squeak.org/treated/Tests-jar.454.diff https://source.squeak.org/treated/Tests-jar.455.diff https://source.squeak.org/treated/Tests-jar.456.diff =============== Diff against Tests-nice.459 =============== Item was added: + ----- Method: ExceptionTester>>doubleOuterTestResults (in category 'signaledException results') ----- + doubleOuterTestResults + + ^OrderedCollection new + add: self doSomethingString; + add: self doYetAnotherThingString; + add: self doSomethingElseString; + yourself! Item was added: + ----- Method: ExceptionTester>>simpleOuterDefaultReturnTest (in category 'signaledException tests') ----- + simpleOuterDefaultReturnTest + "uses #resume" + + [[self doSomething. + MyTestNotification signal. + "self doSomethingElse" + self doSomethingExceptional] + on: MyTestNotification + do: [:ex | ex outer]. self doSomethingElse] + on: MyTestNotification + do: [:ex | self doYetAnotherThing. ex resume]! Item was added: + ----- Method: ExceptionTester>>simpleOuterDefaultReturnTestResults (in category 'signaledException results') ----- + simpleOuterDefaultReturnTestResults + + ^OrderedCollection new + add: self doSomethingString; + add: self doYetAnotherThingString; + add: self doSomethingElseString; + yourself! Item was added: + ----- Method: ExceptionTester>>simpleOuterReturnTest (in category 'signaledException tests') ----- + simpleOuterReturnTest + "uses #resume" + + [[self doSomething. + MyTestNotification signal. + "self doSomethingElse" + self doSomethingExceptional] + on: MyTestNotification + do: [:ex | ex outer. ex return]. self doSomethingElse] + on: MyTestNotification + do: [:ex | self doYetAnotherThing. ex resume]! Item was added: + ----- Method: ExceptionTester>>simpleOuterReturnTestResults (in category 'signaledException results') ----- + simpleOuterReturnTestResults + + ^OrderedCollection new + add: self doSomethingString; + add: self doYetAnotherThingString; + add: self doSomethingElseString; + yourself! Item was added: + ----- Method: ExceptionTests>>testDoubleOuterDoubleResumeTest (in category 'tests - ExceptionTester') ----- + testDoubleOuterDoubleResumeTest + + | path | + path := ''. + [path := path, '1'. + [path := path, '2'. + [1/0] on: ZeroDivide do: [:ex | ex outer. path := path, '5'. ex return]. + path := path, '6' + ] on: ZeroDivide do: [:ex | ex outer. path := path, '4'. ex resume]. + path := path, '7' + ] on: ZeroDivide do: [:ex | path := path, '3'. ex resume]. + self assert: path = '1234567'! Item was added: + ----- Method: ExceptionTests>>testDoubleOuterTest (in category 'tests - ExceptionTester') ----- + testDoubleOuterTest + self assertSuccess: (ExceptionTester new runTest: #doubleOuterTest ) ! Item was added: + ----- Method: ExceptionTests>>testSimpleOuterReturn (in category 'tests - ExceptionTester') ----- + testSimpleOuterReturn + self assertSuccess: (ExceptionTester new runTest: #simpleOuterReturnTest ) ! From commits at source.squeak.org Fri Apr 30 19:45:32 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 19:45:32 0000 Subject: [squeak-dev] The Trunk: Kernel-jar.1395.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-jar.1395.mcz ==================== Summary ==================== Name: Kernel-jar.1395 Author: jar Time: 30 April 2021, 12:25:17.561362 am UUID: 0f589a20-6b8e-a94b-9dbc-9b3f91c84ce8 Ancestors: Kernel-nice.1394 Fix a bug in Exception>>#outer causing a return to an incorrect handler context. Explanation in: http://forum.world.st/A-bug-in-Exception-gt-gt-outer-causing-a-return-to-an-incorrect-handler-context-td5129273.html =============== Diff against Kernel-nice.1394 =============== Item was changed: ----- Method: Exception>>outer (in category 'handling') ----- outer "Evaluate the enclosing exception action and return to here instead of signal if it resumes (see #resumeUnchecked:)." + | prevOuterContext currHandlerContext | - | prevOuterContext | self isResumable ifTrue: [ + currHandlerContext := handlerContext. prevOuterContext := outerContext. outerContext := thisContext contextTag. ]. self pass. ! Item was changed: ----- Method: Exception>>resumeUnchecked: (in category 'handling') ----- resumeUnchecked: resumptionValue "Return resumptionValue as the value of #signal, unless this was called after an #outer message, then return resumptionValue as the value of #outer." | ctxt | outerContext ifNil: [ signalContext return: resumptionValue ] ifNotNil: [ ctxt := outerContext. outerContext := ctxt tempAt: 1. "prevOuterContext in #outer" + handlerContext := ctxt tempAt: 2. "currHandlerContext in #outer" ctxt return: resumptionValue ]. ! From commits at source.squeak.org Fri Apr 30 19:49:01 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 19:49:01 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1397.mcz Message-ID: Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1397.mcz ==================== Summary ==================== Name: Kernel-nice.1397 Author: nice Time: 30 April 2021, 9:48:57.972338 pm UUID: df20ab21-bba8-4919-b4a1-d2c7a6c6e8de Ancestors: Kernel-mt.1396, Kernel-jar.1395 merge Kernel-jar.1395 (fix outer) =============== Diff against Kernel-mt.1396 =============== Item was changed: ----- Method: Exception>>outer (in category 'handling') ----- outer "Evaluate the enclosing exception action and return to here instead of signal if it resumes (see #resumeUnchecked:)." + | prevOuterContext currHandlerContext | - | prevOuterContext | self isResumable ifTrue: [ + currHandlerContext := handlerContext. prevOuterContext := outerContext. outerContext := thisContext contextTag. ]. self pass. ! Item was changed: ----- Method: Exception>>resumeUnchecked: (in category 'handling') ----- resumeUnchecked: resumptionValue "Return resumptionValue as the value of #signal, unless this was called after an #outer message, then return resumptionValue as the value of #outer." | ctxt | outerContext ifNil: [ signalContext return: resumptionValue ] ifNotNil: [ ctxt := outerContext. outerContext := ctxt tempAt: 1. "prevOuterContext in #outer" + handlerContext := ctxt tempAt: 2. "currHandlerContext in #outer" ctxt return: resumptionValue ]. ! From commits at source.squeak.org Fri Apr 30 20:07:20 2021 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 30 Apr 2021 20:07:20 0000 Subject: [squeak-dev] The Trunk: KernelTests-nice.403.mcz Message-ID: Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.403.mcz ==================== Summary ==================== Name: KernelTests-nice.403 Author: nice Time: 30 April 2021, 10:07:18.128533 pm UUID: 6c2a630e-15b7-461c-8bdc-86190918cc71 Ancestors: KernelTests-nice.402 Add two tests for isDenormal and isFinite =============== Diff against KernelTests-nice.402 =============== Item was added: + ----- Method: FloatTest>>testIsDenormal (in category 'tests - characterization') ----- + testIsDenormal + self assert: Float fminNormalized predecessor isDenormal. + self assert: Float fminDenormalized isDenormal. + self assert: Float fminDenormalized negated isDenormal. + + self deny: Float fminNormalized isDenormal. + self deny: 0.0 isDenormal. + self deny: 1.0 isDenormal. + self deny: Float fmax isDenormal. + self deny: Float infinity isDenormal. + self deny: Float negativeInfinity isDenormal. + self deny: Float nan isDenormal.! Item was added: + ----- Method: FloatTest>>testIsFinite (in category 'tests - characterization') ----- + testIsFinite + self assert: Float fminDenormalized isFinite. + self assert: 0.0 isFinite. + self assert: Float pi negated isFinite. + self assert: Float fmax isFinite. + + self deny: Float infinity isFinite. + self deny: Float negativeInfinity isFinite. + self deny: Float nan isFinite.! From leves at caesar.elte.hu Fri Apr 30 20:42:20 2021 From: leves at caesar.elte.hu (Levente Uzonyi) Date: Fri, 30 Apr 2021 22:42:20 +0200 (CEST) Subject: [squeak-dev] Dictionary >> #at:ifAbsentPut:ifPresentPut: In-Reply-To: <8d6d63a2257344c7853cbf45603de7cb@student.hpi.uni-potsdam.de> References: <8d6d63a2257344c7853cbf45603de7cb@student.hpi.uni-potsdam.de> Message-ID: On Fri, 30 Apr 2021, Thiede, Christoph wrote: > > Hi all, > > > recently I stumbled upon an extension method for Dictionary which *might* fit well into the Trunk: > > > Dictionary >> #at: key ifAbsentPut: startBlock ifPresentPut: nextBlock > "(c) 2020 Basti Kruck und Marcel Taeumel. :-)" (self includesKey: key) ifFalse: [ > ^ self at: key put: startBlock value]. ^ self > at: key > put: (nextBlock value: (self at: key)) > > See https://github.com/hpi-swa/vivide/blob/c4ac5ea562bd563358d52ee41c149a3fbcffd90e/repository/Vivide.package/Dictionary.extension/instance/at.ifAbsentPut.ifPresentPut..st. > > > Usage: > > counter := counters at: key ifAbsentPut: [0] ifPresentPut: [:i | i + 1] > > What do you think, should we copy this into the Trunk? Or is it just fine to do something like this instead at the sender side: > > counter := counters at: key put: (counters at: key ifAbsent: [0] ifPresent: [:i | i + 1]) The alternative I would use is the following: counter := counters at: key put: (counters at: key ifAbsent: [0]) + 1 And I think that is good enough. If wanted to have a special method for that case, I would try to look up the key only once. Levente From dev at stlutz.net Fri Apr 30 23:26:38 2021 From: dev at stlutz.net (stlutz) Date: Fri, 30 Apr 2021 18:26:38 -0500 (CDT) Subject: [squeak-dev] Dictionary >> #at:ifAbsentPut:ifPresentPut: In-Reply-To: References: <8d6d63a2257344c7853cbf45603de7cb@student.hpi.uni-potsdam.de> Message-ID: <1619825198885-0.post@n4.nabble.com> Christoph Thiede wrote > What do you think, should we copy this into the Trunk? Personally, I'd get good use out of at:ifPresentPut: and at:ifPresentPut:ifAbsentPut:. I seriously considered adding them as extensions in a couple of projects. Christoph Thiede wrote > Also, I'm not sure about the order of arguments. The pattern other selectors in Squeak follow is present first, absent second. We should probably keep to that pattern. Tobias Pape wrote > I find it a bit too specific for trunk. > It's quite an edge case... FWIW I encountered this case quite a few times over the years. It's essentially always a concern when storing and updating value objects in dictionaries. Levente Uzonyi wrote > If wanted to have a special method for that case, I would try to look up > the key only once. +1 Stephan -- Sent from: http://forum.world.st/Squeak-Dev-f45488.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Fri Apr 30 23:40:11 2021 From: tim at rowledge.org (tim Rowledge) Date: Fri, 30 Apr 2021 16:40:11 -0700 Subject: [squeak-dev] The Trunk: Tests-nice.458.mcz In-Reply-To: References: <8c3676cc5b4f43b390ea6f67ae7087aa@student.hpi.uni-potsdam.de> <985F8BA7-BDE9-4BD3-8A9C-9F1883E5FDFC@rowledge.org> Message-ID: <11BF7E9C-D582-4F50-84BF-49802524BBBE@rowledge.org> > On 2021-04-30, at 11:06 AM, Thiede, Christoph wrote: > > > Tools to help workflow are always welcome; lack of them almost always results in potentially good ideas getting lost in the mire. (Think traits, for example) > > And how can we fight this development? Better visibility/PR? :-) The ideal - you know, that situation that we all pretend to aim for but never get close to achieving - would be that if one creates a new facility (traits, environments, private methods, any sort of abstracting trick) you also create tools and additions to existing tools that make it easy to use the new idea. And until you do, it does not get added to Trunk. Obviously I'm not demanding that the individual must necessarily do this; solving these kinds of problem is what a community ought to be good for. But not putting some new thing into Trunk until the cycle is complete seems like a helpful idea. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- Cackles a lot, but I ain't seen no eggs yet.