From commits at source.squeak.org Thu Nov 3 14:28:56 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 3 Nov 2022 14:28:56 0000 Subject: [squeak-dev] The Inbox: Monticello-ct.786.mcz Message-ID: <20221103142859.446A114D69C@mail.squeak.org> Christoph Thiede uploaded a new version of Monticello to project The Inbox: http://source.squeak.org/inbox/Monticello-ct.786.mcz ==================== Summary ==================== Name: Monticello-ct.786 Author: ct Time: 3 November 2022, 3:28:11.978571 pm UUID: 66a5da38-fa37-8d4a-a77c-deee412d8c1f Ancestors: Monticello-mt.782 Proposal: Handles double-click in some Monticello tools. Double-click on a repository in the working copy browser opens the repository, double-click on a version in a repository inspector browses the version. =============== Diff against Monticello-mt.782 =============== Item was changed: ----- Method: MCRepositoryInspector>>widgetSpecs (in category 'morphic ui') ----- widgetSpecs ^#( ((buttonRow) (0 0 1 0) (0 0 0 defaultButtonPaneHeight)) ((listMorph: package) (0 0 0.5 0.6) (0 defaultButtonPaneHeight 0 0)) + ((listMorph:invoke: version browse) (0.5 0 1 0.6) (0 defaultButtonPaneHeight 0 0)) - ((listMorph: version) (0.5 0 1 0.6) (0 defaultButtonPaneHeight 0 0)) ((textMorph: summary) (0 0.6 1 1) (0 0 0 0)) )! Item was changed: ----- Method: MCToolWindowBuilder>>listMorph: (in category 'building-parts') ----- listMorph: listSymbol ^ self + listMorph: listSymbol + invoke: nil! - listMorph: (listSymbol, 'List') asSymbol - selection: (listSymbol, 'Selection') asSymbol - menu: (listSymbol, 'ListMenu:') asSymbol! Item was added: + ----- Method: MCToolWindowBuilder>>listMorph:invoke: (in category 'building-parts') ----- + listMorph: listSymbol invoke: invokeSymbol + ^ self + listMorph: (listSymbol, 'List') asSymbol + selection: (listSymbol, 'Selection') asSymbol + menu: (listSymbol, 'ListMenu:') asSymbol + keystroke: nil + invoke: invokeSymbol! Item was changed: ----- Method: MCToolWindowBuilder>>listMorph:selection:menu:keystroke: (in category 'building-parts') ----- listMorph: listSymbol selection: selectionSymbol menu: menuSymbol keystroke: keystrokeSymbol + + ^ self listMorph: listSymbol selection: selectionSymbol menu: menuSymbol keystroke: keystrokeSymbol invoke: nil! - | list | - list := builder pluggableListSpec new. - list - model: tool; - list: listSymbol; - getIndex: selectionSymbol; - setIndex: (selectionSymbol, ':') asSymbol; - frame: currentFrame. - menuSymbol ifNotNil: [list menu: menuSymbol]. - keystrokeSymbol ifNotNil: [list keyPress: keystrokeSymbol]. - currentComposite children add: list - ! Item was added: + ----- Method: MCToolWindowBuilder>>listMorph:selection:menu:keystroke:invoke: (in category 'building-parts') ----- + listMorph: listSymbol selection: selectionSymbol menu: menuSymbol keystroke: keystrokeSymbol invoke: invokeSymbol + | list | + list := builder pluggableListSpec new. + list + model: tool; + list: listSymbol; + getIndex: selectionSymbol; + setIndex: (selectionSymbol, ':') asSymbol; + frame: currentFrame. + menuSymbol ifNotNil: [list menu: menuSymbol]. + keystrokeSymbol ifNotNil: [list keyPress: keystrokeSymbol]. + invokeSymbol ifNotNil: [list doubleClick: invokeSymbol]. + currentComposite children add: list + ! Item was changed: ----- Method: MCWorkingCopyBrowser>>widgetSpecs (in category 'morphic ui') ----- widgetSpecs ^ #( ((buttonRow) (0 0 1 0) (0 0 0 defaultButtonPaneHeight)) ((treeOrListMorph: workingCopy) (0 0 0.5 1) (0 defaultButtonPaneHeight 0 0)) + ((listMorph:invoke: repository openRepository) (0.5 0 1 1) (0 defaultButtonPaneHeight 0 0)) - ((listMorph: repository) (0.5 0 1 1) (0 defaultButtonPaneHeight 0 0)) )! From christoph.thiede at student.hpi.uni-potsdam.de Fri Nov 4 15:08:02 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Fri, 4 Nov 2022 16:08:02 +0100 Subject: [squeak-dev] Review Request: recursive-profaide.2.cs Message-ID: <5f31028e-fbe6-497a-8c88-e6947ac3dd10@MX2018-DAG2.hpi.uni-potsdam.de> I will leave this for one more week in the inbox and then merge it into the Trunk if you don't see any other problems. :-) Best, Christoph =============== Summary =============== Change Set:��������recursive-profaide Date:������������4 November 2022 Author:������������Christoph Thiede Adds support for recursive process-faithful debugging and tests. Without this patch, debugging the debugger for a process which sends Processor activeProcess will have a different effect than running the original debugger directly. This is kind of a delayed follow-up on Kernel-mt.1381. Thanks to Marcel for discussing this issue! =============== Diff =============== DebuggerTests>>test25ProcessFaithfulDebugging {tests} � ct 11/4/2022 15:46 + test25ProcessFaithfulDebugging + ����"Debugging a process which sends Processor activeProcess should have the same effect as running the process directly. End-to-end equivalent for ProcessTest>>#testProcessFaithfulSimulation." + + ����| userProcess | + ����process := Process forBlock: [ + ��������Processor activeProcess environmentAt: #plonk put: 42. + ��������Processor activeProcess suspend. + ��������Processor activeProcess environmentAt: #plonk]. + ����process resume. + ����Processor yield. + ����self assert: (process environmentAt: #plonk) = 42. + ���� + ����debugger := process debug. + ���� + ����[userProcess := [debugger stepOver "suspend"; stepOver "activeProcess"; stepOver "environmentAt:"] fork. + ����Processor yield. + ���� + ����self deny: [process isTerminated]. + ����self assert: [userProcess isTerminated]. + ����self assert: [process suspendedContext willReturn and: [process suspendedContext top = 42]]. + ����self assert: (userProcess environmentAt: #plonk ifAbsent: []) = nil] + �������� + ��������ensure: [ + ������������process terminateAggressively. + ������������debugger close. + ������������process := userProcess. + ������������self findDebugger "for correct tearDown"]. DebuggerTests>>test26RecursiveProcessFaithfulDebugging {tests} � ct 11/4/2022 15:46 + test26RecursiveProcessFaithfulDebugging + ����"Debugging the debugger for a process which sends Processor activeProcess should have the same effect as running the original debugger directly. End-to-end equivalent for ProcessTest>>#testProcessFaithfulSimulationMeta." + + ����| userProcess metaDebugger metaProcess | + ����process := Process forBlock: [ + ��������Processor activeProcess environmentAt: #plonk put: 42. + ��������Processor activeProcess suspend. + ��������Processor activeProcess environmentAt: #plonk]. + ����process resume. + ����Processor yield. + ����self assert: (process environmentAt: #plonk) = 42. + ���� + ����debugger := process debug. + ����metaProcess := Process forBlock: [ + ��������[debugger stepOver "suspend"; stepOver "activeProcess"; stepOver "environmentAt:"] value]. + ����metaDebugger := metaProcess debug. + ���� + ����[userProcess := [metaDebugger stepOver "value"] fork. + ����Processor yield. + ���� + ����self deny: [process isTerminated]. + ����self assert: [userProcess isTerminated]. + ����self assert: [process suspendedContext willReturn and: [process suspendedContext top = 42]]. + ����self assert: (userProcess environmentAt: #plonk ifAbsent: []) = nil] + �������� + ��������ensure: [ + ������������process terminateAggressively. + ������������debugger close. + ������������metaProcess terminateAggressively. + ������������metaDebugger close. + ������������process := userProcess. + ������������self findDebugger "for correct tearDown"]. Process>>effectiveProcess {accessing} � ct 11/4/2022 15:38 (changed) effectiveProcess - ����"effectiveProcess is a mechanism to allow process-faithful debugging. The debugger executes code - ���� on behalf of processes, so unless some effort is made the identity of Processor activeProcess is not - ���� correctly maintained when debugging code. The debugger uses evaluate:onBehalfOf: to assign the - ���� debugged process as the effectiveProcess of the process executing the code, preserving process - ���� identity." - ����^effectiveProcess ifNil: [self] + ����"effectiveProcess is a mechanism to allow process-faithful debugging. The debugger executes code on behalf of processes, so unless some effort is made the identity of Processor activeProcess is not correctly maintained when debugging code. The debugger uses evaluate:onBehalfOf: to assign the debugged process as the effectiveProcess of the process executing the code, preserving process identity." + ����^effectiveProcess + �������� ifNil: [self] + ��������ifNotNil: [:p | + ������������"Recursive process-faithful debugging. See DebuggerTests>>#test25RecursiveProcessFaithfulDebugging for a practical example." + ������������p effectiveProcess] ProcessTest>>testProcessFaithfulSimulationMeta {tests} � ct 12/7/2020 17:22 + testProcessFaithfulSimulationMeta + ����"While stacking multiple simulation processes into each other, process variables should be looked up in the process being simulated. Acceptance test for process-faithful debugging, see #evaluate:onBehalfOf:." + + ����| process result metaProcess | + ����process := Process forBlock: [ + ��������result := Processor activeProcess environmentAt: #foo]. + ����process environmentAt: #foo put: 42. + ���� + ����metaProcess := Process forBlock: [ + ��������process runUntil: [:context | context isDead]]. + ����metaProcess runUntil: [:context | context isDead]. + ���� + ����self assert: 42 equals: result. --- Sent from Squeak Inbox Talk ["recursive-profaide.2.cs"] -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: recursive-profaide.2.cs Type: application/octet-stream Size: 4319 bytes Desc: not available URL: From commits at source.squeak.org Fri Nov 4 15:20:56 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 4 Nov 2022 15:20:56 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.2052.mcz Message-ID: <20221104152102.1F8D414D634@mail.squeak.org> Christoph Thiede uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.2052.mcz ==================== Summary ==================== Name: Morphic-ct.2052 Author: ct Time: 4 November 2022, 4:20:08.148791 pm UUID: b49f6fa4-1658-bf49-89ae-5dcb08e955af Ancestors: Morphic-mt.2051 Makes scratch pad scale-factor-aware and improves multilingual support. =============== Diff against Morphic-mt.2051 =============== Item was changed: ----- Method: SearchBar>>layoutScratchPad (in category 'private') ----- layoutScratchPad | world pos width | world := Project current world. world mainDockingBars do: [ : each | each searchBarMorph ifNotNil: [ : searchBar | pos := searchBar bottomLeft. width := searchBar width ] ]. + width ifNil: [ width := 250 px. pos := world topRight - (width @ 5 px) ]. - width ifNil: [ width := 250. pos := world topRight - (width @ 5) ]. scratchPad width: width ; position: pos ; startStepping: #deleteUnlessHasFocus at: Time millisecondClockValue arguments: nil stepTime: 3000! Item was changed: ----- Method: SearchBar>>printIt:result: (in category 'do-its') ----- printIt: code result: object | focusedWidget | focusedWidget := self currentHand keyboardFocus. self removeResultsWidget. ToolBuilder default in: [:builder | resultsWidget := (builder build: (StringHolder new contents: object asString; buildCodePaneWith: builder)). "This might cause the widget disappear to early. Especially if the textMorph is to small but the container needs to maintain a larger size because of its scroll bars." resultsWidget textMorph on: #mouseLeave send: #delete to: resultsWidget. resultsWidget + extent: 1000 px @ 1000 px; fullBounds; "give text a chance to layout good" + width: 250 px; fullBounds; + height: (resultsWidget extentToFit y min: 300 px); - extent: 1000 at 1000; fullBounds; "give text a chance to layout good" - width: 250; fullBounds; - height: (resultsWidget extentToFit y min: 300); position: (focusedWidget ifNotNil: [:w | w owner boundsInWorld bottomLeft] ifNil: [self currentHand position]); color: (BalloonMorph balloonColor alpha: 1.0). Preferences menuAppearance3d ifTrue: [resultsWidget addDropShadow]. resultsWidget openInWorld].! Item was changed: ----- Method: SearchBar>>scratchPad (in category 'accessing') ----- scratchPad ^ scratchPad ifNil: [ scratchPad := TextMorphForEditView new. "we should be able to use TextMorph here; fix later" scratchPad " on: #keyboardFocusChange send: #removeScratchPad to: self ;" on: #mouseLeave send: #removeScratchPad to: self ; on: #keyStroke send: #handleScratchPadKey: to: self ; + margins: (5 px @ 0 corner: 5 px @ 0); - margins: (5 at 0 corner: 5 at 0); backgroundColor: ((UserInterfaceTheme current get: #color for: #NewBalloonMorph) ifNil: [ BalloonMorph balloonColor ]) ; setEditView: PluggableTextMorph new ; "dummy" autoFit: true ; wrapFlag: true ; + newContents: '--scratch area--' translated; - newContents: '--scratch area--' ; font: ((UserInterfaceTheme current get: #font for: #PluggableTextMorph) ifNil: [TextStyle defaultFont]); textColor: ((UserInterfaceTheme current get: #textColor for: #PluggableTextMorph) ifNil: [Color black]); caretColor: ((UserInterfaceTheme current get: #caretColor for: #PluggableTextMorph) ifNil: [Color red]); selectionColor: ((UserInterfaceTheme current get: #selectionColor for: #PluggableTextMorph) ifNil: [Color blue muchDarker] ifNotNil: [ : col | col twiceLighter ]); yourself. self layoutScratchPad. Preferences menuAppearance3d ifTrue: [ scratchPad addDropShadow ]. scratchPad ]! 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]. "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 {1}' translated format: {input})]]. - 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.' translated. - 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 Sat Nov 5 20:36:27 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 5 Nov 2022 20:36:27 0000 Subject: [squeak-dev] The Trunk: VersionNumber-eem.5.mcz Message-ID: <20221105203630.73A0B14D83F@mail.squeak.org> Eliot Miranda uploaded a new version of VersionNumber to project The Trunk: http://source.squeak.org/trunk/VersionNumber-eem.5.mcz ==================== Summary ==================== Name: VersionNumber-eem.5 Author: eem Time: 5 November 2022, 1:36:25.499057 pm UUID: 8883b385-6d1b-4659-b488-c677c700707a Ancestors: VersionNumber-cmm.4 Fix VersionNumber>>< so that version numbers of different lengths can be compared. e.g. 1.8 is clearly less than 1.7.4. At the same time fix the comparison so that it terminates as soon as a difference is found. =============== Diff against VersionNumber-cmm.4 =============== Item was changed: ----- Method: VersionNumber>>< (in category 'comparing') ----- < another + "Answer whether the receiver is less than the argument, another VersionNumber." - "Answer whether the receiver is less than the argument." + | tmp thisSize thatSize this that | - | tmp | - (self inSameBranchAs: another) ifFalse: - [^self error: 'Receiver and argument in different branches']. - tmp := another numbers. + thisSize := numbers size. + thatSize := tmp size. + 1 to: (thisSize min: thatSize) do: + [:i| + (this := numbers at: i) = (that := tmp at: i) ifFalse: + [^this < that]]. + ^thisSize < thatSize! - (tmp size = numbers size) ifTrue: - [1 to: numbers size do: - [ :in | (numbers at: in) < (tmp at: in) ifTrue: [^true]]. - ^false]. - - ^numbers size < tmp size - ! From aj.bertrand at free.fr Sun Nov 6 12:08:00 2022 From: aj.bertrand at free.fr (BERTRAND AJ) Date: Sun, 6 Nov 2022 13:08:00 +0100 Subject: [squeak-dev] problem with accent characters in fileIn (squeak 5.3) Message-ID: <85c33232-33d4-5b84-4722-99c8329d51d7@free.fr> l’m new on this list, so sorry if i am not in the correct use. I have problems with accent characters in fileOut and subsequent fileIn (éèà) because i'm French It seems that Squeak saves fileOut files always in UTF8 now, but uses a converter not UTF8 for the fileIn. With the following modification it works for me, but i did not try all cases so... The modif is : MultiByteFileStream >> setConverterForCode setConverterForCode     | currentPosition |     (SourceFiles at: 2)         ifNotNil: [self fullName = (SourceFiles at: 2) fullName ifTrue: [^ self]].     "currentPosition := self position.     self position: 0.     self binary.     ((self next: 3) = #[ 16rEF 16rBB 16rBF ]) ifTrue: ["         self converter: UTF8TextConverter new     "] ifFalse: [         self converter: MacRomanTextConverter new.     ].     self position: currentPosition."     self text. with this modification, Squeak will always use UTF8TextConverter -- André Jacques BERTRAND, From lewis at mail.msen.com Sun Nov 6 18:23:00 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Sun, 6 Nov 2022 13:23:00 -0500 Subject: [squeak-dev] problem with accent characters in fileIn (squeak 5.3) In-Reply-To: <85c33232-33d4-5b84-4722-99c8329d51d7@free.fr> References: <85c33232-33d4-5b84-4722-99c8329d51d7@free.fr> Message-ID: <20221106182300.GA44067@shell.msen.com> Hello Andr??, On Sun, Nov 06, 2022 at 01:08:00PM +0100, BERTRAND AJ wrote: > l???m new on this list, so sorry if i am not in the correct use. > Yes, this is the right list, and thank you for contributing. > I have problems with accent characters in fileOut and subsequent fileIn > (??????) because i'm French > > It seems that Squeak saves fileOut files always in UTF8 now, but uses a > converter not UTF8 for the fileIn. > > With the following modification it works for me, but i did not try all > cases so... You are right that UTF8 conversion in required. There is actually a fix for this issue in the newer Squeak 6.0 release, but it is part of a much larger set of changes so I do not know if it is easy to back port to Squeak 5.3. Maybe Marcel Taeumel can comment. Marcel, would it make sense to back port just the MultiByteFileStream>>setConverterForCode method to the Squeak53 repository? To avoid name collision with trunk we might want to commit it as a "branch" (e.g. "Multilingual.backport-xyz.254") with an update map entry, I can help with that if you think it is a good idea to backport the method. Dave > > The modif is : > > MultiByteFileStream >> setConverterForCode > setConverterForCode > ???? ??| currentPosition | > ???? ??(SourceFiles at: 2) > ???? ???????? ifNotNil: [self fullName = (SourceFiles at: 2) fullName > ifTrue: [^ self]]. > ???? ??"currentPosition := self position. > ???? ??self position: 0. > ???? ??self binary. > ???? ??((self next: 3) = #[ 16rEF 16rBB 16rBF ]) ifTrue: [" > ???? ???????? self converter: UTF8TextConverter new > ???? ??"] ifFalse: [ > ???? ???????? self converter: MacRomanTextConverter new. > ???? ??]. > ???? ??self position: currentPosition." > ???? ??self text. > > with this modification, Squeak will always use UTF8TextConverter > > -- > Andr?? Jacques BERTRAND, > > From marcel.taeumel at hpi.de Mon Nov 7 06:44:00 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 7 Nov 2022 07:44:00 +0100 Subject: [squeak-dev] The Trunk: VersionNumber-eem.5.mcz In-Reply-To: <20221105203630.73A0B14D83F@mail.squeak.org> References: <20221105203630.73A0B14D83F@mail.squeak.org> Message-ID: > e.g. 1.8 is clearly less than 1.7.4 Eh, no it is not? If less means older here ... Best, Marcel Am 05.11.2022 21:36:40 schrieb commits at source.squeak.org : Eliot Miranda uploaded a new version of VersionNumber to project The Trunk: http://source.squeak.org/trunk/VersionNumber-eem.5.mcz ==================== Summary ==================== Name: VersionNumber-eem.5 Author: eem Time: 5 November 2022, 1:36:25.499057 pm UUID: 8883b385-6d1b-4659-b488-c677c700707a Ancestors: VersionNumber-cmm.4 Fix VersionNumber>> =============== Diff against VersionNumber-cmm.4 =============== Item was changed: ----- Method: VersionNumber>> + "Answer whether the receiver is less than the argument, another VersionNumber." - "Answer whether the receiver is less than the argument." + | tmp thisSize thatSize this that | - | tmp | - (self inSameBranchAs: another) ifFalse: - [^self error: 'Receiver and argument in different branches']. - tmp := another numbers. + thisSize := numbers size. + thatSize := tmp size. + 1 to: (thisSize min: thatSize) do: + [:i| + (this := numbers at: i) = (that := tmp at: i) ifFalse: + [^this + ^thisSize - (tmp size = numbers size) ifTrue: - [1 to: numbers size do: - [ :in | (numbers at: in) - ^false]. - - ^numbers size - ! -------------- next part -------------- An HTML attachment was scrubbed... URL: From Das.Linux at gmx.de Mon Nov 7 09:21:00 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 7 Nov 2022 10:21:00 +0100 Subject: [squeak-dev] The Trunk: VersionNumber-eem.5.mcz In-Reply-To: References: <20221105203630.73A0B14D83F@mail.squeak.org> Message-ID: <889A2FA5-663F-41B6-8877-5649F684FEAC@gmx.de> > On 7. Nov 2022, at 07:44, Marcel Taeumel wrote: > > > e.g. 1.8 is clearly less than 1.7.4 > > Eh, no it is not? If less means older here ... This. 1.8 is exactly the same as 1.8.0, and this sorts definitely _after_ 1.7.4 and is hence, NOT less. Best regards -Tobias > > Best, > Marcel >> Am 05.11.2022 21:36:40 schrieb commits at source.squeak.org : >> >> Eliot Miranda uploaded a new version of VersionNumber to project The Trunk: >> http://source.squeak.org/trunk/VersionNumber-eem.5.mcz >> >> ==================== Summary ==================== >> >> Name: VersionNumber-eem.5 >> Author: eem >> Time: 5 November 2022, 1:36:25.499057 pm >> UUID: 8883b385-6d1b-4659-b488-c677c700707a >> Ancestors: VersionNumber-cmm.4 >> >> Fix VersionNumber>>< so that version numbers of different lengths can be compared. e.g. 1.8 is clearly less than 1.7.4. At the same time fix the comparison so that it terminates as soon as a difference is found. >> >> =============== Diff against VersionNumber-cmm.4 =============== >> >> Item was changed: >> ----- Method: VersionNumber>>< (in category 'comparing') ----- >> < another >> + "Answer whether the receiver is less than the argument, another VersionNumber." >> - "Answer whether the receiver is less than the argument." >> >> + | tmp thisSize thatSize this that | >> - | tmp | >> - (self inSameBranchAs: another) ifFalse: >> - [^self error: 'Receiver and argument in different branches']. >> - >> tmp := another numbers. >> + thisSize := numbers size. >> + thatSize := tmp size. >> + 1 to: (thisSize min: thatSize) do: >> + [:i| >> + (this := numbers at: i) = (that := tmp at: i) ifFalse: >> + [^this < that]]. >> + ^thisSize < thatSize! >> - (tmp size = numbers size) ifTrue: >> - [1 to: numbers size do: >> - [ :in | (numbers at: in) < (tmp at: in) ifTrue: [^true]]. >> - ^false]. >> - >> - ^numbers size < tmp size >> - ! >> >> > From jakres+squeak at gmail.com Mon Nov 7 10:29:10 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 7 Nov 2022 11:29:10 +0100 Subject: [squeak-dev] The Trunk: VersionNumber-eem.5.mcz In-Reply-To: <889A2FA5-663F-41B6-8877-5649F684FEAC@gmx.de> References: <20221105203630.73A0B14D83F@mail.squeak.org> <889A2FA5-663F-41B6-8877-5649F684FEAC@gmx.de> Message-ID: If I understand the code correctly it will do the following: 1.8 < 1.8.0 "true" 1.8.0 < 1.8 "false" 1.7.4 < 1.8 "true" 1.8 < 1.7.4 "false" 1.7.4 < 1.8.0 "true" 1.8.0 < 1.7.4 "false" So concerning 1.8 vs. 1.7.4 the commit message is wrong (typo?), not the implementation. For 1.8 vs 1.8.0 your mileage may vary... but I think the new implementation is consistent with the old one in that case. One might add another line to check whether the rest of the other numbers are all 0. I do not have an image ready on this machine and cannot look into #inSameBranchAs: now. If < previously signalled the error in the 1.8 < 1.7.4 case, this would be a breaking change, depending on how applications rely on it. At work I have software where 1.7 could have been delivered later than 2.0 and may already have features that 2.0 does not have yet (which 2.1 may get and 3.0 will get). While this is not Squeak software, so practically not relevant here, it shows that the change can be debated theoretically. Are there test cases for this already? If yes, a test case should be added or one updated for the particular problem that the new commit tries to solve. Am Mo., 7. Nov. 2022 um 10:21 Uhr schrieb Tobias Pape : > > > > On 7. Nov 2022, at 07:44, Marcel Taeumel wrote: > > > > > e.g. 1.8 is clearly less than 1.7.4 > > > > Eh, no it is not? If less means older here ... > > This. > 1.8 is exactly the same as 1.8.0, and this sorts definitely _after_ 1.7.4 > and is hence, NOT less. > > Best regards > -Tobias > > > > > Best, > > Marcel > >> Am 05.11.2022 21:36:40 schrieb commits at source.squeak.org < > commits at source.squeak.org>: > >> > >> Eliot Miranda uploaded a new version of VersionNumber to project The > Trunk: > >> http://source.squeak.org/trunk/VersionNumber-eem.5.mcz > >> > >> ==================== Summary ==================== > >> > >> Name: VersionNumber-eem.5 > >> Author: eem > >> Time: 5 November 2022, 1:36:25.499057 pm > >> UUID: 8883b385-6d1b-4659-b488-c677c700707a > >> Ancestors: VersionNumber-cmm.4 > >> > >> Fix VersionNumber>>< so that version numbers of different lengths can > be compared. e.g. 1.8 is clearly less than 1.7.4. At the same time fix the > comparison so that it terminates as soon as a difference is found. > >> > >> =============== Diff against VersionNumber-cmm.4 =============== > >> > >> Item was changed: > >> ----- Method: VersionNumber>>< (in category 'comparing') ----- > >> < another > >> + "Answer whether the receiver is less than the argument, another > VersionNumber." > >> - "Answer whether the receiver is less than the argument." > >> > >> + | tmp thisSize thatSize this that | > >> - | tmp | > >> - (self inSameBranchAs: another) ifFalse: > >> - [^self error: 'Receiver and argument in different branches']. > >> - > >> tmp := another numbers. > >> + thisSize := numbers size. > >> + thatSize := tmp size. > >> + 1 to: (thisSize min: thatSize) do: > >> + [:i| > >> + (this := numbers at: i) = (that := tmp at: i) ifFalse: > >> + [^this < that]]. > >> + ^thisSize < thatSize! > >> - (tmp size = numbers size) ifTrue: > >> - [1 to: numbers size do: > >> - [ :in | (numbers at: in) < (tmp at: in) ifTrue: [^true]]. > >> - ^false]. > >> - > >> - ^numbers size < tmp size > >> - ! > >> > >> > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Das.Linux at gmx.de Mon Nov 7 11:11:24 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 7 Nov 2022 12:11:24 +0100 Subject: [squeak-dev] The Trunk: VersionNumber-eem.5.mcz In-Reply-To: References: <20221105203630.73A0B14D83F@mail.squeak.org> <889A2FA5-663F-41B6-8877-5649F684FEAC@gmx.de> Message-ID: <6FC122F4-DA41-4712-BD2F-80D4813C628A@gmx.de> Hi > On 7. Nov 2022, at 11:29, Jakob Reschke wrote: > > If I understand the code correctly it will do the following: > > 1.8 < 1.8.0 "true" > 1.8.0 < 1.8 "false" > 1.7.4 < 1.8 "true" > 1.8 < 1.7.4 "false" > 1.7.4 < 1.8.0 "true" > 1.8.0 < 1.7.4 "false" > > So concerning 1.8 vs. 1.7.4 the commit message is wrong (typo?), not the implementation. > For 1.8 vs 1.8.0 your mileage may vary... but I think the new implementation is consistent with the old one in that case. One might add another line to check whether the rest of the other numbers are all 0. Meeep. Why total order, then? from my Point of view, we should have 1.7.4 <= 1.8 <= 1.8.0 I don't think 1.8 < 1.8.0, but that's debatable anyway. However, if we're just concerned with partial order, things ought to be easier: 1.8 <= 1.8.0, but then we can also have 1.8.0 <= 1.8 which would be OK-ish for me. That said, Eliots implementation is _definitely_ an improvement over the existing one. Let's keep it and then see if we need to augment suff… Best regards -Tobias > > I do not have an image ready on this machine and cannot look into #inSameBranchAs: now. If < previously signalled the error in the 1.8 < 1.7.4 case, this would be a breaking change, depending on how applications rely on it. At work I have software where 1.7 could have been delivered later than 2.0 and may already have features that 2.0 does not have yet (which 2.1 may get and 3.0 will get). While this is not Squeak software, so practically not relevant here, it shows that the change can be debated theoretically. > > Are there test cases for this already? If yes, a test case should be added or one updated for the particular problem that the new commit tries to solve. > > > Am Mo., 7. Nov. 2022 um 10:21 Uhr schrieb Tobias Pape : > > > > On 7. Nov 2022, at 07:44, Marcel Taeumel wrote: > > > > > e.g. 1.8 is clearly less than 1.7.4 > > > > Eh, no it is not? If less means older here ... > > This. > 1.8 is exactly the same as 1.8.0, and this sorts definitely _after_ 1.7.4 and is hence, NOT less. > > Best regards > -Tobias > > > > > Best, > > Marcel > >> Am 05.11.2022 21:36:40 schrieb commits at source.squeak.org : > >> > >> Eliot Miranda uploaded a new version of VersionNumber to project The Trunk: > >> http://source.squeak.org/trunk/VersionNumber-eem.5.mcz > >> > >> ==================== Summary ==================== > >> > >> Name: VersionNumber-eem.5 > >> Author: eem > >> Time: 5 November 2022, 1:36:25.499057 pm > >> UUID: 8883b385-6d1b-4659-b488-c677c700707a > >> Ancestors: VersionNumber-cmm.4 > >> > >> Fix VersionNumber>>< so that version numbers of different lengths can be compared. e.g. 1.8 is clearly less than 1.7.4. At the same time fix the comparison so that it terminates as soon as a difference is found. > >> > >> =============== Diff against VersionNumber-cmm.4 =============== > >> > >> Item was changed: > >> ----- Method: VersionNumber>>< (in category 'comparing') ----- > >> < another > >> + "Answer whether the receiver is less than the argument, another VersionNumber." > >> - "Answer whether the receiver is less than the argument." > >> > >> + | tmp thisSize thatSize this that | > >> - | tmp | > >> - (self inSameBranchAs: another) ifFalse: > >> - [^self error: 'Receiver and argument in different branches']. > >> - > >> tmp := another numbers. > >> + thisSize := numbers size. > >> + thatSize := tmp size. > >> + 1 to: (thisSize min: thatSize) do: > >> + [:i| > >> + (this := numbers at: i) = (that := tmp at: i) ifFalse: > >> + [^this < that]]. > >> + ^thisSize < thatSize! > >> - (tmp size = numbers size) ifTrue: > >> - [1 to: numbers size do: > >> - [ :in | (numbers at: in) < (tmp at: in) ifTrue: [^true]]. > >> - ^false]. > >> - > >> - ^numbers size < tmp size > >> - ! > >> > >> > > > > > > From Das.Linux at gmx.de Mon Nov 7 11:13:23 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 7 Nov 2022 12:13:23 +0100 Subject: [squeak-dev] The Trunk: VersionNumber-eem.5.mcz In-Reply-To: <6FC122F4-DA41-4712-BD2F-80D4813C628A@gmx.de> References: <20221105203630.73A0B14D83F@mail.squeak.org> <889A2FA5-663F-41B6-8877-5649F684FEAC@gmx.de> <6FC122F4-DA41-4712-BD2F-80D4813C628A@gmx.de> Message-ID: <59D75897-FDB0-4AE7-B4E5-026F8EBF1062@gmx.de> Addendum Judging by the current class comment, VersionNumber does not deal with .0 at all. It seems to be just nothing considered... Best regards -Tobias > On 7. Nov 2022, at 12:11, Tobias Pape wrote: > > Hi > > >> On 7. Nov 2022, at 11:29, Jakob Reschke wrote: >> >> If I understand the code correctly it will do the following: >> >> 1.8 < 1.8.0 "true" >> 1.8.0 < 1.8 "false" >> 1.7.4 < 1.8 "true" >> 1.8 < 1.7.4 "false" >> 1.7.4 < 1.8.0 "true" >> 1.8.0 < 1.7.4 "false" >> >> So concerning 1.8 vs. 1.7.4 the commit message is wrong (typo?), not the implementation. >> For 1.8 vs 1.8.0 your mileage may vary... but I think the new implementation is consistent with the old one in that case. One might add another line to check whether the rest of the other numbers are all 0. > > Meeep. Why total order, then? > > from my Point of view, we should have > > 1.7.4 <= 1.8 <= 1.8.0 > > I don't think 1.8 < 1.8.0, but that's debatable anyway. > However, if we're just concerned with partial order, things ought to be easier: > > 1.8 <= 1.8.0, but then we can also have 1.8.0 <= 1.8 which would be OK-ish for me. > > That said, Eliots implementation is _definitely_ an improvement over the existing one. > Let's keep it and then see if we need to augment suff… > > Best regards > -Tobias > >> >> I do not have an image ready on this machine and cannot look into #inSameBranchAs: now. If < previously signalled the error in the 1.8 < 1.7.4 case, this would be a breaking change, depending on how applications rely on it. At work I have software where 1.7 could have been delivered later than 2.0 and may already have features that 2.0 does not have yet (which 2.1 may get and 3.0 will get). While this is not Squeak software, so practically not relevant here, it shows that the change can be debated theoretically. >> >> Are there test cases for this already? If yes, a test case should be added or one updated for the particular problem that the new commit tries to solve. >> >> >> Am Mo., 7. Nov. 2022 um 10:21 Uhr schrieb Tobias Pape : >> >> >>> On 7. Nov 2022, at 07:44, Marcel Taeumel wrote: >>> >>>> e.g. 1.8 is clearly less than 1.7.4 >>> >>> Eh, no it is not? If less means older here ... >> >> This. >> 1.8 is exactly the same as 1.8.0, and this sorts definitely _after_ 1.7.4 and is hence, NOT less. >> >> Best regards >> -Tobias >> >>> >>> Best, >>> Marcel >>>> Am 05.11.2022 21:36:40 schrieb commits at source.squeak.org : >>>> >>>> Eliot Miranda uploaded a new version of VersionNumber to project The Trunk: >>>> http://source.squeak.org/trunk/VersionNumber-eem.5.mcz >>>> >>>> ==================== Summary ==================== >>>> >>>> Name: VersionNumber-eem.5 >>>> Author: eem >>>> Time: 5 November 2022, 1:36:25.499057 pm >>>> UUID: 8883b385-6d1b-4659-b488-c677c700707a >>>> Ancestors: VersionNumber-cmm.4 >>>> >>>> Fix VersionNumber>>< so that version numbers of different lengths can be compared. e.g. 1.8 is clearly less than 1.7.4. At the same time fix the comparison so that it terminates as soon as a difference is found. >>>> >>>> =============== Diff against VersionNumber-cmm.4 =============== >>>> >>>> Item was changed: >>>> ----- Method: VersionNumber>>< (in category 'comparing') ----- >>>> < another >>>> + "Answer whether the receiver is less than the argument, another VersionNumber." >>>> - "Answer whether the receiver is less than the argument." >>>> >>>> + | tmp thisSize thatSize this that | >>>> - | tmp | >>>> - (self inSameBranchAs: another) ifFalse: >>>> - [^self error: 'Receiver and argument in different branches']. >>>> - >>>> tmp := another numbers. >>>> + thisSize := numbers size. >>>> + thatSize := tmp size. >>>> + 1 to: (thisSize min: thatSize) do: >>>> + [:i| >>>> + (this := numbers at: i) = (that := tmp at: i) ifFalse: >>>> + [^this < that]]. >>>> + ^thisSize < thatSize! >>>> - (tmp size = numbers size) ifTrue: >>>> - [1 to: numbers size do: >>>> - [ :in | (numbers at: in) < (tmp at: in) ifTrue: [^true]]. >>>> - ^false]. >>>> - >>>> - ^numbers size < tmp size >>>> - ! >>>> >>>> >>> >> >> >> >> > > > From commits at source.squeak.org Mon Nov 7 19:52:00 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 7 Nov 2022 19:52:00 0000 Subject: [squeak-dev] The Trunk: Kernel-ct.1491.mcz Message-ID: <20221107195204.E28E414D8A4@mail.squeak.org> Christoph Thiede uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-ct.1491.mcz ==================== Summary ==================== Name: Kernel-ct.1491 Author: ct Time: 7 November 2022, 8:51:11.997226 pm UUID: 78f3b27b-1a68-4d42-b796-c7edbe07870c Ancestors: Kernel-ct.1489, Kernel-ct.1294 Merges Kernel-ct.1294: Add #haltOnceIf: to Object, which combines the strengths of #haltOnce and #haltIf:. Especially useful in performance-critical situations: It HaltOnce is disabled, the condition will not be evaluated at all. Revision: Minor refactoring. Argument renaming, make use of #findContextSuchThat:. =============== Diff against Kernel-ct.1489 =============== Item was changed: ----- Method: Object>>haltIf: (in category 'debugging') ----- + haltIf: aBooleanOrBlockOrSelector + "This is the typical message to use for inserting breakpoints during debugging. Param can be a boolean block or value, halt if true. + If the block has one arg, the receiver is bound to that. + If the argument is a selector, we look up in the callchain. Halt if any method's selector equals selector." - haltIf: condition - "This is the typical message to use for inserting breakpoints during - debugging. Param can be a block or expression, halt if true. - If the Block has one arg, the receiver is bound to that. - If the condition is a selector, we look up in the callchain. Halt if - any method's selector equals selector." - | cntxt | + ^ (self meetsHaltCondition: aBooleanOrBlockOrSelector) + ifTrue: [self halt]! - condition isSymbol ifTrue:[ - "only halt if a method with selector symbol is in callchain" - cntxt := thisContext. - [cntxt sender isNil] whileFalse: [ - cntxt := cntxt sender. - (cntxt selector = condition) ifTrue: [Halt signal]. - ]. - ^self. - ]. - (condition isBlock - ifTrue: [condition cull: self] - ifFalse: [condition] - ) ifTrue: [ - Halt signal - ].! Item was added: + ----- Method: Object>>haltOnceIf: (in category 'debugging') ----- + haltOnceIf: aBooleanOrBlockOrSelector + "Check aBooleanOrBlockOrSelector and halt, unless we have already done it once. See #meetsHaltCondition:." + + self haltOnceEnabled ifFalse: [^ self]. + ^ (self meetsHaltCondition: aBooleanOrBlockOrSelector) + ifTrue: + [self clearHaltOnce; halt]! Item was added: + ----- Method: Object>>meetsHaltCondition: (in category 'debugging') ----- + meetsHaltCondition: aBooleanOrBlockOrSelector + "If the condition block has one arg, the receiver is bound to that. + If the condition is a selector, we look up in the callchain. Halt if any method's selector equals selector." + + aBooleanOrBlockOrSelector isSymbol ifTrue: + [^ (thisContext home sender findContextSuchThat: [:ctxt | + ctxt selector = aBooleanOrBlockOrSelector]) + notNil]. + ^ aBooleanOrBlockOrSelector isBlock + ifTrue: [aBooleanOrBlockOrSelector cull: self] + ifFalse: [aBooleanOrBlockOrSelector value]! From commits at source.squeak.org Mon Nov 7 19:52:35 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 7 Nov 2022 19:52:35 0000 Subject: [squeak-dev] The Trunk: KernelTests-ct.437.mcz Message-ID: <20221107195239.0C2F414D8A9@mail.squeak.org> Christoph Thiede uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-ct.437.mcz ==================== Summary ==================== Name: KernelTests-ct.437 Author: ct Time: 7 November 2022, 8:51:49.281226 pm UUID: fc0ce7a3-e562-e741-a923-d825e2ff3b4e Ancestors: KernelTests-jar.436, KernelTests-ct.374 Merges KernelTests-ct.374: Tests #haltOnce and #haltOnceIf:. Refactors tests for #haltIf:. Complements Kernel-ct.1294. Revision: Minor refactoring. =============== Diff against KernelTests-jar.436 =============== Item was added: + ----- Method: ObjectTest>>resetHaltOnceAfter: (in category 'running') ----- + resetHaltOnceAfter: aBlock + + | outerState | + outerState := self haltOnceEnabled. + ^ aBlock ensure: [ + outerState + ifTrue: [self setHaltOnce] + ifFalse: [self clearHaltOnce] ]! Item was added: + ----- Method: ObjectTest>>shouldHalt: (in category 'asserting') ----- + shouldHalt: aBlock + + ^ self + should: aBlock + raise: Halt! Item was added: + ----- Method: ObjectTest>>shouldntHalt: (in category 'asserting') ----- + shouldntHalt: aBlock + + ^ self + shouldnt: aBlock + raise: Halt! Item was changed: + ----- Method: ObjectTest>>testHaltIf (in category 'tests - debugging') ----- - ----- Method: ObjectTest>>testHaltIf (in category 'tests - testing') ----- testHaltIf + self shouldHalt: [self haltIf: true]. + self shouldntHalt: [self haltIf: false]. + + self shouldHalt: [self haltIf: [true]]. + self shouldntHalt: [self haltIf: [false]]. + + self shouldHalt: [self haltIf: #testHaltIf]. + self shouldntHalt: [self haltIf: #teadfasdfltIf]. + + self shouldHalt: [self a]. + self shouldntHalt: [self a1]. + + self shouldHalt: [self haltIf: [:o | o class = self class]]. + self shouldntHalt: [self haltIf: [:o | o class ~= self class]].! - self should: [self haltIf: true] raise: Halt. - self haltIf: false. - - self should: [self haltIf: [true]] raise: Halt. - self haltIf: [false]. - - self should: [self haltIf: #testHaltIf.] raise: Halt. - self haltIf: #teadfasdfltIf. - - self should: [self a] raise: Halt. - self a1. - - self should: [self haltIf: [:o | o class = self class]] raise: Halt. - self haltIf: [:o | o class ~= self class]. - ! Item was added: + ----- Method: ObjectTest>>testHaltOnce (in category 'tests - debugging') ----- + testHaltOnce + + self resetHaltOnceAfter: [ + self setHaltOnce. + self assert: [self haltOnceEnabled]. + self shouldHalt: [self haltOnce]. + self deny: [self haltOnceEnabled]. + self shouldntHalt: [self haltOnce]. + + self setHaltOnce. + self assert: [self haltOnceEnabled]. + self clearHaltOnce. + self deny: [self haltOnceEnabled]. + self shouldntHalt: [self haltOnce]].! Item was added: + ----- Method: ObjectTest>>testHaltOnceIf (in category 'tests - debugging') ----- + testHaltOnceIf + + self resetHaltOnceAfter: [ + | tested | + self setHaltOnce. + self shouldHalt: [self haltOnceIf: true]. + self shouldntHalt: [self haltOnceIf: true]. + + self setHaltOnce. + self shouldntHalt: [self haltOnceIf: false]. + self assert: [self haltOnceEnabled]. + + self setHaltOnce. + tested := false. + self shouldHalt: [self haltOnceIf: [tested := true]]. + self assert: tested. + tested := false. + self shouldntHalt: [self haltOnceIf: [tested := true]]. + self deny: tested. + + self setHaltOnce. + tested := false. + self shouldntHalt: [self haltOnceIf: [(tested := true) not]]. + self assert: [self haltOnceEnabled]. + self assert: tested. + tested := false. + self shouldntHalt: [self haltOnceIf: [(tested := true) not]]. + self assert: [self haltOnceEnabled]. + self assert: tested].! Item was changed: + ----- Method: ObjectTest>>testNotNil (in category 'tests - debugging') ----- - ----- Method: ObjectTest>>testNotNil (in category 'tests - testing') ----- testNotNil self assert: Object new notNil! From commits at source.squeak.org Mon Nov 7 19:53:07 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 7 Nov 2022 19:53:07 0000 Subject: [squeak-dev] The Trunk: Kernel-ct.1294.mcz Message-ID: <20221107195312.28B5C14D8D6@mail.squeak.org> Christoph Thiede uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-ct.1294.mcz ==================== Summary ==================== Name: Kernel-ct.1294 Author: ct Time: 9 January 2020, 3:42:36.672555 pm UUID: 7409dcc3-160e-9d44-9712-f266e0f25973 Ancestors: Kernel-nice.1292 Proposal: Add #haltOnceIf: to Object, which combines the strengths of #haltOnce and #haltIf:. Especially useful in performance-critical situations: It HaltOnce is disabled, the condition will not be evaluated at all. =============== Diff against Kernel-nice.1292 =============== Item was changed: ----- Method: Object>>haltIf: (in category 'debugging') ----- + haltIf: aCondition + "This is the typical message to use for inserting breakpoints during debugging. Param can be a block or expression, halt if true. - haltIf: condition - "This is the typical message to use for inserting breakpoints during - debugging. Param can be a block or expression, halt if true. If the Block has one arg, the receiver is bound to that. + If the condition is a selector, we look up in the callchain. Halt if any method's selector equals selector." - If the condition is a selector, we look up in the callchain. Halt if - any method's selector equals selector." - | cntxt | + ^ (self meetsHaltCondition: aCondition) + ifTrue: [self halt]! - condition isSymbol ifTrue:[ - "only halt if a method with selector symbol is in callchain" - cntxt := thisContext. - [cntxt sender isNil] whileFalse: [ - cntxt := cntxt sender. - (cntxt selector = condition) ifTrue: [Halt signal]. - ]. - ^self. - ]. - (condition isBlock - ifTrue: [condition cull: self] - ifFalse: [condition] - ) ifTrue: [ - Halt signal - ].! Item was added: + ----- Method: Object>>haltOnceIf: (in category 'debugging') ----- + haltOnceIf: aCondition + "Check aCondition and halt, unless we have already done it once. See #meetsHaltCondition:." + + self haltOnceEnabled ifFalse: [^ self]. + ^ (self meetsHaltCondition: aCondition) + ifTrue: [ + self clearHaltOnce; halt].! Item was added: + ----- Method: Object>>meetsHaltCondition: (in category 'debugging') ----- + meetsHaltCondition: aCondition + "If the Block has one arg, the receiver is bound to that. + If the condition is a selector, we look up in the callchain. Halt if any method's selector equals selector." + + aCondition isSymbol ifTrue: [ | ctxt | + "only halt if a method with selector symbol is in callchain" + ctxt := thisContext. + [(ctxt := ctxt sender) isNil] whileFalse: [ + (ctxt selector = aCondition) ifTrue: [^ true] ]. + ^ false ]. + ^ aCondition isBlock + ifTrue: [aCondition cull: self] + ifFalse: [aCondition value]! From commits at source.squeak.org Mon Nov 7 19:53:12 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 7 Nov 2022 19:53:12 0000 Subject: [squeak-dev] The Trunk: KernelTests-ct.374.mcz Message-ID: <20221107195315.23EF714D8D6@mail.squeak.org> Christoph Thiede uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-ct.374.mcz ==================== Summary ==================== Name: KernelTests-ct.374 Author: ct Time: 9 January 2020, 3:45:07.818555 pm UUID: a7466380-609b-8146-b983-af77736d55f0 Ancestors: KernelTests-nice.373 Tests #haltOnce and #haltOnceIf:. Refactors tests for #haltIf:. Complements Kernel-ct.1294. =============== Diff against KernelTests-nice.373 =============== Item was added: + ----- Method: ObjectTest>>resetHaltOnceAfter: (in category 'running') ----- + resetHaltOnceAfter: aBlock + + | outerState | + outerState := self haltOnceEnabled. + ^ aBlock ensure: [ + outerState + ifTrue: [self setHaltOnce] + ifFalse: [self clearHaltOnce] ]! Item was added: + ----- Method: ObjectTest>>shouldHalt: (in category 'asserting') ----- + shouldHalt: aBlock + + ^ self + should: aBlock + raise: Halt! Item was added: + ----- Method: ObjectTest>>shouldntHalt: (in category 'asserting') ----- + shouldntHalt: aBlock + + ^ self + shouldnt: aBlock + raise: Halt! Item was changed: + ----- Method: ObjectTest>>testHaltIf (in category 'tests - debugging') ----- - ----- Method: ObjectTest>>testHaltIf (in category 'tests - testing') ----- testHaltIf + self shouldHalt: [self haltIf: true]. + self shouldntHalt: [self haltIf: false]. - self should: [self haltIf: true] raise: Halt. - self haltIf: false. + self shouldHalt: [self haltIf: [true]]. + self shouldntHalt: [self haltIf: [false]]. - self should: [self haltIf: [true]] raise: Halt. - self haltIf: [false]. + self shouldHalt: [self haltIf: #testHaltIf]. + self shouldntHalt: [self haltIf: #teadfasdfltIf]. - self should: [self haltIf: #testHaltIf.] raise: Halt. - self haltIf: #teadfasdfltIf. + self shouldHalt: [self a]. + self shouldntHalt: [self a1]. - self should: [self a] raise: Halt. - self a1. + self shouldHalt: [self haltIf: [:o | o class = self class]]. + self shouldntHalt: [self haltIf: [:o | o class ~= self class]]. - self should: [self haltIf: [:o | o class = self class]] raise: Halt. - self haltIf: [:o | o class ~= self class]. ! Item was added: + ----- Method: ObjectTest>>testHaltOnce (in category 'tests - debugging') ----- + testHaltOnce + + self resetHaltOnceAfter: [ + self setHaltOnce. + self assert: [self haltOnceEnabled]. + self shouldHalt: [self haltOnce]. + self deny: [self haltOnceEnabled]. + self shouldntHalt: [self haltOnce]. + + self setHaltOnce. + self assert: [self haltOnceEnabled]. + self clearHaltOnce. + self deny: [self haltOnceEnabled]. + self shouldntHalt: [self haltOnce]].! Item was added: + ----- Method: ObjectTest>>testHaltOnceIf (in category 'tests - debugging') ----- + testHaltOnceIf + + self resetHaltOnceAfter: [ + | requested | + self setHaltOnce. + self shouldHalt: [self haltOnceIf: true]. + self shouldntHalt: [self haltOnceIf: true]. + + self setHaltOnce. + self shouldntHalt: [self haltOnceIf: false]. + self assert: [self haltOnceEnabled]. + + self setHaltOnce. + requested := false. + self shouldHalt: [self haltOnceIf: [requested := true]]. + self assert: requested. + requested := false. + self shouldntHalt: [self haltOnceIf: [requested := true]]. + self deny: requested. + + self setHaltOnce. + requested := false. + self shouldntHalt: [self haltOnceIf: [(requested := true) not]]. + self assert: [self haltOnceEnabled]. + self assert: requested. + requested := false. + self shouldntHalt: [self haltOnceIf: [(requested := true) not]]. + self assert: [self haltOnceEnabled]. + self assert: requested].! Item was changed: + ----- Method: ObjectTest>>testNotNil (in category 'tests - debugging') ----- - ----- Method: ObjectTest>>testNotNil (in category 'tests - testing') ----- testNotNil self assert: Object new notNil! From eliot.miranda at gmail.com Wed Nov 9 16:54:55 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed, 9 Nov 2022 08:54:55 -0800 Subject: [squeak-dev] Fwd: Posits [circular mapping between real numbers and the repressntation] References: Message-ID: It would be nice to have these alongside Float. Perhaps with a 128 bit representation… Begin forwarded message: > From: Annick Fron > Date: November 9, 2022 at 1:14:46 AM PST > To: vwnc NC > Subject: [vwnc] Posits > Reply-To: Annick Fron > > Hi, > > Does anybody know about posits ? > > https://www.cs.cornell.edu/courses/cs6120/2019fa/blog/posits/ > > Best regards > > Annick Eliot _,,,^..^,,,_ (phone) -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Thu Nov 10 07:33:34 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 10 Nov 2022 08:33:34 +0100 Subject: [squeak-dev] Fwd: Posits [circular mapping between real numbers and the repressntation] In-Reply-To: References: Message-ID: +1 That would be nice to have indeed! :-) Best, Marcel Am 09.11.2022 17:55:08 schrieb Eliot Miranda : It would be nice to have these alongside Float. Perhaps with a 128 bit representation… Begin forwarded message: From: Annick Fron Date: November 9, 2022 at 1:14:46 AM PST To: vwnc NC Subject: [vwnc] Posits Reply-To: Annick Fron Hi, Does anybody know about posits ? https://www.cs.cornell.edu/courses/cs6120/2019fa/blog/posits/ [https://urldefense.com/v3/__https://www.cs.cornell.edu/courses/cs6120/2019fa/blog/posits/__;!!DZ3fjg!8ZFeJGgwKT3DrC7GRX-etEsxEr2reSMpw3FsWLtn9ii_vrAS4JnKYdvhfXKjKmYpLLIHsrZQ5awY7nXRmJSzyC4$] Best regards Annick Eliot _,,,^..^,,,_ (phone) -------------- next part -------------- An HTML attachment was scrubbed... URL: From tonyg at leastfixedpoint.com Thu Nov 10 13:55:36 2022 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Thu, 10 Nov 2022 14:55:36 +0100 Subject: [squeak-dev] Fwd: Posits [circular mapping between real numbers and the repressntation] In-Reply-To: References: Message-ID: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Thanks for that link, Eliot! That led me down a rabbit hole [1][2], and upon coming out I can say I officially love posits. Very cool stuff. (To other readers of this message: if you read or skim only one document, it should be [1] IMO.) Cheers, Tony [1]: https://posithub.org/docs/Posits4.pdf [2]: https://posithub.org/docs/posit_standard-2.pdf On 11/9/22 17:54, Eliot Miranda wrote: > It would be nice to have these alongside Float. Perhaps with a 128 bit > representation… > > Begin forwarded message: > >> *From:* Annick Fron >> *Date:* November 9, 2022 at 1:14:46 AM PST >> *To:* vwnc NC >> *Subject:* *[vwnc] Posits* >> *Reply-To:* Annick Fron >> >> Hi, >> >> Does anybody know about posits ? >> >> https://www.cs.cornell.edu/courses/cs6120/2019fa/blog/posits/ >> >> Best regards >> >> Annick > > Eliot > _,,,^..^,,,_ (phone) > > From drurowin at gmail.com Thu Nov 10 17:34:17 2022 From: drurowin at gmail.com (Lauren P) Date: Thu, 10 Nov 2022 10:34:17 -0700 Subject: [squeak-dev] Fwd: Posits [circular mapping between real numbers and the repressntation] In-Reply-To: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: Hi Lists, This is the first I've ever heard of posits. I certainly don't see the harm in including them in Squeak! If it isn't too arduous, I think we should. On Thu, Nov 10, 2022, 06:55 Tony Garnock-Jones wrote: > Thanks for that link, Eliot! That led me down a rabbit hole [1][2], and > upon coming out I can say I officially love posits. Very cool stuff. (To > other readers of this message: if you read or skim only one document, it > should be [1] IMO.) > > Cheers, > Tony > > [1]: https://posithub.org/docs/Posits4.pdf > [2]: https://posithub.org/docs/posit_standard-2.pdf > > On 11/9/22 17:54, Eliot Miranda wrote: > > It would be nice to have these alongside Float. Perhaps with a 128 bit > > representation… > > > > Begin forwarded message: > > > >> *From:* Annick Fron > >> *Date:* November 9, 2022 at 1:14:46 AM PST > >> *To:* vwnc NC > >> *Subject:* *[vwnc] Posits* > >> *Reply-To:* Annick Fron > >> > >> Hi, > >> > >> Does anybody know about posits ? > >> > >> https://www.cs.cornell.edu/courses/cs6120/2019fa/blog/posits/ > >> > >> Best regards > >> > >> Annick > > > > Eliot > > _,,,^..^,,,_ (phone) > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jr at amanue.com Thu Nov 10 21:28:06 2022 From: jr at amanue.com (Jim Rosenberg) Date: Thu, 10 Nov 2022 16:28:06 -0500 Subject: [squeak-dev] OH NO!!! .morph format change? Message-ID: <20221110162806.f0fde9f5de0280963be537f0@amanue.com> Oh dear. Big trouble. I use Squeak for artistic work, and rely crucially on .morph files to preserve my content. (Since you changed the format at one point for projects and didn't provide a way to convert, ahem ahem ahem ...) I have a morph saved under Squeak 4.3 and am trying to load it into Squeak 6.0. I am getting an error from SmartRefStream>>verifyStructure that there is a missing key, #DisplayObject. HELP!!! How do I convert .morph files to the format used by 6.0??? PLEASE PLEASE PLEASE!!!: When you guys change a format like this, please give a thought to us content developers. -Thanks in advance, Jim From jr at amanue.com Thu Nov 10 21:57:57 2022 From: jr at amanue.com (Jim Rosenberg) Date: Thu, 10 Nov 2022 16:57:57 -0500 Subject: [squeak-dev] OH NO!!! .morph format change? In-Reply-To: <20221110162806.f0fde9f5de0280963be537f0@amanue.com> References: <20221110162806.f0fde9f5de0280963be537f0@amanue.com> Message-ID: <20221110165757.fa0aa7f322d31dcfe0090d95@amanue.com> Apologies, sorry for screaming. When I try to load an older .morph (Squeak 3.8) it seems to work fine. I think my problem is there were some .st files I didn't have loaded before trying to load the 4.3 morph. Plea still stands, however: Please do not even THINK ABOUT changing the format of .morph without giving us a way to convert. On Thu, 10 Nov 2022 16:28:06 -0500 Jim Rosenberg wrote: > Oh dear. Big trouble. I use Squeak for artistic work, and rely crucially > on .morph files to preserve my content. (Since you changed the format at > one point for projects and didn't provide a way to convert, ahem ahem > ahem ...) > > I have a morph saved under Squeak 4.3 and am trying to load it into > Squeak 6.0. I am getting an error from SmartRefStream>>verifyStructure > that there is a missing key, #DisplayObject. > > HELP!!! How do I convert .morph files to the format used by 6.0??? > > PLEASE PLEASE PLEASE!!!: When you guys change a format like this, please > give a thought to us content developers. > > -Thanks in advance, Jim > From craig at blackpagedigital.com Fri Nov 11 03:34:12 2022 From: craig at blackpagedigital.com (Craig Latta) Date: Thu, 10 Nov 2022 19:34:12 -0800 Subject: [squeak-dev] Posits In-Reply-To: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: This critique was interesting also, by William Kahan, the main architect of the IEEE 754-1985 floating-point spec: https://people.eecs.berkeley.edu/~wkahan/UnumSORN.pdf -C -- Craig Latta :: research computer scientist :: Black Page Digital :: Berkeley, California :: 663137D7940BF5C0AF :: C1349FB2ADA32C4D5314CE :: From marcel.taeumel at hpi.de Fri Nov 11 08:42:54 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 11 Nov 2022 09:42:54 +0100 Subject: [squeak-dev] Posits In-Reply-To: References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: Hmm... Patrick just pointed out to me that this critique addresses Unum I. "Posits" are Unum III: https://en.wikipedia.org/wiki/Unum_(number_format) [https://en.wikipedia.org/wiki/Unum_(number_format)] Hmm... Best, Marcel Am 11.11.2022 04:34:31 schrieb Craig Latta : This critique was interesting also, by William Kahan, the main architect of the IEEE 754-1985 floating-point spec: https://people.eecs.berkeley.edu/~wkahan/UnumSORN.pdf -C -- Craig Latta :: research computer scientist :: Black Page Digital :: Berkeley, California :: 663137D7940BF5C0AF :: C1349FB2ADA32C4D5314CE :: -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Fri Nov 11 08:47:11 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Fri, 11 Nov 2022 09:47:11 +0100 Subject: [squeak-dev] OH NO!!! .morph format change? In-Reply-To: <20221110165757.fa0aa7f322d31dcfe0090d95@amanue.com> References: <20221110162806.f0fde9f5de0280963be537f0@amanue.com> <20221110165757.fa0aa7f322d31dcfe0090d95@amanue.com> Message-ID: Hi Jim -- If you would provide examples of .morph or .project, we can surely figure out the regressions that happened since 3.8 or 4.3. I am not aware of a fundamental "format change" regarding ImageSegment or DataStream in Squeak. If so, backwards compatibility should still be a thing. ;-) Feel free to document your issues here: https://github.com/squeak-smalltalk/squeak-object-memory/issues [https://github.com/squeak-smalltalk/squeak-object-memory/issues] Best, Marcel Am 10.11.2022 22:58:06 schrieb Jim Rosenberg : Apologies, sorry for screaming. When I try to load an older .morph (Squeak 3.8) it seems to work fine. I think my problem is there were some .st files I didn't have loaded before trying to load the 4.3 morph. Plea still stands, however: Please do not even THINK ABOUT changing the format of .morph without giving us a way to convert. On Thu, 10 Nov 2022 16:28:06 -0500 Jim Rosenberg wrote: > Oh dear. Big trouble. I use Squeak for artistic work, and rely crucially > on .morph files to preserve my content. (Since you changed the format at > one point for projects and didn't provide a way to convert, ahem ahem > ahem ...) > > I have a morph saved under Squeak 4.3 and am trying to load it into > Squeak 6.0. I am getting an error from SmartRefStream>>verifyStructure > that there is a missing key, #DisplayObject. > > HELP!!! How do I convert .morph files to the format used by 6.0??? > > PLEASE PLEASE PLEASE!!!: When you guys change a format like this, please > give a thought to us content developers. > > -Thanks in advance, Jim > -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Fri Nov 11 22:22:34 2022 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Fri, 11 Nov 2022 23:22:34 +0100 Subject: [squeak-dev] Fwd: Posits [circular mapping between real numbers and the repressntation] In-Reply-To: References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: I have published an early implementation of Posit with very few PositTests at http://www.squeaksource.com/STEM Currently, reciprocal is not correct (it's the rough approximation given by circle symmetry) , and the implementation of mathematical functions rely on Float, which is only a good idea for small Posit representations (low range, low precision). The rest of arithmetic uses asFraction, which is not fast, but is exact. I have not implemented a Quire, since by now we can perform all arithmetic asFraction with infinite precision. Quire has an interest if accelerated. Also, the Posit intervals are not implemented, that would be interesting too. The decoding of Posit bit fields is duplicated at many places, and that might be better factored. The algorithm for correctly rounding to a Posit is also duplicated in Float/Integer/Fraction. Since it is not trivial, it definitely lacks tests. If you wanna play... Le jeu. 10 nov. 2022 à 18:34, Lauren P a écrit : > Hi Lists, > > This is the first I've ever heard of posits. > > I certainly don't see the harm in including them in Squeak! If it isn't > too arduous, I think we should. > > On Thu, Nov 10, 2022, 06:55 Tony Garnock-Jones > wrote: > >> Thanks for that link, Eliot! That led me down a rabbit hole [1][2], and >> upon coming out I can say I officially love posits. Very cool stuff. (To >> other readers of this message: if you read or skim only one document, it >> should be [1] IMO.) >> >> Cheers, >> Tony >> >> [1]: https://posithub.org/docs/Posits4.pdf >> [2]: https://posithub.org/docs/posit_standard-2.pdf >> >> On 11/9/22 17:54, Eliot Miranda wrote: >> > It would be nice to have these alongside Float. Perhaps with a 128 bit >> > representation… >> > >> > Begin forwarded message: >> > >> >> *From:* Annick Fron >> >> *Date:* November 9, 2022 at 1:14:46 AM PST >> >> *To:* vwnc NC >> >> *Subject:* *[vwnc] Posits* >> >> *Reply-To:* Annick Fron >> >> >> >> Hi, >> >> >> >> Does anybody know about posits ? >> >> >> >> https://www.cs.cornell.edu/courses/cs6120/2019fa/blog/posits/ >> >> >> >> Best regards >> >> >> >> Annick >> > >> > Eliot >> > _,,,^..^,,,_ (phone) >> > >> > >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From craig at blackpagedigital.com Fri Nov 11 23:09:32 2022 From: craig at blackpagedigital.com (Craig Latta) Date: Fri, 11 Nov 2022 15:09:32 -0800 Subject: [squeak-dev] Posits In-Reply-To: References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: Hi Marcel-- > Hmm... Patrick just pointed out to me that this critique addresses > Unum I. "Posits" are Unum III (Wikipedia link). Sure, the Wikipedia article is where I noticed the critique. Not all of its criticisms are addressed by Unum II and III. And it's still interesting, given who wrote it. :) I think posits are lovely, and I've never enjoyed dealing with IEEE 754, but it's not clear to me that the resource-use discussion is closed. > Hmm... What are you trying to say? -C -- Craig Latta :: research computer scientist :: Black Page Digital :: Berkeley, California :: 663137D7940BF5C0AF :: C1349FB2ADA32C4D5314CE :: From nicolas.cellier.aka.nice at gmail.com Sun Nov 13 13:52:32 2022 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Sun, 13 Nov 2022 14:52:32 +0100 Subject: [squeak-dev] Posits In-Reply-To: References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: Hi all, the criticism of Kahan is essentially about the replacement of the variety of rounding modes by interval arithmetic, ubox and SORN (decomposition in union of smaller intervals to refine the bounds) as a universal solution. It's not a criticism of the Posit format per se. Implementing a single rounding mode certainly participates in the simplification of the arithmetic unit, but it's not mandatory, it's orthogonal to the representation. Posits have a formal beauty and may reduce the complexity of hardware, power consumption, etc... I like the idea of using short Posits in neural networks. It remains to see if it does not complicate error analysis, because precision is floating (like denormals in IEEE754). Maybe that could be a grief for Kahan too, but that would deserve an update from his side. Nicolas Le sam. 12 nov. 2022 à 00:10, Craig Latta a écrit : > > Hi Marcel-- > > > Hmm... Patrick just pointed out to me that this critique addresses > > Unum I. "Posits" are Unum III (Wikipedia link). > > Sure, the Wikipedia article is where I noticed the critique. Not > all of its criticisms are addressed by Unum II and III. And it's still > interesting, given who wrote it. :) I think posits are lovely, and I've > never enjoyed dealing with IEEE 754, but it's not clear to me that the > resource-use discussion is closed. > > > Hmm... > > What are you trying to say? > > > -C > > -- > Craig Latta :: research computer scientist :: > Black Page Digital :: Berkeley, California :: > 663137D7940BF5C0AF :: C1349FB2ADA32C4D5314CE :: > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From tonyg at leastfixedpoint.com Mon Nov 14 09:22:34 2022 From: tonyg at leastfixedpoint.com (Tony Garnock-Jones) Date: Mon, 14 Nov 2022 10:22:34 +0100 Subject: [squeak-dev] Posits In-Reply-To: References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: Here's a more up-to-date criticism: https://hal.inria.fr/hal-01959581v2/document Florent de Dinechin, Luc Forget, Jean-Michel Muller, Yohann Uguen. Posits: the good, the bad and the ugly. 2018. hal-01959581v2 I still very much like the theory of posits, and their potential for use as a storage format. What my reading over the last few days has taught me, though, is that I'm not qualified to opine on their uses for *computation*! They still seem really promising - it seems like they're perhaps *usually* superior to floats for many numerical algorithms, but not *always* superior? And you still have to do Proper Numerical Analysis, just like with IEEE754. And since the standard posit formats have a slightly smaller range of precisely-encoded contiguous integers in them, maybe regular floats/doubles are better where you're doing something shady like using them in place of a proper integer type (*cough cough javascript*)... On 11/11/22 09:42, Marcel Taeumel wrote: > Hmm... Patrick just pointed out to me that this critique addresses Unum > I. "Posits" are Unum III: > https://en.wikipedia.org/wiki/Unum_(number_format) > > > Hmm... > > Best, > Marcel >> >> Am 11.11.2022 04:34:31 schrieb Craig Latta : >> >> >> This critique was interesting also, by William Kahan, the main >> architect of the IEEE 754-1985 floating-point spec: >> >> https://people.eecs.berkeley.edu/~wkahan/UnumSORN.pdf >> >> >> -C >> >> -- >> Craig Latta :: research computer scientist :: >> Black Page Digital :: Berkeley, California :: >> 663137D7940BF5C0AF :: C1349FB2ADA32C4D5314CE :: >> >> >> >> > > From nicolas.cellier.aka.nice at gmail.com Mon Nov 14 15:29:51 2022 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Mon, 14 Nov 2022 16:29:51 +0100 Subject: [squeak-dev] Posits In-Reply-To: References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: Thank you for this excellent link. When you know that both Microsoft and Apple have a bug in ldexp in the gradual underflow range on x64, that's a warning that tapered arithmetic might be error prone indeed ;) IMO, a very good property of Posits is the ease of converting to/from increased precision (if conserving es). I would inquire the cost/benefit of what we could get with one register containing 1 or few extra bytes of precision filled by each elementary arithmetic op. IMO it would restore some good properties for TwoSum, Twoproduct, etc... Concerning languages like Javascript, please note that all integers up to 2^48 are representable on Posit64 with es=2, or up to 2^52 on Posit64 with es=3, if I'm not mistaken... So it does not make a great difference with Float64. Le lun. 14 nov. 2022 à 10:22, Tony Garnock-Jones a écrit : > Here's a more up-to-date criticism: > > https://hal.inria.fr/hal-01959581v2/document > > Florent de Dinechin, Luc Forget, Jean-Michel Muller, Yohann Uguen. > Posits: the good, the bad and the ugly. 2018. hal-01959581v2 > > I still very much like the theory of posits, and their potential for use > as a storage format. What my reading over the last few days has taught > me, though, is that I'm not qualified to opine on their uses for > *computation*! They still seem really promising - it seems like they're > perhaps *usually* superior to floats for many numerical algorithms, but > not *always* superior? And you still have to do Proper Numerical > Analysis, just like with IEEE754. And since the standard posit formats > have a slightly smaller range of precisely-encoded contiguous integers > in them, maybe regular floats/doubles are better where you're doing > something shady like using them in place of a proper integer type > (*cough cough javascript*)... > > > On 11/11/22 09:42, Marcel Taeumel wrote: > > Hmm... Patrick just pointed out to me that this critique addresses Unum > > I. "Posits" are Unum III: > > https://en.wikipedia.org/wiki/Unum_(number_format) > > > > > > Hmm... > > > > Best, > > Marcel > >> > >> Am 11.11.2022 04:34:31 schrieb Craig Latta >: > >> > >> > >> This critique was interesting also, by William Kahan, the main > >> architect of the IEEE 754-1985 floating-point spec: > >> > >> https://people.eecs.berkeley.edu/~wkahan/UnumSORN.pdf > >> > >> > >> -C > >> > >> -- > >> Craig Latta :: research computer scientist :: > >> Black Page Digital :: Berkeley, California :: > >> 663137D7940BF5C0AF :: C1349FB2ADA32C4D5314CE :: > >> > >> > >> > >> > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From craig at blackpagedigital.com Mon Nov 14 18:37:36 2022 From: craig at blackpagedigital.com (Craig Latta) Date: Mon, 14 Nov 2022 10:37:36 -0800 Subject: [squeak-dev] Posits In-Reply-To: References: <2806493c-9d0e-fbf6-03fd-1eb06521138e@leastfixedpoint.com> Message-ID: Hi-- Tony writes: > Here's a more up-to-date criticism: > > https://hal.inria.fr/hal-01959581v2/document > > Florent de Dinechin, Luc Forget, Jean-Michel Muller, Yohann Uguen. > Posits: the good, the bad and the ugly. 2018. hal-01959581v2 Thank you! Lots of compelling future work suggested there. > ...since the standard posit formats have a slightly smaller range of > precisely-encoded contiguous integers in them, maybe regular > floats/doubles are better where you're doing something shady like > using them in place of a proper integer type (*cough cough > javascript*)... Nicolas responds: > Concerning languages like Javascript, please note that all integers up > to 2^48 are representable on Posit64 with es=2, or up to 2^52 on > Posit64 with es=3, if I'm not mistaken... So it does not make a great > difference with Float64. In the announcement[1] in March 2022 of the first ratified version of Posit standard[2]: "NOTE: Contrary to the original paper by Gustafson and Yonemoto, and to early versions of the Standard, the exponent size (eS) is always 2 and does not vary with the precision. This greatly simplifies conversions between precisions and the creation of correctly-rounded math library functions, and in hundreds of experiments with real applications has shown to be a better choice. 
We thank all members of the Posit Working Group for their efforts." -C [1] https://posithub.org/khub_doc [2] https://posithub.org/docs/posit_standard-2.pdf -- Craig Latta :: research computer scientist :: Black Page Digital :: Berkeley, California :: 663137D7940BF5C0AF :: C1349FB2ADA32C4D5314CE :: From eliot.miranda at gmail.com Fri Nov 18 21:52:56 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri, 18 Nov 2022 13:52:56 -0800 Subject: [squeak-dev] Windows mapping from CF_UNICODE to Unicode Message-ID: Hi All, does anyone know how Windows maps Unicode text to the CF_UNICODE format used in the clipboard? It seems to me that CF_UNICODE might simply be two-byte characters, excluding any codes beyond 16rFFFF. Is it in fact UTF-16? If it is UTF-16 has anyone fixed our UTF16TextConverter? I don't see any of the conveniences that exist for the UTF8TextConverter such as decodeString: etc. _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From Das.Linux at gmx.de Fri Nov 18 22:05:23 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Fri, 18 Nov 2022 23:05:23 +0100 Subject: [squeak-dev] Windows mapping from CF_UNICODE to Unicode In-Reply-To: References: Message-ID: <4830D150-1B55-4A44-9998-CFA3DA22A34C@gmx.de> > On 18. Nov 2022, at 22:52, Eliot Miranda wrote: > > Hi All, > > does anyone know how Windows maps Unicode text to the CF_UNICODE format used in the clipboard? It seems to me that CF_UNICODE might simply be two-byte characters, excluding any codes beyond 16rFFFF. Is it in fact UTF-16? Windows being windows, this ought to be UTF-16. When MS adopted Unicode in the 90s, it was still "small" enough for 16Bit, and was, in fact, UCS2. It got "upgraded" to UTF-16 around Windows 2000. See: https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows NOTE: UTF-16 has a lot of fun with "surrogate pairs", which makes it possible to have the whole UCS4-spectrum of code points. This is a lot messy, and surrogate pairs are invalid UTF-8, go figure. Sidenode: This is the reason, why https://simonsapin.github.io/wtf-8/ exists. Best regards -Tobias > > If it is UTF-16 has anyone fixed our UTF16TextConverter? I don't see any of the conveniences that exist for the UTF8TextConverter such as decodeString: etc. > _,,,^..^,,,_ > best, Eliot > From commits at source.squeak.org Fri Nov 18 23:05:58 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 18 Nov 2022 23:05:58 0000 Subject: [squeak-dev] The Inbox: Installer-Core-ct.453.mcz Message-ID: <20221118230601.2A48C14D697@mail.squeak.org> Christoph Thiede uploaded a new version of Installer-Core to project The Inbox: http://source.squeak.org/inbox/Installer-Core-ct.453.mcz ==================== Summary ==================== Name: Installer-Core-ct.453 Author: ct Time: 19 November 2022, 12:05:57.795955 am UUID: d2a0cc9f-69ed-a149-b661-62b19024829a Ancestors: Installer-Core-ct.452 Proposal: Stores API selectors for Metacello in MetacelloStub to avoid UnknownSelector warnings upon initial Metacello usage. E.g., if you evaluate any installation script from the web in a vanilla Squeak image that uses Metacello's #githubUser:project:path: selector, the image will no longer complain about an unknown selector, which sometimes causes confusion in beginners and experts. :-) =============== Diff against Installer-Core-ct.452 =============== Item was added: + ----- Method: MetacelloStub class>>apiSelectors (in category 'support') ----- + apiSelectors + "To avoid UnknownSelector warnings upon initial Metacello usage. Support only. By adding this method, these selectors will already be contained in the symbol table before Metacello is installed." + + "(Metacello selectors , Metacello class selectors) withoutDuplicates sorted" + ^ #(#addStatement:args: #baseline: #bitbucketUser:project:commitish:path: #blueplane: #cacheRepository: #className: #classic #configuration: #croquet: #execute:args: #executorSpec #executorSpec: #fetch #fetch: #filetreeDirectory: #gemsource: #get #githubUser:project:commitish:path: #githubUser:project:path: #ignoreImage #image #impara: #list #load #load: #lock #locked #onConflict: #onConflictUseIncoming #onConflictUseIncoming:useLoaded: #onConflictUseLoaded #onDowngrade: #onDowngradeUseIncoming #onDowngradeUseIncoming: #onLock: #onLockBreak #onLockBreak: #onUpgrade: #onUpgradeUseLoaded #onUpgradeUseLoaded: #onWarning: #onWarningLog #password: #project: #record #record: #register #registrations #registry #renggli: #repository: #repositoryOverrides: #saltypickle: #scriptExecutor #scriptExecutorClass #scriptExecutorClass: #silently #smalltalkhubUser:project: #squeakfoundation: #squeaksource3: #squeaksource: #ss3: #statements #statements: #swa: #swasource: #unlock #unregister #usernam e: #version: #wiresong:) ! From commits at source.squeak.org Sat Nov 19 05:14:03 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 19 Nov 2022 05:14:03 0000 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz Message-ID: <20221119051408.44B5614D697@mail.squeak.org> Chris Muller uploaded a new version of Collections to project The Inbox: http://source.squeak.org/inbox/Collections-cmm.1022.mcz ==================== Summary ==================== Name: Collections-cmm.1022 Author: cmm Time: 18 November 2022, 11:14:01.223447 pm UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 Ancestors: Collections-nice.1021 Allow empty fields when using #subStrings:. =============== Diff against Collections-nice.1021 =============== Item was changed: ----- Method: String>>subStrings: (in category 'converting') ----- subStrings: separators "Answer an array containing the substrings in the receiver separated by the elements of separators." | char result sourceStream subString | - #Collectn. - "Changed 2000/04/08 For ANSI protocol." (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse: [^ self error: 'separators must be Characters.']. sourceStream := ReadStream on: self. result := OrderedCollection new. subString := String new. [sourceStream atEnd] whileFalse: [char := sourceStream next. (separators includes: char) + ifTrue: [result add: subString copy. + subString := String new] - ifTrue: [subString notEmpty - ifTrue: - [result add: subString copy. - subString := String new]] ifFalse: [subString := subString , (String with: char)]]. subString notEmpty ifTrue: [result add: subString copy]. ^ result asArray! From asqueaker at gmail.com Sat Nov 19 05:24:43 2022 From: asqueaker at gmail.com (Chris Muller) Date: Fri, 18 Nov 2022 23:24:43 -0600 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: <20221119051408.44B5614D697@mail.squeak.org> References: <20221119051408.44B5614D697@mail.squeak.org> Message-ID: I don't know why subStrings: should behave differently for empty fields as non-empty. Before this change, empty fields are ignored: 'a:b::d' subStrings: ':' ==> " #('a' 'b' 'd') " '::::' subStrings: ':' ==> #() after this change, empty fields are honored: 'a:b::d' subStrings: ':' ==> " #('a' 'b' '' 'd') " '::::' subStrings: ':' ==> #('' '' '' '') Thoughts? - Chris On Fri, Nov 18, 2022 at 11:14 PM wrote: > Chris Muller uploaded a new version of Collections to project The Inbox: > http://source.squeak.org/inbox/Collections-cmm.1022.mcz > > ==================== Summary ==================== > > Name: Collections-cmm.1022 > Author: cmm > Time: 18 November 2022, 11:14:01.223447 pm > UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 > Ancestors: Collections-nice.1021 > > Allow empty fields when using #subStrings:. > > =============== Diff against Collections-nice.1021 =============== > > Item was changed: > ----- Method: String>>subStrings: (in category 'converting') ----- > subStrings: separators > "Answer an array containing the substrings in the receiver > separated > by the elements of separators." > | char result sourceStream subString | > - #Collectn. > - "Changed 2000/04/08 For ANSI protocol." > (separators isString or:[separators allSatisfy: [:element | > element isCharacter]]) ifFalse: > [^ self error: 'separators must be Characters.']. > sourceStream := ReadStream on: self. > result := OrderedCollection new. > subString := String new. > [sourceStream atEnd] > whileFalse: > [char := sourceStream next. > (separators includes: char) > + ifTrue: [result add: subString copy. > + subString := > String new] > - ifTrue: [subString notEmpty > - ifTrue: > - [result add: > subString copy. > - subString := > String new]] > ifFalse: [subString := subString , (String > with: char)]]. > subString notEmpty ifTrue: [result add: subString copy]. > ^ result asArray! > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Sat Nov 19 12:23:20 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sat, 19 Nov 2022 12:23:20 +0000 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: References: <20221119051408.44B5614D697@mail.squeak.org>, Message-ID: <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> Hm ... don't we have #splitBy: for this? This seems like a possibly dangerous breaking change to me. No strong opinion, though. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Chris Muller Gesendet: Samstag, 19. November 2022 06:24:43 An: squeak-dev at lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Inbox: Collections-cmm.1022.mcz I don't know why subStrings: should behave differently for empty fields as non-empty. Before this change, empty fields are ignored: 'a:b::d' subStrings: ':' ==> " #('a' 'b' 'd') " '::::' subStrings: ':' ==> #() after this change, empty fields are honored: 'a:b::d' subStrings: ':' ==> " #('a' 'b' '' 'd') " '::::' subStrings: ':' ==> #('' '' '' '') Thoughts? - Chris On Fri, Nov 18, 2022 at 11:14 PM > wrote: Chris Muller uploaded a new version of Collections to project The Inbox: http://source.squeak.org/inbox/Collections-cmm.1022.mcz ==================== Summary ==================== Name: Collections-cmm.1022 Author: cmm Time: 18 November 2022, 11:14:01.223447 pm UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 Ancestors: Collections-nice.1021 Allow empty fields when using #subStrings:. =============== Diff against Collections-nice.1021 =============== Item was changed: ----- Method: String>>subStrings: (in category 'converting') ----- subStrings: separators "Answer an array containing the substrings in the receiver separated by the elements of separators." | char result sourceStream subString | - #Collectn. - "Changed 2000/04/08 For ANSI protocol." (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse: [^ self error: 'separators must be Characters.']. sourceStream := ReadStream on: self. result := OrderedCollection new. subString := String new. [sourceStream atEnd] whileFalse: [char := sourceStream next. (separators includes: char) + ifTrue: [result add: subString copy. + subString := String new] - ifTrue: [subString notEmpty - ifTrue: - [result add: subString copy. - subString := String new]] ifFalse: [subString := subString , (String with: char)]]. subString notEmpty ifTrue: [result add: subString copy]. ^ result asArray! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Sat Nov 19 15:38:31 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 19 Nov 2022 15:38:31 0000 Subject: [squeak-dev] The Inbox: System-ct.1374.mcz Message-ID: <20221119153837.1473E14D781@mail.squeak.org> A new version of System was added to project The Inbox: http://source.squeak.org/inbox/System-ct.1374.mcz ==================== Summary ==================== Name: System-ct.1374 Author: ct Time: 19 November 2022, 4:38:24.247392 pm UUID: 24c7f156-4cfc-7b43-8110-31c482fa909e Ancestors: System-ct.1372 Fixes formatting of greeting message when entering author initials. Commonly, punctuation marks after a word should have the same bold emphasis as the word before. =============== Diff against System-ct.1372 =============== Item was changed: ----- Method: Utilities class>>setAuthorInitials (in category 'identification') ----- setAuthorInitials "Put up a dialog allowing the user to specify the author's initials. Inform the user about collisions with known contributors. See SystemNavigation class >> #authors. " | newInitials newName | newInitials := Project uiManager request: 'Please type your initials:' translated initialAnswer: AuthorInitials. newInitials ifEmpty: [^ self "No Change"]. (SystemNavigation authorsInverted at: newInitials ifPresent: [:existingNames | newName := existingNames sorted joinSeparatedBy: '/'. + (self confirm: ('Hello, {1}!! :-)

Our list of known contributors associates the initials you have entered with this name. If this is not you, please consider alternative initials, preferably more than just a few characters, to avoid collisions.

Do you want to use these author initials?

{2}' translated format: { - (self confirm: ('Hello, {1}!! :-)

Our
list of known contributors associates the initials you have entered with this name. If this is not you, please consider alternative initials, preferably more than just a few characters, to avoid collisions.

Do you want to use these author initials?

{2}' translated format: { newName ifNil: [newInitials]. newInitials. 'SystemReporter open model categoryAt: 1 put: true'. "mt: Avoid triggering the Windows Defender. See http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-December/217346.html" 'a' }) asTextFromHtml) ] ifAbsent: [true]) ifTrue: [self authorInitials: newInitials].! From lewis at mail.msen.com Sat Nov 19 16:06:57 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Sat, 19 Nov 2022 11:06:57 -0500 Subject: [squeak-dev] Inboard Squeak Sources In-Reply-To: <20221022014331.GA68593@shell.msen.com> References: <20220927000631.GA98845@shell.msen.com> <20221022014331.GA68593@shell.msen.com> Message-ID: <20221119160657.GA18282@shell.msen.com> Attached is an update to the Internalize changes file change set, notes below. On Fri, Oct 21, 2022 at 09:43:31PM -0400, David T. Lewis wrote: > On Mon, Sep 26, 2022 at 08:06:31PM -0400, David T. Lewis wrote: > > Attached is a change set that allows the changes log to be kept in the image, > > rather than in an exteral file. Along with our existing "Cache sources file" > > preference, the "Cache changes file" preference allows the image to be moved, > > copied, and run independent of any external sources and changes files. > > > > This is (sort of, and rather belatedly) a follow-up from this email from > > Dan Ingalls back in 1998: > > > > http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-March/007670.html > > > > Dan was referring to Scott Wallace's inplementation from 1996, which can be > > seen in early Squeak images. For example, go to http://try.squeak.org and try > > running the Squeak 1.13 under SqueakJS in your web browser. Scott's original > > implementation is in SystemDictionary>>internalizeChangeLog and > > SystemDictionary>>internalizeSources. > > > > This change set is the trivial re-implementation of moving the changes log > > into the image. It allows myimage.image to be saved with the sources and > > changes files internalized, then started and run on another computer with > > no sources file or changes file present. > > > > I have tried to do sensible things with respect to writing the changes log > > back out to the file system when the preference setting is changed. I've > > been playing with this for a couple of days and it seems to work well so > > far, although I have tested only on Linux. The basic file policy is: > > > > - When internalizing the changes log, leave the existing changes file > > alone, do not delete it. > > > > - When externalizing the changes log, check first if a changes file exists, > > if yes then give the user the option of overwriting it (or doing nothing). > > If no changes file is present, create a new one. > > > > Dave > > Attached is an update to the change set that fixes an issue that I found > after using it for a while. When internalizing the changes log, we should > read the changes file with a StandardFileStream to avoid accidental > conversion of the file contents to WideString (thereby consuming 4X the > memory space, not what we are looking for here). > > This is a small but useful change set. I will live with it a while longer, > then add it to trunk if no further issues. > The 'Internalize changes file.17.cs' change set adds UTF8 conversion for source chunks that contain Japanese characters or other wide characters. The internal changes log is represented as ChangeLogStream, which works as an extension of ReadWriteStream on a ByteStream. Positioning in the stream is by byte position, and reading and writing source chunks is done with a UTF8TextConverter that handles four byte characters in the same manner as a MultiByteFileStream on a changes file. In addition to handling source text conversion properly for wide characters, I also found an interesting (and to me unexpected) behavior. If we have a ReadWriteStream on a ByteString, and then put a wide character to the stream, the ByteString automatically becomes a WideString. This is four times the size of the original string (4 bytes per character), which is definitely not what we want for a changes log stored in the image. I have been using this change set in a couple of working images, and it seems to be safe for general use at this point. If anyone else is using it, please say if there are any issues or problems. I will plan to put this update into trunk in another week or so. Thanks, Dave -------------- next part -------------- ���'From Squeak6.1alpha of 18 October 2022 [latest update: #22263] on 6 November 2022 at 12:55:35 pm'! "Change Set: Internalize changes file Date: 6 November 2022 Author: David T. Lewis Allow the changes log to be maintained within the image rather than as an external file. Provide a preference for changing the configuration. UTF8 encoding is assumed, and several conversion methods are duplicated from MultiByteFileStream. Inspired by the original Scott Wallace implementation circa 1996, see SystemDictionary>>internalizeChangeLog and SystemDictionary>>internalizeSources in early Squeak images."! ReadWriteStream subclass: #ChangeLogStream instanceVariableNames: 'TextConverter' classVariableNames: '' poolDictionaries: '' category: 'Files-System'! !ChangeLogStream commentStamp: 'dtl 11/5/2022 16:22' prior: 0! A ChangeLogStream is a memory resident changes log, equivalent to the traditional file based changes but not stored on the external file system. UTF8 encoding is assumed for all sources and a UTF8TextConverter is used for reading and writing to the stream. ! SequenceableCollection subclass: #SourceFileArray instanceVariableNames: '' classVariableNames: 'CachedChanges ' poolDictionaries: '' category: 'Files-System'! !ChangeLogStream methodsFor: 'converting' stamp: 'dtl 11/5/2022 16:09'! converter "Assume UTF8 for all sources" ^TextConverter ifNil: [TextConverter := UTF8TextConverter new].! ! !ChangeLogStream methodsFor: 'converting' stamp: 'dtl 9/25/2022 16:56'! readOnlyCopy ^ self! ! !ChangeLogStream methodsFor: 'converting' stamp: 'dtl 9/25/2022 10:53'! reopen ^self! ! !ChangeLogStream methodsFor: 'fileIn/Out' stamp: 'dtl 11/6/2022 12:48'! nextChunkText "Deliver the next chunk as a Text. Decode the following ]style[ chunk if present. Position at start of next real chunk." ^self converter nextChunkTextFromStream: self! ! !ChangeLogStream methodsFor: 'testing' stamp: 'dtl 9/24/2022 19:14'! isReadOnly ^false! ! !ChangeLogStream methodsFor: 'accessing' stamp: 'dtl 11/5/2022 16:17'! nextPut: aCharacter ^self converter nextPut: aCharacter toStream: self! ! !ChangeLogStream methodsFor: 'accessing' stamp: 'dtl 11/5/2022 16:13'! nextPutAll: aCollection ^self converter nextPutAll: aCollection toStream: self! ! !ChangeLogStream methodsFor: 'private basic' stamp: 'ul 1/31/2011 02:05'! basicNext: anInteger putAll: aCollection startingAt: startIndex ^super next: anInteger putAll: aCollection startingAt: startIndex! ! !ChangeLogStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'! basicNextPut: char ^ super nextPut: char. ! ! !ChangeLogStream methodsFor: 'private basic' stamp: 'yo 8/28/2002 11:07'! basicNextPutAll: aString ^ super nextPutAll: aString. ! ! !SmalltalkImage methodsFor: 'image, changes names' stamp: 'dtl 9/25/2022 16:15'! openSourcesAndChanges: changesName forImage: imageName "Open the changes and sources files and install them in SourceFiles. Inform the user of problems regarding write permissions or CR/CRLF mixups." "Note: SourcesName and imageName are full paths; changesName is a local name." | sources changes msg wmsg | msg := 'Squeak cannot locate {1}. Please check that the file is named properly and is in the same directory as this image.'. wmsg := 'Squeak cannot write to {1}. Please check that you have write permission for this file. You won''t be able to save this image correctly until you fix this.'. sources := Smalltalk openSources. sources ifNotNil: [sources setConverterForCode]. changes := SourceFileArray cachedChanges ifNil: [Smalltalk openChanges: changesName forImage: imageName]. changes ifNotNil: [changes setConverterForCode]. ((sources == nil or: [sources atEnd]) and: [Preferences valueOfFlag: #warnIfNoSourcesFile]) ifTrue: [Smalltalk platformName = 'Mac OS' ifTrue: [msg := msg , ' Make sure the sources file is not an Alias.']. self inform: (msg format: { 'the sources file named ' , self sourcesName })]. (changes == nil and: [Preferences valueOfFlag: #warnIfNoChangesFile]) ifTrue: [self inform: (msg format: { 'the changes file named ' , changesName })]. ((Preferences valueOfFlag: #warnIfNoChangesFile) and: [changes notNil]) ifTrue: [changes isReadOnly ifTrue: [self inform: (wmsg format: { 'the changes file named ' , changesName })]. ((changes next: 200) includesSubstring: String crlf) ifTrue: [self inform: ('The changes file named {1} has been injured by an unpacking utility. Line endings were changed from Cr to CrLf.

Please set the preferences in your decompressing program to do not convert text files and unpack the system again.' translated format: { changesName }) asTextFromHtml]]. SourceFiles := Array with: sources with: changes! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dtl 9/26/2022 11:22'! saveAs: newName "Save the image under that new name." newName ifNil:[^ self]. (SourceFileArray internalizeChanges or: (SourceFiles at: 2) isNil) ifFalse: [self closeSourceFiles; "so copying the changes file will always work" saveChangesInFileNamed: (self fullNameForChangesNamed: newName)]. self saveImageInFileNamed: (self fullNameForImageNamed: newName)! ! !SmalltalkImage methodsFor: 'sources, changes log' stamp: 'dtl 9/26/2022 11:25'! saveAsNewVersion "Save the image/changes using the next available version number." "Smalltalk saveAsNewVersion" | newName changesName aName anIndex | aName := FileDirectory baseNameFor: (FileDirectory default localNameFor: self imageName). anIndex := aName lastIndexOf: FileDirectory dot asCharacter ifAbsent: [nil]. (anIndex notNil and: [(aName copyFrom: anIndex + 1 to: aName size) isAllDigits]) ifTrue: [aName := aName copyFrom: 1 to: anIndex - 1]. newName := FileDirectory default nextNameFor: aName extension: FileDirectory imageSuffix. changesName := self fullNameForChangesNamed: newName. (SourceFileArray internalizeChanges or: (SourceFiles at: 2) isNil) ifFalse: [ "Check to see if there is a .changes file that would cause a problem if we saved a new .image file with the new version number" (FileDirectory default fileOrDirectoryExists: changesName) ifTrue: [^ self inform: 'There is already .changes file of the desired name, ', newName, ' curiously already present, even though there is no corresponding .image file. Please remedy manually and then repeat your request.']. self closeSourceFiles; "so copying the changes file will always work" saveChangesInFileNamed: (self fullNameForChangesNamed: newName) ]. self saveImageInFileNamed: (self fullNameForImageNamed: newName) ! ! !SourceFileArray class methodsFor: 'internalize changes' stamp: 'dtl 9/25/2022 17:57'! cachedChanges "When present, CachedChanges replaces the traditional external changes file with an internal stream in the image." ^CachedChanges! ! !SourceFileArray class methodsFor: 'internalize changes' stamp: 'dtl 10/19/2022 19:03'! changeLogContents | changes fs contents | changes := SourceFiles at: 2. (changes isKindOf: FileStream) ifTrue: [[fs := StandardFileStream "Use StandardFileStream, not FileStream concreteStream, to avoid WideString conversion" readOnlyFileNamed: changes name. fs binary. contents := fs upToEnd] ensure: [fs close]. "Smalltalk openSourceFiles." ^ contents asString] ifFalse: [^ changes contents]! ! !SourceFileArray class methodsFor: 'internalize changes' stamp: 'dtl 11/5/2022 15:06'! externalizeChangeLog "Move the changes log to an external file. This is the traditional packaging, in which the sources file and changes file are maintained separately from the image file." self safeToExportChanges ifTrue: [ | fs | [fs := FileStream fileNamed: Smalltalk changesName. fs binary. fs nextPutAll: CachedChanges contents. CachedChanges := nil] ensure: [ fs close ]. Smalltalk openSourceFiles]. ! ! !SourceFileArray class methodsFor: 'internalize changes' stamp: 'dtl 11/5/2022 15:47'! internalizeChangeLog "Move the change log to an internal stream and maintain it within the image. This configuration may be risky because the record of recently logged changes is no longer available in a separate external file. If the image file itself becomes unusable, the recent changes log file will not be available." (ChangeLogStream with: self changeLogContents) ifNotNil: [:strm | CachedChanges := strm. SourceFiles at: 2 put: CachedChanges]! ! !SourceFileArray class methodsFor: 'internalize changes' stamp: 'dtl 9/25/2022 17:35'! internalizeChanges ^CachedChanges notNil ! ! !SourceFileArray class methodsFor: 'internalize changes' stamp: 'dtl 9/25/2022 16:43'! internalizeChanges: internalize internalize ifTrue: [ self internalizeChangeLog ] ifFalse: [self externalizeChangeLog ].! ! !SourceFileArray class methodsFor: 'internalize changes' stamp: 'dtl 9/25/2022 17:32'! safeToExportChanges "Changes log is currently internal, and there is no external changes file with the name that would be used for saving externally or the user confirms that it safe to overwrite that existing file. Existing changes file will be removed if user confirms." ^ CachedChanges ifNil: [ false ] ifNotNil: [ (FileDirectory default fileExists: Smalltalk changesName) ifTrue: [ | response | (response :=self confirm: Smalltalk changesName , ' exists, overwrite?') ifTrue: [[ FileDirectory default deleteFileNamed: Smalltalk changesName ] on: Error do: [ self notify: 'cannot delete ', Smalltalk changesName. ^false ]]. ^ response ] ifFalse: [true]]. ! ! SequenceableCollection subclass: #SourceFileArray instanceVariableNames: '' classVariableNames: 'CachedChanges' poolDictionaries: '' category: 'Files-System'! From commits at source.squeak.org Sat Nov 19 18:04:57 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 19 Nov 2022 18:04:57 0000 Subject: [squeak-dev] The Trunk: EToys-ct.486.mcz Message-ID: <20221119180505.6E99114D7B5@mail.squeak.org> Christoph Thiede uploaded a new version of EToys to project The Trunk: http://source.squeak.org/trunk/EToys-ct.486.mcz ==================== Summary ==================== Name: EToys-ct.486 Author: ct Time: 19 November 2022, 7:04:16.24343 pm UUID: 7824dd20-441e-3342-a4bf-18f7463f6c65 Ancestors: EToys-ct.485 Makes WatchMorph scale-factor-aware. =============== Diff against EToys-ct.485 =============== Item was changed: ----- Method: WatchMorph>>initialize (in category 'initialization') ----- initialize "initialize the state of the receiver" super initialize. "" self handsColor: Color red. self centerColor: Color gray. romanNumerals := false. antialias := false. fontName := 'NewYork'. + self extent: 130 px @ 130 px. - self extent: 130 @ 130. self start! From jakres+squeak at gmail.com Sat Nov 19 18:09:10 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sat, 19 Nov 2022 19:09:10 +0100 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> References: <20221119051408.44B5614D697@mail.squeak.org> <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> Message-ID: Hi, Were the method new, I wouldn't mind if it treated empty fields differently. But since it is not new, I think this is indeed a change that may break applications if they have relied on the previous behavior. Therefore I vote against it unless it is shown that Squeak is the only Smalltalk that implements subStrings: in the current way. The ANSI standard is unfortunately vague and not much guidance: Synopsis Answer an array containing the substrings in the receiver separated by the elements of separators. Definition: Answer an array of strings. Each element represents a group of characters separated by any of the characters in the list of separators. Return Values unspecified @Chris: does splitBy:, as recommended by Christoph, cover your requirements? Should we add a message to split on _any_ of the elements of the argument (like subStrings:, unlike splitBy:), preserving empty groups (like splitBy:, unlike subStrings:)? For example, #splitByAnyOf: Kind regards, Jakob Am Sa., 19. Nov. 2022 um 13:23 Uhr schrieb Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de>: > Hm ... don't we have #splitBy: for this? This seems like a possibly > dangerous breaking change to me. No strong opinion, though. :-) > > > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Chris Muller > *Gesendet:* Samstag, 19. November 2022 06:24:43 > *An:* squeak-dev at lists.squeakfoundation.org > *Betreff:* Re: [squeak-dev] The Inbox: Collections-cmm.1022.mcz > > I don't know why subStrings: should behave differently for empty fields as > non-empty. > > Before this change, empty fields are ignored: > > 'a:b::d' subStrings: ':' ==> " #('a' 'b' 'd') " > '::::' subStrings: ':' ==> #() > > after this change, empty fields are honored: > > 'a:b::d' subStrings: ':' ==> " #('a' 'b' '' 'd') " > '::::' subStrings: ':' ==> #('' '' '' '') > > Thoughts? > > - Chris > > On Fri, Nov 18, 2022 at 11:14 PM wrote: > >> Chris Muller uploaded a new version of Collections to project The Inbox: >> http://source.squeak.org/inbox/Collections-cmm.1022.mcz >> >> ==================== Summary ==================== >> >> Name: Collections-cmm.1022 >> Author: cmm >> Time: 18 November 2022, 11:14:01.223447 pm >> UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 >> Ancestors: Collections-nice.1021 >> >> Allow empty fields when using #subStrings:. >> >> =============== Diff against Collections-nice.1021 =============== >> >> Item was changed: >> ----- Method: String>>subStrings: (in category 'converting') ----- >> subStrings: separators >> "Answer an array containing the substrings in the receiver >> separated >> by the elements of separators." >> | char result sourceStream subString | >> - #Collectn. >> - "Changed 2000/04/08 For ANSI protocol." >> (separators isString or:[separators allSatisfy: [:element | >> element isCharacter]]) ifFalse: >> [^ self error: 'separators must be Characters.']. >> sourceStream := ReadStream on: self. >> result := OrderedCollection new. >> subString := String new. >> [sourceStream atEnd] >> whileFalse: >> [char := sourceStream next. >> (separators includes: char) >> + ifTrue: [result add: subString copy. >> + subString := >> String new] >> - ifTrue: [subString notEmpty >> - ifTrue: >> - [result add: >> subString copy. >> - subString := >> String new]] >> ifFalse: [subString := subString , >> (String with: char)]]. >> subString notEmpty ifTrue: [result add: subString copy]. >> ^ result asArray! >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Sat Nov 19 19:36:03 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 19 Nov 2022 19:36:03 0000 Subject: [squeak-dev] The Inbox: Morphic-ct.2051.mcz Message-ID: <20221119193609.AB3AA14D7C5@mail.squeak.org> Christoph Thiede uploaded a new version of Morphic to project The Inbox: http://source.squeak.org/inbox/Morphic-ct.2051.mcz ==================== Summary ==================== Name: Morphic-ct.2051 Author: ct Time: 19 November 2022, 8:35:59.299387 pm UUID: 6d037f4d-9ad4-8f48-8a0b-b40df261c00c Ancestors: Morphic-mt.2049 Makes keyboard exerciser scale-factor-aware. Fixes layout of instruction text, which was previously not wrapped within the morph, overlapped the check buttons, and caused invalidations when moving or closing the exerciser. For this, uses a classical row-based tabel layout. =============== Diff against Morphic-mt.2049 =============== Item was changed: Morph subclass: #KeyboardExerciser + instanceVariableNames: 'checkButtons eventPane' - instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-Demo'! Item was added: + ----- Method: KeyboardExerciser>>addCheckButtons (in category 'initialization') ----- + addCheckButtons + + | buttonPane | + buttonPane := Morph new + beTransparent; + changeTableLayout; + hResizing: #spaceFill; + vResizing: #shrinkWrap; + listDirection: #leftToRight; + wrapDirection: #topToBottom; + cellGap: 10 px; + yourself. + + checkButtons := OrderedCollection new. + #(processKeyStroke 'Test key stroke' + processKeyDown 'Test key down' + processKeyUp 'Test key up') + groupsDo: [:selector :label | + | button | + button := ThreePhaseButtonMorph checkBox + target: self; + actionSelector: selector; + label: label; + yourself. + checkButtons addLast: button. + buttonPane addMorphBack: button]. + + self addMorphBack: buttonPane. + ^ buttonPane! Item was added: + ----- Method: KeyboardExerciser>>addEventPane (in category 'initialization') ----- + addEventPane + + eventPane := Morph new + beTransparent; + changeTableLayout; + listDirection: #leftToRight; + wrapDirection: #topToBottom; + hResizing: #spaceFill; + vResizing: #shrinkWrap; + cellGap: 10 px; + height: 0; + yourself. + + self addMorphBack: eventPane. + ^ eventPane! Item was added: + ----- Method: KeyboardExerciser>>addTitle (in category 'initialization') ----- + addTitle + + | title | + title := TextMorph new + contents: 'Move your mouse cursor to here and start typing. Try modifiers, too.' translated; + font: Preferences standardButtonFont; + color: Color gray; + hResizing: #spaceFill; + lock; + yourself. + + self addMorphBack: title. + ^ title! Item was changed: ----- Method: KeyboardExerciser>>checkButton: (in category 'initialization') ----- checkButton: checkIndex + self checkButtons do: [:button | + button state: #off]. - 1 to: 3 do: [:index | - (self submorphs at: index) - state: #off]. + (self checkButtons at: checkIndex) state: #on.! - (self submorphs at: checkIndex) state: #on.! Item was added: + ----- Method: KeyboardExerciser>>checkButtons (in category 'accessing') ----- + checkButtons + + ^ checkButtons! Item was changed: ----- Method: KeyboardExerciser>>clear (in category 'initialization') ----- clear + eventPane removeAllMorphs. + eventPane height: 0.! - (self submorphs allButFirst: 3) do: [:m | m delete].! Item was removed: - ----- 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.' translated - at: self topLeft - font: Preferences standardButtonFont - color: Color gray.! Item was added: + ----- Method: KeyboardExerciser>>eventMorphs (in category 'accessing') ----- + eventMorphs + + ^ eventPane submorphs! Item was changed: ----- Method: KeyboardExerciser>>handleEvent:inspect: (in category 'actions') ----- handleEvent: mouseEvent inspect: morph + mouseEvent shiftPressed - mouseEvent shiftPressed ifTrue: [(morph valueOfProperty: #event) explore] ifFalse: [(morph valueOfProperty: #event) inspect].! Item was changed: ----- Method: KeyboardExerciser>>initialize (in category 'initialization') ----- initialize super initialize. self + color: ((self userInterfaceTheme get: #color for: #ScrollPane) ifNil: [Color white]); + borderStyle: ((self userInterfaceTheme get: #borderStyle for: #ScrollPane) ifNil: [BorderStyle simple]) copy; + borderColor: ((self userInterfaceTheme get: #borderColor for: #ScrollPane) ifNil: [Color gray: 0.6]); + borderWidth: (((self userInterfaceTheme get: #borderWidth for: #ScrollPane) ifNil: [1]) * RealEstateAgent scaleFactor) truncated; + extent: 300 px @ 50 px; - color: (self userInterfaceTheme get: #color for: #ScrollPane); - extent: 300 at 50; layoutPolicy: TableLayout new; + listDirection: #topToBottom; - listDirection: #leftToRight; - wrapDirection: #topToBottom; hResizing: #rigid; vResizing: #shrinkWrap; + cellGap: 10 px; + layoutInset: 20 px; - cellGap: 10; - layoutInset: 20; yourself. + self addTitle. + self addCheckButtons. + self addEventPane. - #(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>>instructionMorph (in category 'accessing') ----- + instructionMorph + + ^ self hasSubmorphs ifTrue: [self firstSubmorph]! Item was changed: ----- Method: KeyboardExerciser>>lastEvent (in category 'accessing') ----- lastEvent | view event | + view := (self eventMorphs ifEmpty: [^ nil]) last. - view := self submorphs last. (view hasProperty: #event) ifFalse: [^ nil]. event := view valueOfProperty: #event. event isCollection ifTrue: [event := event last]. ^ event! Item was changed: ----- Method: KeyboardExerciser>>logEvent: (in category 'event handling') ----- logEvent: evt | eventMorph | evt = self lastEvent ifTrue: [^ self logEventRepetition: evt]. eventMorph := evt asMorph. eventMorph setProperty: #event toValue: evt copy; balloonText: ('Click to inspect. Shift+click to explore.\\Virtual key: {8}\Virtual modifiers: {5}\\Physical key: {9}\Physical modifiers: {6}\\Key value: 0x{1} ({2}) \Key character: {3}\Key string: {4}\\{7}' translated withCRs format: { evt keyValue printPaddedWith: $0 to: 2 base: 16. evt keyValue. evt isKeystroke ifTrue: [evt keyCharacter printString] ifFalse: ['-']. evt isKeystroke ifTrue: [evt keyString printString] ifFalse: ['-']. (evt virtualModifiers joinSeparatedBy: ' ') asUppercase. (evt physicalModifiers joinSeparatedBy: ' ') asUppercase. evt printString. evt virtualKey printString. evt physicalKey asString printString}). eventMorph on: #mouseEnter send: #handleEvent:emphasize: to: self; on: #mouseLeave send: #handleEvent:deemphasize: to: self; on: #mouseDown send: #handleEvent:inspect: to: self. + eventPane addMorphBack: eventMorph.! - self addMorphBack: eventMorph.! Item was changed: ----- Method: KeyboardExerciser>>logEventRepetition: (in category 'event handling') ----- logEventRepetition: evt | label lastEvents box | + (self eventMorphs last hasProperty: #repetition) + ifTrue: [box := self eventMorphs last. label := box submorphs first] - (self submorphs last hasProperty: #repetition) - ifTrue: [box := self submorphs last. label := box submorphs first] ifFalse: [ box := Morph new setProperty: #repetition toValue: true; color: Color transparent; layoutPolicy: TableLayout new; hResizing: #shrinkWrap; vResizing:#shrinkWrap; yourself. label := '' asText asMorph lock. box addMorph: label. box setProperty: #event toValue: (OrderedCollection with: self lastEvent). + eventPane addMorphBack: box]. - self addMorphBack: box]. lastEvents := box valueOfProperty: #event. lastEvents add: evt copy. box setProperty: #event toValue: lastEvents. label newContents: (('x ', (lastEvents size)) asText addAttribute: (TextFontReference toFont: Preferences standardButtonFont); yourself). box balloonText: ('{1}{2}' format: { lastEvents size > 10 ifTrue: ['... {1} older events and:\' translated withCRs format: {lastEvents size - 10}] ifFalse: ['']. (lastEvents last: (10 min: lastEvents size)) joinSeparatedBy: String cr. }). box on: #mouseEnter send: #handleEvent:emphasize: to: self; on: #mouseLeave send: #handleEvent:deemphasize: to: self; on: #mouseDown send: #handleEvent:inspect: to: self.! From lewis at mail.msen.com Sat Nov 19 19:59:57 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Sat, 19 Nov 2022 14:59:57 -0500 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: References: <20221119051408.44B5614D697@mail.squeak.org> <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> Message-ID: <20221119195957.GA44187@shell.msen.com> On Sat, Nov 19, 2022 at 07:09:10PM +0100, Jakob Reschke wrote: > > Should we add a message to split on _any_ of the elements of the argument > (like subStrings:, unlike splitBy:), preserving empty groups (like > splitBy:, unlike subStrings:)? For example, #splitByAnyOf: > I would say to add it if only if it is really going to be used, otherwise no. With #splitBy: #subStrings: and #findTokens: the protocol already seems a bit cluttered. Dave From Das.Linux at gmx.de Sat Nov 19 20:05:06 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Sat, 19 Nov 2022 21:05:06 +0100 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> References: <20221119051408.44B5614D697@mail.squeak.org> <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> Message-ID: <4611BC10-51BB-4DD9-A100-2E2D1D42BBCA@gmx.de> So does that throw away ANSI compat? -t > On 19. Nov 2022, at 13:23, Thiede, Christoph wrote: > > Allow empty fields when using #subStrings:. > > =============== Diff against Collections-nice.1021 =============== > > Item was changed: > ----- Method: String>>subStrings: (in category 'converting') ----- > subStrings: separators > "Answer an array containing the substrings in the receiver separated > by the elements of separators." > | char result sourceStream subString | > - #Collectn. > - "Changed 2000/04/08 For ANSI protocol." > (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse: > [^ self error: 'separators must be Characters.']. > sourceStream := ReadStream on: self. > result := OrderedCollection new. > subString := String new. > [sourceStream atEnd] > whileFalse: > [char := sourceStream next. > (separators includes: char) > + ifTrue: [result add: subString copy. > + subString := String new] > - ifTrue: [subString notEmpty > - ifTrue: > - [result add: subString copy. > - subString := String new]] > ifFalse: [subString := subString , (String with: char)]]. > subString notEmpty ifTrue: [result add: subString copy]. > ^ result asArray! From asqueaker at gmail.com Sun Nov 20 23:00:06 2022 From: asqueaker at gmail.com (Chris Muller) Date: Sun, 20 Nov 2022 17:00:06 -0600 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> References: <20221119051408.44B5614D697@mail.squeak.org> <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> Message-ID: You're all 100% right. I had forgotten about #splitBy:, but changing subStrings: certainly didn't feel right. Interestingly, the in-image Method Finder doesn't find either one. Thank you, community! :) I moved this to Treated. - Chris On Sat, Nov 19, 2022 at 6:23 AM Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de> wrote: > Hm ... don't we have #splitBy: for this? This seems like a possibly > dangerous breaking change to me. No strong opinion, though. :-) > > > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Chris Muller > *Gesendet:* Samstag, 19. November 2022 06:24:43 > *An:* squeak-dev at lists.squeakfoundation.org > *Betreff:* Re: [squeak-dev] The Inbox: Collections-cmm.1022.mcz > > I don't know why subStrings: should behave differently for empty fields as > non-empty. > > Before this change, empty fields are ignored: > > 'a:b::d' subStrings: ':' ==> " #('a' 'b' 'd') " > '::::' subStrings: ':' ==> #() > > after this change, empty fields are honored: > > 'a:b::d' subStrings: ':' ==> " #('a' 'b' '' 'd') " > '::::' subStrings: ':' ==> #('' '' '' '') > > Thoughts? > > - Chris > > On Fri, Nov 18, 2022 at 11:14 PM wrote: > >> Chris Muller uploaded a new version of Collections to project The Inbox: >> http://source.squeak.org/inbox/Collections-cmm.1022.mcz >> >> ==================== Summary ==================== >> >> Name: Collections-cmm.1022 >> Author: cmm >> Time: 18 November 2022, 11:14:01.223447 pm >> UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 >> Ancestors: Collections-nice.1021 >> >> Allow empty fields when using #subStrings:. >> >> =============== Diff against Collections-nice.1021 =============== >> >> Item was changed: >> ----- Method: String>>subStrings: (in category 'converting') ----- >> subStrings: separators >> "Answer an array containing the substrings in the receiver >> separated >> by the elements of separators." >> | char result sourceStream subString | >> - #Collectn. >> - "Changed 2000/04/08 For ANSI protocol." >> (separators isString or:[separators allSatisfy: [:element | >> element isCharacter]]) ifFalse: >> [^ self error: 'separators must be Characters.']. >> sourceStream := ReadStream on: self. >> result := OrderedCollection new. >> subString := String new. >> [sourceStream atEnd] >> whileFalse: >> [char := sourceStream next. >> (separators includes: char) >> + ifTrue: [result add: subString copy. >> + subString := >> String new] >> - ifTrue: [subString notEmpty >> - ifTrue: >> - [result add: >> subString copy. >> - subString := >> String new]] >> ifFalse: [subString := subString , >> (String with: char)]]. >> subString notEmpty ifTrue: [result add: subString copy]. >> ^ result asArray! >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From asqueaker at gmail.com Sun Nov 20 23:02:08 2022 From: asqueaker at gmail.com (Chris Muller) Date: Sun, 20 Nov 2022 17:02:08 -0600 Subject: [squeak-dev] The Inbox: System-ct.1374.mcz In-Reply-To: <20221119153837.1473E14D781@mail.squeak.org> References: <20221119153837.1473E14D781@mail.squeak.org> Message-ID: > Commonly, punctuation marks after a word should have the same bold emphasis as the word before. Agreed. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Nov 21 00:11:28 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 21 Nov 2022 00:11:28 +0000 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: References: <20221119051408.44B5614D697@mail.squeak.org> <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de>, Message-ID: > Interestingly, the in-image Method Finder doesn't find either one. Simulation Method Finder does. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Chris Muller Gesendet: Montag, 21. November 2022, 00:00 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: Collections-cmm.1022.mcz You're all 100% right. I had forgotten about #splitBy:, but changing subStrings: certainly didn't feel right. Interestingly, the in-image Method Finder doesn't find either one. Thank you, community! :) I moved this to Treated. - Chris On Sat, Nov 19, 2022 at 6:23 AM Thiede, Christoph > wrote: Hm ... don't we have #splitBy: for this? This seems like a possibly dangerous breaking change to me. No strong opinion, though. :-) Best, Christoph ________________________________ Von: Squeak-dev > im Auftrag von Chris Muller > Gesendet: Samstag, 19. November 2022 06:24:43 An: squeak-dev at lists.squeakfoundation.org Betreff: Re: [squeak-dev] The Inbox: Collections-cmm.1022.mcz I don't know why subStrings: should behave differently for empty fields as non-empty. Before this change, empty fields are ignored: 'a:b::d' subStrings: ':' ==> " #('a' 'b' 'd') " '::::' subStrings: ':' ==> #() after this change, empty fields are honored: 'a:b::d' subStrings: ':' ==> " #('a' 'b' '' 'd') " '::::' subStrings: ':' ==> #('' '' '' '') Thoughts? - Chris On Fri, Nov 18, 2022 at 11:14 PM > wrote: Chris Muller uploaded a new version of Collections to project The Inbox: http://source.squeak.org/inbox/Collections-cmm.1022.mcz ==================== Summary ==================== Name: Collections-cmm.1022 Author: cmm Time: 18 November 2022, 11:14:01.223447 pm UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 Ancestors: Collections-nice.1021 Allow empty fields when using #subStrings:. =============== Diff against Collections-nice.1021 =============== Item was changed: ----- Method: String>>subStrings: (in category 'converting') ----- subStrings: separators "Answer an array containing the substrings in the receiver separated by the elements of separators." | char result sourceStream subString | - #Collectn. - "Changed 2000/04/08 For ANSI protocol." (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse: [^ self error: 'separators must be Characters.']. sourceStream := ReadStream on: self. result := OrderedCollection new. subString := String new. [sourceStream atEnd] whileFalse: [char := sourceStream next. (separators includes: char) + ifTrue: [result add: subString copy. + subString := String new] - ifTrue: [subString notEmpty - ifTrue: - [result add: subString copy. - subString := String new]] ifFalse: [subString := subString , (String with: char)]]. subString notEmpty ifTrue: [result add: subString copy]. ^ result asArray! -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Mon Nov 21 05:28:29 2022 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sun, 20 Nov 2022 21:28:29 -0800 Subject: [squeak-dev] Squeak 6 on SqueakJS Message-ID: ... works now with release 1.0.5 of SqueakJS: https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip We only had to recognize the new image format – sorry it took me so long. Thank you, Christoph Tiede and Dave Lewis! (https://github.com/codefrau/SqueakJS/pull/138) TODO: actually implement primitive 578 (but then, quite a few non-essential prims are still missing) Enjoy! Vanessa -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Nov 21 08:50:25 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 21 Nov 2022 09:50:25 +0100 Subject: [squeak-dev] Squeak 6 on SqueakJS In-Reply-To: References: Message-ID: Hi Vanessa -- Thank you!! :-D High-DPI also works: https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip&highdpi=true [https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip&highdpi=true] Best, Marcel Am 21.11.2022 06:29:19 schrieb Vanessa Freudenberg : ... works now with release 1.0.5 of SqueakJS: https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip [https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip] We only had to recognize the new image format – sorry it took me so long. Thank you, Christoph Tiede and Dave Lewis! (https://github.com/codefrau/SqueakJS/pull/138 [https://github.com/codefrau/SqueakJS/pull/138]) TODO: actually implement primitive 578 (but then, quite a few non-essential prims are still missing) Enjoy! Vanessa -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Nov 21 08:58:47 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 21 Nov 2022 09:58:47 +0100 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: References: <20221119051408.44B5614D697@mail.squeak.org> <7e30b498b37a44869f6d9191ddbafad7@student.hpi.uni-potsdam.de> <,> Message-ID: FYI https://github.com/LinqLover/SimulationStudio#simulationstudio-tools [https://github.com/LinqLover/SimulationStudio#simulationstudio-tools] Best, Marcel Am 21.11.2022 01:11:41 schrieb Thiede, Christoph : > Interestingly, the in-image Method Finder doesn't find either one. Simulation Method Finder does. :-) Best, Christoph Von: Squeak-dev im Auftrag von Chris Muller Gesendet: Montag, 21. November 2022, 00:00 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Inbox: Collections-cmm.1022.mcz You're all 100% right.  I had forgotten about #splitBy:, but changing subStrings: certainly didn't feel right.  Interestingly, the in-image Method Finder doesn't find either one.  Thank you, community!  :) I moved this to Treated.  - Chris On Sat, Nov 19, 2022 at 6:23 AM Thiede, Christoph wrote: Hm ... don't we have #splitBy: for this? This seems like a possibly dangerous breaking change to me. No strong opinion, though. :-) Best, Christoph Von: Squeak-dev im Auftrag von Chris Muller Gesendet: Samstag, 19. November 2022 06:24:43 An: squeak-dev at lists.squeakfoundation.org [mailto:squeak-dev at lists.squeakfoundation.org] Betreff: Re: [squeak-dev] The Inbox: Collections-cmm.1022.mcz   I don't know why subStrings: should behave differently for empty fields as non-empty. Before this change, empty fields are ignored:     'a:b::d' subStrings: ':'  ==> " #('a' 'b' 'd') "     '::::' subStrings: ':' ==> #() after this change, empty fields are honored:     'a:b::d' subStrings: ':'  ==> " #('a' 'b' '' 'd') "     '::::' subStrings: ':' ==>  #('' '' '' '') Thoughts?  - Chris     On Fri, Nov 18, 2022 at 11:14 PM wrote: Chris Muller uploaded a new version of Collections to project The Inbox: http://source.squeak.org/inbox/Collections-cmm.1022.mcz [http://source.squeak.org/inbox/Collections-cmm.1022.mcz] ==================== Summary ==================== Name: Collections-cmm.1022 Author: cmm Time: 18 November 2022, 11:14:01.223447 pm UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 Ancestors: Collections-nice.1021 Allow empty fields when using #subStrings:. =============== Diff against Collections-nice.1021 =============== Item was changed:   ----- Method: String>>subStrings: (in category 'converting') -----   subStrings: separators         "Answer an array containing the substrings in the receiver separated         by the elements of separators."         | char result sourceStream subString | -       #Collectn. -       "Changed 2000/04/08 For ANSI protocol."         (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse:                 [^ self error: 'separators must be Characters.'].         sourceStream := ReadStream on: self.         result := OrderedCollection new.         subString := String new.         [sourceStream atEnd]                 whileFalse:                         [char := sourceStream next.                         (separators includes: char) +                               ifTrue: [result add: subString copy. +                                                       subString := String new] -                               ifTrue: [subString notEmpty -                                               ifTrue: -                                                       [result add: subString copy. -                                                       subString := String new]]                                 ifFalse: [subString := subString , (String with: char)]].         subString notEmpty ifTrue: [result add: subString copy].         ^ result asArray! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Nov 21 09:01:05 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 21 Nov 2022 10:01:05 +0100 Subject: [squeak-dev] The Inbox: System-ct.1374.mcz In-Reply-To: References: <20221119153837.1473E14D781@mail.squeak.org> Message-ID: I did not do that by intention to make it clear, what "full name" we actually have. ... Maybe remove that second ! while you are at it... Best, Marcel Am 21.11.2022 00:10:10 schrieb Chris Muller : > Commonly, punctuation marks after a word should have the same bold emphasis as the word before. Agreed. -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Mon Nov 21 09:04:24 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 21 Nov 2022 10:04:24 +0100 Subject: [squeak-dev] The Inbox: Morphic-ct.2051.mcz In-Reply-To: <20221119193609.AB3AA14D7C5@mail.squeak.org> References: <20221119193609.AB3AA14D7C5@mail.squeak.org> Message-ID: If you care for it, go ahead and merge it. Yet, notice the extra complexity in the form of two new instVars etc. That was one of the reasons I did not do it. :-) You should also mention that you also decided on some visual updates in the form of border etc. I did not use that by intention as well ;-) Best, Marcel Am 19.11.2022 20:36:17 schrieb commits at source.squeak.org : Christoph Thiede uploaded a new version of Morphic to project The Inbox: http://source.squeak.org/inbox/Morphic-ct.2051.mcz ==================== Summary ==================== Name: Morphic-ct.2051 Author: ct Time: 19 November 2022, 8:35:59.299387 pm UUID: 6d037f4d-9ad4-8f48-8a0b-b40df261c00c Ancestors: Morphic-mt.2049 Makes keyboard exerciser scale-factor-aware. Fixes layout of instruction text, which was previously not wrapped within the morph, overlapped the check buttons, and caused invalidations when moving or closing the exerciser. For this, uses a classical row-based tabel layout. =============== Diff against Morphic-mt.2049 =============== Item was changed: Morph subclass: #KeyboardExerciser + instanceVariableNames: 'checkButtons eventPane' - instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'Morphic-Demo'! Item was added: + ----- Method: KeyboardExerciser>>addCheckButtons (in category 'initialization') ----- + addCheckButtons + + | buttonPane | + buttonPane := Morph new + beTransparent; + changeTableLayout; + hResizing: #spaceFill; + vResizing: #shrinkWrap; + listDirection: #leftToRight; + wrapDirection: #topToBottom; + cellGap: 10 px; + yourself. + + checkButtons := OrderedCollection new. + #(processKeyStroke 'Test key stroke' + processKeyDown 'Test key down' + processKeyUp 'Test key up') + groupsDo: [:selector :label | + | button | + button := ThreePhaseButtonMorph checkBox + target: self; + actionSelector: selector; + label: label; + yourself. + checkButtons addLast: button. + buttonPane addMorphBack: button]. + + self addMorphBack: buttonPane. + ^ buttonPane! Item was added: + ----- Method: KeyboardExerciser>>addEventPane (in category 'initialization') ----- + addEventPane + + eventPane := Morph new + beTransparent; + changeTableLayout; + listDirection: #leftToRight; + wrapDirection: #topToBottom; + hResizing: #spaceFill; + vResizing: #shrinkWrap; + cellGap: 10 px; + height: 0; + yourself. + + self addMorphBack: eventPane. + ^ eventPane! Item was added: + ----- Method: KeyboardExerciser>>addTitle (in category 'initialization') ----- + addTitle + + | title | + title := TextMorph new + contents: 'Move your mouse cursor to here and start typing. Try modifiers, too.' translated; + font: Preferences standardButtonFont; + color: Color gray; + hResizing: #spaceFill; + lock; + yourself. + + self addMorphBack: title. + ^ title! Item was changed: ----- Method: KeyboardExerciser>>checkButton: (in category 'initialization') ----- checkButton: checkIndex + self checkButtons do: [:button | + button state: #off]. - 1 to: 3 do: [:index | - (self submorphs at: index) - state: #off]. + (self checkButtons at: checkIndex) state: #on.! - (self submorphs at: checkIndex) state: #on.! Item was added: + ----- Method: KeyboardExerciser>>checkButtons (in category 'accessing') ----- + checkButtons + + ^ checkButtons! Item was changed: ----- Method: KeyboardExerciser>>clear (in category 'initialization') ----- clear + eventPane removeAllMorphs. + eventPane height: 0.! - (self submorphs allButFirst: 3) do: [:m | m delete].! Item was removed: - ----- 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.' translated - at: self topLeft - font: Preferences standardButtonFont - color: Color gray.! Item was added: + ----- Method: KeyboardExerciser>>eventMorphs (in category 'accessing') ----- + eventMorphs + + ^ eventPane submorphs! Item was changed: ----- Method: KeyboardExerciser>>handleEvent:inspect: (in category 'actions') ----- handleEvent: mouseEvent inspect: morph + mouseEvent shiftPressed - mouseEvent shiftPressed ifTrue: [(morph valueOfProperty: #event) explore] ifFalse: [(morph valueOfProperty: #event) inspect].! Item was changed: ----- Method: KeyboardExerciser>>initialize (in category 'initialization') ----- initialize super initialize. self + color: ((self userInterfaceTheme get: #color for: #ScrollPane) ifNil: [Color white]); + borderStyle: ((self userInterfaceTheme get: #borderStyle for: #ScrollPane) ifNil: [BorderStyle simple]) copy; + borderColor: ((self userInterfaceTheme get: #borderColor for: #ScrollPane) ifNil: [Color gray: 0.6]); + borderWidth: (((self userInterfaceTheme get: #borderWidth for: #ScrollPane) ifNil: [1]) * RealEstateAgent scaleFactor) truncated; + extent: 300 px @ 50 px; - color: (self userInterfaceTheme get: #color for: #ScrollPane); - extent: 300 at 50; layoutPolicy: TableLayout new; + listDirection: #topToBottom; - listDirection: #leftToRight; - wrapDirection: #topToBottom; hResizing: #rigid; vResizing: #shrinkWrap; + cellGap: 10 px; + layoutInset: 20 px; - cellGap: 10; - layoutInset: 20; yourself. + self addTitle. + self addCheckButtons. + self addEventPane. - #(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>>instructionMorph (in category 'accessing') ----- + instructionMorph + + ^ self hasSubmorphs ifTrue: [self firstSubmorph]! Item was changed: ----- Method: KeyboardExerciser>>lastEvent (in category 'accessing') ----- lastEvent | view event | + view := (self eventMorphs ifEmpty: [^ nil]) last. - view := self submorphs last. (view hasProperty: #event) ifFalse: [^ nil]. event := view valueOfProperty: #event. event isCollection ifTrue: [event := event last]. ^ event! Item was changed: ----- Method: KeyboardExerciser>>logEvent: (in category 'event handling') ----- logEvent: evt | eventMorph | evt = self lastEvent ifTrue: [^ self logEventRepetition: evt]. eventMorph := evt asMorph. eventMorph setProperty: #event toValue: evt copy; balloonText: ('Click to inspect. Shift+click to explore.\\Virtual key: {8}\Virtual modifiers: {5}\\Physical key: {9}\Physical modifiers: {6}\\Key value: 0x{1} ({2}) \Key character: {3}\Key string: {4}\\{7}' translated withCRs format: { evt keyValue printPaddedWith: $0 to: 2 base: 16. evt keyValue. evt isKeystroke ifTrue: [evt keyCharacter printString] ifFalse: ['-']. evt isKeystroke ifTrue: [evt keyString printString] ifFalse: ['-']. (evt virtualModifiers joinSeparatedBy: ' ') asUppercase. (evt physicalModifiers joinSeparatedBy: ' ') asUppercase. evt printString. evt virtualKey printString. evt physicalKey asString printString}). eventMorph on: #mouseEnter send: #handleEvent:emphasize: to: self; on: #mouseLeave send: #handleEvent:deemphasize: to: self; on: #mouseDown send: #handleEvent:inspect: to: self. + eventPane addMorphBack: eventMorph.! - self addMorphBack: eventMorph.! Item was changed: ----- Method: KeyboardExerciser>>logEventRepetition: (in category 'event handling') ----- logEventRepetition: evt | label lastEvents box | + (self eventMorphs last hasProperty: #repetition) + ifTrue: [box := self eventMorphs last. label := box submorphs first] - (self submorphs last hasProperty: #repetition) - ifTrue: [box := self submorphs last. label := box submorphs first] ifFalse: [ box := Morph new setProperty: #repetition toValue: true; color: Color transparent; layoutPolicy: TableLayout new; hResizing: #shrinkWrap; vResizing:#shrinkWrap; yourself. label := '' asText asMorph lock. box addMorph: label. box setProperty: #event toValue: (OrderedCollection with: self lastEvent). + eventPane addMorphBack: box]. - self addMorphBack: box]. lastEvents := box valueOfProperty: #event. lastEvents add: evt copy. box setProperty: #event toValue: lastEvents. label newContents: (('x ', (lastEvents size)) asText addAttribute: (TextFontReference toFont: Preferences standardButtonFont); yourself). box balloonText: ('{1}{2}' format: { lastEvents size > 10 ifTrue: ['... {1} older events and:\' translated withCRs format: {lastEvents size - 10}] ifFalse: ['']. (lastEvents last: (10 min: lastEvents size)) joinSeparatedBy: String cr. }). box on: #mouseEnter send: #handleEvent:emphasize: to: self; on: #mouseLeave send: #handleEvent:deemphasize: to: self; on: #mouseDown send: #handleEvent:inspect: to: self.! -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Mon Nov 21 10:27:06 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Mon, 21 Nov 2022 10:27:06 0000 Subject: [squeak-dev] The Trunk: Morphic-mt.2053.mcz Message-ID: <20221121102714.6BBBA14D9BD@mail.squeak.org> Marcel Taeumel uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-mt.2053.mcz ==================== Summary ==================== Name: Morphic-mt.2053 Author: mt Time: 21 November 2022, 11:26:08.284072 am UUID: e5103676-4f14-f245-8dee-e81e3f692664 Ancestors: Morphic-ct.2052 More commentary for mouse and keyboard events. =============== Diff against Morphic-ct.2052 =============== Item was changed: ----- Method: Morph>>handleKeyDown: (in category 'events-processing') ----- handleKeyDown: anEvent + "System level event handling. AVOID OVERRIDE if possible. Instead, please use #handlesKeyboard: and #keyDown: in your custom morphs." + - "System level event handling." anEvent wasHandled ifTrue: [^ self]. (self handlesKeyboard: anEvent) ifFalse: [^ self]. (anEvent hand keyboardFocus ~~ self and: [self handlesKeyboardOnlyOnFocus]) ifTrue: [^ self]. anEvent wasHandled: true. ^ self keyDown: anEvent! Item was changed: ----- Method: Morph>>handleKeyUp: (in category 'events-processing') ----- handleKeyUp: anEvent + "System level event handling. AVOID OVERRIDE if possible. Instead, please use #handlesKeyboard: and #keyUp: in your custom morphs." + - "System level event handling." anEvent wasHandled ifTrue: [^ self]. (self handlesKeyboard: anEvent) ifFalse: [^ self]. (anEvent hand keyboardFocus ~~ self and: [self handlesKeyboardOnlyOnFocus]) ifTrue: [^ self]. anEvent wasHandled: true. ^ self keyUp: anEvent! Item was changed: ----- Method: Morph>>handleKeystroke: (in category 'events-processing') ----- handleKeystroke: anEvent + "System level event handling. Supports automatically grabbing the keyboard focus via keyboard focus delegate; see #newKeyboardFocus:. - "System level event handling. Has support for automatically grabbing the keyboard focus considering the keyboard focus delegate. See #newKeyboardFocus:" + AVOID OVERRIDE if possible. Instead, please use #handlesKeyboard: and #keyStroke: in your custom morphs." + | handler | anEvent wasHandled ifTrue: [^ self]. (self handlesKeyboard: anEvent) ifFalse: [^ self]. (anEvent hand keyboardFocus ~~ self and: [self handlesKeyboardOnlyOnFocus]) ifTrue: [^ self]. handler := self wantsKeyboardFocus ifFalse: [self] ifTrue: [(anEvent hand newKeyboardFocus: self) ifNil: [self]]. anEvent handler: handler. anEvent wasHandled: true. ^ handler keyStroke: anEvent! Item was changed: ----- Method: Morph>>handleMouseDown: (in category 'events-processing') ----- handleMouseDown: anEvent + "System level event handling. AVOID OVERRIDE if possible. Instead, please use #handlesMouseDown: and #mouseDown: in your custom morphs. See #handlerForMouseDown: and #mouseDownPriority." + - "System level event handling." anEvent wasHandled ifTrue:[^self]. "not interested" anEvent hand removePendingBalloonFor: self. anEvent hand removePendingHaloFor: self. anEvent wasHandled: true. "Make me modal during mouse transitions" anEvent hand newMouseFocus: self event: anEvent. "this mouse down could be the start of a gesture, or the end of a gesture focus" (self isGestureStart: anEvent) ifTrue: [^ self gestureStart: anEvent]. self mouseDown: anEvent. (self handlesMouseStillDown: anEvent) ifTrue:[ self startStepping: #handleMouseStillDown: at: Time millisecondClockValue + self mouseStillDownThreshold arguments: {anEvent copy resetHandlerFields} stepTime: self mouseStillDownStepRate ]. ! Item was changed: ----- Method: Morph>>handleMouseEnter: (in category 'events-processing') ----- handleMouseEnter: anEvent + "System level event handling. AVOID OVERRIDE if possible. Instead, please use #handlesMouseOver: and #mouseEnter: in your custom morphs. Also see/use #handlesMouseOverDragging: and #mouseEnterDragging:." + - "System level event handling." (anEvent isDraggingEvent) ifTrue:[ (self handlesMouseOverDragging: anEvent) ifTrue:[ anEvent wasHandled: true. self mouseEnterDragging: anEvent]. ^self]. self wantsHalo "If receiver wants halo and balloon, trigger balloon after halo" ifTrue:[anEvent hand triggerHaloFor: self after: self haloDelayTime] ifFalse:[self wantsBalloon ifTrue:[anEvent hand triggerBalloonFor: self after: self balloonHelpDelayTime]]. (self handlesMouseOver: anEvent) ifTrue:[ anEvent wasHandled: true. self mouseEnter: anEvent. ].! Item was changed: ----- Method: Morph>>handleMouseLeave: (in category 'events-processing') ----- handleMouseLeave: anEvent + "System level event handling. AVOID OVERRIDE if possible. Instead, please use #handlesMouseOver: and #mouseLeave: in your custom morphs. Also see/use #handlesMouseOverDragging: and #mouseLeaveDragging:." + - "System level event handling." anEvent hand removePendingBalloonFor: self. anEvent hand removePendingHaloFor: self. anEvent isDraggingEvent ifTrue:[ (self handlesMouseOverDragging: anEvent) ifTrue:[ anEvent wasHandled: true. self mouseLeaveDragging: anEvent]. ^self]. (self handlesMouseOver: anEvent) ifTrue:[ anEvent wasHandled: true. self mouseLeave: anEvent. ]. ! Item was changed: ----- Method: Morph>>handleMouseMove: (in category 'events-processing') ----- handleMouseMove: anEvent + "System level event handling. AVOID OVERRIDE if possible. Instead, please use #handlesMouseMove: and #mouseMove: in your custom morphs. Also see/use #wantsEveryMouseMove." + - "System level event handling." anEvent wasHandled ifTrue: [ ^ self ]. "not interested" (self handlesMouseMove: anEvent) ifFalse: [ ^ self ]. anEvent wasHandled: true. self mouseMove: anEvent. (self handlesMouseStillDown: anEvent) ifTrue: [ "Step at the new location" self startStepping: #handleMouseStillDown: at: Time millisecondClockValue arguments: {anEvent copy resetHandlerFields} stepTime: self mouseStillDownStepRate ]! Item was changed: ----- Method: Morph>>handleMouseOver: (in category 'events-processing') ----- handleMouseOver: anEvent + "System level event handling. DO NOT OVERRIDE. See #handleMouseMove:, #handleMouseEnter:, #handleMouseLeave:." + - "System level event handling." anEvent hand mouseFocus == self ifTrue:[ "Got this directly through #handleFocusEvent: so check explicitly" (self containsPoint: anEvent position event: anEvent) ifFalse:[^self]]. anEvent hand noticeMouseOver: self event: anEvent! Item was changed: ----- Method: Morph>>handleMouseUp: (in category 'events-processing') ----- handleMouseUp: anEvent + "System level event handling. Complements #handleMouseDown: (and #mouseDown:). AVOID OVERRIDE if possible. Instead, please use #handlesMouseDown: and #mouseUp: in your custom morphs. See #handlerForMouseDown: and #mouseDownPriority." + - "System level event handling." anEvent wasHandled ifTrue:[^self]. "not interested" anEvent hand mouseFocus == self ifFalse:[^self]. "Not interested in other parties" anEvent hand releaseMouseFocus: self. anEvent wasHandled: true. self mouseUp: anEvent. self stopSteppingSelector: #handleMouseStillDown:.! Item was changed: ----- Method: Morph>>handleMouseWheel: (in category 'events-processing') ----- handleMouseWheel: anEvent + "System level event handling. AVOID OVERRIDE if possible. Instead, please use #handlesMouseWheel: and #mouseWheel: in your custom morphs." - "System level event handling." anEvent wasHandled ifTrue: [^self]. (self handlesMouseWheel: anEvent) ifFalse: [^ self]. anEvent wasHandled: true. ^ self mouseWheel: anEvent! Item was changed: ----- Method: Morph>>keyDown: (in category 'event handling') ----- keyDown: anEvent + "Handle a key down event. The default response is to let my eventHandler, if any, handle it. Ask anEvent for #key to work with a cross-platform representation of virtual-key presses. DO NOT access #keyValue or #keyCharacter as those are for #keyStroke: only. + + For #virtualModifiers, ask for #shiftPressed, #controlKeyPressed, #optionKeyPressed, or #commandKeyPressed. Note that if you want to SHOW platform-specific information about modifiers (e.g., ALT on Windows), see #physicalModifiers. For control-flow expressions (e.g., #ifTrue:), only use #virtualModifiers to remain cross-platform compatible." - "Handle a key down event. The default response is to let my eventHandler, if any, handle it." self eventHandler ifNotNil: [self eventHandler keyDown: anEvent fromMorph: self]. ! Item was changed: ----- Method: Morph>>keyStroke: (in category 'event handling') ----- keyStroke: anEvent + "Handle a keystroke event. The default response is to let my eventHandler, if any, handle it. Ask anEvent for #keyCharacter to work with the (Unicode) character the user entered. See class comment in Character. + + Please implement keyboard shortcuts via #keyDown: instead. Here, as in #keyDown: and #keyUp, you may ask anEvent for #key but should do that in #keyDown: or #keyUp: if possible. + + Please AVOID checking #modifiers (or #virtualModifiers) in combination with #keyCharacter as, for example, #shiftPressed has an effect on #keyCharacter as well. This is not the case for #key (or #virtualKey)." - "Handle a keystroke event. The default response is to let my eventHandler, if any, handle it." self eventHandler ifNotNil: [self eventHandler keyStroke: anEvent fromMorph: self]. ! Item was changed: ----- Method: Morph>>keyUp: (in category 'event handling') ----- keyUp: anEvent + "Handle a key up event. The default response is to let my eventHandler, if any, handle it. Ask anEvent for #key to work with a cross-platform representation of virtual-key releases. DO NOT access #keyValue or #keyCharacter as those are for #keyStroke: only. + + For #virtualModifiers, ask for #shiftPressed, #controlKeyPressed, #optionKeyPressed, or #commandKeyPressed. Note that if you want to SHOW platform-specific information about modifiers (e.g., ALT on Windows), see #physicalModifiers. For control-flow expressions (e.g., #ifTrue:), only use #virtualModifiers to remain cross-platform compatible." - "Handle a key up event. The default response is to let my eventHandler, if any, handle it." self eventHandler ifNotNil: [self eventHandler keyUp: anEvent fromMorph: self]. ! From marcel.taeumel at hpi.de Mon Nov 21 13:10:27 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Mon, 21 Nov 2022 14:10:27 +0100 Subject: [squeak-dev] The Inbox: Installer-Core-ct.453.mcz In-Reply-To: <20221118230601.2A48C14D697@mail.squeak.org> References: <20221118230601.2A48C14D697@mail.squeak.org> Message-ID: +1 Am 19.11.2022 00:06:09 schrieb commits at source.squeak.org : Christoph Thiede uploaded a new version of Installer-Core to project The Inbox: http://source.squeak.org/inbox/Installer-Core-ct.453.mcz ==================== Summary ==================== Name: Installer-Core-ct.453 Author: ct Time: 19 November 2022, 12:05:57.795955 am UUID: d2a0cc9f-69ed-a149-b661-62b19024829a Ancestors: Installer-Core-ct.452 Proposal: Stores API selectors for Metacello in MetacelloStub to avoid UnknownSelector warnings upon initial Metacello usage. E.g., if you evaluate any installation script from the web in a vanilla Squeak image that uses Metacello's #githubUser:project:path: selector, the image will no longer complain about an unknown selector, which sometimes causes confusion in beginners and experts. :-) =============== Diff against Installer-Core-ct.452 =============== Item was added: + ----- Method: MetacelloStub class>>apiSelectors (in category 'support') ----- + apiSelectors + "To avoid UnknownSelector warnings upon initial Metacello usage. Support only. By adding this method, these selectors will already be contained in the symbol table before Metacello is installed." + + "(Metacello selectors , Metacello class selectors) withoutDuplicates sorted" + ^ #(#addStatement:args: #baseline: #bitbucketUser:project:commitish:path: #blueplane: #cacheRepository: #className: #classic #configuration: #croquet: #execute:args: #executorSpec #executorSpec: #fetch #fetch: #filetreeDirectory: #gemsource: #get #githubUser:project:commitish:path: #githubUser:project:path: #ignoreImage #image #impara: #list #load #load: #lock #locked #onConflict: #onConflictUseIncoming #onConflictUseIncoming:useLoaded: #onConflictUseLoaded #onDowngrade: #onDowngradeUseIncoming #onDowngradeUseIncoming: #onLock: #onLockBreak #onLockBreak: #onUpgrade: #onUpgradeUseLoaded #onUpgradeUseLoaded: #onWarning: #onWarningLog #password: #project: #record #record: #register #registrations #registry #renggli: #repository: #repositoryOverrides: #saltypickle: #scriptExecutor #scriptExecutorClass #scriptExecutorClass: #silently #smalltalkhubUser:project: #squeakfoundation: #squeaksource3: #squeaksource: #ss3: #statements #statements: #swa: #swasource: #unlock #unregister #usernam e: #version: #wiresong:) ! -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Mon Nov 21 13:11:23 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon, 21 Nov 2022 05:11:23 -0800 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: <20221119051408.44B5614D697@mail.squeak.org> References: <20221119051408.44B5614D697@mail.squeak.org> Message-ID: Hi Chris, why “add: subString copy” and not just “add: subString”? subString’s values are all instantiated locally to subStrings:, don’t escape other than through the result sequence, and are not duplicated. The send of copy looks to me to have been a misunderstanding on behalf of a prior author. I’d also love to see the argument be able to be either a string or a character, with two separate loops in ifTrue:ifFalse: gif efficiency, avoiding instantiating a singleton collection if the arg is a character. _,,,^..^,,,_ (phone) > On Nov 18, 2022, at 9:14 PM, commits at source.squeak.org wrote: > > Chris Muller uploaded a new version of Collections to project The Inbox: > http://source.squeak.org/inbox/Collections-cmm.1022.mcz > > ==================== Summary ==================== > > Name: Collections-cmm.1022 > Author: cmm > Time: 18 November 2022, 11:14:01.223447 pm > UUID: 9a05d251-4f02-43de-94e8-0f077ec51680 > Ancestors: Collections-nice.1021 > > Allow empty fields when using #subStrings:. > > =============== Diff against Collections-nice.1021 =============== > > Item was changed: > ----- Method: String>>subStrings: (in category 'converting') ----- > subStrings: separators > "Answer an array containing the substrings in the receiver separated > by the elements of separators." > | char result sourceStream subString | > - #Collectn. > - "Changed 2000/04/08 For ANSI protocol." > (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse: > [^ self error: 'separators must be Characters.']. > sourceStream := ReadStream on: self. > result := OrderedCollection new. > subString := String new. > [sourceStream atEnd] > whileFalse: > [char := sourceStream next. > (separators includes: char) > + ifTrue: [result add: subString copy. > + subString := String new] > - ifTrue: [subString notEmpty > - ifTrue: > - [result add: subString copy. > - subString := String new]] > ifFalse: [subString := subString , (String with: char)]]. > subString notEmpty ifTrue: [result add: subString copy]. > ^ result asArray! > > From lewis at mail.msen.com Mon Nov 21 15:04:29 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Mon, 21 Nov 2022 10:04:29 -0500 Subject: [squeak-dev] Squeak 6 on SqueakJS In-Reply-To: References: Message-ID: <20221121150429.GA6208@shell.msen.com> Woohoo! Thank you Vanessa Dave On Sun, Nov 20, 2022 at 09:28:29PM -0800, Vanessa Freudenberg wrote: > ... works now with release 1.0.5 of SqueakJS: > > https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip > > We only had to recognize the new image format ??? sorry it took me so long. > Thank you, Christoph Tiede and Dave Lewis! > (https://github.com/codefrau/SqueakJS/pull/138) > > TODO: actually implement primitive 578 (but then, quite a few non-essential > prims are still missing) > > Enjoy! > Vanessa From eliot.miranda at gmail.com Mon Nov 21 20:17:41 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon, 21 Nov 2022 12:17:41 -0800 Subject: [squeak-dev] any objections if I make TextConverter>>decodeString: consume unsigned integer arrays (ByteArray et al) also? Message-ID: Hi All, in porting the ClipboardExtendedPlugin to Windows and starting using it I want to do UTF-16 => string conversion on ByteArray. The innards of textConverter>>decodeString: et al are specific for characters for no good reason I can see. If I don't break the tests does anyone object my adding this polymorphism? _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From giovanni at corriga.net Mon Nov 21 20:23:18 2022 From: giovanni at corriga.net (Giovanni Corriga) Date: Mon, 21 Nov 2022 20:23:18 +0000 Subject: [squeak-dev] Looking for presenters for UK Smalltalk User Group online meetings Message-ID: Hi, The UK Smalltalk User Group is looking for presenters for the online events that we have been running since April 2020. If you have anything you'd like to share with the community - no matter how small! - please contact us at info at uksmalltalk.org or giovanni at corriga.net to discuss what you can offer. Cheers, Giovanni -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Mon Nov 21 21:05:26 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 21 Nov 2022 22:05:26 +0100 Subject: [squeak-dev] any objections if I make TextConverter>>decodeString: consume unsigned integer arrays (ByteArray et al) also? In-Reply-To: References: Message-ID: Hi Eliot, My gut feeling tells me: please go right ahead. I find it irritating how some ByteStrings are really just bytes with the "wrong" type anyway. That you can look at strings of bytes through those two different lenses always reminds me of C and that does not feel well. ;-) Besides, if you process UTF-16 bytes, why not use DoubleByteArray? Kind regards, Jakob Am Mo., 21. Nov. 2022 um 21:18 Uhr schrieb Eliot Miranda < eliot.miranda at gmail.com>: > Hi All, > > in porting the ClipboardExtendedPlugin to Windows and starting using > it I want to do UTF-16 => string conversion on ByteArray. The innards of > textConverter>>decodeString: et al are specific for characters for no good > reason I can see. If I don't break the tests does anyone object my > adding this polymorphism? > _,,,^..^,,,_ > best, Eliot > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Mon Nov 21 21:30:53 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Mon, 21 Nov 2022 13:30:53 -0800 Subject: [squeak-dev] any objections if I make TextConverter>>decodeString: consume unsigned integer arrays (ByteArray et al) also? In-Reply-To: References: Message-ID: On Mon, Nov 21, 2022 at 1:05 PM Jakob Reschke wrote: > Hi Eliot, > > My gut feeling tells me: please go right ahead. I find it irritating how > some ByteStrings are really just bytes with the "wrong" type anyway. That > you can look at strings of bytes through those two different lenses always > reminds me of C and that does not feel well. ;-) > +1 > Besides, if you process UTF-16 bytes, why not use DoubleByteArray? > Godo question and I'm not entirely sure, but I think it comes down to endianness. Accessing a UTF-16 stream as bytes allows one to support either endianness. Using DoubleByteArray makes it straight-forward to use the platform's endianness, and more difficult to use the other endianness. > Kind regards, > Jakob > > > Am Mo., 21. Nov. 2022 um 21:18 Uhr schrieb Eliot Miranda < > eliot.miranda at gmail.com>: > >> Hi All, >> >> in porting the ClipboardExtendedPlugin to Windows and starting using >> it I want to do UTF-16 => string conversion on ByteArray. The innards of >> textConverter>>decodeString: et al are specific for characters for no good >> reason I can see. If I don't break the tests does anyone object my >> adding this polymorphism? >> _,,,^..^,,,_ >> best, Eliot >> >> > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From Das.Linux at gmx.de Mon Nov 21 21:46:19 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 21 Nov 2022 22:46:19 +0100 Subject: [squeak-dev] any objections if I make TextConverter>>decodeString: consume unsigned integer arrays (ByteArray et al) also? In-Reply-To: References: Message-ID: Hi > On 21. Nov 2022, at 21:17, Eliot Miranda wrote: > > Hi All, > > in porting the ClipboardExtendedPlugin to Windows and starting using it I want to do UTF-16 => string conversion on ByteArray. The innards of textConverter>>decodeString: et al are specific for characters for no good reason I can see. If I don't break the tests does anyone object my adding this polymorphism? > _,,,^..^,,,_ > best, Eliot > I often have the "make it right" glasses on. I know thats not really pragmatic, but hear me out a second: _Decoding_ should always work bytes/number -> Characters/string _encoding_ should always work characters/strings -> bytes/numbers I know that's not very light hearted. That said, making TextConverter consume bytes is a good thing in my book. I don't think #decodeString is a good message name when it can _consume_ strings but only when it can _produce_ strings. But that was not the question :D Best regards -Tobias From commits at source.squeak.org Tue Nov 22 05:36:55 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 22 Nov 2022 05:36:55 0000 Subject: [squeak-dev] The Trunk: Collections-eem.1022.mcz Message-ID: <20221122053701.80B5C14D7BB@mail.squeak.org> Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-eem.1022.mcz ==================== Summary ==================== Name: Collections-eem.1022 Author: eem Time: 21 November 2022, 9:26:32.233055 pm UUID: 11b99e4c-0597-4f7d-b3bf-667ea9ad2edf Ancestors: Collections-nice.1021 Fix PositionableStream>>#isBinary, which was implemented in terms of ByteArray, implemented using the new Collection>>isUnsignedIntegerArray. Add Collection>>isSignedIntegerArray for symmetry. =============== Diff against Collections-nice.1021 =============== Item was added: + ----- Method: Collection>>isSignedIntegerArray (in category 'testing') ----- + isSignedIntegerArray + ^false! Item was added: + ----- Method: Collection>>isUnsignedIntegerArray (in category 'testing') ----- + isUnsignedIntegerArray + ^false! Item was changed: ----- Method: PositionableStream>>isBinary (in category 'testing') ----- isBinary + "Answer if the receiver is a binary stream" + ^collection isCollection and: [collection isUnsignedIntegerArray]! - "Return true if the receiver is a binary byte stream" - ^collection class == ByteArray! Item was added: + ----- Method: SignedIntegerArray>>isSignedIntegerArray (in category 'testing') ----- + isSignedIntegerArray + ^true! Item was added: + ----- Method: UnsignedIntegerArray>>isUnsignedIntegerArray (in category 'testing') ----- + isUnsignedIntegerArray + ^true! From marcel.taeumel at hpi.de Tue Nov 22 09:58:09 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 22 Nov 2022 10:58:09 +0100 Subject: [squeak-dev] RawBitsArray vs. DataStream Message-ID: Hi all -- Should the following work? class := DoubleByteArray. size := 10. dummy := 123. array := class new: size. array  atAllPut: dummy. (DataStream newFileNamed: 'numbers') nextPut: array; close. stream := DataStream fileNamed: 'numbers'.  load := stream readArray. stream close. load explore Best, Marcel -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Tue Nov 22 10:55:37 2022 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 22 Nov 2022 11:55:37 +0100 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: Message-ID: Hi Marcel, I would expect that a RawBitsArray just store the raw bits on the dataStream... I would not expect that a low level layer would interpret the contents of raw bits! Le mar. 22 nov. 2022 à 10:58, Marcel Taeumel a écrit : > Hi all -- > > Should the following work? > > class := DoubleByteArray. > size := 10. > dummy := 123. > > array := class new: size. > array atAllPut: dummy. > > (DataStream newFileNamed: 'numbers') > nextPut: array; > close. > > stream := DataStream fileNamed: 'numbers'. > load := stream readArray. > stream close. > load explore > > Best, > Marcel > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Tue Nov 22 12:50:02 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue, 22 Nov 2022 04:50:02 -0800 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: Message-ID: Hi Marcel, On Tue, Nov 22, 2022 at 1:58 AM Marcel Taeumel wrote: > Hi all -- > > Should the following work? > > class := DoubleByteArray. > size := 10. > dummy := 123. > > array := class new: size. > array atAllPut: dummy. > > (DataStream newFileNamed: 'numbers') > nextPut: array; > close. > > stream := DataStream fileNamed: 'numbers'. > load := stream readArray. > stream close. > load explore > Write a test :-) testRawBits ((RawBitsArray subclasses reject: #isAbstract), ((RawBitsArray subclasses select: #isAbstract) collect: #subclasses)) flatten do: [:class| | instance | instance := class new: 10. instance first isColor ifTrue: [1 to: instance size do: [:i| instance at: i put: (Color r: i * 1 g: i * 2 b: i * 3)]] ifFalse: [1 to: instance size do: [:i| instance at: i put: i]]. self assert: instance equals: (self testObject: instance) description: 'A ', class name, ' should be serializable'] see Tests-eem.494 > Best, > Marcel > > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Nov 22 12:51:36 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 22 Nov 2022 12:51:36 0000 Subject: [squeak-dev] The Trunk: Tests-eem.494.mcz Message-ID: <20221122125140.9766E14D7D3@mail.squeak.org> Eliot Miranda uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-eem.494.mcz ==================== Summary ==================== Name: Tests-eem.494 Author: eem Time: 22 November 2022, 4:48:01.49217 am UUID: 6a6ee2f8-2a13-4372-b7cc-d43e0bbb8ffe Ancestors: Tests-mt.493 Test that various RawBitsArrays are serializable on DataStream et al. =============== Diff against Tests-mt.493 =============== Item was added: + ----- Method: DataStreamTest>>testRawBits (in category 'tests') ----- + testRawBits + ((RawBitsArray subclasses reject: #isAbstract), ((RawBitsArray subclasses select: #isAbstract) collect: #subclasses)) flatten do: + [:class| | instance | + instance := class new: 10. + instance first isColor + ifTrue: + [1 to: instance size do: [:i| instance at: i put: (Color r: i * 1 g: i * 2 b: i * 3)]] + ifFalse: + [1 to: instance size do: [:i| instance at: i put: i]]. + self assert: instance equals: (self testObject: instance) description: 'A ', class name, ' should be serializable']! From marcel.taeumel at hpi.de Tue Nov 22 12:53:54 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 22 Nov 2022 13:53:54 +0100 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: Message-ID: Hi Eliot -- > Write a test :-) My image freezes. It seems totally broken. That's why I asked. I wanted to learn more about the expected behavior. After that, I could write a test. ;-) Best, Marcel Am 22.11.2022 13:50:30 schrieb Eliot Miranda : Hi Marcel, On Tue, Nov 22, 2022 at 1:58 AM Marcel Taeumel wrote: Hi all -- Should the following work? class := DoubleByteArray. size := 10. dummy := 123. array := class new: size. array  atAllPut: dummy. (DataStream newFileNamed: 'numbers') nextPut: array; close. stream := DataStream fileNamed: 'numbers'.  load := stream readArray. stream close. load explore Write a test :-) testRawBits     ((RawBitsArray subclasses reject: #isAbstract), ((RawBitsArray subclasses select: #isAbstract) collect: #subclasses)) flatten do:         [:class| | instance |         instance := class new: 10.         instance first isColor             ifTrue:                 [1 to: instance size do: [:i| instance at: i put: (Color r: i * 1 g: i * 2 b: i * 3)]]             ifFalse:                 [1 to: instance size do: [:i| instance at: i put: i]].         self assert: instance equals: (self testObject: instance) description: 'A ', class name, ' should be serializable'] see Tests-eem.494 Best, Marcel -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Tue Nov 22 12:56:52 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue, 22 Nov 2022 04:56:52 -0800 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: Message-ID: On Tue, Nov 22, 2022 at 4:54 AM Marcel Taeumel wrote: > Hi Eliot -- > > > Write a test :-) > > My image freezes. It seems totally broken. That's why I asked. I wanted to > learn more about the expected behavior. After that, I could write a test. > ;-) > Interesting! The test worked second time for me (I used "instance first class = Color", which is false since in that case "instance first class = TransparentColor :-) ). That's 64 bits macOS. Are you seeing this on 32-bit Windows? or...? > Best, > Marcel > > Am 22.11.2022 13:50:30 schrieb Eliot Miranda : > Hi Marcel, > > On Tue, Nov 22, 2022 at 1:58 AM Marcel Taeumel > wrote: > >> Hi all -- >> >> Should the following work? >> >> class := DoubleByteArray. >> size := 10. >> dummy := 123. >> >> array := class new: size. >> array atAllPut: dummy. >> >> (DataStream newFileNamed: 'numbers') >> nextPut: array; >> close. >> >> stream := DataStream fileNamed: 'numbers'. >> load := stream readArray. >> stream close. >> load explore >> > > Write a test :-) > > testRawBits > ((RawBitsArray subclasses reject: #isAbstract), ((RawBitsArray > subclasses select: #isAbstract) collect: #subclasses)) flatten do: > [:class| | instance | > instance := class new: 10. > instance first isColor > ifTrue: > [1 to: instance size do: [:i| instance at: i put: (Color > r: i * 1 g: i * 2 b: i * 3)]] > ifFalse: > [1 to: instance size do: [:i| instance at: i put: i]]. > self assert: instance equals: (self testObject: instance) > description: 'A ', class name, ' should be serializable'] > > see Tests-eem.494 > > >> Best, >> Marcel >> >> > > -- > _,,,^..^,,,_ > best, Eliot > > > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Tue Nov 22 13:00:49 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Tue, 22 Nov 2022 14:00:49 +0100 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: Message-ID: Hi Eliot -- > The test worked second time for me ... Well, you wrote a test that does not account for the example I provided in my first e-mail. ;-) Maybe I used the wrong API. I combined #nextPut: with #nextArray. Looks reasonable to me. The code in DataStreamTest looks scary: #testObject: #get: #put: #unStream: #streamedRepresentationOf: ... oh my ... Best, Marcel Am 22.11.2022 13:57:19 schrieb Eliot Miranda : On Tue, Nov 22, 2022 at 4:54 AM Marcel Taeumel wrote: Hi Eliot -- > Write a test :-) My image freezes. It seems totally broken. That's why I asked. I wanted to learn more about the expected behavior. After that, I could write a test. ;-) Interesting! The test worked second time for me (I used "instance first class = Color", which is false since in that case "instance first class = TransparentColor :-) ). That's 64 bits macOS. Are you seeing this on 32-bit Windows? or...? Best, Marcel Am 22.11.2022 13:50:30 schrieb Eliot Miranda : Hi Marcel, On Tue, Nov 22, 2022 at 1:58 AM Marcel Taeumel wrote: Hi all -- Should the following work? class := DoubleByteArray. size := 10. dummy := 123. array := class new: size. array  atAllPut: dummy. (DataStream newFileNamed: 'numbers') nextPut: array; close. stream := DataStream fileNamed: 'numbers'.  load := stream readArray. stream close. load explore Write a test :-) testRawBits     ((RawBitsArray subclasses reject: #isAbstract), ((RawBitsArray subclasses select: #isAbstract) collect: #subclasses)) flatten do:         [:class| | instance |         instance := class new: 10.         instance first isColor             ifTrue:                 [1 to: instance size do: [:i| instance at: i put: (Color r: i * 1 g: i * 2 b: i * 3)]]             ifFalse:                 [1 to: instance size do: [:i| instance at: i put: i]].         self assert: instance equals: (self testObject: instance) description: 'A ', class name, ' should be serializable'] see Tests-eem.494 Best, Marcel -- _,,,^..^,,,_ best, Eliot -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From nicolas.cellier.aka.nice at gmail.com Tue Nov 22 14:45:38 2022 From: nicolas.cellier.aka.nice at gmail.com (Nicolas Cellier) Date: Tue, 22 Nov 2022 15:45:38 +0100 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: Message-ID: Le mar. 22 nov. 2022 à 14:01, Marcel Taeumel a écrit : > Hi Eliot -- > > > The test worked second time for me ... > > Well, you wrote a test that does not account for the example I provided in > my first e-mail. ;-) Maybe I used the wrong API. I combined #nextPut: with > #nextArray. Looks reasonable to me. > > The code in DataStreamTest looks scary: #testObject: #get: #put: > #unStream: #streamedRepresentationOf: ... oh my ... > > Well, you have used readArray which is marked as private in comment, and will fail because we did not write an Array... (i would recommend to classify those methods in a private category/protocol) The example should use next instead, in which case it works for me. > Best, > Marcel > > Am 22.11.2022 13:57:19 schrieb Eliot Miranda : > > > On Tue, Nov 22, 2022 at 4:54 AM Marcel Taeumel > wrote: > >> Hi Eliot -- >> >> > Write a test :-) >> >> My image freezes. It seems totally broken. That's why I asked. I wanted >> to learn more about the expected behavior. After that, I could write a >> test. ;-) >> > > Interesting! The test worked second time for me (I used "instance first > class = Color", which is false since in that case "instance first class = > TransparentColor :-) ). That's 64 bits macOS. > > Are you seeing this on 32-bit Windows? or...? > > > >> Best, >> Marcel >> >> Am 22.11.2022 13:50:30 schrieb Eliot Miranda : >> Hi Marcel, >> >> On Tue, Nov 22, 2022 at 1:58 AM Marcel Taeumel >> wrote: >> >>> Hi all -- >>> >>> Should the following work? >>> >>> class := DoubleByteArray. >>> size := 10. >>> dummy := 123. >>> >>> array := class new: size. >>> array atAllPut: dummy. >>> >>> (DataStream newFileNamed: 'numbers') >>> nextPut: array; >>> close. >>> >>> stream := DataStream fileNamed: 'numbers'. >>> load := stream readArray. >>> stream close. >>> load explore >>> >> >> Write a test :-) >> >> testRawBits >> ((RawBitsArray subclasses reject: #isAbstract), ((RawBitsArray >> subclasses select: #isAbstract) collect: #subclasses)) flatten do: >> [:class| | instance | >> instance := class new: 10. >> instance first isColor >> ifTrue: >> [1 to: instance size do: [:i| instance at: i put: (Color >> r: i * 1 g: i * 2 b: i * 3)]] >> ifFalse: >> [1 to: instance size do: [:i| instance at: i put: i]]. >> self assert: instance equals: (self testObject: instance) >> description: 'A ', class name, ' should be serializable'] >> >> see Tests-eem.494 >> >> >>> Best, >>> Marcel >>> >>> >> >> -- >> _,,,^..^,,,_ >> best, Eliot >> >> >> > > -- > _,,,^..^,,,_ > best, Eliot > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From asqueaker at gmail.com Wed Nov 23 01:53:32 2022 From: asqueaker at gmail.com (Chris Muller) Date: Tue, 22 Nov 2022 19:53:32 -0600 Subject: [squeak-dev] The Inbox: Collections-cmm.1022.mcz In-Reply-To: References: <20221119051408.44B5614D697@mail.squeak.org> Message-ID: Hi Eliot, why “add: subString copy” and not just “add: subString”? subString’s > values are all instantiated locally to subStrings:, don’t escape other than > through the result sequence, and are not duplicated. The send of copy > looks to me to have been a misunderstanding on behalf of a prior author. > I actually noticed and wondered about that, but didn't want to distract too much from my main question in case there was some magical need for it. It's so peculiar it was proposed to survive its third developer initials, ha ha. :) Looks like we have a minor optimization opportunity there the next time someone swings around to subStrings:. > I’d also love to see the argument be able to be either a string or a > character, with two separate loops in ifTrue:ifFalse: gif efficiency, > avoiding instantiating a singleton collection if the arg is a character. +1. - Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: From lewis at mail.msen.com Wed Nov 23 02:54:47 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Tue, 22 Nov 2022 21:54:47 -0500 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: Message-ID: <20221123025447.GA23388@shell.msen.com> On Tue, Nov 22, 2022 at 10:58:09AM +0100, Marcel Taeumel wrote: > Hi all -- > > Should the following work? > No, it should not work. And yes, it will lock up the image (confirmed on Linux 64-bit). > class := DoubleByteArray. > size := 10. > dummy := 123. > > array := class new: size. > array?? atAllPut: dummy. > > (DataStream newFileNamed: 'numbers') > nextPut: array; > close. > > stream := DataStream fileNamed: 'numbers'.?? > load := stream readArray. > stream close. > load explore > DataStream>>readArray is a private method that will do bad things if you call it at the wrong time. In the example above, it reads a number from the wrong place in the stream (because it should not have been called at that point). This number is used to allocate an array with over 150 million 8-byte slots, leading to the apparent image lockup. The fix would be to put the private methods into a method category labeled "private". Dave From commits at source.squeak.org Wed Nov 23 03:10:30 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 23 Nov 2022 03:10:30 0000 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz Message-ID: <20221123031033.E174A14D821@mail.squeak.org> Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.480.mcz ==================== Summary ==================== Name: Compiler-eem.480 Author: eem Time: 22 November 2022, 7:10:27.324796 pm UUID: 3e5ba19e-c44a-4390-9004-de1246736cbc Ancestors: Compiler-eem.479 Do not warn of an uninitialized temporary if it is being sent ifNil: or ifNotNil:. =============== Diff against Compiler-eem.479 =============== Item was changed: ----- Method: Parser>>primaryExpression (in category 'expression types') ----- primaryExpression hereType == #word ifTrue: [parseNode := self variable. + (parseNode isUndefTemp + and: [(#('ifNil:' 'ifNotNil:') includes: here) not + and: [self interactive]]) + ifTrue: + [self queryUndefined]. - (parseNode isUndefTemp and: [self interactive]) - ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal or: [hereType == #character]]]) ifTrue: [parseNode := encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) ifTrue: [self advance. parseNode := encoder encodeLiteral: self advance negated. ^true]. ^false! From commits at source.squeak.org Wed Nov 23 03:12:56 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 23 Nov 2022 03:12:56 0000 Subject: [squeak-dev] The Trunk: Collections-eem.1023.mcz Message-ID: <20221123031300.8217714D822@mail.squeak.org> Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-eem.1023.mcz ==================== Summary ==================== Name: Collections-eem.1023 Author: eem Time: 22 November 2022, 7:12:52.434373 pm UUID: 9c7f84f0-35b9-476f-9d51-75cc12248c26 Ancestors: Collections-eem.1022 Reimplement subStrings: in SequenceableCollection (this is where it belongs; subStrings: on arbitrary sequeances is useful). Allow the argument to be a singleton, if not a collection. Reimplement to use an index and copyFrom:to: instead of consing up a string on each element. =============== Diff against Collections-eem.1022 =============== Item was added: + ----- Method: SequenceableCollection>>subStrings: (in category 'converting') ----- + subStrings: separatorsOrElement + "Answer an array containing the substrings in the receiver separated + by the elements of separatorsOrElement, if it is a Collection, or a + singleton separator object, if it is not." + + | result size thing subsequenceStart | + result := OrderedCollection new. + size := self size. + separatorsOrElement isCollection + ifTrue: + [1 to: size do: + [:i| + thing := self at: i. + (separatorsOrElement includes: thing) + ifTrue: + [subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: i - 1)]. + subsequenceStart := nil] + ifFalse: + [subsequenceStart ifNil: [subsequenceStart := i]]]] + ifFalse: + [1 to: size do: + [:i| + thing := self at: i. + separatorsOrElement = thing + ifTrue: + [subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: i - 1)]. + subsequenceStart := nil] + ifFalse: + [subsequenceStart ifNil: [subsequenceStart := i]]]]. + subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: size)]. + ^result asArray + + "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: Character space" + + "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: ' ,.-'"! Item was changed: ----- Method: String>>subStrings: (in category 'converting') ----- subStrings: separators "Answer an array containing the substrings in the receiver separated + by the elements of separators, which should be a collection of Characters, + or, for convenience, a single character.." + (separators isCharacter or: [separators isString or:[separators allSatisfy: [:element | element isCharacter]]]) ifTrue: + [^super subStrings: separators]. + ^self error: 'separators must be Characters.' + + "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: Character space" + + "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: ' ,.-'"! - by the elements of separators." - | char result sourceStream subString | - #Collectn. - "Changed 2000/04/08 For ANSI protocol." - (separators isString or:[separators allSatisfy: [:element | element isCharacter]]) ifFalse: - [^ self error: 'separators must be Characters.']. - sourceStream := ReadStream on: self. - result := OrderedCollection new. - subString := String new. - [sourceStream atEnd] - whileFalse: - [char := sourceStream next. - (separators includes: char) - ifTrue: [subString notEmpty - ifTrue: - [result add: subString copy. - subString := String new]] - ifFalse: [subString := subString , (String with: char)]]. - subString notEmpty ifTrue: [result add: subString copy]. - ^ result asArray! From commits at source.squeak.org Wed Nov 23 03:38:00 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 23 Nov 2022 03:38:00 0000 Subject: [squeak-dev] The Trunk: Collections-eem.1024.mcz Message-ID: <20221123033804.9E54D14D826@mail.squeak.org> Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-eem.1024.mcz ==================== Summary ==================== Name: Collections-eem.1024 Author: eem Time: 22 November 2022, 7:37:55.158009 pm UUID: 4c57a48d-50a0-4209-a01b-643c0da598f6 Ancestors: Collections-eem.1023 Replace the two implementations of [Byte]String>>substrings with one using the same scheme as SequenceableCollection>>subStrings:; it's at least 23% faster. =============== Diff against Collections-eem.1023 =============== Item was removed: - ----- Method: ByteString>>substrings (in category 'converting') ----- - substrings - "Answer an array of the substrings that compose the receiver." - - ^Array streamContents: [ :stream | - | end start | - end := 1. - "find one substring each time through this loop" - [ "find the beginning of the next substring" - (start := self - indexOfAnyOf: CharacterSet nonSeparators - startingAt: end) = 0 ] - whileFalse: [ - "find the end" - end := self - indexOfAnyOf: CharacterSet separators - startingAt: start - ifAbsent: [ self size + 1 ]. - stream nextPut: (self copyFrom: start to: end - 1) ] ]! Item was changed: ----- Method: String>>substrings (in category 'converting') ----- substrings "Answer an array of the substrings that compose the receiver." + | result size subsequenceStart | + result := OrderedCollection new. + size := self size. + 1 to: size do: + [:i| + (self at: i) isSeparator + ifTrue: + [subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: i - 1)]. + subsequenceStart := nil] + ifFalse: + [subsequenceStart ifNil: [subsequenceStart := i]]]. + subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: size)]. + ^result asArray + ! - | result end beginning | - result := WriteStream on: (Array new: 10). - end := 0. - "find one substring each time through this loop" - [ "find the beginning of the next substring" - beginning := end+1. - [beginning <= self size and:[(self at: beginning) isSeparator]] - whileTrue:[beginning := beginning + 1]. - beginning <= self size] whileTrue: [ - "find the end" - end := beginning. - [end <= self size and:[(self at: end) isSeparator not]] - whileTrue:[end := end + 1]. - end := end - 1. - result nextPut: (self copyFrom: beginning to: end). - ]. - ^result contents! From eliot.miranda at gmail.com Wed Nov 23 03:50:10 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue, 22 Nov 2022 19:50:10 -0800 Subject: [squeak-dev] The Trunk: Collections-eem.1023.mcz In-Reply-To: <20221123031300.8217714D822@mail.squeak.org> References: <20221123031300.8217714D822@mail.squeak.org> Message-ID: On Tue, Nov 22, 2022 at 7:13 PM wrote: > Eliot Miranda uploaded a new version of Collections to project The Trunk: > http://source.squeak.org/trunk/Collections-eem.1023.mcz > > ==================== Summary ==================== > > Name: Collections-eem.1023 > Author: eem > Time: 22 November 2022, 7:12:52.434373 pm > UUID: 9c7f84f0-35b9-476f-9d51-75cc12248c26 > Ancestors: Collections-eem.1022 > > Reimplement subStrings: in SequenceableCollection (this is where it > belongs; subStrings: on arbitrary sequeances is useful). Allow the > argument to be a singleton, if not a collection. Reimplement to use an > index and copyFrom:to: instead of consing up a string on each element. > Hence (1 to: 100) subStrings: (10 to: 90 by: 10) {(1 to: 9) . (11 to: 19) . (21 to: 29) . (31 to: 39) . (41 to: 49) . (51 to: 59) . (61 to: 69) . (71 to: 79) . (81 to: 89) . (91 to: 100)} Smalltalk is beautiful. _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Nov 23 10:00:31 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 23 Nov 2022 10:00:31 +0000 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <20221123031033.E174A14D821@mail.squeak.org> References: <20221123031033.E174A14D821@mail.squeak.org> Message-ID: Hi Eliot, hi all, I'm skeptical about this change, as it creates or expands a special role of the selectors #ifNil:, #ifNotNil:, and their combinations. IMHO, it unnecessarily complicates the simple Smalltalk syntax. While I know and sometimes dislike these UndefinedVariable notifications, too, I don't know whether differentiating them by the selector is the right strategy to improve this situation. Consider the following examples: | a b c d e f g h | a ifNil: [a := 1]. c := b. c ifNil: [c := 3]. #(1 2 3) sorted: d. e := 5. (e isNil or: [f isNil]) ifTrue: [e := f := 6]. g perform: #ifNotNil: with: [b := g]. h ifNotNilDo: [h := 8]. How would you explain to a naive Smalltalker which of these variables will be marked as undefined at this point and why? (Of course, you can explain it by pointing to the implementation, but I think that's a significantly less intuitive explanation than just saying "you must declare any variable before using it".) This behavior leads to a mental model that disambiguates between null and undefined similar to JavaScript which I never have found helpful. Also, with this change, the compiler leaks the default value of any temporary variable, which we previously were able to hide at least partially. In many cases, I think explicitly setting a temporary variable to nil before it is initialized within some non-trivial conditional complex would be more explicit, thus more readable, and something which we should generally encourage programmers to do. Looking forward to your opinion! Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 23. November 2022 04:10:30 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Compiler-eem.480.mcz Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.480.mcz ==================== Summary ==================== Name: Compiler-eem.480 Author: eem Time: 22 November 2022, 7:10:27.324796 pm UUID: 3e5ba19e-c44a-4390-9004-de1246736cbc Ancestors: Compiler-eem.479 Do not warn of an uninitialized temporary if it is being sent ifNil: or ifNotNil:. =============== Diff against Compiler-eem.479 =============== Item was changed: ----- Method: Parser>>primaryExpression (in category 'expression types') ----- primaryExpression hereType == #word ifTrue: [parseNode := self variable. + (parseNode isUndefTemp + and: [(#('ifNil:' 'ifNotNil:') includes: here) not + and: [self interactive]]) + ifTrue: + [self queryUndefined]. - (parseNode isUndefTemp and: [self interactive]) - ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal or: [hereType == #character]]]) ifTrue: [parseNode := encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) ifTrue: [self advance. parseNode := encoder encodeLiteral: self advance negated. ^true]. ^false! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Nov 23 10:13:09 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 23 Nov 2022 11:13:09 +0100 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: <20221123025447.GA23388@shell.msen.com> References: <20221123025447.GA23388@shell.msen.com> Message-ID: Aha! Thanks for the clarification! :-) Best, Marcel Am 23.11.2022 03:54:55 schrieb David T. Lewis : On Tue, Nov 22, 2022 at 10:58:09AM +0100, Marcel Taeumel wrote: > Hi all -- > > Should the following work? > No, it should not work. And yes, it will lock up the image (confirmed on Linux 64-bit). > class := DoubleByteArray. > size := 10. > dummy := 123. > > array := class new: size. > array?? atAllPut: dummy. > > (DataStream newFileNamed: 'numbers') > nextPut: array; > close. > > stream := DataStream fileNamed: 'numbers'.?? > load := stream readArray. > stream close. > load explore > DataStream>>readArray is a private method that will do bad things if you call it at the wrong time. In the example above, it reads a number from the wrong place in the stream (because it should not have been called at that point). This number is used to allocate an array with over 150 million 8-byte slots, leading to the apparent image lockup. The fix would be to put the private methods into a method category labeled "private". Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Nov 23 10:19:52 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 23 Nov 2022 11:19:52 +0100 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: <20221123025447.GA23388@shell.msen.com> Message-ID: Hmm... 1024 bytes in a ByteArray will be 1029 bytes on disk. So it's okay, I suppose. Interestingly, a DoubleByteArray is use 5142 bytes on disk. A WordArray uses 4101 bytes hmm... okay. Strange for the DoubleByteArray though... Am 23.11.2022 11:13:09 schrieb Marcel Taeumel : Aha! Thanks for the clarification! :-) Best, Marcel Am 23.11.2022 03:54:55 schrieb David T. Lewis : On Tue, Nov 22, 2022 at 10:58:09AM +0100, Marcel Taeumel wrote: > Hi all -- > > Should the following work? > No, it should not work. And yes, it will lock up the image (confirmed on Linux 64-bit). > class := DoubleByteArray. > size := 10. > dummy := 123. > > array := class new: size. > array?? atAllPut: dummy. > > (DataStream newFileNamed: 'numbers') > nextPut: array; > close. > > stream := DataStream fileNamed: 'numbers'.?? > load := stream readArray. > stream close. > load explore > DataStream>>readArray is a private method that will do bad things if you call it at the wrong time. In the example above, it reads a number from the wrong place in the stream (because it should not have been called at that point). This number is used to allocate an array with over 150 million 8-byte slots, leading to the apparent image lockup. The fix would be to put the private methods into a method category labeled "private". Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Nov 23 10:24:51 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 23 Nov 2022 11:24:51 +0100 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <20221123031033.E174A14D821@mail.squeak.org> Message-ID: Hi Christoph -- >  IMHO, it unnecessarily complicates the simple Smalltalk syntax.  [...] Nah, this is just a tooling change, not a syntactical one.  Yes, I would like to have this info skipped for #isNil as well. Note that one should not use  #ifNotNilDo: anymore. Best, Marcel Am 23.11.2022 11:00:43 schrieb Thiede, Christoph : Hi Eliot, hi all, I'm skeptical about this change, as it creates or expands a special role of the selectors #ifNil:, #ifNotNil:, and their combinations. IMHO, it unnecessarily complicates the simple Smalltalk syntax. While I know and sometimes dislike these UndefinedVariable notifications, too, I don't know whether differentiating them by the selector is the right strategy to improve this situation. Consider the following examples: | a b c d e f g h | a ifNil: [a := 1]. c := b. c ifNil: [c := 3]. #(1 2 3) sorted: d. e := 5. (e isNil or: [f isNil]) ifTrue: [e := f := 6]. g perform: #ifNotNil: with: [b := g]. h ifNotNilDo: [h := 8]. How would you explain to a naive Smalltalker which of these variables will be marked as undefined at this point and why? (Of course, you can explain it by pointing to the implementation, but I think that's a significantly less intuitive explanation than just saying "you must declare any variable before using it".) This behavior leads to a mental model that disambiguates between null and undefined similar to JavaScript which I never have found helpful. Also, with this change, the compiler leaks the default value of any temporary variable, which we previously were able to hide at least partially. In many cases, I think explicitly setting a temporary variable to nil before it is initialized within some non-trivial conditional complex would be more explicit, thus more readable, and something which we should generally encourage programmers to do. Looking forward to your opinion! Best, Christoph Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 23. November 2022 04:10:30 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Compiler-eem.480.mcz   Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.480.mcz [http://source.squeak.org/trunk/Compiler-eem.480.mcz] ==================== Summary ==================== Name: Compiler-eem.480 Author: eem Time: 22 November 2022, 7:10:27.324796 pm UUID: 3e5ba19e-c44a-4390-9004-de1246736cbc Ancestors: Compiler-eem.479 Do not warn of an uninitialized temporary if it is being sent ifNil: or ifNotNil:. =============== Diff against Compiler-eem.479 =============== Item was changed:   ----- Method: Parser>>primaryExpression (in category 'expression types') -----   primaryExpression          hereType == #word                  ifTrue:                          [parseNode := self variable. +                        (parseNode isUndefTemp +                         and: [(#('ifNil:' 'ifNotNil:') includes: here) not +                         and: [self interactive]]) +                                ifTrue: +                                        [self queryUndefined]. -                        (parseNode isUndefTemp and: [self interactive]) -                                ifTrue: [self queryUndefined].                          parseNode nowHasRef.                          ^ true].          hereType == #leftBracket                  ifTrue:                          [self advance.                          self blockExpression.                          ^true].          hereType == #leftBrace                  ifTrue:                          [self braceExpression.                          ^true].          hereType == #leftParenthesis                  ifTrue:                          [self advance.                          self expression ifFalse: [^self expected: 'expression'].                          (self match: #rightParenthesis)                                  ifFalse: [^self expected: 'right parenthesis'].                          ^true].          (hereType == #string or: [hereType == #number or: [hereType == #literal or: [hereType == #character]]])                  ifTrue:                          [parseNode := encoder encodeLiteral: self advance.                          ^true].          (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]])                  ifTrue:                          [self advance.                          parseNode := encoder encodeLiteral: self advance negated.                          ^true].          ^false! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Nov 23 10:27:16 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 23 Nov 2022 11:27:16 +0100 Subject: [squeak-dev] The Trunk: Collections-eem.1023.mcz In-Reply-To: References: <20221123031300.8217714D822@mail.squeak.org> Message-ID: Ehm ... please offer something like #subCollections:. Having #subStrings: on SequenceableCollection is a nasty misuse of domain vocabulary... Only String should offer #subStrings:. Other code should write subCollections: instead. Best, Marcel Am 23.11.2022 04:50:37 schrieb Eliot Miranda : On Tue, Nov 22, 2022 at 7:13 PM wrote: Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-eem.1023.mcz [http://source.squeak.org/trunk/Collections-eem.1023.mcz] ==================== Summary ==================== Name: Collections-eem.1023 Author: eem Time: 22 November 2022, 7:12:52.434373 pm UUID: 9c7f84f0-35b9-476f-9d51-75cc12248c26 Ancestors: Collections-eem.1022 Reimplement subStrings: in SequenceableCollection (this is where it belongs; subStrings: on arbitrary sequeances is useful).  Allow the argument to be a singleton, if not a collection.  Reimplement to use an index and copyFrom:to: instead of consing up a string on each element. Hence (1 to: 100) subStrings: (10 to: 90 by: 10) {(1 to: 9) . (11 to: 19) . (21 to: 29) . (31 to: 39) . (41 to: 49) . (51 to: 59) . (61 to: 69) . (71 to: 79) . (81 to: 89) . (91 to: 100)} Smalltalk is beautiful. _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Nov 23 10:41:42 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 23 Nov 2022 10:41:42 +0000 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <20221123031033.E174A14D821@mail.squeak.org> , Message-ID: <56c350a99d684fc794e31d95aefebf58@student.hpi.uni-potsdam.de> Hi Marcel, > Nah, this is just a tooling change, not a syntactical one. Yes, but the compiler is one of the main tools (maybe *the* main tool?) for learning about Smalltalk syntax. If we encode certain idioms/patterns in it, users may learn them as a syntactical part of the language, may they not? > Yes, I would like to have this info skipped for #isNil as well. Note that one should not use #ifNotNilDo: anymore. So build a comprehensive list of "nil-aware selectors"? I don't know ... What would be about #notNil? #isEmptyOrNil? What if Etoys also added a #test:ifNil:ifNotNil: besides the existing #test:ifTrue:ifFalse:? By encoding such information in the compiler, we make the language design less flexible. I feel reminded of the recent debate on keyboard shortcuts for ifFalse:/ifTrue: in the SmalltalkEditor. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Mittwoch, 23. November 2022 11:24:51 An: squeak-dev Betreff: Re: [squeak-dev] The Trunk: Compiler-eem.480.mcz Hi Christoph -- > IMHO, it unnecessarily complicates the simple Smalltalk syntax. [...] Nah, this is just a tooling change, not a syntactical one. Yes, I would like to have this info skipped for #isNil as well. Note that one should not use #ifNotNilDo: anymore. Best, Marcel Am 23.11.2022 11:00:43 schrieb Thiede, Christoph : Hi Eliot, hi all, I'm skeptical about this change, as it creates or expands a special role of the selectors #ifNil:, #ifNotNil:, and their combinations. IMHO, it unnecessarily complicates the simple Smalltalk syntax. While I know and sometimes dislike these UndefinedVariable notifications, too, I don't know whether differentiating them by the selector is the right strategy to improve this situation. Consider the following examples: | a b c d e f g h | a ifNil: [a := 1]. c := b. c ifNil: [c := 3]. #(1 2 3) sorted: d. e := 5. (e isNil or: [f isNil]) ifTrue: [e := f := 6]. g perform: #ifNotNil: with: [b := g]. h ifNotNilDo: [h := 8]. How would you explain to a naive Smalltalker which of these variables will be marked as undefined at this point and why? (Of course, you can explain it by pointing to the implementation, but I think that's a significantly less intuitive explanation than just saying "you must declare any variable before using it".) This behavior leads to a mental model that disambiguates between null and undefined similar to JavaScript which I never have found helpful. Also, with this change, the compiler leaks the default value of any temporary variable, which we previously were able to hide at least partially. In many cases, I think explicitly setting a temporary variable to nil before it is initialized within some non-trivial conditional complex would be more explicit, thus more readable, and something which we should generally encourage programmers to do. Looking forward to your opinion! Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von commits at source.squeak.org Gesendet: Mittwoch, 23. November 2022 04:10:30 An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org Betreff: [squeak-dev] The Trunk: Compiler-eem.480.mcz Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.480.mcz ==================== Summary ==================== Name: Compiler-eem.480 Author: eem Time: 22 November 2022, 7:10:27.324796 pm UUID: 3e5ba19e-c44a-4390-9004-de1246736cbc Ancestors: Compiler-eem.479 Do not warn of an uninitialized temporary if it is being sent ifNil: or ifNotNil:. =============== Diff against Compiler-eem.479 =============== Item was changed: ----- Method: Parser>>primaryExpression (in category 'expression types') ----- primaryExpression hereType == #word ifTrue: [parseNode := self variable. + (parseNode isUndefTemp + and: [(#('ifNil:' 'ifNotNil:') includes: here) not + and: [self interactive]]) + ifTrue: + [self queryUndefined]. - (parseNode isUndefTemp and: [self interactive]) - ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal or: [hereType == #character]]]) ifTrue: [parseNode := encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) ifTrue: [self advance. parseNode := encoder encodeLiteral: self advance negated. ^true]. ^false! -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcel.taeumel at hpi.de Wed Nov 23 10:45:41 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Wed, 23 Nov 2022 11:45:41 +0100 Subject: [squeak-dev] The Trunk: Collections-eem.1023.mcz In-Reply-To: References: <20221123031300.8217714D822@mail.squeak.org> Message-ID: To be more clear: Please tweak this change ASAP before strange code gets written where #subStrings: is sent to collections other than String ... I opt for #subCollections: ... in String, that can forward from #subStrings:. Best, Marcel Am 23.11.2022 11:27:16 schrieb Marcel Taeumel : Ehm ... please offer something like #subCollections:. Having #subStrings: on SequenceableCollection is a nasty misuse of domain vocabulary... Only String should offer #subStrings:. Other code should write subCollections: instead. Best, Marcel Am 23.11.2022 04:50:37 schrieb Eliot Miranda : On Tue, Nov 22, 2022 at 7:13 PM wrote: Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-eem.1023.mcz [http://source.squeak.org/trunk/Collections-eem.1023.mcz] ==================== Summary ==================== Name: Collections-eem.1023 Author: eem Time: 22 November 2022, 7:12:52.434373 pm UUID: 9c7f84f0-35b9-476f-9d51-75cc12248c26 Ancestors: Collections-eem.1022 Reimplement subStrings: in SequenceableCollection (this is where it belongs; subStrings: on arbitrary sequeances is useful).  Allow the argument to be a singleton, if not a collection.  Reimplement to use an index and copyFrom:to: instead of consing up a string on each element. Hence (1 to: 100) subStrings: (10 to: 90 by: 10) {(1 to: 9) . (11 to: 19) . (21 to: 29) . (31 to: 39) . (41 to: 49) . (51 to: 59) . (61 to: 69) . (71 to: 79) . (81 to: 89) . (91 to: 100)} Smalltalk is beautiful. _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Wed Nov 23 14:31:35 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Wed, 23 Nov 2022 14:31:35 +0000 Subject: [squeak-dev] Squeak 6 on SqueakJS In-Reply-To: References: , Message-ID: <3c9d0c6b9f4b4600859c98bb1e32e225@student.hpi.uni-potsdam.de> Thank you Vanessa! If I open Marcel's link https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip&highdpi=true on my high-dpi device (250%), it loads about one minute and then reproducibly says: [cid:d55a7c42-b511-42f1-a8d9-e11df05c64f3] But I have more than 1 GB free RAM. If open the link on a low-DPI screen instead, and move it to the other screen afterward, everything works fine. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 21. November 2022 09:50:25 An: squeak-dev; vm-dev Betreff: Re: [squeak-dev] Squeak 6 on SqueakJS Hi Vanessa -- Thank you!! :-D High-DPI also works: https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip&highdpi=true Best, Marcel Am 21.11.2022 06:29:19 schrieb Vanessa Freudenberg : ... works now with release 1.0.5 of SqueakJS: https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip We only had to recognize the new image format – sorry it took me so long. Thank you, Christoph Tiede and Dave Lewis! (https://github.com/codefrau/SqueakJS/pull/138) TODO: actually implement primitive 578 (but then, quite a few non-essential prims are still missing) Enjoy! Vanessa -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: pastedImage.png Type: image/png Size: 149709 bytes Desc: pastedImage.png URL: From commits at source.squeak.org Wed Nov 23 14:43:13 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 23 Nov 2022 14:43:13 0000 Subject: [squeak-dev] The Trunk: Collections-eem.1025.mcz Message-ID: <20221123144316.D8FDF14D817@mail.squeak.org> Eliot Miranda uploaded a new version of Collections to project The Trunk: http://source.squeak.org/trunk/Collections-eem.1025.mcz ==================== Summary ==================== Name: Collections-eem.1025 Author: eem Time: 23 November 2022, 6:43:09.849872 am UUID: b326199c-16c6-4df6-9f70-fc55b0718f20 Ancestors: Collections-eem.1024 Respond to Marcel's excellent suggestion. Rename SequenceableCollection>>subStrings: to subsequences: and implement String>>subStrings: upon it. =============== Diff against Collections-eem.1024 =============== Item was removed: - ----- Method: SequenceableCollection>>subStrings: (in category 'converting') ----- - subStrings: separatorsOrElement - "Answer an array containing the substrings in the receiver separated - by the elements of separatorsOrElement, if it is a Collection, or a - singleton separator object, if it is not." - - | result size thing subsequenceStart | - result := OrderedCollection new. - size := self size. - separatorsOrElement isCollection - ifTrue: - [1 to: size do: - [:i| - thing := self at: i. - (separatorsOrElement includes: thing) - ifTrue: - [subsequenceStart ifNotNil: - [result addLast: (self copyFrom: subsequenceStart to: i - 1)]. - subsequenceStart := nil] - ifFalse: - [subsequenceStart ifNil: [subsequenceStart := i]]]] - ifFalse: - [1 to: size do: - [:i| - thing := self at: i. - separatorsOrElement = thing - ifTrue: - [subsequenceStart ifNotNil: - [result addLast: (self copyFrom: subsequenceStart to: i - 1)]. - subsequenceStart := nil] - ifFalse: - [subsequenceStart ifNil: [subsequenceStart := i]]]]. - subsequenceStart ifNotNil: - [result addLast: (self copyFrom: subsequenceStart to: size)]. - ^result asArray - - "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: Character space" - - "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: ' ,.-'"! Item was added: + ----- Method: SequenceableCollection>>subsequences: (in category 'converting') ----- + subsequences: separatorsOrElement + "Answer an array containing the subsequences in the receiver separated + by the elements of separatorsOrElement, if it is a Collection, or a + single separator object, if it is not." + + | result size thing subsequenceStart | + result := OrderedCollection new. + size := self size. + separatorsOrElement isCollection + ifTrue: + [1 to: size do: + [:i| + thing := self at: i. + (separatorsOrElement includes: thing) + ifTrue: + [subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: i - 1)]. + subsequenceStart := nil] + ifFalse: + [subsequenceStart ifNil: [subsequenceStart := i]]]] + ifFalse: + [1 to: size do: + [:i| + thing := self at: i. + separatorsOrElement = thing + ifTrue: + [subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: i - 1)]. + subsequenceStart := nil] + ifFalse: + [subsequenceStart ifNil: [subsequenceStart := i]]]]. + subsequenceStart ifNotNil: + [result addLast: (self copyFrom: subsequenceStart to: size)]. + ^result asArray + + "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: Character space" + + "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: ' ,.-'"! Item was changed: ----- Method: String>>subStrings: (in category 'converting') ----- subStrings: separators "Answer an array containing the substrings in the receiver separated by the elements of separators, which should be a collection of Characters, or, for convenience, a single character.." (separators isCharacter or: [separators isString or:[separators allSatisfy: [:element | element isCharacter]]]) ifTrue: + [^self subsequences: separators]. - [^super subStrings: separators]. ^self error: 'separators must be Characters.' "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: Character space" "'Now is the time for all good people to come to the aid of the cause of world peace. It is just fine, even desirable, to love your country, if that means wanting it to play a beneficial role in the course of world events and be the best possible example of a good society. But if it means wanting dominion over the rest of the world, it is not love but defensiveness or self-glorification, and will lead only to oblivion.' subStrings: ' ,.-'"! From eliot.miranda at gmail.com Wed Nov 23 14:49:53 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed, 23 Nov 2022 06:49:53 -0800 Subject: [squeak-dev] RawBitsArray vs. DataStream In-Reply-To: References: <20221123025447.GA23388@shell.msen.com> Message-ID: Hi Marcel, On Wed, Nov 23, 2022 at 2:20 AM Marcel Taeumel wrote: > Hmm... 1024 bytes in a ByteArray will be 1029 bytes on disk. So it's okay, > I suppose. Interestingly, a DoubleByteArray is use 5142 bytes on disk. A > WordArray uses 4101 bytes hmm... okay. Strange for the DoubleByteArray > though... > IIRC these files include textual Smalltalk code for certain post-processing operations (if not, I apologise). So it may be worth-while "reading" the file in the FileList and seeing if there are any obvious differences between the generated files. I expect that there are a small set of privileged classes that have special support while others get more voluminous support. > Am 23.11.2022 11:13:09 schrieb Marcel Taeumel : > Aha! Thanks for the clarification! :-) > > Best, > Marcel > > Am 23.11.2022 03:54:55 schrieb David T. Lewis : > On Tue, Nov 22, 2022 at 10:58:09AM +0100, Marcel Taeumel wrote: > > Hi all -- > > > > Should the following work? > > > > No, it should not work. And yes, it will lock up the image (confirmed > on Linux 64-bit). > > > > class := DoubleByteArray. > > size := 10. > > dummy := 123. > > > > array := class new: size. > > array?? atAllPut: dummy. > > > > (DataStream newFileNamed: 'numbers') > > nextPut: array; > > close. > > > > stream := DataStream fileNamed: 'numbers'.?? > > load := stream readArray. > > stream close. > > load explore > > > > DataStream>>readArray is a private method that will do bad things > if you call it at the wrong time. In the example above, it reads > a number from the wrong place in the stream (because it should not > have been called at that point). This number is used to allocate > an array with over 150 million 8-byte slots, leading to the apparent > image lockup. > > The fix would be to put the private methods into a method category > labeled "private". > > Dave > > > > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Wed Nov 23 15:36:09 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed, 23 Nov 2022 07:36:09 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <20221123031033.E174A14D821@mail.squeak.org> Message-ID: Hi Christoph, Hi Marcel, apologies about the font size mismatches... On Wed, Nov 23, 2022 at 2:25 AM Marcel Taeumel wrote: > Hi Christoph -- > > > IMHO, it unnecessarily complicates the simple Smalltalk syntax. [...] > > Nah, this is just a tooling change, not a syntactical one. > +1 > > Yes, I would like to have this info skipped for #isNil as well. Note that one > should not use #ifNotNilDo: anymore. > Good idea. I'll include it. > > Best, > Marcel > > Am 23.11.2022 11:00:43 schrieb Thiede, Christoph < > christoph.thiede at student.hpi.uni-potsdam.de>: > > Hi Eliot, hi all, > > > I'm skeptical about this change, as it creates or expands a special role > of the selectors #ifNil:, #ifNotNil:, and their combinations. IMHO, it > unnecessarily complicates the simple Smalltalk syntax. While I know and > sometimes dislike these UndefinedVariable notifications, too, I don't know > whether differentiating them by the selector is the right strategy > to improve this situation. > > Please indulge me. It's f***ing irritating to be told by the compiler that as temp var appears to be uninitialized when one is intentionally using the fact that temps are initialized to nil. And that temp vars are initialized to nil is a) essential knowledge and b) a good thing (no uninitialized local variables a la C, a sensible value to initialize a variable with). BTW, I find it more than sad (a little alarming in fact) that someSmalltalkers don't know that the value of several conditionals that take blocks is nil when the condition doesn't select the block. e.g. false ifTrue: [self anything] is nil. I see "expr ifNotNil: [...] ifNil: [nil]" and it strikes me as illiterate. I recently visited code written by a strong programmer who open coded a lot of point arithmetic, decomposing e.g. a * b into (a x * b x) @ (a y * b y). It's bad. It gradually degrades the code base in that it isn't always an exemplar of best practice, > > Consider the following examples: > > > | a b c d e f g h | > a ifNil: [a := 1]. > c := b. > c ifNil: [c := 3]. > #(1 2 3) sorted: d. > e := 5. > (e isNil or: [f isNil]) ifTrue: [e := f := 6]. > g perform: #ifNotNil: with: [b := g]. > h ifNotNilDo: [h := 8]. > > How would you explain to a naive Smalltalker which of these variables will > be marked as undefined at this point and why? (Of course, you can explain > it by pointing to the implementation, but I think that's a significantly > less intuitive explanation than just saying "you must declare any variable > before using it".) > > No. It's a hard-and-fast rule that all temp vars are initialized to nil. And initializing a variable (to other than nil) is done by assigning it. In the above a through h are declared within the vertical bars.n They are initialized in the assignments. I want a warning for the usage of b in "c := b", "d" in "#(1 2 3) sorted: d", g in "g perform: #ifNotNil: with: [b := g]". I *don't* want to be told about a in "a ifNil: [a := 1]", c in "c ifNil: [c := 3]", or e & f in "(e isNil or: [f isNil]) ifTrue: [e := f := 6]". I never want to see "ifNotNilDo", ever ;-) (* note that a couple of years back we fixed a bad bug in the compiler where block local temps were not (re)initialized to nil on each iteration, leaking their values from previous iterations, breaking the "all temp vars are initialized to nil rule, and revealing implementation details in the compiler's inlining of to:[by:]do: forms) > This behavior leads to a mental model that disambiguates between null and > undefined similar to JavaScript which I never have found helpful. > > I don't see how that applies. Smalltalk has no undefined. It has nil & zero, and these values are used to initialize any and all variables. This is not an artifact of the implementation. It is a fundamental part of the language design. It results in no dangling referents or uninitialized variables. The language used in Parser>>#queryUndefined is problematic. It should be "unassigned", not "undefined". There is nothing undefined about these variables. But they are indeed unassigned. In some cases (see my i=diomatic implementation of subsequences: and substrings) this can (and *should*) be used to advantage. And all Smalltalk programming courses should explain that variables are always initialized (either to nil or zero, & hence by extension 0.0, Character null, Color transparent, et al), and may need assignment before their referents get sent messages. I see the same kind of sloppiness in people not knowing that conditionals that take blocks typically evaluate to nil when the condition doesn;t select the block. So always "expr ifNotNil: [...]", never "expr ifNotNil: [...] ifNil: [nil]", or "expr ifNotNil: [...] ifNil: []". I recently cleaned up code by as string programmer who had open coded point arithmetic (e.g. a * b written as (a x * b x) @ (a y * b y) ). This is really bad: it's exemplifying poor practice, it's verbose, it takes away at least as much understanding as it conveys, it leads to more difficult to manage code. If we fail to teach the language properly we start on a slippery slope to duplication (which is an awful evil, leading to much increased maintennance effort, and brittleness), and rendering perfectly good, well thought-out idioms mysterious. It;'s not like Smalltalk has a lot of rules; the number, compared to C & C++ et al is tiny. And terseness has not just aesthetic benefit, but real practical benefit in terms of readability & maintainability. > Also, with this change, the compiler leaks the default value of any > temporary variable, which we previously were able to hide at least > partially. > > But that is a MISTAKE!! The language designers didn't arrange for temps to be initialized to nil just because that's the only default. They did it to ensure that there is no such thing as an uninitialized variable in Smalltalk. That's why nil ids an object, with a class, not just nil. That's why nil ~~ false. It's carefully thought out and not just some artifact of the implementation. And that rationale (read the blue book carefully) and its implications, should be taught/learned/known, and especially exemplified by the core code of Squeak trunk, and hence supported by the compiler. > In many cases, I think explicitly setting a temporary variable to nil > before it is initialized within some non-trivial conditional complex would > be more explicit, thus more readable, and something which we should > generally encourage programmers to do. > > I disagree. You're advocating for absurdities such as | colors | colors :=- ColorArray new: 256. colors atAllPut: Color transparent This is the kind of thinking that leads to cycling wearing American Football clothes. It won't keep you from being run over by a truck, but it'll make you so slow and reduce your peripheral vision so much, not to mention give you a false sense of security, that you'll be much more likely to be run over by a truck... > Looking forward to your opinion! > > :-) Hope I'm not too strident :-) > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von commits at source.squeak.org > *Gesendet:* Mittwoch, 23. November 2022 04:10:30 > *An:* squeak-dev at lists.squeakfoundation.org; > packages at lists.squeakfoundation.org > *Betreff:* [squeak-dev] The Trunk: Compiler-eem.480.mcz > > Eliot Miranda uploaded a new version of Compiler to project The Trunk: > http://source.squeak.org/trunk/Compiler-eem.480.mcz > > ==================== Summary ==================== > > Name: Compiler-eem.480 > Author: eem > Time: 22 November 2022, 7:10:27.324796 pm > UUID: 3e5ba19e-c44a-4390-9004-de1246736cbc > Ancestors: Compiler-eem.479 > > Do not warn of an uninitialized temporary if it is being sent ifNil: or > ifNotNil:. > > =============== Diff against Compiler-eem.479 =============== > > Item was changed: > ----- Method: Parser>>primaryExpression (in category 'expression types') > ----- > primaryExpression > hereType == #word > ifTrue: > [parseNode := self variable. > + (parseNode isUndefTemp > + and: [(#('ifNil:' 'ifNotNil:') includes: here) > not > + and: [self interactive]]) > + ifTrue: > + [self queryUndefined]. > - (parseNode isUndefTemp and: [self interactive]) > - ifTrue: [self queryUndefined]. > parseNode nowHasRef. > ^ true]. > hereType == #leftBracket > ifTrue: > [self advance. > self blockExpression. > ^true]. > hereType == #leftBrace > ifTrue: > [self braceExpression. > ^true]. > hereType == #leftParenthesis > ifTrue: > [self advance. > self expression ifFalse: [^self expected: > 'expression']. > (self match: #rightParenthesis) > ifFalse: [^self expected: 'right > parenthesis']. > ^true]. > (hereType == #string or: [hereType == #number or: [hereType == > #literal or: [hereType == #character]]]) > ifTrue: > [parseNode := encoder encodeLiteral: self advance. > ^true]. > (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) > ifTrue: > [self advance. > parseNode := encoder encodeLiteral: self advance > negated. > ^true]. > ^false! > > > > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Wed Nov 23 15:38:22 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 23 Nov 2022 15:38:22 0000 Subject: [squeak-dev] The Trunk: Compiler-eem.481.mcz Message-ID: <20221123153825.5711014D9FD@mail.squeak.org> Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.481.mcz ==================== Summary ==================== Name: Compiler-eem.481 Author: eem Time: 23 November 2022, 7:38:19.39867 am UUID: 0a4ff524-0585-4dcb-bd44-d3fa8b800b69 Ancestors: Compiler-eem.480 Respond to Marcel's suggestion. We don't need no steenkin' warnings for isNil or notNil either... =============== Diff against Compiler-eem.480 =============== Item was changed: ----- Method: Parser>>primaryExpression (in category 'expression types') ----- primaryExpression hereType == #word ifTrue: [parseNode := self variable. (parseNode isUndefTemp + and: [(#('ifNil:' 'ifNotNil:' 'isNil' 'notNil') includes: here) not - and: [(#('ifNil:' 'ifNotNil:') includes: here) not and: [self interactive]]) ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal or: [hereType == #character]]]) ifTrue: [parseNode := encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) ifTrue: [self advance. parseNode := encoder encodeLiteral: self advance negated. ^true]. ^false! From commits at source.squeak.org Wed Nov 23 15:41:00 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Wed, 23 Nov 2022 15:41:00 0000 Subject: [squeak-dev] The Trunk: Compiler-eem.482.mcz Message-ID: <20221123154104.289AD14DA01@mail.squeak.org> Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.482.mcz ==================== Summary ==================== Name: Compiler-eem.482 Author: eem Time: 23 November 2022, 7:40:58.01402 am UUID: 1f5e2fa1-d9fe-4cbc-9665-5be34958f925 Ancestors: Compiler-eem.481 But using selectors, not strings, makes the reference to these keywords more findable/less hidden. =============== Diff against Compiler-eem.481 =============== Item was changed: ----- Method: Parser>>primaryExpression (in category 'expression types') ----- primaryExpression hereType == #word ifTrue: [parseNode := self variable. (parseNode isUndefTemp + and: [(#(ifNil: ifNotNil: isNil notNil) includes: here) not - and: [(#('ifNil:' 'ifNotNil:' 'isNil' 'notNil') includes: here) not and: [self interactive]]) ifTrue: [self queryUndefined]. parseNode nowHasRef. ^ true]. hereType == #leftBracket ifTrue: [self advance. self blockExpression. ^true]. hereType == #leftBrace ifTrue: [self braceExpression. ^true]. hereType == #leftParenthesis ifTrue: [self advance. self expression ifFalse: [^self expected: 'expression']. (self match: #rightParenthesis) ifFalse: [^self expected: 'right parenthesis']. ^true]. (hereType == #string or: [hereType == #number or: [hereType == #literal or: [hereType == #character]]]) ifTrue: [parseNode := encoder encodeLiteral: self advance. ^true]. (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) ifTrue: [self advance. parseNode := encoder encodeLiteral: self advance negated. ^true]. ^false! From tim at rowledge.org Wed Nov 23 18:34:00 2022 From: tim at rowledge.org (tim Rowledge) Date: Wed, 23 Nov 2022 10:34:00 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <20221123031033.E174A14D821@mail.squeak.org> Message-ID: <1A5201F8-CC3C-4DFE-B8C9-403BAE8C35CF@rowledge.org> I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- His page was intentionally left blank. From Das.Linux at gmx.de Wed Nov 23 20:23:15 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Wed, 23 Nov 2022 21:23:15 +0100 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <1A5201F8-CC3C-4DFE-B8C9-403BAE8C35CF@rowledge.org> References: <20221123031033.E174A14D821@mail.squeak.org> <1A5201F8-CC3C-4DFE-B8C9-403BAE8C35CF@rowledge.org> Message-ID: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> Yet, nil is only seldom a good domain object. -t > On 23. Nov 2022, at 19:34, tim Rowledge wrote: > > I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! > > tim From ron at usmedrec.com Thu Nov 24 00:33:34 2022 From: ron at usmedrec.com (Ron Teitelbaum) Date: Wed, 23 Nov 2022 19:33:34 -0500 Subject: [squeak-dev] Fwd: [Esug-list] [ Smalltalkers wanted... ] In-Reply-To: References: Message-ID: ---------- Forwarded message --------- From: stephane ducasse Date: Wed, Nov 23, 2022 at 2:25 PM Subject: [Esug-list] [ Smalltalkers wanted... ] To: Pharo Development List , Any question about pharo is welcome , ESUG < esug-list at lists.esug.org> We are looking for Smalltalkers for adesso insurance solutions GmbH. Remote work is possible and German language is required (at least B2). Links: https://www.adesso.de/de/jobs-karriere/unsere-stellenangebote/Software-Engineer-Smalltalk-all-genders-fuer-die-adesso-in-de-j2429.html https://www.linkedin.com/jobs/view/3353601212/ Text: *About the job* Für unsere Tochtergesellschaft, die adesso insurance solutions GmbH, suchen wir einen Software Engineer Smalltalk (all genders) Als Teil der adesso group bündelt die adesso insurance solutions GmbH das eigene Produktportfolio für den Versicherungsmarkt und treibt innovative Software-Lösungen in diesem Umfeld voran. Wir sind ein Team aus über 200 engagierten Kollegen und Kolleginnen. Und du kannst ein Teil davon werden. *DEINE ROLLE - DAS WARTET AUF DICH*Du kennst dich mit objektorientierter Programmierung aus? Smalltalk ist für dich eine Programmiersprache mit Tiefgang? Dann suchen wir genau dich als Software Engineer für unser Professional Services Team im Umfeld des Pensionsmanagements. Bei uns arbeitest du gemeinsam im Team mit Entwicklern, Testern und Projektmanagern an den besten Lösungen für unsere CollPhir-Software. Übrigens: Wir sind langjähriger Sponsor der EUSG. *Deine Aufgaben* · Auf Basis von Smalltalk programmierst du neue Anforderungen und Erweiterungen. · Neue Anforderungen unserer CollPhir-Software setzt du um. · Du analysierst, konzipierst und realisierst eigenständig kundenspezifische Erweiterungen. · Im Third-Level unterstützt du das Support-Team bei technischen Fragen zur Software. · Die Dokumentation und das Beheben von Fehlern gehören auch zu deinen Aufgaben. *Deine Skills - Das Bringst Du Mit* · Du verfügst über einen technischen Hochschulabschluss (Informatik, Ingenieurwissenschaften, Mathematik, Physik, o.Ä.) oder hast bereits Erfahrung in der Softwareentwicklung mit Smalltalk gesammelt · Du hast keine Scheu vor Datenbankmanagementsystemen und verfügst über – zumindest rudimentäres – Wissen in technologisch benachbarten Bereichen (z.B. Java) · Du bist neugierig und lernbereit, denn bei uns wird Weiterentwicklung sowohl technologisch als auch persönlich großgeschrieben · Deine Deutschkenntnisse sind sehr gut und mindestens auf Level B2 *CHANCENGEBER - WAS ADESSO AUSMACHT*Unser Versprechen: Du wirst dich bei uns wohlfühlen! Kollegial, familiär und auf Augenhöhe – wir leben Austausch, Teamgeist und einen respektvollen Umgang miteinander. Das und viel mehr steht für unser ganz besonderes Wir-Gefühl. Für das es sogar ein Wort gibt: adessi. Denn wir sind alle adessi ab Tag Eins und bei uns bist du von Anfang an Teil des Teams. Unsere Kultur und das Zusammenarbeiten sind geprägt von gegenseitiger Wertschätzung, Anerkennung und Unterstützung. Das verbindet uns hierarchieübergreifend – auch im Home-Office. Jeder und jedem adessi stehen alle Möglichkeiten zur persönlichen und beruflichen Entwicklung offen. Unser umfangreiches Trainings- und Weiterbildungsangebot sorgt dafür, dass deine Entwicklung bei uns nicht stillsteht. Denn Chancengeber zu sein, das liegt in unserer DNA. · Welcome Days - Zwei Tage zum Reinkommen und Netzwerken · Bis zu drei Tage mobiles Arbeiten – keine Frage von Pandemien, sondern von Überzeugung · Deine Entwicklung - über 260 Lern- und Trainingsthemen · Events - fachlich und mit Spaßfaktor · Hemden-/Blusenreinigung - zweimal die Woche frisch aufgebügelt · Sportförderung - Zuschuss zum Fitnessstudio und mehr über qualitrain sowie Übernahme der Platzmiete für die Sporthalle · adesso Mind - Das adesso-Programm rund um Mindfulness · Prämien für Mitarbeitende - eine Vielzahl an Prämien für zusätzliches Engagement · Auszeitprogramm - Raum für deine persönliche Lebensplanung *KONTAKT*Du bist offen für neue und anspruchsvolle Aufgaben? Dann sende uns deine Bewerbungsunterlagen (inkl. deines CV, deiner Arbeits- und Studienzeugnisse sowie deiner Gehaltsvorstellungen und dem frühestmöglichen Eintrittstermin) vorzugsweise über unser Webformular. · Sina Möschl · Recruiting · +49 231 7000 7100 Best wishes, -- Félix Madrid *adesso insurance solutions GmbH* Agrippinawerft 26 50678 Köln T +49 221 27850-355 M +49 152 38869-784 F +49 221-27850-500 E felix.madrid at adesso-insurance-solutions.de www.adesso-insure.de _______________________________________________ Esug-list mailing list -- esug-list at lists.esug.org To unsubscribe send an email to esug-list-leave at lists.esug.org -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Nov 24 04:27:36 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 24 Nov 2022 04:27:36 0000 Subject: [squeak-dev] The Trunk: System-dtl.1373.mcz Message-ID: <20221124042741.5DBB114DA0B@mail.squeak.org> David T. Lewis uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-dtl.1373.mcz ==================== Summary ==================== Name: System-dtl.1373 Author: dtl Time: 23 November 2022, 11:27:30.771886 pm UUID: f3d54b26-e023-4d20-a023-c490f507a778 Ancestors: System-ct.1372 Categorize methods in DataStream for clarity. No changes to methods, category organization only. =============== Diff against System-ct.1372 =============== Item was changed: + ----- Method: DataStream>>atEnd (in category 'stream access') ----- - ----- Method: DataStream>>atEnd (in category 'other') ----- atEnd "Answer true if the stream is at the end." ^ byteStream atEnd! Item was changed: + ----- Method: DataStream>>beginInstance:size: (in category 'object storage') ----- - ----- Method: DataStream>>beginInstance:size: (in category 'write and read') ----- beginInstance: aClass size: anInteger "This is for use by storeDataOn: methods. Cf. Object>>storeDataOn:." "Addition of 1 seems to make extra work, since readInstance has to compensate. Here for historical reasons dating back to Kent Beck's original implementation in late 1988. In ReferenceStream, class is just 5 bytes for shared symbol. SmartRefStream puts out the names and number of class's instances variables for checking." byteStream nextNumber: 4 put: anInteger + 1. self nextPut: aClass name! Item was changed: + ----- Method: DataStream>>beginReference: (in category 'object storage') ----- - ----- Method: DataStream>>beginReference: (in category 'write and read') ----- beginReference: anObject "We're starting to read anObject. Remember it and its reference position (if we care; ReferenceStream cares). Answer the reference position." ^ 0! Item was changed: + ----- Method: DataStream>>byteStream (in category 'accessing') ----- - ----- Method: DataStream>>byteStream (in category 'other') ----- byteStream ^ byteStream! Item was changed: + ----- Method: DataStream>>close (in category 'stream access') ----- - ----- Method: DataStream>>close (in category 'other') ----- close "Close the stream." | bytes | byteStream closed ifFalse: [ bytes := byteStream position. byteStream close] ifTrue: [bytes := 'unknown']. ^ bytes! Item was changed: + ----- Method: DataStream>>contents (in category 'accessing') ----- - ----- Method: DataStream>>contents (in category 'other') ----- contents ^byteStream contents! Item was changed: + ----- Method: DataStream>>errorWriteReference: (in category 'private - write') ----- - ----- Method: DataStream>>errorWriteReference: (in category 'other') ----- errorWriteReference: anInteger "PRIVATE -- Raise an error because this case of nextPut:'s perform: shouldn't be called. -- 11/15/92 jhm" self error: 'This should never be called'! Item was changed: + ----- Method: DataStream>>flush (in category 'stream access') ----- - ----- Method: DataStream>>flush (in category 'other') ----- flush "Guarantee that any writes to me are actually recorded on disk. -- 11/17/92 jhm" ^ byteStream flush! Item was changed: + ----- Method: DataStream>>getCurrentReference (in category 'object storage') ----- - ----- Method: DataStream>>getCurrentReference (in category 'write and read') ----- getCurrentReference "PRIVATE -- Return the currentReference posn. Overridden by ReferenceStream." ^ 0! Item was changed: + ----- Method: DataStream>>insideASegment (in category 'object storage') ----- - ----- Method: DataStream>>insideASegment (in category 'write and read') ----- insideASegment ^ false! Item was changed: + ----- Method: DataStream>>maybeBeginReference: (in category 'private - read') ----- - ----- Method: DataStream>>maybeBeginReference: (in category 'write and read') ----- maybeBeginReference: internalObject "Do nothing. See ReferenceStream|maybeBeginReference:" ^ internalObject! Item was changed: + ----- Method: DataStream>>next (in category 'stream access') ----- - ----- Method: DataStream>>next (in category 'write and read') ----- next "Answer the next object in the stream." | type selector anObject isARefType pos internalObject | type := byteStream next. type ifNil: [pos := byteStream position. "absolute!!!!" byteStream close. "clean up" byteStream position = 0 ifTrue: [self error: 'The file did not exist in this directory'] ifFalse: [self error: 'Unexpected end of object file']. pos. "so can see it in debugger" ^ nil]. type = 0 ifTrue: [pos := byteStream position. "absolute!!!!" byteStream close. "clean up" self error: 'Expected start of object, but found 0'. ^ nil]. isARefType := self noteCurrentReference: type. selector := #(readNil readTrue readFalse readInteger "<-4" readStringOld readSymbol readByteArray "<-7" readArray readInstance readReference readBitmap "<-11" readClass readUser readFloat readRectangle readShortInst "<-16" readString readWordArray readWordArrayForSegment "<-19" readWordLike readMethod "<-21") at: type ifAbsent: [ pos := byteStream position. "absolute!!!!" byteStream close. self error: 'file is more recent than this system'. ^ nil]. anObject := self perform: selector. "A method that recursively calls next (readArray, readInstance, objectAt:) must save & restore the current reference position." isARefType ifTrue: [self beginReference: anObject]. "After reading the externalObject, internalize it. #readReference is a special case. Either: (1) We actually have to read the object, recursively calling next, which internalizes the object. (2) We just read a reference to an object already read and thus already interalized. Either way, we must not re-internalize the object here." selector == #readReference ifTrue: [^ anObject]. internalObject := anObject comeFullyUpOnReload: self. internalObject == String ifTrue:[ "This is a hack to figure out if we're loading a String class that really should be a ByteString. Note that these days this will no longer be necessary since we use #withClassVersion: for constructing the global thus using a different classVersion will perfectly do the trick." ((anObject isKindOf: DiskProxy) and:[anObject globalObjectName == #String and:[anObject constructorSelector == #yourself]]) ifTrue:[ internalObject := ByteString]]. ^ self maybeBeginReference: internalObject! Item was changed: + ----- Method: DataStream>>next: (in category 'stream access') ----- - ----- Method: DataStream>>next: (in category 'other') ----- next: anInteger "Answer an Array of the next anInteger objects in the stream." | array | array := Array new: anInteger. 1 to: anInteger do: [:i | array at: i put: self next]. ^ array! Item was changed: + ----- Method: DataStream>>nextAndClose (in category 'stream access') ----- - ----- Method: DataStream>>nextAndClose (in category 'other') ----- nextAndClose "Speedy way to grab one object. Only use when we are inside an object binary file. Do not use for the start of a SmartRefStream mixed code-and-object file." | obj | obj := self next. self close. ^ obj! Item was changed: + ----- Method: DataStream>>nextPut: (in category 'stream access') ----- - ----- Method: DataStream>>nextPut: (in category 'write and read') ----- nextPut: anObject "Write anObject to the receiver stream. Answer anObject." | typeID selector objectToStore | typeID := self typeIDFor: anObject. (self tryToPutReference: anObject typeID: typeID) ifTrue: [^ anObject]. objectToStore := (self objectIfBlocked: anObject) objectForDataStream: self. objectToStore == anObject ifFalse: [typeID := self typeIDFor: objectToStore. (self tryToPutReference: objectToStore typeID: typeID) ifTrue: [^ anObject]]. byteStream nextPut: typeID. selector := #(writeNil: writeTrue: writeFalse: writeInteger: writeStringOld: writeSymbol: writeByteArray: writeArray: writeInstance: errorWriteReference: writeBitmap: writeClass: writeUser: writeFloat: writeRectangle: == "<-16 short inst" writeString: writeBitmap: writeBitmap: writeWordLike: writeInstance: "CompiledMethod") at: typeID. self perform: selector with: objectToStore. ^ anObject "NOTE: If anObject is a reference type (one that we write cross-references to) but its externalized form (result of objectForDataStream:) isn't (e.g. CompiledMethod and ViewState), then we should remember its externalized form but not add to 'references'. Putting that object again should just put its external form again. That's more compact and avoids seeks when reading. But we just do the simple thing here, allowing backward-references for non-reference types like nil. So objectAt: has to compensate. Objects that externalize nicely won't contain the likes of ViewStates, so this shouldn't hurt much. writeReference: -> errorWriteReference:."! Item was changed: + ----- Method: DataStream>>nextPutAll: (in category 'stream access') ----- - ----- Method: DataStream>>nextPutAll: (in category 'write and read') ----- nextPutAll: aCollection "Write each of the objects in aCollection to the receiver stream. Answer aCollection." ^ aCollection do: [:each | self nextPut: each]! Item was changed: + ----- Method: DataStream>>noteCurrentReference: (in category 'private - read') ----- - ----- Method: DataStream>>noteCurrentReference: (in category 'write and read') ----- noteCurrentReference: typeID "PRIVATE -- If we support references for type typeID, remember the current byteStream position so we can add the next object to the 'objects' dictionary, and return true. Else return false. This method is here to be overridden by ReferenceStream" ^ false! Item was changed: + ----- Method: DataStream>>objectAt: (in category 'object storage') ----- - ----- Method: DataStream>>objectAt: (in category 'write and read') ----- objectAt: anInteger "PRIVATE -- Read & return the object at a given stream position. anInteger is a relative file position. " | savedPosn anObject refPosn | savedPosn := byteStream position. "absolute" refPosn := self getCurrentReference. "relative position" byteStream position: anInteger + basePos. "was relative" anObject := self next. self setCurrentReference: refPosn. "relative position" byteStream position: savedPosn. "absolute" ^ anObject! Item was changed: + ----- Method: DataStream>>objectIfBlocked: (in category 'private - write') ----- - ----- Method: DataStream>>objectIfBlocked: (in category 'write and read') ----- objectIfBlocked: anObject "We don't do any blocking" ^ anObject! Item was changed: + ----- Method: DataStream>>outputReference: (in category 'private - write') ----- - ----- Method: DataStream>>outputReference: (in category 'write and read') ----- outputReference: referencePosn "PRIVATE -- Output a reference to the object at integer stream position referencePosn (relative to basePos). To output a weak reference to an object not yet written, supply (self vacantRef) for referencePosn." byteStream nextPut: 10. "reference typeID" byteStream nextNumber: 4 put: referencePosn "relative position"! Item was changed: + ----- Method: DataStream>>project (in category 'accessing') ----- - ----- Method: DataStream>>project (in category 'other') ----- project ^nil! Item was changed: + ----- Method: DataStream>>readArray (in category 'private - read') ----- - ----- Method: DataStream>>readArray (in category 'write and read') ----- readArray "PRIVATE -- Read the contents of an Array. We must do beginReference: here after instantiating the Array but before reading its contents, in case the contents reference the Array. beginReference: will be sent again when we return to next, but that's ok as long as we save and restore the current reference position over recursive calls to next." | count array refPosn | count := byteStream nextNumber: 4. refPosn := self beginReference: (array := Array new: count). "relative pos" 1 to: count do: [:i | array at: i put: self next]. self setCurrentReference: refPosn. "relative pos" ^ array! Item was changed: + ----- Method: DataStream>>readBitmap (in category 'private - read') ----- - ----- Method: DataStream>>readBitmap (in category 'write and read') ----- readBitmap "PRIVATE -- Read the contents of a Bitmap." ^ Bitmap newFromStream: byteStream "Note that the reader knows that the size is in long words, but the data is in bytes."! Item was changed: + ----- Method: DataStream>>readBoolean (in category 'private - read') ----- - ----- Method: DataStream>>readBoolean (in category 'write and read') ----- readBoolean "PRIVATE -- Read the contents of a Boolean. This is here only for compatibility with old data files." ^ byteStream next ~= 0! Item was changed: + ----- Method: DataStream>>readByteArray (in category 'private - read') ----- - ----- Method: DataStream>>readByteArray (in category 'write and read') ----- readByteArray "PRIVATE -- Read the contents of a ByteArray." | count | count := byteStream nextNumber: 4. ^ byteStream next: count "assume stream is in binary mode" ! Item was changed: + ----- Method: DataStream>>readClass (in category 'private - read') ----- - ----- Method: DataStream>>readClass (in category 'write and read') ----- readClass "Should never be executed because a DiskProxy, not a clas comes in." ^ self error: 'Classes should be filed in'! Item was changed: + ----- Method: DataStream>>readFalse (in category 'private - read') ----- - ----- Method: DataStream>>readFalse (in category 'write and read') ----- readFalse "PRIVATE -- Read the contents of a False." ^ false! Item was changed: + ----- Method: DataStream>>readFloat (in category 'private - read') ----- - ----- Method: DataStream>>readFloat (in category 'write and read') ----- readFloat "PRIVATE -- Read the contents of a Float. This is the fast way to read a Float. We support 8-byte Floats here. Non-IEEE" | new | new := Float new: 2. "To get an instance" new at: 1 put: (byteStream nextNumber: 4). new at: 2 put: (byteStream nextNumber: 4). ^ new! Item was changed: + ----- Method: DataStream>>readFloatString (in category 'private - read') ----- - ----- Method: DataStream>>readFloatString (in category 'write and read') ----- readFloatString "PRIVATE -- Read the contents of a Float string. This is the slow way to read a Float--via its string rep'n. It's here for compatibility with old data files." ^ Float readFrom: (byteStream next: (byteStream nextNumber: 4))! Item was changed: + ----- Method: DataStream>>readInstance (in category 'private - read') ----- - ----- Method: DataStream>>readInstance (in category 'write and read') ----- readInstance "PRIVATE -- Read the contents of an arbitrary instance. ASSUMES: readDataFrom:size: sends me beginReference: after it instantiates the new object but before reading nested objects. NOTE: We must restore the current reference position after recursive calls to next. Let the instance, not the class read the data. " | instSize aSymbol refPosn anObject newClass | instSize := (byteStream nextNumber: 4) - 1. refPosn := self getCurrentReference. aSymbol := self next. newClass := Smalltalk at: aSymbol asSymbol. self setCurrentReference: refPosn. "before readDataFrom:size:" anObject := newClass isImmediateClass ifTrue: [newClass readImmediateFrom: self size: instSize] ifFalse: [anObject := newClass isVariable "Create object here" ifFalse: [newClass basicNew] ifTrue: [newClass basicNew: instSize - (newClass instSize)]. anObject readDataFrom: self size: instSize]. self setCurrentReference: refPosn. "before returning to next" ^ anObject! Item was changed: + ----- Method: DataStream>>readInteger (in category 'private - read') ----- - ----- Method: DataStream>>readInteger (in category 'write and read') ----- readInteger "PRIVATE -- Read the contents of a SmallInteger." ^ byteStream nextInt32 "signed!!!!!!"! Item was changed: + ----- Method: DataStream>>readMethod (in category 'private - read') ----- - ----- Method: DataStream>>readMethod (in category 'write and read') ----- readMethod "PRIVATE -- Read the contents of an arbitrary instance. ASSUMES: readDataFrom:size: sends me beginReference: after it instantiates the new object but before reading nested objects. NOTE: We must restore the current reference position after recursive calls to next. Let the instance, not the class read the data. " | instSize refPosn newClass className xxHeader nLits byteCodeSizePlusTrailer newMethod lits | instSize := (byteStream nextNumber: 4) - 1. refPosn := self getCurrentReference. className := self next. newClass := Smalltalk at: className asSymbol. xxHeader := self next. "nArgs := (xxHeader >> 24) bitAnd: 16rF." "nTemps := (xxHeader >> 18) bitAnd: 16r3F." "largeBit := (xxHeader >> 17) bitAnd: 1." nLits := xxHeader bitAnd: 16r7FFF. byteCodeSizePlusTrailer := instSize - (newClass instSize "0") - (nLits + 1 * Smalltalk wordSize). newMethod := newClass newMethod: byteCodeSizePlusTrailer header: xxHeader. self setCurrentReference: refPosn. "before readDataFrom:size:" self beginReference: newMethod. lits := newMethod numLiterals + 1. "counting header" 2 to: lits do: [:ii | newMethod objectAt: ii put: self next]. lits*Smalltalk wordSize+1 to: newMethod basicSize do: [:ii | newMethod basicAt: ii put: byteStream next]. "Get raw bytes directly from the file" self setCurrentReference: refPosn. "before returning to next" ^newMethod! Item was changed: + ----- Method: DataStream>>readNil (in category 'private - read') ----- - ----- Method: DataStream>>readNil (in category 'write and read') ----- readNil "PRIVATE -- Read the contents of an UndefinedObject." ^ nil! Item was changed: + ----- Method: DataStream>>readRectangle (in category 'private - read') ----- - ----- Method: DataStream>>readRectangle (in category 'write and read') ----- readRectangle "Read a compact Rectangle. Rectangles with values outside +/- 2047 were stored as normal objects (type=9). They will not come here. 17:22 tk" "Encoding is four 12-bit signed numbers. 48 bits in next 6 bytes. 17:24 tk" | acc left top right bottom | acc := byteStream nextNumber: 3. left := acc bitShift: -12. (left bitAnd: 16r800) ~= 0 ifTrue: [left := left - 16r1000]. "sign" top := acc bitAnd: 16rFFF. (top bitAnd: 16r800) ~= 0 ifTrue: [top := top - 16r1000]. "sign" acc := byteStream nextNumber: 3. right := acc bitShift: -12. (right bitAnd: 16r800) ~= 0 ifTrue: [right := right - 16r1000]. "sign" bottom := acc bitAnd: 16rFFF. (bottom bitAnd: 16r800) ~= 0 ifTrue: [bottom := bottom - 16r1000]. "sign" ^ Rectangle left: left right: right top: top bottom: bottom ! Item was changed: + ----- Method: DataStream>>readReference (in category 'private - read') ----- - ----- Method: DataStream>>readReference (in category 'write and read') ----- readReference "Read the contents of an object reference. (Cf. outputReference:) File is not now positioned at this object." | referencePosition | ^ (referencePosition := (byteStream nextNumber: 4)) = self vacantRef "relative" ifTrue: [nil] ifFalse: [self objectAt: referencePosition] "relative pos"! Item was changed: + ----- Method: DataStream>>readShortInst (in category 'private - read') ----- - ----- Method: DataStream>>readShortInst (in category 'write and read') ----- readShortInst "Read the contents of an arbitrary instance that has a short header. ASSUMES: readDataFrom:size: sends me beginReference: after it instantiates the new object but before reading nested objects. NOTE: We must restore the current reference position after recursive calls to next. Let the instance, not the class read the data. " | instSize aSymbol refPosn anObject newClass | instSize := (byteStream next) - 1. "one byte of size" refPosn := self getCurrentReference. aSymbol := self readShortRef. "class symbol in two bytes of file pos" newClass := Smalltalk at: aSymbol asSymbol. anObject := newClass isVariable "Create object here" ifFalse: [newClass basicNew] ifTrue: [newClass basicNew: instSize - (newClass instSize)]. self setCurrentReference: refPosn. "before readDataFrom:size:" anObject := anObject readDataFrom: self size: instSize. self setCurrentReference: refPosn. "before returning to next" ^ anObject! Item was changed: + ----- Method: DataStream>>readShortRef (in category 'private - read') ----- - ----- Method: DataStream>>readShortRef (in category 'write and read') ----- readShortRef "Read an object reference from two bytes only. Original object must be in first 65536 bytes of the file. Relative to start of data. vacantRef not a possibility." ^ self objectAt: (byteStream nextNumber: 2)! Item was changed: + ----- Method: DataStream>>readString (in category 'private - read') ----- - ----- Method: DataStream>>readString (in category 'write and read') ----- readString ^byteStream nextString ! Item was changed: + ----- Method: DataStream>>readStringOld (in category 'private - read') ----- - ----- Method: DataStream>>readStringOld (in category 'write and read') ----- readStringOld ^ byteStream nextStringOld! Item was changed: + ----- Method: DataStream>>readSymbol (in category 'private - read') ----- - ----- Method: DataStream>>readSymbol (in category 'write and read') ----- readSymbol "PRIVATE -- Read the contents of a Symbol." ^ self readString asSymbol! Item was changed: + ----- Method: DataStream>>readTrue (in category 'private - read') ----- - ----- Method: DataStream>>readTrue (in category 'write and read') ----- readTrue "PRIVATE -- Read the contents of a True." ^ true! Item was changed: + ----- Method: DataStream>>readUser (in category 'private - read') ----- - ----- Method: DataStream>>readUser (in category 'write and read') ----- readUser "Reconstruct both the private class and the instance. Still used??" ^ self readInstance. "Will create new unique class" ! Item was changed: + ----- Method: DataStream>>readWordArray (in category 'private - read') ----- - ----- Method: DataStream>>readWordArray (in category 'write and read') ----- readWordArray "PRIVATE -- Read the contents of a WordArray." ^ WordArray newFromStream: byteStream "Size is number of long words."! Item was changed: + ----- Method: DataStream>>readWordArrayForSegment (in category 'private - read') ----- - ----- Method: DataStream>>readWordArrayForSegment (in category 'write and read') ----- readWordArrayForSegment "Read the contents of a WordArray ignoring endianness." ^ WordArrayForSegment newFromStream: byteStream "Size is number of long words."! Item was changed: + ----- Method: DataStream>>readWordLike (in category 'private - read') ----- - ----- Method: DataStream>>readWordLike (in category 'write and read') ----- readWordLike | refPosn aSymbol newClass anObject | "Can be used by any class that is bits and not bytes (WordArray, Bitmap, SoundBuffer, etc)." refPosn := self getCurrentReference. aSymbol := self next. newClass := Smalltalk at: aSymbol asSymbol. anObject := newClass newFromStream: byteStream. "Size is number of long words." self setCurrentReference: refPosn. "before returning to next" ^ anObject ! Item was changed: + ----- Method: DataStream>>replace:with: (in category 'object storage') ----- - ----- Method: DataStream>>replace:with: (in category 'write and read') ----- replace: original with: proxy "We may wish to remember that in some field, the original object is being replaced by the proxy. For the hybred scheme that collects with a DummyStream and writes an ImageSegment, it needs to hold onto the originals so they will appear in outPointers, and be replaced." "do nothing"! Item was changed: + ----- Method: DataStream>>reset (in category 'stream access') ----- - ----- Method: DataStream>>reset (in category 'other') ----- reset "Reset the stream." byteStream reset! Item was changed: + ----- Method: DataStream>>rootObject (in category 'accessing') ----- - ----- Method: DataStream>>rootObject (in category 'other') ----- rootObject "Return the object at the root of the tree we are filing out. " ^ topCall! Item was changed: + ----- Method: DataStream>>rootObject: (in category 'accessing') ----- - ----- Method: DataStream>>rootObject: (in category 'other') ----- rootObject: anObject "Return the object at the root of the tree we are filing out. " topCall := anObject! Item was changed: + ----- Method: DataStream>>setCurrentReference: (in category 'private - read') ----- - ----- Method: DataStream>>setCurrentReference: (in category 'write and read') ----- setCurrentReference: refPosn "PRIVATE -- Set currentReference to refPosn. Noop here. Cf. ReferenceStream."! Item was changed: + ----- Method: DataStream>>setStream: (in category 'initialize-release') ----- - ----- Method: DataStream>>setStream: (in category 'other') ----- setStream: aStream "PRIVATE -- Initialization method." aStream binary. basePos := aStream position. "Remember where we start. Earlier part of file contains a class or method file-in. Allow that to be edited. We don't deal in absolute file locations." byteStream := aStream.! Item was changed: + ----- Method: DataStream>>setStream:reading: (in category 'initialize-release') ----- - ----- Method: DataStream>>setStream:reading: (in category 'other') ----- setStream: aStream reading: isReading "PRIVATE -- Initialization method." aStream binary. basePos := aStream position. "Remember where we start. Earlier part of file contains a class or method file-in. Allow that to be edited. We don't deal in absolute file locations." byteStream := aStream.! Item was changed: + ----- Method: DataStream>>size (in category 'accessing') ----- - ----- Method: DataStream>>size (in category 'other') ----- size "Answer the stream's size." ^ byteStream size! Item was changed: + ----- Method: DataStream>>tryToPutReference:typeID: (in category 'private - write') ----- - ----- Method: DataStream>>tryToPutReference:typeID: (in category 'write and read') ----- tryToPutReference: anObject typeID: typeID "PRIVATE -- If we support references for type typeID, and if anObject already appears in my output stream, then put a reference to the place where anObject already appears. If we support references for typeID but didn't already put anObject, then associate the current stream position with anObject in case one wants to nextPut: it again. Return true after putting a reference; false if the object still needs to be put. For DataStream this is trivial. ReferenceStream overrides this." ^ false! Item was changed: + ----- Method: DataStream>>typeIDFor: (in category 'object storage') ----- - ----- Method: DataStream>>typeIDFor: (in category 'write and read') ----- typeIDFor: anObject "Return the typeID for anObject's class. This is where the tangle of objects is clipped to stop everything from going out. Classes can control their instance variables by defining objectToStoreOnDataStream. Any object in blockers is not written out. See ReferenceStream.objectIfBlocked: and DataStream nextPut:. Morphs do not write their owners. See Morph.storeDataOn: Each morph tells itself to 'prepareToBeSaved' before writing out." anObject isFloat ifTrue: [^14]. "shortcut floats of any representation." ^ TypeMap at: anObject class ifAbsent: [9 "instance of any normal class"] "See DataStream initialize. nil=1. true=2. false=3. a SmallInteger=4. (a String was 5). a Symbol=6. a ByteArray=7. an Array=8. other = 9. a Bitmap=11. a Metaclass=12. a Float=14. a Rectangle=15. any instance that can have a short header=16. a String=17 (new format). a WordArray=18."! Item was changed: + ----- Method: DataStream>>vacantRef (in category 'object storage') ----- - ----- Method: DataStream>>vacantRef (in category 'other') ----- vacantRef "Answer the magic 32-bit constant we use ***ON DISK*** as a stream 'reference position' to identify a reference that's not yet filled in. This must be a value that won't be used as an ordinary reference. Cf. outputReference: and readReference. -- NOTE: We could use a different type ID for vacant-refs rather than writing object-references with a magic value. (The type ID and value are overwritten by ordinary object-references when weak refs are fullfilled.)" ^1073741823 "Hardcode former SmallInteger maxVal"! Item was changed: + ----- Method: DataStream>>writeArray: (in category 'private - write') ----- - ----- Method: DataStream>>writeArray: (in category 'write and read') ----- writeArray: anArray "PRIVATE -- Write the contents of an Array." byteStream nextNumber: 4 put: anArray size. self nextPutAll: anArray.! Item was changed: + ----- Method: DataStream>>writeBitmap: (in category 'private - write') ----- - ----- Method: DataStream>>writeBitmap: (in category 'write and read') ----- writeBitmap: aBitmap "PRIVATE -- Write the contents of a Bitmap." aBitmap writeOn: byteStream "Note that this calls (byteStream nextPutAll: aBitmap) which knows enough to put 4-byte quantities on the stream!! Reader must know that size is in long words."! Item was changed: + ----- Method: DataStream>>writeBoolean: (in category 'private - write') ----- - ----- Method: DataStream>>writeBoolean: (in category 'write and read') ----- writeBoolean: aBoolean "PRIVATE -- Write the contents of a Boolean. This method is now obsolete." byteStream nextPut: (aBoolean ifTrue: [1] ifFalse: [0])! Item was changed: + ----- Method: DataStream>>writeByteArray: (in category 'private - write') ----- - ----- Method: DataStream>>writeByteArray: (in category 'write and read') ----- writeByteArray: aByteArray "PRIVATE -- Write the contents of a ByteArray." byteStream nextNumber: 4 put: aByteArray size. "May have to convert types here..." byteStream nextPutAll: aByteArray.! Item was changed: + ----- Method: DataStream>>writeClass: (in category 'private - write') ----- - ----- Method: DataStream>>writeClass: (in category 'write and read') ----- writeClass: aClass "Write out a DiskProxy for the class. It will look up the class's name in Smalltalk in the new sustem. Never write classes or methodDictionaries as objects. For novel classes, front part of file is a fileIn of the new class." "This method never executed because objectToStoreOnDataStream returns a DiskProxy. See DataStream.nextPut:" ^ self error: 'Write a DiskProxy instead'! Item was changed: + ----- Method: DataStream>>writeFalse: (in category 'private - write') ----- - ----- Method: DataStream>>writeFalse: (in category 'write and read') ----- writeFalse: aFalse "PRIVATE -- Write the contents of a False."! Item was changed: + ----- Method: DataStream>>writeFloat: (in category 'private - write') ----- - ----- Method: DataStream>>writeFloat: (in category 'write and read') ----- writeFloat: aFloat "PRIVATE -- Write the contents of a Float. We support 8-byte Floats here." byteStream nextNumber: 4 put: (aFloat at: 1). byteStream nextNumber: 4 put: (aFloat at: 2). ! Item was changed: + ----- Method: DataStream>>writeFloatString: (in category 'private - write') ----- - ----- Method: DataStream>>writeFloatString: (in category 'write and read') ----- writeFloatString: aFloat "PRIVATE -- Write the contents of a Float string. This is the slow way to write a Float--via its string rep'n." self writeByteArray: (aFloat printString)! Item was changed: + ----- Method: DataStream>>writeInstance: (in category 'private - write') ----- - ----- Method: DataStream>>writeInstance: (in category 'write and read') ----- writeInstance: anObject "PRIVATE -- Write the contents of an arbitrary instance." ^ anObject storeDataOn: self! Item was changed: + ----- Method: DataStream>>writeInteger: (in category 'private - write') ----- - ----- Method: DataStream>>writeInteger: (in category 'write and read') ----- writeInteger: anInteger "PRIVATE -- Write the contents of a SmallInteger." byteStream nextInt32Put: anInteger "signed!!!!!!!!!!"! Item was changed: + ----- Method: DataStream>>writeNil: (in category 'private - write') ----- - ----- Method: DataStream>>writeNil: (in category 'write and read') ----- writeNil: anUndefinedObject "PRIVATE -- Write the contents of an UndefinedObject."! Item was changed: + ----- Method: DataStream>>writeRectangle: (in category 'private - write') ----- - ----- Method: DataStream>>writeRectangle: (in category 'write and read') ----- writeRectangle: anObject "Write the contents of a Rectangle. See if it can be a compact Rectangle (type=15). Rectangles with values outside +/- 2047 were stored as normal objects (type=9). 17:22 tk" | ok right bottom top left acc | ok := true. (right := anObject right) > 2047 ifTrue: [ok := false]. right < -2048 ifTrue: [ok := false]. (bottom := anObject bottom) > 2047 ifTrue: [ok := false]. bottom < -2048 ifTrue: [ok := false]. (top := anObject top) > 2047 ifTrue: [ok := false]. top < -2048 ifTrue: [ok := false]. (left := anObject left) > 2047 ifTrue: [ok := false]. left < -2048 ifTrue: [ok := false]. ok := ok & left isInteger & right isInteger & top isInteger & bottom isInteger. ok ifFalse: [ byteStream skip: -1; nextPut: 9; skip: 0. "rewrite type to be normal instance" ^ anObject storeDataOn: self]. acc := ((left bitAnd: 16rFFF) bitShift: 12) + (top bitAnd: 16rFFF). byteStream nextNumber: 3 put: acc. acc := ((right bitAnd: 16rFFF) bitShift: 12) + (bottom bitAnd: 16rFFF). byteStream nextNumber: 3 put: acc.! Item was changed: + ----- Method: DataStream>>writeString: (in category 'private - write') ----- - ----- Method: DataStream>>writeString: (in category 'write and read') ----- writeString: aString "PRIVATE -- Write the contents of a String." byteStream nextStringPut: aString.! Item was changed: + ----- Method: DataStream>>writeStringOld: (in category 'private - write') ----- - ----- Method: DataStream>>writeStringOld: (in category 'write and read') ----- writeStringOld: aString "PRIVATE -- Write the contents of a String." | length | aString size < 16384 ifTrue: [ (length := aString size) < 192 ifTrue: [byteStream nextPut: length] ifFalse: [byteStream nextPut: (length // 256 + 192). byteStream nextPut: (length \\ 256)]. aString do: [:char | byteStream nextPut: char asciiValue]] ifFalse: [self writeByteArray: aString]. "takes more space"! Item was changed: + ----- Method: DataStream>>writeSymbol: (in category 'private - write') ----- - ----- Method: DataStream>>writeSymbol: (in category 'write and read') ----- writeSymbol: aSymbol "PRIVATE -- Write the contents of a Symbol." self writeString: aSymbol! Item was changed: + ----- Method: DataStream>>writeTrue: (in category 'private - write') ----- - ----- Method: DataStream>>writeTrue: (in category 'write and read') ----- writeTrue: aTrue "PRIVATE -- Write the contents of a True."! Item was changed: + ----- Method: DataStream>>writeUser: (in category 'private - write') ----- - ----- Method: DataStream>>writeUser: (in category 'write and read') ----- writeUser: anObject "Write the contents of an arbitrary User instance (and its devoted class)." " 7/29/96 tk" "If anObject is an instance of a unique user class, will lie and say it has a generic class" ^ anObject storeDataOn: self! Item was changed: + ----- Method: DataStream>>writeWordLike: (in category 'private - write') ----- - ----- Method: DataStream>>writeWordLike: (in category 'write and read') ----- writeWordLike: aWordArray "Note that we put the class name before the size." self nextPut: aWordArray class name. aWordArray writeOn: byteStream "Note that this calls (byteStream nextPutAll: aBitmap) which knows enough to put 4-byte quantities on the stream!! Reader must know that size is in long words or double-bytes."! From marcel.taeumel at hpi.de Thu Nov 24 09:03:11 2022 From: marcel.taeumel at hpi.de (Marcel Taeumel) Date: Thu, 24 Nov 2022 10:03:11 +0100 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> References: <20221123031033.E174A14D821@mail.squeak.org> <1A5201F8-CC3C-4DFE-B8C9-403BAE8C35CF@rowledge.org> <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> Message-ID: +1 Even for a loop-based algorithm, clarity would improve if the initial case would be flagged with a symbol, not nil: x := #start. [ ... ] whileTrue: [    x = #start ifTrue: [x := ... ].    ... ]. Best, Marcel Am 23.11.2022 21:23:27 schrieb Tobias Pape : Yet, nil is only seldom a good domain object. -t > On 23. Nov 2022, at 19:34, tim Rowledge wrote: > > I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! > > tim -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Thu Nov 24 11:56:40 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 24 Nov 2022 11:56:40 0000 Subject: [squeak-dev] The Trunk: KernelTests-nice.438.mcz Message-ID: <20221124115644.0EB2C14DA11@mail.squeak.org> Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.438.mcz ==================== Summary ==================== Name: KernelTests-nice.438 Author: nice Time: 24 November 2022, 12:56:33.877687 pm UUID: 21319d21-b5a9-1342-b984-31b767a2cafc Ancestors: KernelTests-ct.437 Document SqNumberParser behavior when an exponent is provided without a fraction part. For example 1e5 or 1e-4. Uncover a bug: failure to round to nearest Float for large negative exponent. Because (10 raisedToInteger: exp) isAnExactFloat is false for any exp abs > 22, we shall not recompose the float as integerPart * (base asFloat raisedTo: exponent), that's potentially two inexact operations in a row, and a chance of incorrect rounding. =============== Diff against KernelTests-ct.437 =============== Item was added: + ----- Method: SqNumberParserTest>>testIntegerWithNegativeExponent (in category 'tests - Integer') ----- + testIntegerWithNegativeExponent + self assert: (SqNumberParser parse: '1200e-2') isInteger. + self assert: 12 equals: (SqNumberParser parse: '1200e-2'). + + self assert: (SqNumberParser parse: '1200e-3') isFloat. + self assert: 1.2 equals: (SqNumberParser parse: '1200e-3'). + + "This may fail if using 25 * (10.0 raisedTo: -108)" + self assert: 25.0e-108 equals: (SqNumberParser parse: '25e-108').! Item was added: + ----- Method: SqNumberParserTest>>testIntegerWithPositiveExponent (in category 'tests - Integer') ----- + testIntegerWithPositiveExponent + self assert: (SqNumberParser parse: '12e3') isInteger. + self assert: 1200 equals: (SqNumberParser parse: '12e3').! From commits at source.squeak.org Thu Nov 24 12:03:28 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 24 Nov 2022 12:03:28 0000 Subject: [squeak-dev] The Trunk: Kernel-nice.1492.mcz Message-ID: <20221124120335.7FCCA14DA12@mail.squeak.org> Nicolas Cellier uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-nice.1492.mcz ==================== Summary ==================== Name: Kernel-nice.1492 Author: nice Time: 24 November 2022, 1:03:20.758687 pm UUID: cec2ead5-112d-5e4f-9ffe-969e3a7f575a Ancestors: Kernel-ct.1491 Fix a failure to round to nearest Float for large negative exponent when no fraction part is provided. For example, this should be true: 25e-108 = 25.0e-108. Because (10 raisedToInteger: exp) isAnExactFloat is false for any exp abs > 22, we shall not recompose the float as integerPart * (base asFloat raisedTo: exponent), that's potentially two inexact operations in a row, and a chance of incorrect rounding. =============== Diff against Kernel-ct.1491 =============== Item was changed: ----- Method: SqNumberParser>>makeIntegerOrScaledInteger (in category 'parsing-private') ----- makeIntegerOrScaledInteger "At this point, there is no digit, nor fractionPart. Maybe it can be a scaled decimal with fraction omitted... Maybe it can be a Float with a negative exponent" neg ifTrue: [integerPart := integerPart negated]. self readExponent ifTrue: ["Check that the result is an integer, otherwise answer a Float. Fractions are /not/ valid literals." + | temp | + temp := integerPart * (base raisedToInteger: exponent). + temp isInteger ifFalse: [^temp asFloat]. + ^temp]. - (exponent >= 0 or: [(integerPart * (base raisedToInteger: exponent)) isInteger]) ifFalse: - [base := base asFloat]. - ^integerPart * (base raisedToInteger: exponent)]. (self readScaleWithDefaultNumberOfDigits: 0) ifTrue: [^integerPart asScaledDecimal: scale]. ^ integerPart! From commits at source.squeak.org Thu Nov 24 12:32:29 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Thu, 24 Nov 2022 12:32:29 0000 Subject: [squeak-dev] The Trunk: KernelTests-nice.439.mcz Message-ID: <20221124123232.B80D114DA12@mail.squeak.org> Nicolas Cellier uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-nice.439.mcz ==================== Summary ==================== Name: KernelTests-nice.439 Author: nice Time: 24 November 2022, 1:32:33.892191 pm UUID: 8df6517c-ba65-fd4f-b9b9-91da634a832c Ancestors: KernelTests-nice.438 Oups, fix my own miserable mistake. =============== Diff against KernelTests-nice.438 =============== Item was changed: ----- Method: SqNumberParserTest>>testIntegerWithPositiveExponent (in category 'tests - Integer') ----- testIntegerWithPositiveExponent self assert: (SqNumberParser parse: '12e3') isInteger. + self assert: 12000 equals: (SqNumberParser parse: '12e3').! - self assert: 1200 equals: (SqNumberParser parse: '12e3').! From eliot.miranda at gmail.com Thu Nov 24 18:51:15 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu, 24 Nov 2022 10:51:15 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> References: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> Message-ID: > On Nov 23, 2022, at 12:23 PM, Tobias Pape wrote: > > Yet, nil is only seldom a good domain object. Precisely. Being disjoint from any domain it is the ideal “I am not a domain object” marker. So when one wants a variable to range over a domain and the singleton “not a member of the domain” nil is a great choice. And that’s exactly how I use it below. > -t > >> On 23. Nov 2022, at 19:34, tim Rowledge wrote: >> >> I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! >> >> tim > > > > From eliot.miranda at gmail.com Thu Nov 24 18:53:35 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu, 24 Nov 2022 10:53:35 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: Message-ID: <88025F01-33DE-4396-B280-8B5BB26C684D@gmail.com> Hi Marcel, > On Nov 24, 2022, at 1:03 AM, Marcel Taeumel wrote: > >  > +1 Even for a loop-based algorithm, clarity would improve if the initial case would be flagged with a symbol, not nil: > > x := #start. > [ ... ] whileTrue: [ > x = #start ifTrue: [x := ... ]. > ... > ]. Please don’t take this personally; I find the above pretentious in the extreme, and, given how much thought Smalltalk-80’s designers gave to initializing with nil (again it’s in the blue book), displaying and/or celebrating ignorance. So -1,000. > > Best, > Marcel >> Am 23.11.2022 21:23:27 schrieb Tobias Pape : >> >> Yet, nil is only seldom a good domain object. >> -t >> >> > On 23. Nov 2022, at 19:34, tim Rowledge wrote: >> > >> > I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! >> > >> > tim >> >> >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Marcel.Taeumel at hpi.de Thu Nov 24 19:15:50 2022 From: Marcel.Taeumel at hpi.de (Taeumel, Marcel) Date: Thu, 24 Nov 2022 19:15:50 +0000 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <88025F01-33DE-4396-B280-8B5BB26C684D@gmail.com> References: , <88025F01-33DE-4396-B280-8B5BB26C684D@gmail.com> Message-ID: Hehe. Of course you do. 😉 I just wanted to highlight the fact that nil is no domain object. Exceptional usage should be done by intention. In general, ifNil checks interfere with readability of domain logic. Still, I see no harm in such ifNil checks. Who would agree on a domain-specific symbol for start anyway 😅 ________________________________ From: Squeak-dev on behalf of Eliot Miranda Sent: Thursday, November 24, 2022 7:53:35 PM To: The general-purpose Squeak developers list Subject: Re: [squeak-dev] The Trunk: Compiler-eem.480.mcz Hi Marcel, On Nov 24, 2022, at 1:03 AM, Marcel Taeumel wrote:  +1 Even for a loop-based algorithm, clarity would improve if the initial case would be flagged with a symbol, not nil: x := #start. [ ... ] whileTrue: [ x = #start ifTrue: [x := ... ]. ... ]. Please don’t take this personally; I find the above pretentious in the extreme, and, given how much thought Smalltalk-80’s designers gave to initializing with nil (again it’s in the blue book), displaying and/or celebrating ignorance. So -1,000. Best, Marcel Am 23.11.2022 21:23:27 schrieb Tobias Pape : Yet, nil is only seldom a good domain object. -t > On 23. Nov 2022, at 19:34, tim Rowledge wrote: > > I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! > > tim -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Thu Nov 24 19:23:52 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu, 24 Nov 2022 11:23:52 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> References: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> Message-ID: Hi Tobi, let me try again (https://youtu.be/Cj8n4MfhjUc)… > On Nov 23, 2022, at 12:23 PM, Tobias Pape wrote: > > Yet, nil is only seldom a good domain object. Precisely. Being disjoint from any domain it is the ideal “I am not a domain object” marker. So when one wants a variable to range over a domain and the singleton “not a member of the domain” nil is a great choice. And that’s exactly how I use it below. There is another excellent marker of a non-domain object, and that is a newly instantiated object. That object is known to not be any other object, since objects are unique. So if code is searching for something (eg applying a block to every literal in the system), having the newly instantiated object that implements the search use itself as the “I’m not in the domain of all pre-existing objects” is a sensible choice. This is the pattern InstructionStream uses when scanning for selectors. > -t > >> On 23. Nov 2022, at 19:34, tim Rowledge wrote: >> >> I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! >> >> tim _,,,^..^,,,_ (phone) -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Thu Nov 24 19:25:56 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Thu, 24 Nov 2022 11:25:56 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: Message-ID: > On Nov 24, 2022, at 11:15 AM, Taeumel, Marcel wrote: > >  Hehe. Of course you do. 😉 I just wanted to highlight the fact that nil is no domain object. Exceptional usage should be done by intention. In general, ifNil checks interfere with readability of domain logic. Still, I see no harm in such ifNil checks. Who would agree on a domain-specific symbol for start anyway 😅 😅 <3 > > From: Squeak-dev on behalf of Eliot Miranda > Sent: Thursday, November 24, 2022 7:53:35 PM > To: The general-purpose Squeak developers list > Subject: Re: [squeak-dev] The Trunk: Compiler-eem.480.mcz > > Hi Marcel, > >>> On Nov 24, 2022, at 1:03 AM, Marcel Taeumel wrote: >>> >>  >> +1 Even for a loop-based algorithm, clarity would improve if the initial case would be flagged with a symbol, not nil: >> >> x := #start. >> [ ... ] whileTrue: [ >> x = #start ifTrue: [x := ... ]. >> ... >> ]. > > Please don’t take this personally; I find the above pretentious in the extreme, and, given how much thought Smalltalk-80’s designers gave to initializing with nil (again it’s in the blue book), displaying and/or celebrating ignorance. So -1,000. > >> >> Best, >> Marcel >>> Am 23.11.2022 21:23:27 schrieb Tobias Pape : >>> >>> Yet, nil is only seldom a good domain object. >>> -t >>> >>> > On 23. Nov 2022, at 19:34, tim Rowledge wrote: >>> > >>> > I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! >>> > >>> > tim -------------- next part -------------- An HTML attachment was scrubbed... URL: From Das.Linux at gmx.de Thu Nov 24 20:18:33 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Thu, 24 Nov 2022 21:18:33 +0100 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> Message-ID: <093B4101-F5ED-4136-ABD8-2AD705722929@gmx.de> Hi Eliot First things first, I did not raise objections in my admittedly short quip. > On 24. Nov 2022, at 20:23, Eliot Miranda wrote: > > Hi Tobi, > > let me try again (https://youtu.be/Cj8n4MfhjUc)… :D I already got my comfy chair! > >> On Nov 23, 2022, at 12:23 PM, Tobias Pape wrote: >> >> Yet, nil is only seldom a good domain object. > > Precisely. Being disjoint from any domain it is the ideal “I am not a domain object” marker. So when one wants a variable to range over a domain and the singleton “not a member of the domain” nil is a great choice. And that’s exactly how I use it below. Second things second, I got that. > > There is another excellent marker of a non-domain object, and that is a newly instantiated object. That object is known to not be any other object, since objects are unique. So if code is searching for something (eg applying a block to every literal in the system), having the newly instantiated object that implements the search use itself as the “I’m not in the domain of all pre-existing objects” is a sensible choice. This is the pattern InstructionStream uses when scanning for selectors. And #someObject/#nextObject. I get that. And it is actually a beautiful thing you cannot do everywhere[0]. My fear is as follows: I hope we can agree that "nil" is part of the "system domain" of Smalltalk, or - said differently - the meta-level. So are the concepts of variables, classes etc. The non-meta, base, or "domain proper" layer can be anything you want to computationally achieve.[1] Let's arbitrarily chose finance[2]. A domain object would be an account, a transaction, an account holder, etc. (Note that we can chose how to represent each, and we do not necessarily need objects for each, but I digress). My take: in code dealing with such domain objects, nil should appear next to never, because it is an object from the Metalevel. The problems with accepting nil as the general "nothing to see" marker include: - There are too many. In our example, an account holder could have an instVar "account" which could be nil when not having an account yet, BUT ALSO an account could have a "closingDate" for when the account folded, which is "nil" when the account is still open, AND ALSO, a transaction could have an "auditor" which is nil as long as no audit has taken place etc. Just like that, nil takes _different roles_ just by being convenient. - Nil has problematic provenance. When somewhere during debugging (the all-known MNU for UndefinedObject) a nil pops up, it is often reallllly hard to say whence it came from. So dealing with a lot of nil-bearing code will send you down rabbit holes after the other. - Nil begets polymorphism, nil defies polymorphism. It is one of the most awesome feats of Smalltalk that nil is NOT like NULL, in that it can respond to messages. That is exceptionally powerful and has given Smalltalk a lot of resilience. But cluttering UndefinedObject with custom, even domain-specifc methods is a really bad idea. However, that means it is often unwise to just have object that could be nil be sent arbitrary messages. Hence a multitude of #isNil/#ifNil-Checks. Proper domain objects that model absence, pre-valid state, or error conditions can deal much better with that. - Nil is in a collection-superposition (just like your good old USB-A plug which you have to turn at least twice to fit). You only know whether nil _actually_ could be a collection when you know that a non-nil object in its place is a collection [3]. Said differently: in contrast to LISPy languages, our nil is _by design_ no collection, while LISPy null _by design_ IS the empty list. This makes for funny messages like #isEmptyOrNil, which bails on non-nil-non-collection objects. So every time you have to deal with nil, you automatically at lease once have to answer the question "could the non-nil version of this object be a collection"? There are a lot of interesting approaches to each or combinations of these issues. This includes Null-Object patterns, Sane-default-initializers, exceptions, or explicit models of multiplicity[4]. But back to the beginning. In code that does, for example blaFooAnAccount | fooAccount | self accounts processBla: [:ea | fooAccount ifNil: [fooAccount := ea]. fooAccount := (ea doesBork: fooAccount) ifTrue: [fooAccount] ifFalse: [ea]] ^ fooAccount we find two things: First, we could inadvertently return nil from that method. But this is technical and I think most here can deal with that. But second, the line "fooAccount ifNil: [fooAccount := ea]." ACTUALLY says "if fooAccount is an uninitialized temporary variable, populate it". This is technically correct, but conflates domains. In our world of finance, the idea of a "temporary variable" does no make sense. It is part of the meta-level domain, the system. I don't say this is wrong _per se_ but people reading, and even more so, people writing such code MUST be aware that they are crossing domains, and especially, entering a meta level. That's why I think these warnings are really ok. I won't fight the commit "Compiler-eem.480.mcz", especially since it more or less is descriptive of a pervasive style of writing Smalltalk of Squeak Core contributors. I hope people find theses ideas useful. Best regards -Tobias [0]: I've used it in Python code to much joy. [1]: Caveat lector: the "domain layer" can surely be the "system layer". In fact that is what a lot of system code deals with. But this is messy for our considerations above and lets treat it as _exceptional_. [2]: Semi-arbitrarly, just because I received my tax returns :P [3]: yes, that is a strange sentence. It's late. Also, Ardbeg. [4]: For example, as in the work of Steimann (https://dl.acm.org/doi/10.1145/2509578.2509582 ). It seems they had a Smalltalk implementation in 2017. > >> -t >> >>> On 23. Nov 2022, at 19:34, tim Rowledge wrote: >>> >>> I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! >>> >>> tim > > > _,,,^..^,,,_ (phone) > From lewis at mail.msen.com Fri Nov 25 15:03:00 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Fri, 25 Nov 2022 10:03:00 -0500 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <093B4101-F5ED-4136-ABD8-2AD705722929@gmx.de> References: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> <093B4101-F5ED-4136-ABD8-2AD705722929@gmx.de> Message-ID: <20221125150300.GA17219@shell.msen.com> On Thu, Nov 24, 2022 at 09:18:33PM +0100, Tobias Pape wrote: > > I hope people find theses ideas useful. > Yes, thank you. And thanks Eliot also for the conversation. I was expecting this thread to be a flame war but instead I find it instructive and thought provoking. Dave From christoph.thiede at student.hpi.uni-potsdam.de Fri Nov 25 15:46:52 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Fri, 25 Nov 2022 16:46:52 +0100 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <20221123031033.E174A14D821@mail.squeak.org> , Message-ID: <4121d105-f261-4a85-82ef-68201168cbb4@MX2018-DAG2.hpi.uni-potsdam.de> Hi Eliot, thanks for the great discussion. Your reply cleared a lot of things up for me -- I very much agree that the default value of any variable is not "undefined", but specifically nil. What I still find an interesting trade-off is that of "implicit vs explicit" aka "terseness vs readability". I think its solution depends on the typical readers of the code I am writing. If they are Squeak Core developers or VM developers, I can assume that they know the default value for any variable. For unexperienced programmers, I hope they do know. Still, it's easier for anyone to forget if it's not explicitly written down. Yes, I can translate | a | to | a := nil | in my head, but that also might be a tiny portion of mental overhead. Example 2, ColorArray: My first take would be indeed be to favor ColorArray new: 256 withAll: Color transparent over ColorArray new: 256, because I have never used this class before and would not be sure whether the values default to black or transparent or anything else. I could look it up, but I would likely forget it several times before remembering. Why should I do this to myself (and to any other non-ColorArray expert)? Example 3, point arithmetic: Here I'm completely with you, but maybe I'm also biased because I have already spent some time working with visual domains in Squeak. :-) Example 4, coreutils: ls, cat, and less are all lisping, catastrophic, or at least less intuitive names IMHO. Most of us will have got familiar with them, but from a Smalltalk perspective that is seeking for readability, I still would favor them to be named ListFiles, PrintFile, and OpenFileForRead. On the contrary, many people who are used the present nomenclature would dismiss these proposals as hard to write and maybe even hard to read. Is "terseness vs readability" as this syntactical point really a matter of data (code) quality (that must be ensured by the writer), or more a matter of the right tooling (that can be adjusted by the editor/reader)? --- > I want a warning for the usage of b in "c := b", "d" in "#(1 2 3) sorted: d", g in "g perform: #ifNotNil: with: [b := g]". I *don't* want to be told about a in "a ifNil: [a := 1]", c in "c ifNil: [c := 3]", or e & f in "(e isNil or: [f isNil]) ifTrue: [e := f := 6]". Thank you for clarification. So the idea of #queryUndefined (will rename that) is to fix human forgetfulness. In the second group of examples, you explicitly consider these variables being nil, so you don't need a reminder from the compiler (or with regards to Tobi's argument, you're already dealing with the meta-level). In the first group of examples, one could say that you are covering tracks of your own possible forgetfulness and spreading possibly unsassigned values, so it's more important for the tooling to point you to that possible slip. Yes, I guess now that makes more sense to me. :-) Still, the scope of this warning remains a bit blurry for me. Maybe that's because we are approximating a type analysis engine here with a *very* rough heuristic. For instance: | a | a ifNotNil: [a := a + 1]. ^ a In this example, I do *not* want a warning for "a + 1" but I *do* want a warning for "^ a" as a still might be unassigned. Currently, the reality is just the other way around. But that is probably out of scope for the current architecture ... (As a side note, some other confusing thing around this notification for me is the fact that our compiler essentially integrates a few rudimentary linter tools (namely, UndefinedVariable and UnknownSelector) and forces the user to interact with them in a modal fashion. To be honest, I never liked that "modal linter style" and often wish we had some more contemporary annotation-/wiggle-line-based tooling for that. My typical interaction with #queryUndefined looks like this: me: accept new code, compiler: you did not assign foobar, me: oops, you're right, let me fix that; or alternatively: yes, that was intended, let me explicate that. Ignoring and proceeding from this warning has never felt acceptable for me as this would put the same confusion on any future editor of the method.) > :-) Hope I'm not too strident :-) No problem, it was very interesting and I learn a lot from your replies. :-) Best, Christoph --- Sent from Squeak Inbox Talk On 2022-11-22T23:36:09-08:00, eliot.miranda at gmail.com wrote: > Hi Christoph, Hi Marcel, > > apologies about the font size mismatches... > > On Wed, Nov 23, 2022 at 2:25 AM Marcel Taeumel > wrote: > > > Hi Christoph -- > > > > > IMHO, it unnecessarily complicates the simple Smalltalk syntax. [...] > > > > Nah, this is just a tooling change, not a syntactical one. > > > > +1 > > > > > Yes, I would like to have this info skipped for #isNil as well. Note that one > > should not use #ifNotNilDo: anymore. > > > > Good idea. I'll include it. > > > > > Best, > > Marcel > > > > Am 23.11.2022 11:00:43 schrieb Thiede, Christoph < > > christoph.thiede at student.hpi.uni-potsdam.de>: > > > > Hi Eliot, hi all, > > > > > > I'm skeptical about this change, as it creates or expands a special role > > of the selectors #ifNil:, #ifNotNil:, and their combinations. IMHO, it > > unnecessarily complicates the simple Smalltalk syntax. While I know and > > sometimes dislike these UndefinedVariable notifications, too, I don't know > > whether differentiating them by the selector is the right strategy > > to improve this situation. > > > > Please indulge me. It's f***ing irritating to be told by the compiler > that as temp var appears to be uninitialized when one is intentionally > using the fact that temps are initialized to nil. And that temp vars are > initialized to nil is a) essential knowledge and b) a good thing (no > uninitialized local variables a la C, a sensible value to initialize a > variable with). > > BTW, I find it more than sad (a little alarming in fact) that > someSmalltalkers don't know that the value of several conditionals that > take blocks is nil when the condition doesn't select the block. e.g. false > ifTrue: [self anything] is nil. I see "expr ifNotNil: [...] ifNil: [nil]" > and it strikes me as illiterate. I recently visited code written by a > strong programmer who open coded a lot of point arithmetic, decomposing > e.g. a * b into (a x * b x) @ (a y * b y). It's bad. It gradually > degrades the code base in that it isn't always an exemplar of best > practice, > > > > > Consider the following examples: > > > > > > | a b c d e f g h | > > a ifNil: [a := 1]. > > c := b. > > c ifNil: [c := 3]. > > #(1 2 3) sorted: d. > > e := 5. > > (e isNil or: [f isNil]) ifTrue: [e := f := 6]. > > g perform: #ifNotNil: with: [b := g]. > > h ifNotNilDo: [h := 8]. > > > > How would you explain to a naive Smalltalker which of these variables will > > be marked as undefined at this point and why? (Of course, you can explain > > it by pointing to the implementation, but I think that's a significantly > > less intuitive explanation than just saying "you must declare any variable > > before using it".) > > > > > No. It's a hard-and-fast rule that all temp vars are initialized to nil. > And initializing a variable (to other than nil) is done by assigning it. > In the above a through h are declared within the vertical bars.n They are > initialized in the assignments. I want a warning for the usage of b in "c > := b", "d" in "#(1 2 3) sorted: d", g in "g perform: #ifNotNil: with: [b := > g]". I *don't* want to be told about a in "a ifNil: [a := 1]", c in "c > ifNil: [c := 3]", or e & f in "(e isNil or: [f isNil]) ifTrue: [e := f := > 6]". I never want to see "ifNotNilDo", ever ;-) > (* note that a couple of years back we fixed a bad bug in the compiler > where block local temps were not (re)initialized to nil on each iteration, > leaking their values from previous iterations, breaking the "all temp vars > are initialized to nil rule, and revealing implementation details in the > compiler's inlining of to:[by:]do: forms) > > > This behavior leads to a mental model that disambiguates between null and > > undefined similar to JavaScript which I never have found helpful. > > > > > I don't see how that applies. Smalltalk has no undefined. It has nil & > zero, and these values are used to initialize any and all variables. This > is not an artifact of the implementation. It is a fundamental part of the > language design. It results in no dangling referents or > uninitialized variables. The language used in Parser>>#queryUndefined is > problematic. It should be "unassigned", not "undefined". There is nothing > undefined about these variables. But they are indeed unassigned. In some > cases (see my i=diomatic implementation of subsequences: and substrings) > this can (and *should*) be used to advantage. And all Smalltalk > programming courses should explain that variables are always initialized > (either to nil or zero, & hence by extension 0.0, Character null, Color > transparent, et al), and may need assignment before their referents get > sent messages. > > I see the same kind of sloppiness in people not knowing that conditionals > that take blocks typically evaluate to nil when the condition doesn;t > select the block. So always "expr ifNotNil: [...]", never "expr ifNotNil: > [...] ifNil: [nil]", or "expr ifNotNil: [...] ifNil: []". I recently > cleaned up code by as string programmer who had open coded point arithmetic > (e.g. a * b written as (a x * b x) @ (a y * b y) ). This is really bad: > it's exemplifying poor practice, it's verbose, it takes away at least as > much understanding as it conveys, it leads to more difficult to manage code. > > If we fail to teach the language properly we start on a slippery slope to > duplication (which is an awful evil, leading to much increased maintennance > effort, and brittleness), and rendering perfectly good, well thought-out > idioms mysterious. It;'s not like Smalltalk has a lot of rules; the > number, compared to C & C++ et al is tiny. And terseness has not just > aesthetic benefit, but real practical benefit in terms of readability & > maintainability. > > > Also, with this change, the compiler leaks the default value of any > > temporary variable, which we previously were able to hide at least > > partially. > > > > > But that is a MISTAKE!! The language designers didn't arrange for temps to > be initialized to nil just because that's the only default. They did it to > ensure that there is no such thing as an uninitialized variable in > Smalltalk. That's why nil ids an object, with a class, not just nil. > That's why nil ~~ false. It's carefully thought out and not just some > artifact of the implementation. And that rationale (read the blue book > carefully) and its implications, should be taught/learned/known, and > especially exemplified by the core code of Squeak trunk, and hence > supported by the compiler. > > > In many cases, I think explicitly setting a temporary variable to nil > > before it is initialized within some non-trivial conditional complex would > > be more explicit, thus more readable, and something which we should > > generally encourage programmers to do. > > > > > I disagree. You're advocating for absurdities such as > > | colors | > colors :=- ColorArray new: 256. > colors atAllPut: Color transparent > > This is the kind of thinking that leads to cycling wearing American > Football clothes. It won't keep you from being run over by a truck, but > it'll make you so slow and reduce your peripheral vision so much, not to > mention give you a false sense of security, that you'll be much more likely > to be run over by a truck... > > > Looking forward to your opinion! > > > > > :-) Hope I'm not too strident :-) > > > Best, > > > > Christoph > > ------------------------------ > > *Von:* Squeak-dev im > > Auftrag von commits at source.squeak.org > > *Gesendet:* Mittwoch, 23. November 2022 04:10:30 > > *An:* squeak-dev at lists.squeakfoundation.org; > > packages at lists.squeakfoundation.org > > *Betreff:* [squeak-dev] The Trunk: Compiler-eem.480.mcz > > > > Eliot Miranda uploaded a new version of Compiler to project The Trunk: > > http://source.squeak.org/trunk/Compiler-eem.480.mcz > > > > ==================== Summary ==================== > > > > Name: Compiler-eem.480 > > Author: eem > > Time: 22 November 2022, 7:10:27.324796 pm > > UUID: 3e5ba19e-c44a-4390-9004-de1246736cbc > > Ancestors: Compiler-eem.479 > > > > Do not warn of an uninitialized temporary if it is being sent ifNil: or > > ifNotNil:. > > > > =============== Diff against Compiler-eem.479 =============== > > > > Item was changed: > > ----- Method: Parser>>primaryExpression (in category 'expression types') > > ----- > > primaryExpression > > hereType == #word > > ifTrue: > > [parseNode := self variable. > > + (parseNode isUndefTemp > > + and: [(#('ifNil:' 'ifNotNil:') includes: here) > > not > > + and: [self interactive]]) > > + ifTrue: > > + [self queryUndefined]. > > - (parseNode isUndefTemp and: [self interactive]) > > - ifTrue: [self queryUndefined]. > > parseNode nowHasRef. > > ^ true]. > > hereType == #leftBracket > > ifTrue: > > [self advance. > > self blockExpression. > > ^true]. > > hereType == #leftBrace > > ifTrue: > > [self braceExpression. > > ^true]. > > hereType == #leftParenthesis > > ifTrue: > > [self advance. > > self expression ifFalse: [^self expected: > > 'expression']. > > (self match: #rightParenthesis) > > ifFalse: [^self expected: 'right > > parenthesis']. > > ^true]. > > (hereType == #string or: [hereType == #number or: [hereType == > > #literal or: [hereType == #character]]]) > > ifTrue: > > [parseNode := encoder encodeLiteral: self advance. > > ^true]. > > (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) > > ifTrue: > > [self advance. > > parseNode := encoder encodeLiteral: self advance > > negated. > > ^true]. > > ^false! > > > > > > > > > > -- > _,,,^..^,,,_ > best, Eliot > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Fri Nov 25 17:03:44 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 17:03:44 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.2054.mcz Message-ID: <20221125170352.538C114D634@mail.squeak.org> Christoph Thiede uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.2054.mcz ==================== Summary ==================== Name: Morphic-ct.2054 Author: ct Time: 25 November 2022, 6:03:40.232495 pm UUID: 50a95075-43f1-024e-ba2f-c74863e21f26 Ancestors: Morphic-mt.2053 Fixes dangling keyboard focus for children of deleted morphs. Thanks to Robert (rhi) for the original bug report and to Marcel (mt) for the solution! =============== Diff against Morphic-mt.2053 =============== Item was changed: ----- Method: HandMorph>>releaseKeyboardFocus: (in category 'focus handling') ----- releaseKeyboardFocus: aMorph "If the given morph had the keyboard focus before, release it" self keyboardFocus == aMorph keyboardFocusDelegate + ifTrue: [self releaseKeyboardFocus]. + + "Also release the keyboard focus for any child of aMorph." + self keyboardFocus ifNotNil: [:focus | + "like #hasOwner:, but identity instead of equality comparison" + focus allOwnersDo: [:m | + m == aMorph ifTrue: [ + ^ self releaseKeyboardFocus]]].! - ifTrue:[self releaseKeyboardFocus].! From commits at source.squeak.org Fri Nov 25 17:19:53 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 17:19:53 0000 Subject: [squeak-dev] The Trunk: ToolsTests-ct.117.mcz Message-ID: <20221125171956.C695014D634@mail.squeak.org> Christoph Thiede uploaded a new version of ToolsTests to project The Trunk: http://source.squeak.org/trunk/ToolsTests-ct.117.mcz ==================== Summary ==================== Name: ToolsTests-ct.117 Author: ct Time: 25 November 2022, 6:19:53.110214 pm UUID: 8fd1a806-e8a6-a942-8dcd-28e258d88d39 Ancestors: ToolsTests-jar.116 Complements Kernel-ct.1493 (recursive process-faithful debugging)/merges recursive-profaide. Also adds an e2e test for simple process-faithful debugging. =============== Diff against ToolsTests-jar.116 =============== Item was added: + ----- Method: DebuggerTests>>test25ProcessFaithfulDebugging (in category 'tests') ----- + test25ProcessFaithfulDebugging + "Debugging a process which sends Processor activeProcess should have the same effect as running the process directly. End-to-end equivalent for ProcessTest>>#testProcessFaithfulSimulation." + + | userProcess | + process := Process forBlock: [ + Processor activeProcess environmentAt: #plonk put: 42. + Processor activeProcess suspend. + Processor activeProcess environmentAt: #plonk]. + process resume. + Processor yield. + self assert: (process environmentAt: #plonk) = 42. + + debugger := process debug. + + [userProcess := [debugger stepOver "suspend"; stepOver "activeProcess"; stepOver "environmentAt:"] fork. + Processor yield. + + self deny: [process isTerminated]. + self assert: [userProcess isTerminated]. + self assert: [process suspendedContext willReturn and: [process suspendedContext top = 42]]. + self assert: (userProcess environmentAt: #plonk ifAbsent: []) = nil] + + ensure: [ + process terminateAggressively. + debugger close. + process := userProcess. + self findDebugger "for correct tearDown"].! Item was added: + ----- Method: DebuggerTests>>test26RecursiveProcessFaithfulDebugging (in category 'tests') ----- + test26RecursiveProcessFaithfulDebugging + "Debugging the debugger for a process which sends Processor activeProcess should have the same effect as running the original debugger directly. End-to-end equivalent for ProcessTest>>#testProcessFaithfulSimulationMeta." + + | userProcess metaDebugger metaProcess | + process := Process forBlock: [ + Processor activeProcess environmentAt: #plonk put: 42. + Processor activeProcess suspend. + Processor activeProcess environmentAt: #plonk]. + process resume. + Processor yield. + self assert: (process environmentAt: #plonk) = 42. + + debugger := process debug. + metaProcess := Process forBlock: [ + [debugger stepOver "suspend"; stepOver "activeProcess"; stepOver "environmentAt:"] value]. + metaDebugger := metaProcess debug. + + [userProcess := [metaDebugger stepOver "value"] fork. + Processor yield. + + self deny: [process isTerminated]. + self assert: [userProcess isTerminated]. + self assert: [process suspendedContext willReturn and: [process suspendedContext top = 42]]. + self assert: (userProcess environmentAt: #plonk ifAbsent: []) = nil] + + ensure: [ + process terminateAggressively. + debugger close. + metaProcess terminateAggressively. + metaDebugger close. + process := userProcess. + self findDebugger "for correct tearDown"].! From commits at source.squeak.org Fri Nov 25 17:19:59 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 17:19:59 0000 Subject: [squeak-dev] The Trunk: KernelTests-ct.440.mcz Message-ID: <20221125172004.2220614D7DE@mail.squeak.org> Christoph Thiede uploaded a new version of KernelTests to project The Trunk: http://source.squeak.org/trunk/KernelTests-ct.440.mcz ==================== Summary ==================== Name: KernelTests-ct.440 Author: ct Time: 25 November 2022, 6:19:58.271214 pm UUID: 968dccd6-663d-7a45-9093-76cfa43220e5 Ancestors: KernelTests-nice.439 Complements Kernel-ct.1493 (recursive process-faithful debugging)/merges recursive-profaide. =============== Diff against KernelTests-nice.439 =============== Item was added: + ----- Method: ProcessTest>>testProcessFaithfulSimulationMeta (in category 'tests') ----- + testProcessFaithfulSimulationMeta + "While stacking multiple simulation processes into each other, process variables should be looked up in the process being simulated. Acceptance test for process-faithful debugging, see #evaluate:onBehalfOf:." + + | process result metaProcess | + process := Process forBlock: [ + result := Processor activeProcess environmentAt: #foo]. + process environmentAt: #foo put: 42. + + metaProcess := Process forBlock: [ + process runUntil: [:context | context isDead]]. + metaProcess runUntil: [:context | context isDead]. + + self assert: 42 equals: result.! From commits at source.squeak.org Fri Nov 25 17:20:06 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 17:20:06 0000 Subject: [squeak-dev] The Trunk: Kernel-ct.1493.mcz Message-ID: <20221125172011.EB8BB14D805@mail.squeak.org> Christoph Thiede uploaded a new version of Kernel to project The Trunk: http://source.squeak.org/trunk/Kernel-ct.1493.mcz ==================== Summary ==================== Name: Kernel-ct.1493 Author: ct Time: 25 November 2022, 6:20:03.170214 pm UUID: 4ed198f9-d0db-ec40-884f-88826ffae1f5 Ancestors: Kernel-nice.1492 Merges recursive-profaide: Adds support for recursive process-faithful debugging. Without this patch, debugging the debugger for a process which sends Processor activeProcess will have a different effect than running the original debugger directly. See tests in KernelTests-ct.440 and ToolsTests-ct.117. This is kind of a delayed follow-up on Kernel-mt.1381. Thanks to Marcel for discussing this issue! =============== Diff against Kernel-nice.1492 =============== Item was changed: ----- Method: Process>>effectiveProcess (in category 'accessing') ----- effectiveProcess + "effectiveProcess is a mechanism to allow process-faithful debugging. The debugger executes code on behalf of processes, so unless some effort is made the identity of Processor activeProcess is not correctly maintained when debugging code. The debugger uses evaluate:onBehalfOf: to assign the debugged process as the effectiveProcess of the process executing the code, preserving process identity." + + ^effectiveProcess + ifNil: [self] + ifNotNil: [:process | + "Recursive process-faithful debugging. See DebuggerTests>>#test25RecursiveProcessFaithfulDebugging for a practical example." + process effectiveProcess]! - "effectiveProcess is a mechanism to allow process-faithful debugging. The debugger executes code - on behalf of processes, so unless some effort is made the identity of Processor activeProcess is not - correctly maintained when debugging code. The debugger uses evaluate:onBehalfOf: to assign the - debugged process as the effectiveProcess of the process executing the code, preserving process - identity." - ^effectiveProcess ifNil: [self]! From commits at source.squeak.org Fri Nov 25 17:21:38 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 17:21:38 0000 Subject: [squeak-dev] The Trunk: Tools-ct.1179.mcz Message-ID: <20221125172142.C902714D805@mail.squeak.org> Christoph Thiede uploaded a new version of Tools to project The Trunk: http://source.squeak.org/trunk/Tools-ct.1179.mcz ==================== Summary ==================== Name: Tools-ct.1179 Author: ct Time: 25 November 2022, 6:21:36.545214 pm UUID: db8819d6-e148-fc41-a0b5-5a2110920b4c Ancestors: Tools-mt.1178 Adds drop-in-world support for messages and classes in change sorters. =============== Diff against Tools-mt.1178 =============== Item was changed: ----- 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:; + dragType: #dragTypeForClassListAt:. - dragItem: #dragClass:. ^ listSpec! Item was changed: ----- 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:; + dragType: #dragTypeForMessageListAt:. - dragItem: #dragMessage:. ^ listSpec! Item was added: + ----- Method: ChangeSorter>>dragTypeForClassListAt: (in category 'dragging') ----- + dragTypeForClassListAt: index + + ^ #sourceCode! Item was added: + ----- Method: ChangeSorter>>dragTypeForMessageListAt: (in category 'dragging') ----- + dragTypeForMessageListAt: index + + ^ #sourceCode! From commits at source.squeak.org Fri Nov 25 17:21:47 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 17:21:47 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.2055.mcz Message-ID: <20221125172155.F179C14D819@mail.squeak.org> Christoph Thiede uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.2055.mcz ==================== Summary ==================== Name: Morphic-ct.2055 Author: ct Time: 25 November 2022, 6:21:43.230214 pm UUID: 6142d161-9038-804c-84d2-2b390ba17fcc Ancestors: Morphic-ct.2054 Complements Tools-ct.1179 (drop-in-world support for classes in change sorters). =============== Diff against Morphic-ct.2054 =============== Item was changed: ----- Method: PasteUpMorph>>dropSourceCode:event: (in category 'event handling') ----- dropSourceCode: anObject event: evt (anObject isMethodReference and: [anObject isValid]) ifTrue: [^ self dropSourceCode: anObject compiledMethod event: evt]. + (anObject isClassReference and: [anObject isValid]) + ifTrue: [^ self dropSourceCode: anObject actualClass event: evt]. (anObject isBehavior or: [anObject isCompiledMethod]) ifTrue: [ | tool window | tool := anObject isBehavior ifTrue: [Browser new setClass: anObject] ifFalse: [CodeHolder new setClass: anObject methodClass selector: anObject selector]. window := ToolBuilder open: tool. window center: evt position. window bounds: (window bounds translatedToBeWithin: self bounds)]. anObject isString ifTrue: [anObject edit].! From commits at source.squeak.org Fri Nov 25 17:41:28 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 17:41:28 0000 Subject: [squeak-dev] The Trunk: Tests-ct.495.mcz Message-ID: <20221125174132.3C20714D81C@mail.squeak.org> Christoph Thiede uploaded a new version of Tests to project The Trunk: http://source.squeak.org/trunk/Tests-ct.495.mcz ==================== Summary ==================== Name: Tests-ct.495 Author: ct Time: 25 November 2022, 6:41:26.980861 pm UUID: a3ee3a6b-6274-4443-8fc2-bc458742f921 Ancestors: Tests-eem.494 Silences clean-up of CompilerExceptionsTests. =============== Diff against Tests-eem.494 =============== Item was changed: ----- Method: CompilerExceptionsTest>>removeGeneratedMethods (in category 'private') ----- removeGeneratedMethods + SystemChangeNotifier uniqueInstance doSilently: + [self class removeCategory: 'generated'].! - self class removeCategory: 'generated'! From christoph.thiede at student.hpi.uni-potsdam.de Fri Nov 25 17:43:18 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Fri, 25 Nov 2022 18:43:18 +0100 Subject: [squeak-dev] Review Request: UnassignedVariable.1.cs Message-ID: =============== Summary =============== Change Set:��������UnassignedVariable Date:������������25 November 2022 Author:������������Christoph Thiede Renames 'undeclared variable' warning to 'unassigned variable' as proposed by Eliot (emm) in [1]. Note that for now, I'd stick with the vocabulary #hasDef in ParseNodes as it a) aligns with #hasRef and b) has more than a few senders. Please report back whether you'd like to see that renamed, too. [1] https://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November/222668.html#:~:text=the%20language%20used%20in%20parser%3E%3E%23queryundefined =============== Postscript =============== CompilerExceptionsTest removeSelector: #testUndefinedVariable =============== Diff =============== CompilerExceptionsTest>>testUnassignedVariable {tests} � ct 11/25/2022 18:31 + testUnassignedVariable + + ����self + ��������compiling: 'griffle | goo | ^ goo' + ��������shouldRaise: UnassignedVariable + ��������andSelect: [(text allRangesOfRegexMatches: '(?<=\^ )goo') first] + ��������testing: { + ������������true -> [self assertSucceeded]. + ������������false -> [self assertCanceled] }. + ����self + ��������compiling: 'griffle [ | goo | ^ goo ] value' + ��������shouldRaise: UnassignedVariable + ��������andSelect: [(text allRangesOfRegexMatches: '(?<=\^ )goo') first] + ��������testing: { + ������������true -> [self assertSucceeded]. + ������������false -> [self assertCanceled] }. Parser>>primaryExpression {expression types} � ct 11/25/2022 18:30 (changed) primaryExpression ����hereType == #word ��������ifTrue: ������������[parseNode := self variable. ������������(parseNode isUndefTemp ������������ and: [(#(ifNil: ifNotNil: isNil notNil) includes: here) not ������������ and: [self interactive]]) ����������������ifTrue: - ��������������������[self queryUndefined]. + ��������������������[self queryUnassigned]. ������������parseNode nowHasRef. ������������^ true]. ����hereType == #leftBracket ��������ifTrue: ������������[self advance. ������������self blockExpression. ������������^true]. ����hereType == #leftBrace ��������ifTrue: ������������[self braceExpression. ������������^true]. ����hereType == #leftParenthesis ��������ifTrue: ������������[self advance. ������������self expression ifFalse: [^self expected: 'expression']. ������������(self match: #rightParenthesis) ����������������ifFalse: [^self expected: 'right parenthesis']. ������������^true]. ����(hereType == #string or: [hereType == #number or: [hereType == #literal or: [hereType == #character]]]) ��������ifTrue: ������������[parseNode := encoder encodeLiteral: self advance. ������������^true]. ����(here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) ��������ifTrue: ������������[self advance. ������������parseNode := encoder encodeLiteral: self advance negated. ������������^true]. ����^false Parser>>queryUnassigned {error correction} � ct 11/25/2022 18:31 + queryUnassigned + ����| varStart varName | + ����varName := parseNode key. + ����varStart := self endOfLastToken + requestorOffset - varName size + 1. + ����self selectFrom: varStart to: varStart + varName size - 1 during: [ + ��������(UnassignedVariable name: varName) ifFalse: [^ self fail]]. UnassignedVariable>>openMenuIn: {handling} � ct 11/25/2022 18:31 + openMenuIn: aBlock + + ����self resume: (Project uiManager + ��������confirm: ('{1} appears to be unassigned at this point.\Proceed anyway?' translated withCRs asText + ������������format: {name asText allBold}) + ��������orCancel: [false] + ��������title: 'Unassigned Variable' translated). --- Sent from Squeak Inbox Talk ["UnassignedVariable.1.cs"] -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: UnassignedVariable.1.cs Type: application/octet-stream Size: 3150 bytes Desc: not available URL: From commits at source.squeak.org Fri Nov 25 18:59:10 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 18:59:10 0000 Subject: [squeak-dev] The Trunk: Files-dtl.199.mcz Message-ID: <20221125185913.A422414D83A@mail.squeak.org> David T. Lewis uploaded a new version of Files to project The Trunk: http://source.squeak.org/trunk/Files-dtl.199.mcz ==================== Summary ==================== Name: Files-dtl.199 Author: dtl Time: 25 November 2022, 1:59:09.407907 pm UUID: d67aa170-9fb2-45df-9981-5cd5e6e7e5b9 Ancestors: Files-ct.198 Add ChangeLogStream to allow the changes log to be maintained within the image rather than as an external file. Provide a "Cache changes file" preference for changing the configuration. UTF8 encoding is assumed, and several conversion methods are duplicated from MultiByteFileStream. Inspired by the original Scott Wallace implementation circa 1996, see SystemDictionary>>internalizeChangeLog and SystemDictionary>>internalizeSources in early Squeak images. =============== Diff against Files-ct.198 =============== Item was added: + ReadWriteStream subclass: #ChangeLogStream + instanceVariableNames: 'TextConverter' + classVariableNames: '' + poolDictionaries: '' + category: 'Files-System'! + + !ChangeLogStream commentStamp: 'dtl 11/5/2022 16:22' prior: 0! + A ChangeLogStream is a memory resident changes log, equivalent to the traditional file based changes but not stored on the external file system. UTF8 encoding is assumed for all sources and a UTF8TextConverter is used for reading and writing to the stream. + ! Item was added: + ----- Method: ChangeLogStream>>basicNext:putAll:startingAt: (in category 'private basic') ----- + basicNext: anInteger putAll: aCollection startingAt: startIndex + + ^super next: anInteger putAll: aCollection startingAt: startIndex! Item was added: + ----- Method: ChangeLogStream>>basicNextPut: (in category 'private basic') ----- + basicNextPut: char + + ^ super nextPut: char. + ! Item was added: + ----- Method: ChangeLogStream>>basicNextPutAll: (in category 'private basic') ----- + basicNextPutAll: aString + + ^ super nextPutAll: aString. + ! Item was added: + ----- Method: ChangeLogStream>>converter (in category 'converting') ----- + converter + "Assume UTF8 for all sources" + + ^TextConverter ifNil: [TextConverter := UTF8TextConverter new].! Item was added: + ----- Method: ChangeLogStream>>isReadOnly (in category 'testing') ----- + isReadOnly + ^false! Item was added: + ----- Method: ChangeLogStream>>nextChunkText (in category 'fileIn/Out') ----- + nextChunkText + "Deliver the next chunk as a Text. Decode the following ]style[ chunk if present. Position at start of next real chunk." + + ^self converter nextChunkTextFromStream: self! Item was added: + ----- Method: ChangeLogStream>>nextPut: (in category 'accessing') ----- + nextPut: aCharacter + + ^self converter nextPut: aCharacter toStream: self! Item was added: + ----- Method: ChangeLogStream>>nextPutAll: (in category 'accessing') ----- + nextPutAll: aCollection + + ^self converter nextPutAll: aCollection toStream: self! Item was added: + ----- Method: ChangeLogStream>>readOnlyCopy (in category 'converting') ----- + readOnlyCopy + ^ self! Item was added: + ----- Method: ChangeLogStream>>reopen (in category 'converting') ----- + reopen + ^self! Item was changed: SequenceableCollection subclass: #SourceFileArray instanceVariableNames: '' + classVariableNames: 'CachedChanges' - classVariableNames: '' poolDictionaries: '' category: 'Files-System'! !SourceFileArray commentStamp: '' prior: 0! This class is an abstract superclass for source code access mechanisms. It defines the messages that need to be understood by those subclasses that store and retrieve source chunks on files, over the network or in databases. The first concrete subclass, StandardSourceFileArray, supports access to the traditional sources and changes files. Other subclasses might implement multiple source files for different applications, or access to a network source server.! Item was added: + ----- Method: SourceFileArray class>>cachedChanges (in category 'internalize changes') ----- + cachedChanges + "When present, CachedChanges replaces the traditional external changes + file with an internal stream in the image." + ^CachedChanges! Item was added: + ----- Method: SourceFileArray class>>changeLogContents (in category 'internalize changes') ----- + changeLogContents + | changes fs contents | + changes := SourceFiles at: 2. + (changes isKindOf: FileStream) + ifTrue: [[fs := StandardFileStream "Use StandardFileStream, not FileStream concreteStream, to avoid WideString conversion" + readOnlyFileNamed: changes name. + fs binary. + contents := fs upToEnd] + ensure: [fs close]. + "Smalltalk openSourceFiles." + ^ contents asString] + ifFalse: [^ changes contents]! Item was added: + ----- Method: SourceFileArray class>>externalizeChangeLog (in category 'internalize changes') ----- + externalizeChangeLog + "Move the changes log to an external file. This is the traditional packaging, in + which the sources file and changes file are maintained separately from the + image file." + self safeToExportChanges + ifTrue: [ | fs | + [fs := FileStream fileNamed: Smalltalk changesName. + fs binary. + fs nextPutAll: CachedChanges contents. + CachedChanges := nil] + ensure: [ fs close ]. + Smalltalk openSourceFiles]. + ! Item was added: + ----- Method: SourceFileArray class>>internalizeChangeLog (in category 'internalize changes') ----- + internalizeChangeLog + "Move the change log to an internal stream and maintain it within the image. + This configuration may be risky because the record of recently logged changes + is no longer available in a separate external file. If the image file itself becomes + unusable, the recent changes log file will not be available." + (ChangeLogStream with: self changeLogContents) + ifNotNil: [:strm | + CachedChanges := strm. + SourceFiles at: 2 put: CachedChanges]! Item was added: + ----- Method: SourceFileArray class>>internalizeChanges (in category 'internalize changes') ----- + internalizeChanges + + + ^CachedChanges notNil + ! Item was added: + ----- Method: SourceFileArray class>>internalizeChanges: (in category 'internalize changes') ----- + internalizeChanges: internalize + + internalize + ifTrue: [ self internalizeChangeLog ] + ifFalse: [self externalizeChangeLog ].! Item was added: + ----- Method: SourceFileArray class>>safeToExportChanges (in category 'internalize changes') ----- + safeToExportChanges + "Changes log is currently internal, and there is no external changes file with + the name that would be used for saving externally or the user confirms that + it safe to overwrite that existing file. Existing changes file will be removed if + user confirms." + + ^ CachedChanges + ifNil: [ false ] + ifNotNil: [ (FileDirectory default fileExists: Smalltalk changesName) + ifTrue: [ | response | + (response :=self confirm: Smalltalk changesName , ' exists, overwrite?') + ifTrue: [[ FileDirectory default deleteFileNamed: Smalltalk changesName ] + on: Error do: [ self notify: 'cannot delete ', Smalltalk changesName. ^false ]]. + ^ response ] + ifFalse: [true]]. + + ! From commits at source.squeak.org Fri Nov 25 19:00:30 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 19:00:30 0000 Subject: [squeak-dev] The Trunk: System-dtl.1374.mcz Message-ID: <20221125190035.8E49514DA34@mail.squeak.org> David T. Lewis uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-dtl.1374.mcz ==================== Summary ==================== Name: System-dtl.1374 Author: dtl Time: 25 November 2022, 2:00:24.392665 pm UUID: f4b3b5ed-db5c-445a-be6b-3f29ea6552e3 Ancestors: System-dtl.1373 Support use of ChangeLogStream for changes log maintained within the image. =============== Diff against System-dtl.1373 =============== Item was changed: ----- Method: SmalltalkImage>>openSourcesAndChanges:forImage: (in category 'image, changes names') ----- openSourcesAndChanges: changesName forImage: imageName "Open the changes and sources files and install them in SourceFiles. Inform the user of problems regarding write permissions or CR/CRLF mixups." "Note: SourcesName and imageName are full paths; changesName is a local name." | sources changes msg wmsg | msg := 'Squeak cannot locate {1}. Please check that the file is named properly and is in the same directory as this image.'. wmsg := 'Squeak cannot write to {1}. Please check that you have write permission for this file. You won''t be able to save this image correctly until you fix this.'. sources := Smalltalk openSources. sources ifNotNil: [sources setConverterForCode]. + changes := SourceFileArray cachedChanges + ifNil: [Smalltalk openChanges: changesName forImage: imageName]. - changes := Smalltalk openChanges: changesName forImage: imageName. changes ifNotNil: [changes setConverterForCode]. - ((sources == nil or: [sources atEnd]) and: [Preferences valueOfFlag: #warnIfNoSourcesFile]) ifTrue: [Smalltalk platformName = 'Mac OS' ifTrue: [msg := msg , ' Make sure the sources file is not an Alias.']. self inform: (msg format: { 'the sources file named ' , self sourcesName })]. (changes == nil and: [Preferences valueOfFlag: #warnIfNoChangesFile]) ifTrue: [self inform: (msg format: { 'the changes file named ' , changesName })]. ((Preferences valueOfFlag: #warnIfNoChangesFile) and: [changes notNil]) ifTrue: [changes isReadOnly ifTrue: [self inform: (wmsg format: { 'the changes file named ' , changesName })]. ((changes next: 200) includesSubstring: String crlf) ifTrue: [self inform: ('The changes file named {1} has been injured by an unpacking utility. Line endings were changed from Cr to CrLf.

Please set the preferences in your decompressing program to do not convert text files and unpack the system again.' translated format: { changesName }) asTextFromHtml]]. SourceFiles := Array with: sources with: changes! Item was changed: ----- Method: SmalltalkImage>>saveAs: (in category 'sources, changes log') ----- saveAs: newName "Save the image under that new name." newName ifNil:[^ self]. + + (SourceFileArray internalizeChanges or: (SourceFiles at: 2) isNil) ifFalse: - (SourceFiles at: 2) ifNotNil: [self closeSourceFiles; "so copying the changes file will always work" saveChangesInFileNamed: (self fullNameForChangesNamed: newName)]. self saveImageInFileNamed: (self fullNameForImageNamed: newName)! Item was changed: ----- Method: SmalltalkImage>>saveAsNewVersion (in category 'sources, changes log') ----- saveAsNewVersion "Save the image/changes using the next available version number." "Smalltalk saveAsNewVersion" | newName changesName aName anIndex | aName := FileDirectory baseNameFor: (FileDirectory default localNameFor: self imageName). anIndex := aName lastIndexOf: FileDirectory dot asCharacter ifAbsent: [nil]. (anIndex notNil and: [(aName copyFrom: anIndex + 1 to: aName size) isAllDigits]) ifTrue: [aName := aName copyFrom: 1 to: anIndex - 1]. newName := FileDirectory default nextNameFor: aName extension: FileDirectory imageSuffix. changesName := self fullNameForChangesNamed: newName. + (SourceFileArray internalizeChanges or: (SourceFiles at: 2) isNil) ifFalse: [ + "Check to see if there is a .changes file that would cause a problem if we saved a new .image file with the new version number" + (FileDirectory default fileOrDirectoryExists: changesName) + ifTrue: + [^ self inform: - "Check to see if there is a .changes file that would cause a problem if we saved a new .image file with the new version number" - (FileDirectory default fileOrDirectoryExists: changesName) - ifTrue: - [^ self inform: 'There is already .changes file of the desired name, ', newName, ' curiously already present, even though there is no corresponding .image file. Please remedy manually and then repeat your request.']. + self closeSourceFiles; "so copying the changes file will always work" + saveChangesInFileNamed: (self fullNameForChangesNamed: newName) + ]. - (SourceFiles at: 2) ifNotNil: - [self closeSourceFiles; "so copying the changes file will always work" - saveChangesInFileNamed: (self fullNameForChangesNamed: newName)]. self saveImageInFileNamed: (self fullNameForImageNamed: newName) ! From eliot.miranda at gmail.com Fri Nov 25 19:22:42 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri, 25 Nov 2022 11:22:42 -0800 Subject: [squeak-dev] The Trunk: Kernel-ct.1493.mcz In-Reply-To: <20221125172011.EB8BB14D805@mail.squeak.org> References: <20221125172011.EB8BB14D805@mail.squeak.org> Message-ID: Hi Christoph, doh! of course! On Fri, Nov 25, 2022 at 9:20 AM wrote: > Christoph Thiede uploaded a new version of Kernel to project The Trunk: > http://source.squeak.org/trunk/Kernel-ct.1493.mcz > > ==================== Summary ==================== > > Name: Kernel-ct.1493 > Author: ct > Time: 25 November 2022, 6:20:03.170214 pm > UUID: 4ed198f9-d0db-ec40-884f-88826ffae1f5 > Ancestors: Kernel-nice.1492 > > Merges recursive-profaide: > Adds support for recursive process-faithful debugging. Without > this patch, debugging the debugger for a process which sends Processor > activeProcess will have a different effect than running the original > debugger directly. See tests in KernelTests-ct.440 and ToolsTests-ct.117. > > This is kind of a delayed follow-up on Kernel-mt.1381. Thanks to > Marcel for discussing this issue! > > =============== Diff against Kernel-nice.1492 =============== > > Item was changed: > ----- Method: Process>>effectiveProcess (in category 'accessing') ----- > effectiveProcess > + "effectiveProcess is a mechanism to allow process-faithful > debugging. The debugger executes code on behalf of processes, so unless > some effort is made the identity of Processor activeProcess is not > correctly maintained when debugging code. The debugger uses > evaluate:onBehalfOf: to assign the debugged process as the effectiveProcess > of the process executing the code, preserving process identity." > + > + ^effectiveProcess > + ifNil: [self] > + ifNotNil: [:process | > + "Recursive process-faithful debugging. See > DebuggerTests>>#test25RecursiveProcessFaithfulDebugging for a practical > example." > + process effectiveProcess]! > - "effectiveProcess is a mechanism to allow process-faithful > debugging. The debugger executes code > - on behalf of processes, so unless some effort is made the > identity of Processor activeProcess is not > - correctly maintained when debugging code. The debugger uses > evaluate:onBehalfOf: to assign the > - debugged process as the effectiveProcess of the process executing > the code, preserving process > - identity." > - ^effectiveProcess ifNil: [self]! > > > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Fri Nov 25 19:25:24 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri, 25 Nov 2022 11:25:24 -0800 Subject: [squeak-dev] Review Request: UnassignedVariable.1.cs In-Reply-To: References: Message-ID: On Fri, Nov 25, 2022 at 9:43 AM wrote: > *=============== Summary ===============* > > Change Set: UnassignedVariable > Date: 25 November 2022 > Author: Christoph Thiede > > Renames 'undeclared variable' warning to 'unassigned variable' as proposed > by Eliot (emm) in [1]. Note that for now, I'd stick with the vocabulary > #hasDef in ParseNodes as it a) aligns with #hasRef and b) has more than a > few senders. Please report back whether you'd like to see that renamed, too. > Since it's my proposal I shouldn't vote. But thankyou very much for the code!! > > [1] > https://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November/222668.html#:~:text=the%20language%20used%20in%20parser%3E%3E%23queryundefined > > *=============== Postscript ===============* > > CompilerExceptionsTest removeSelector: #testUndefinedVariable > > *=============== Diff ===============* > > *CompilerExceptionsTest>>testUnassignedVariable {tests} · ct 11/25/2022 > 18:31* > + testUnassignedVariable > + > + self > + compiling: 'griffle | goo | ^ goo' > + shouldRaise: UnassignedVariable > + andSelect: [(text allRangesOfRegexMatches: '(?<=\^ )goo') first] > + testing: { > + true -> [self assertSucceeded]. > + false -> [self assertCanceled] }. > + self > + compiling: 'griffle [ | goo | ^ goo ] value' > + shouldRaise: UnassignedVariable > + andSelect: [(text allRangesOfRegexMatches: '(?<=\^ )goo') first] > + testing: { > + true -> [self assertSucceeded]. > + false -> [self assertCanceled] }. > > *Parser>>primaryExpression {expression types} · ct 11/25/2022 18:30 > (changed)* > primaryExpression > hereType == #word > ifTrue: > [parseNode := self variable. > (parseNode isUndefTemp > and: [(#(ifNil: ifNotNil: isNil notNil) includes: here) not > and: [self interactive]]) > ifTrue: > - [self queryUndefined]. > + [self queryUnassigned]. > parseNode nowHasRef. > ^ true]. > hereType == #leftBracket > ifTrue: > [self advance. > self blockExpression. > ^true]. > hereType == #leftBrace > ifTrue: > [self braceExpression. > ^true]. > hereType == #leftParenthesis > ifTrue: > [self advance. > self expression ifFalse: [^self expected: 'expression']. > (self match: #rightParenthesis) > ifFalse: [^self expected: 'right parenthesis']. > ^true]. > (hereType == #string or: [hereType == #number or: [hereType == > #literal or: [hereType == #character]]]) > ifTrue: > [parseNode := encoder encodeLiteral: self advance. > ^true]. > (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) > ifTrue: > [self advance. > parseNode := encoder encodeLiteral: self advance negated. > ^true]. > ^false > > *Parser>>queryUnassigned {error correction} · ct 11/25/2022 18:31* > + queryUnassigned > + | varStart varName | > + varName := parseNode key. > + varStart := self endOfLastToken + requestorOffset - varName size + 1. > + self selectFrom: varStart to: varStart + varName size - 1 during: [ > + (UnassignedVariable name: varName) ifFalse: [^ self fail]]. > > *UnassignedVariable>>openMenuIn: {handling} · ct 11/25/2022 18:31* > + openMenuIn: aBlock > + > + self resume: (Project uiManager > + confirm: ('{1} appears to be unassigned at this point.\Proceed > anyway?' translated withCRs asText > + format: {name asText allBold}) > + orCancel: [false] > + title: 'Unassigned Variable' translated). > > --- > *Sent from **Squeak Inbox Talk > * > ["UnassignedVariable.1.cs"] > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Fri Nov 25 19:28:58 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Fri, 25 Nov 2022 11:28:58 -0800 Subject: [squeak-dev] The Trunk: System-dtl.1374.mcz In-Reply-To: <20221125190035.8E49514DA34@mail.squeak.org> References: <20221125190035.8E49514DA34@mail.squeak.org> Message-ID: Hi David, this seems backwards to me. It seems to me that one would want to cache the sources but keep the changes gfile for crash recovery. Sicne the changes file should mbe empty at the start of a release this would mean that all sources were cached. What am I getting wrong? And how does your scheme do crash recovery, if at all? On Fri, Nov 25, 2022 at 11:00 AM wrote: > David T. Lewis uploaded a new version of System to project The Trunk: > http://source.squeak.org/trunk/System-dtl.1374.mcz > > ==================== Summary ==================== > > Name: System-dtl.1374 > Author: dtl > Time: 25 November 2022, 2:00:24.392665 pm > UUID: f4b3b5ed-db5c-445a-be6b-3f29ea6552e3 > Ancestors: System-dtl.1373 > > Support use of ChangeLogStream for changes log maintained within the image. > > =============== Diff against System-dtl.1373 =============== > > Item was changed: > ----- Method: SmalltalkImage>>openSourcesAndChanges:forImage: (in > category 'image, changes names') ----- > openSourcesAndChanges: changesName forImage: imageName > "Open the changes and sources files and install them in > SourceFiles. Inform the user of problems regarding write permissions or > CR/CRLF mixups." > "Note: SourcesName and imageName are full paths; changesName is a > local name." > | sources changes msg wmsg | > msg := 'Squeak cannot locate {1}. > > Please check that the file is named properly and is in the same > directory as this image.'. > wmsg := 'Squeak cannot write to {1}. > > Please check that you have write permission for this file. > > You won''t be able to save this image correctly until you fix this.'. > > sources := Smalltalk openSources. > sources ifNotNil: [sources setConverterForCode]. > + changes := SourceFileArray cachedChanges > + ifNil: [Smalltalk openChanges: changesName forImage: > imageName]. > - changes := Smalltalk openChanges: changesName forImage: imageName. > changes ifNotNil: [changes setConverterForCode]. > - > ((sources == nil or: [sources atEnd]) > and: [Preferences valueOfFlag: > #warnIfNoSourcesFile]) > ifTrue: [Smalltalk platformName = 'Mac OS' > ifTrue: [msg := msg , ' > Make sure the sources file is not an Alias.']. > self inform: (msg format: { 'the sources file named ' , self sourcesName > })]. > > (changes == nil > and: [Preferences valueOfFlag: > #warnIfNoChangesFile]) > ifTrue: [self inform: (msg format: { 'the changes file > named ' , changesName })]. > > ((Preferences valueOfFlag: #warnIfNoChangesFile) and: [changes > notNil]) > ifTrue: [changes isReadOnly > ifTrue: [self inform: (wmsg format: { 'the > changes file named ' , changesName })]. > > ((changes next: 200) > includesSubstring: String crlf) > ifTrue: [self inform: ('The changes file > named {1} has been injured by an unpacking utility. Line endings > were changed from Cr to CrLf.

Please set the preferences in your > decompressing program to > do not convert text files and unpack the system again.' > translated format: { changesName }) asTextFromHtml]]. > > SourceFiles := Array with: sources with: changes! > > Item was changed: > ----- Method: SmalltalkImage>>saveAs: (in category 'sources, changes > log') ----- > saveAs: newName > "Save the image under that new name." > newName ifNil:[^ self]. > + > + (SourceFileArray internalizeChanges or: (SourceFiles at: 2) isNil) > ifFalse: > - (SourceFiles at: 2) ifNotNil: > [self closeSourceFiles; "so copying the changes file will > always work" > saveChangesInFileNamed: (self > fullNameForChangesNamed: newName)]. > self saveImageInFileNamed: (self fullNameForImageNamed: newName)! > > Item was changed: > ----- Method: SmalltalkImage>>saveAsNewVersion (in category 'sources, > changes log') ----- > saveAsNewVersion > "Save the image/changes using the next available version number." > "Smalltalk saveAsNewVersion" > > | newName changesName aName anIndex | > aName := FileDirectory baseNameFor: (FileDirectory default > localNameFor: self imageName). > anIndex := aName lastIndexOf: FileDirectory dot asCharacter > ifAbsent: [nil]. > (anIndex notNil and: [(aName copyFrom: anIndex + 1 to: aName size) > isAllDigits]) > ifTrue: > [aName := aName copyFrom: 1 to: anIndex - 1]. > > newName := FileDirectory default nextNameFor: aName extension: > FileDirectory imageSuffix. > changesName := self fullNameForChangesNamed: newName. > > + (SourceFileArray internalizeChanges or: (SourceFiles at: 2) isNil) > ifFalse: [ > + "Check to see if there is a .changes file that would cause > a problem if we saved a new .image file with the new version number" > + (FileDirectory default fileOrDirectoryExists: changesName) > + ifTrue: > + [^ self inform: > - "Check to see if there is a .changes file that would cause a > problem if we saved a new .image file with the new version number" > - (FileDirectory default fileOrDirectoryExists: changesName) > - ifTrue: > - [^ self inform: > 'There is already .changes file of the desired name, > ', newName, ' > curiously already present, even though there is > no corresponding .image file. Please remedy > manually and then repeat your request.']. > > + self closeSourceFiles; "so copying the changes file will > always work" > + saveChangesInFileNamed: (self > fullNameForChangesNamed: newName) > + ]. > - (SourceFiles at: 2) ifNotNil: > - [self closeSourceFiles; "so copying the changes file will > always work" > - saveChangesInFileNamed: (self > fullNameForChangesNamed: newName)]. > self saveImageInFileNamed: (self fullNameForImageNamed: newName) > > > ! > > > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Fri Nov 25 19:49:00 2022 From: tim at rowledge.org (tim Rowledge) Date: Fri, 25 Nov 2022 11:49:00 -0800 Subject: [squeak-dev] The Trunk: System-dtl.1374.mcz In-Reply-To: References: <20221125190035.8E49514DA34@mail.squeak.org> Message-ID: <9EA8B42E-2FCC-4CD8-AE87-A7897B30B9A9@rowledge.org> > On 2022-11-25, at 11:28 AM, Eliot Miranda wrote: > > Hi David, > > this seems backwards to me. It seems to me that one would want to cache the sources but keep the changes gfile for crash recovery. Sicne the changes file should mbe empty at the start of a release this would mean that all sources were cached. What am I getting wrong? Generally we don't condense sources for most releases, so the changes does tend to be around. The 5.3 release changes was ~18Mb for example. > And how does your scheme do crash recovery, if at all? I don't think this version of Dave's idea does, which is certainly something I'd like to see. Having the changes 'file' cached in-image is fine but having at least an option to make it write-through to an outside destination would be good. There's a lot of different ways we could do this. Last time I tried a similar approach I made the source pointer stuff be an object that could be a Smallint to point into a file or a String or a link of some sort to something I don't even remember. That meant you could mix'n'match where source came from, which seemed plausibly interesting. You might even make it go via a web service that serves up the source and stores new source & doits in a shareable manner, merging in with some monticello capabilities. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Oxymorons: New classic From christoph.thiede at student.hpi.uni-potsdam.de Fri Nov 25 19:49:27 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Fri, 25 Nov 2022 20:49:27 +0100 Subject: [squeak-dev] Review Request: url-fragment-encoding.1.cs Message-ID: <0cd1047e-f742-4265-aed4-6b4fc272b4f9@MX2018-DAG2.hpi.uni-potsdam.de> Please object within one week before I merge this into the Trunk. Support for text fragments would be pretty useful for SqueakInboxTalk. :-) Best, Christoph =============== Summary =============== Change Set:��������url-fragment-encoding Date:������������25 November 2022 Author:������������Christoph Thiede Fixes encoding and decoding of URL fragments and adds rough support for fragment directives. Adds tests. Concretely, this patch enables the following things: * parse an encoded URL fragment like #See%20also (previously, the fragment was not decoded but encoded again) * print a URL with fragment directive (previously, the directive prefix was also encoded, and text directives were encoded incorrectly) Adds new accessors for fragment parts. Note that there is only rough support for directives at the moment, i.e., we don't do a deep parse of the directive but only make sure that we don't break the directive during decoding and reencoding (see #testAbsoluteHTTP). Improved support might follow in the future, but for now, just let's make it possible to open a URL with fragment directive in your browser. For instance, SqueakInboxTalk/ExternalWebBrowser needs this. Baby steps. ;-). For more details, see: https://wicg.github.io/scroll-to-text-fragment/ =============== Diff =============== FileUrl>>printOn: {printing} � ct 11/25/2022 19:29 (changed) printOn: aStream ����"Return the FileUrl according to RFC1738 plus supporting fragments: ��������'file:///#' ����Note that being '' is equivalent to 'localhost'. ����Note: The pathString can not start with a leading $/ ����to indicate an 'absolute' file path. ����This is not according to RFC1738 where the path should have ����no leading or trailing slashes, and always ����be considered absolute relative to the filesystem." ����aStream nextPutAll: self schemeName, '://'. ����host ifNotNil: [aStream nextPutAll: host]. ����aStream ��������nextPut: $/; ��������nextPutAll: self pathString. - ����fragment ifNotNil: - ��������[aStream - ������������nextPut: $#; - ������������nextPutAll: fragment encodeForHTTP]. + ����self printFragmentOn: aStream. GenericUrl>>printOn: {printing} � ct 11/25/2022 19:29 (changed) printOn: aStream ����aStream nextPutAll: self schemeName. ����aStream nextPut: $:. ����aStream nextPutAll: self locator. - ����self fragment ifNotNil: - ��������[aStream nextPut: $#. - ��������aStream nextPutAll: self fragment]. + ����self printFragmentOn: aStream. HierarchicalUrl>>printOn: {printing} � ct 11/25/2022 19:29 (changed) printOn: aStream ����aStream nextPutAll: self schemeName. ����aStream nextPutAll: '://'. ����self username ifNotNil: [ ��������aStream nextPutAll: self username encodeForHTTP. ��������self password ifNotNil: [ ������������aStream nextPutAll: ':'. ������������aStream nextPutAll: self password encodeForHTTP]. ��������aStream nextPutAll: '@' ]. ����aStream nextPutAll: self authority. ����port ifNotNil: [aStream nextPut: $:; print: port]. ����path do: [ :pathElem | ��������aStream nextPut: $/. ��������aStream nextPutAll: pathElem encodeForHTTP. ]. ����self query isNil ifFalse: [ ��������aStream nextPut: $?. ��������aStream nextPutAll: self query. ]. - ����self fragment isNil ifFalse: [ - ��������aStream nextPut: $#. - ��������aStream nextPutAll: self fragment encodeForHTTP. ]. + ����self printFragmentOn: aStream. Url class>>absoluteFromText: {parsing} � ct 11/25/2022 19:03 (changed) absoluteFromText: aString ����"Return a URL from a string and handle ����a String without a scheme as a HttpUrl." ����"Url absoluteFromText: 'http://chaos.resnet.gatech.edu:8000/docs/java/index.html?A%20query%20#part'" ����"Url absoluteFromText: 'msw://chaos.resnet.gatech.edu:9000/testbook?top'" ����"Url absoluteFromText: 'telnet:chaos.resnet.gatech.edu'" ����"Url absoluteFromText: 'file:/etc/passwd'" ����| remainder index scheme fragment newUrl | ����"trim surrounding whitespace" ����remainder := aString withBlanksTrimmed.���� ����"extract the fragment, if any" ����index := remainder indexOf: $#. ����index > 0 ifTrue: [ - ��������fragment := remainder copyFrom: index + 1 to: remainder size. + ��������fragment := (remainder copyFrom: index + 1 to: remainder size) unescapePercents. ��������remainder := remainder copyFrom: 1 to: index - 1]. ����"choose class based on the scheme name, and let that class do the bulk of the parsing" ����scheme := self schemeNameForString: remainder. ����newUrl := (self urlClassForScheme: scheme) new privateInitializeFromText: remainder. ����newUrl privateFragment: fragment. ����^newUrl Url>>fragmentDirective {fragment} � ct 11/25/2022 19:52 + fragmentDirective + + ����^ self + ��������splitFragmentDirectiveDo: [:fragment :directive | directive] + ��������otherwise: [:fragment | nil] Url>>fragmentDirectivePrefix {private} � ct 11/25/2022 20:40 + fragmentDirectivePrefix + ����"See comment in #splitFragmentDirectiveDo:otherwise:." + + ����^ ':~:' Url>>fragmentWithoutDirective {fragment} � ct 11/25/2022 19:51 + fragmentWithoutDirective + + ����^ self + ��������splitFragmentDirectiveDo: [:fragment :directive | fragment] + ��������otherwise: [:fragment | fragment] Url>>newFromRelativeText: {parsing} � ct 11/25/2022 19:07 (changed) newFromRelativeText: aString ����"return a URL relative to the current one, given by aString. For instance, if self is 'http://host/dir/file', and aString is '/dir2/file2', then the return will be a Url for 'http://host/dir2/file2'" ����"if the scheme is the same, or not specified, then use the same class" ����| newSchemeName remainder fragmentStart newFragment newUrl bare | ����bare := aString withBlanksTrimmed. ����newSchemeName := Url schemeNameForString: bare. ����(newSchemeName isNil not and: [ newSchemeName ~= self schemeName ]) ifTrue: [ ��������"different scheme -- start from scratch" ��������^Url absoluteFromText: aString ]. ����remainder := bare. ����"remove the fragment, if any" ����fragmentStart := remainder indexOf: $#. ����fragmentStart > 0 ifTrue: [ - ��������newFragment := remainder copyFrom: fragmentStart+1 to: remainder size. + ��������newFragment := (remainder copyFrom: fragmentStart+1 to: remainder size) unescapePercents. ��������remainder := remainder copyFrom: 1 to: fragmentStart-1]. ����"remove the scheme name" ����newSchemeName ifNotNil: [ ��������remainder := remainder copyFrom: (newSchemeName size + 2) to: remainder size ]. ����"create and initialize the new url" ����newUrl := self class new privateInitializeFromText: remainder relativeTo: self. ����"set the fragment" ����newUrl privateFragment: newFragment. ����^newUrl Url>>printFragmentOn: {printing} � ct 11/25/2022 20:42 + printFragmentOn: aStream + + ����self fragment ifNil: [^ self]. + ����aStream nextPut: $#. + ���� + ����self + ��������splitFragmentDirectiveDo: [:fragmentWithoutDirective :directive | + ������������| index | + ������������aStream + ����������������nextPutAll: fragmentWithoutDirective encodeForHTTP; + ����������������nextPutAll: self fragmentDirectivePrefix "do not encode!". + ������������(index := directive indexOf: $=) > 0 + ����������������ifTrue: [ "TextDirective" + ��������������������aStream + ������������������������nextPutAll: (directive first: index) "do not encode!"; + ������������������������nextPutAll: ((directive allButFirst: index) + ����������������������������encodeForHTTPWithTextEncoding: 'utf-8' + ����������������������������conditionBlock: [:character | + ��������������������������������"TextDirectiveExplicitChar" + ��������������������������������character isSafeForHTTP and: [('&-,' includes: character) not]])] + ����������������ifFalse: [ "UnknownDirective" + ��������������������aStream nextPutAll: directive encodeForHTTP]] + ��������otherwise: [:totalFragment | + ������������aStream nextPutAll: totalFragment encodeForHTTP]. Url>>splitFragmentDirectiveDo:otherwise: {fragment} � ct 11/25/2022 20:40 + splitFragmentDirectiveDo: fragmentDirectiveBlock otherwise: fragmentBlock + ����"Search the fragment for a directive. If one was found, evaluate fragmentDirectiveBlock with the fragment and the directive separated; if the fragment exists but does not have a directive, evaluate fragmentBlock instead. Note that there is only rough support for directives at the moment, i.e., we don't do a deep parse of the directive but only make sure that we don't break the directive during decoding and reencoding (see #testAbsoluteHTTP). + ���� + ����For more information on fragment directives, see: https://wicg.github.io/scroll-to-text-fragment/" + + ����| directiveIndex | + ����fragment ifNil: [^ nil]. + ���� + ����directiveIndex := fragment findString: self fragmentDirectivePrefix. + ����directiveIndex = 0 ifTrue: [^ fragmentBlock value: fragment]. + ����^ fragmentDirectiveBlock + ��������value: (fragment first: directiveIndex - 1) + ��������value: (fragment allButFirst: directiveIndex - 1 + self fragmentDirectivePrefix size) UrlTest>>testAbsoluteHTTP {tests - absolute urls} � ct 11/25/2022 20:34 (changed) testAbsoluteHTTP ���� - ����url := 'hTTp://chaos.resnet.gatech.edu:8000/docs/java/index.html?A%20query%20#part' asUrl. + ����url := 'hTTp://chaos.resnet.gatech.edu:8000/docs/java/index.html?A%20query%20#a%20part :~:text=text-start%20' asUrl. ����self assert: url schemeName = 'http'. ����self assert: url authority = 'chaos.resnet.gatech.edu'. ����self assert: url path first = 'docs'. ����self assert: url path size = 3. ����self assert: url query = 'A%20query%20'. - ����self assert: url fragment = 'part'. + ����self assert: url fragment = 'a part :~:text=text-start '. + ����self assert: url fragmentWithoutDirective = 'a part '. + ����self assert: url fragmentDirective = 'text=text-start '. + ���� + ����self assert: url asString = 'http://chaos.resnet.gatech.edu:8000/docs/java/index.html?A%20query%20#a%20part%20:~:text=text%2Dstart%20'. UrlTest>>testRelativeHTTP {tests - relative} � ct 11/25/2022 20:03 (changed) testRelativeHTTP ���� ����baseUrl := 'http://some.where/some/dir?query1#fragment1' asUrl. - ����url := baseUrl newFromRelativeText: '../another/dir/?query2#fragment2'. + ����url := baseUrl newFromRelativeText: '../another/dir/?query%202#fragment%202'. - ����self assert: url asString = 'http://some.where/another/dir/?query2#fragment2'. + ����self assert: url asString = 'http://some.where/another/dir/?query%202#fragment%202'. --- Sent from Squeak Inbox Talk ["url-fragment-encoding.1.cs"] -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: url-fragment-encoding.1.cs Type: application/octet-stream Size: 8611 bytes Desc: not available URL: From commits at source.squeak.org Fri Nov 25 20:03:04 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 20:03:04 0000 Subject: [squeak-dev] The Trunk: ToolBuilder-Morphic-ct.322.mcz Message-ID: <20221125200309.B9CB614DA42@mail.squeak.org> Christoph Thiede uploaded a new version of ToolBuilder-Morphic to project The Trunk: http://source.squeak.org/trunk/ToolBuilder-Morphic-ct.322.mcz ==================== Summary ==================== Name: ToolBuilder-Morphic-ct.322 Author: ct Time: 25 November 2022, 9:03:03.384883 pm UUID: d913a7d8-7ecc-684a-aac5-c3c3e4d98b9c Ancestors: ToolBuilder-Morphic-ct.320 Fixes small regression in directory chooser: After typing an invalid path and selecting a valid tree item, the accept button must be enabled again. =============== Diff against ToolBuilder-Morphic-ct.320 =============== Item was added: + ----- Method: DirectoryChooserDialog>>setDirectoryTo: (in category 'directory tree') ----- + setDirectoryTo: dir + + super setDirectoryTo: dir. + + self changed: #canAccept.! From commits at source.squeak.org Fri Nov 25 20:50:34 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Fri, 25 Nov 2022 20:50:34 0000 Subject: [squeak-dev] The Trunk: Morphic-ct.2056.mcz Message-ID: <20221125205042.15F0D14D7DB@mail.squeak.org> Christoph Thiede uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.2056.mcz ==================== Summary ==================== Name: Morphic-ct.2056 Author: ct Time: 25 November 2022, 9:50:29.694279 pm UUID: 530972e6-066d-574c-9b6e-fabcddee4403 Ancestors: Morphic-ct.2055 refactor: Uses existing magic number selectors for MouseButtonEvent>>*buttonChanged. =============== Diff against Morphic-ct.2055 =============== Item was changed: ----- Method: MouseButtonEvent>>blueButtonChanged (in category 'accessing') ----- blueButtonChanged "Answer true if the blue mouse button has changed. This is the third mouse button or cmd+click on the Mac." + ^ whichButton anyMask: self class blueButton! - ^ whichButton anyMask: 1! Item was changed: ----- Method: MouseButtonEvent>>redButtonChanged (in category 'accessing') ----- redButtonChanged "Answer true if the red mouse button has changed. This is the first mouse button." + ^ whichButton anyMask: self class redButton! - ^ whichButton anyMask: 4! Item was changed: ----- Method: MouseButtonEvent>>yellowButtonChanged (in category 'accessing') ----- yellowButtonChanged "Answer true if the yellow mouse button has changed. This is the second mouse button or option+click on the Mac." + ^ whichButton anyMask: self class yellowButton! - ^ whichButton anyMask: 2! From lewis at mail.msen.com Fri Nov 25 20:51:45 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Fri, 25 Nov 2022 15:51:45 -0500 Subject: [squeak-dev] The Trunk: System-dtl.1374.mcz In-Reply-To: References: <20221125190035.8E49514DA34@mail.squeak.org> Message-ID: <20221125205145.GA46487@shell.msen.com> Hi Eliot, On Fri, Nov 25, 2022 at 11:28:58AM -0800, Eliot Miranda wrote: > Hi David, > > this seems backwards to me. It seems to me that one would want to cache > the sources but keep the changes gfile for crash recovery. You can already do that, see the "Cache sources file" preference. > Sicne the > changes file should mbe empty at the start of a release this would mean > that all sources were cached. What am I getting wrong? And how does your > scheme do crash recovery, if at all? > There is no crash recovery. Some earlier discussion (well I suppose it was more of a monologue) is at http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-October/222570.html. The original 1996 implementation is referenced here http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-March/007670.html As Dan said at that time: "It has one wonderful property - you can run for long periods without spinning up the disk of a portable computer. -- and the analogous awful property -- if anything crashes, there's nothing to replay :-( Nowadays we are not so worried about wearing out the bearings on our hard drives, but we do have cases where it is useful to be able to move an image around without carrying extra disk file references along with it. This is definitely /not/ intended for use in distributing Squeak release images. And putting the changes file back out on your file system is just a matter of "SourceFileArray internalizeChanges: false" (a preference). Here are some use cases that are of interest to me: 1) Forking the running VM on Unix with #forkSqueak. The changes file management in this case works by accident, but it really would be better if two or more images were not attempting to share the same changes file on disk. 2) SqueakJS. It would be nice to run an image on SqueakJS without worrying about keeping the associated files with the image. 3) SnapshotServer resume image on another server, one of my hobby projects at http://www.squeaksource.com/SnapshotServer I should note that although the sources file is compressed when the source file is inboarded ("Cache sources file" preference), so such optimization is attempted for "Cache changes file". That might be a topic for some other day. Dave From lewis at mail.msen.com Fri Nov 25 22:10:03 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Fri, 25 Nov 2022 17:10:03 -0500 Subject: [squeak-dev] The Trunk: System-dtl.1374.mcz In-Reply-To: <20221125205145.GA46487@shell.msen.com> References: <20221125190035.8E49514DA34@mail.squeak.org> <20221125205145.GA46487@shell.msen.com> Message-ID: <20221125221003.GA65810@shell.msen.com> On Fri, Nov 25, 2022 at 03:51:45PM -0500, David T. Lewis wrote: > > I should note that although the sources file is compressed when the > source file is inboarded ("Cache sources file" preference), so such > optimization is attempted for "Cache changes file". That might be > a topic for some other day. I meant to say "no such optimization is attempted", sorry for the typo. Dave From lewis at mail.msen.com Sat Nov 26 01:45:40 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Fri, 25 Nov 2022 20:45:40 -0500 Subject: [squeak-dev] The Trunk: System-dtl.1374.mcz In-Reply-To: <9EA8B42E-2FCC-4CD8-AE87-A7897B30B9A9@rowledge.org> References: <20221125190035.8E49514DA34@mail.squeak.org> <9EA8B42E-2FCC-4CD8-AE87-A7897B30B9A9@rowledge.org> Message-ID: <20221126014540.GA88573@shell.msen.com> On Fri, Nov 25, 2022 at 11:49:00AM -0800, tim Rowledge wrote: > > Last time I tried a similar approach I made the source pointer stuff be > an object that could be a Smallint to point into a file or a String or > a link of some sort to something I don't even remember. That meant you > could mix'n'match where source came from, which seemed plausibly > interesting. You might even make it go via a web service that serves > up the source and stores new source & doits in a shareable manner, > merging in with some monticello capabilities. > I think there are a lot of really interesting things that might be done with this idea. I really hope someone picks up on it and tries a few experiments. There is certainly no reason that SourceFiles must have exactly two elements, and no reason that source pointers cannot point to things other than file positions. Dave From jakres+squeak at gmail.com Sat Nov 26 02:05:53 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Sat, 26 Nov 2022 03:05:53 +0100 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <4121d105-f261-4a85-82ef-68201168cbb4@MX2018-DAG2.hpi.uni-potsdam.de> References: <20221123031033.E174A14D821@mail.squeak.org> <4121d105-f261-4a85-82ef-68201168cbb4@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: schrieb am Fr., 25. Nov. 2022, 16:47: > > Example 4, coreutils: ls, cat, and less are all lisping, catastrophic, or > at least less intuitive names IMHO. > Wait, you don't enjoy the joke in "less is more"?! ;-P -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Sat Nov 26 12:50:45 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 26 Nov 2022 12:50:45 0000 Subject: [squeak-dev] The Inbox: Morphic-ct.2057.mcz Message-ID: <20221126125051.5FE6314D7E9@mail.squeak.org> Christoph Thiede uploaded a new version of Morphic to project The Inbox: http://source.squeak.org/inbox/Morphic-ct.2057.mcz ==================== Summary ==================== Name: Morphic-ct.2057 Author: ct Time: 26 November 2022, 1:50:40.467518 pm UUID: 0bc53b37-9fd5-9643-8be1-722f0c6fd475 Ancestors: Morphic-ct.2056 Prevents pluggable buttons without a menu from acting on yellow-click. Why did we never notice this earlier? Yellow-click is for menus only ... =============== Diff against Morphic-ct.2056 =============== Item was changed: ----- Method: PluggableButtonMorph>>mouseUp: (in category 'event handling') ----- mouseUp: evt + evt yellowButtonChanged ifTrue: [^ super mouseUp: evt]. self updateFillStyle: evt. (self containsPoint: evt cursorPoint) ifTrue: [self performAction].! From commits at source.squeak.org Sat Nov 26 14:28:37 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 26 Nov 2022 14:28:37 0000 Subject: [squeak-dev] The Trunk: Installer-Core-ct.453.mcz Message-ID: <20221126142840.8CDE214D7EB@mail.squeak.org> Christoph Thiede uploaded a new version of Installer-Core to project The Trunk: http://source.squeak.org/trunk/Installer-Core-ct.453.mcz ==================== Summary ==================== Name: Installer-Core-ct.453 Author: ct Time: 19 November 2022, 12:05:57.795955 am UUID: d2a0cc9f-69ed-a149-b661-62b19024829a Ancestors: Installer-Core-ct.452 Proposal: Stores API selectors for Metacello in MetacelloStub to avoid UnknownSelector warnings upon initial Metacello usage. E.g., if you evaluate any installation script from the web in a vanilla Squeak image that uses Metacello's #githubUser:project:path: selector, the image will no longer complain about an unknown selector, which sometimes causes confusion in beginners and experts. :-) =============== Diff against Installer-Core-ct.452 =============== Item was added: + ----- Method: MetacelloStub class>>apiSelectors (in category 'support') ----- + apiSelectors + "To avoid UnknownSelector warnings upon initial Metacello usage. Support only. By adding this method, these selectors will already be contained in the symbol table before Metacello is installed." + + "(Metacello selectors , Metacello class selectors) withoutDuplicates sorted" + ^ #(#addStatement:args: #baseline: #bitbucketUser:project:commitish:path: #blueplane: #cacheRepository: #className: #classic #configuration: #croquet: #execute:args: #executorSpec #executorSpec: #fetch #fetch: #filetreeDirectory: #gemsource: #get #githubUser:project:commitish:path: #githubUser:project:path: #ignoreImage #image #impara: #list #load #load: #lock #locked #onConflict: #onConflictUseIncoming #onConflictUseIncoming:useLoaded: #onConflictUseLoaded #onDowngrade: #onDowngradeUseIncoming #onDowngradeUseIncoming: #onLock: #onLockBreak #onLockBreak: #onUpgrade: #onUpgradeUseLoaded #onUpgradeUseLoaded: #onWarning: #onWarningLog #password: #project: #record #record: #register #registrations #registry #renggli: #repository: #repositoryOverrides: #saltypickle: #scriptExecutor #scriptExecutorClass #scriptExecutorClass: #silently #smalltalkhubUser:project: #squeakfoundation: #squeaksource3: #squeaksource: #ss3: #statements #statements: #swa: #swasource: #unlock #unregister #usernam e: #version: #wiresong:) ! From Christoph.Thiede at student.hpi.uni-potsdam.de Sat Nov 26 14:32:12 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Sat, 26 Nov 2022 14:32:12 +0000 Subject: [squeak-dev] The Inbox: System-ct.1374.mcz In-Reply-To: References: <20221119153837.1473E14D781@mail.squeak.org> , Message-ID: Merged. > Maybe remove that second ! while you are at it... I think you were tricked by the mailing service's escaping of exclamation marks. :-) [cid:eb6b914a-8d5e-4763-927c-6d5273e59f01] Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Taeumel, Marcel Gesendet: Montag, 21. November 2022 10:01:05 An: squeak-dev Betreff: Re: [squeak-dev] The Inbox: System-ct.1374.mcz I did not do that by intention to make it clear, what "full name" we actually have. ... Maybe remove that second ! while you are at it... Best, Marcel Am 21.11.2022 00:10:10 schrieb Chris Muller : > Commonly, punctuation marks after a word should have the same bold emphasis as the word before. Agreed. -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: pastedImage.png Type: image/png Size: 46290 bytes Desc: pastedImage.png URL: From commits at source.squeak.org Sat Nov 26 14:32:12 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Sat, 26 Nov 2022 14:32:12 0000 Subject: [squeak-dev] The Trunk: System-ct.1375.mcz Message-ID: <20221126143219.DBCCE14D82E@mail.squeak.org> Christoph Thiede uploaded a new version of System to project The Trunk: http://source.squeak.org/trunk/System-ct.1375.mcz ==================== Summary ==================== Name: System-ct.1375 Author: ct Time: 26 November 2022, 3:32:09.169627 pm UUID: 48f83c02-9051-4c40-b43e-f5aade1bb7ab Ancestors: System-dtl.1374, System-ct.1374 Merges System-ct.1374: Fixes formatting of greeting message when entering author initials. =============== Diff against System-dtl.1374 =============== Item was changed: ----- Method: Utilities class>>setAuthorInitials (in category 'identification') ----- setAuthorInitials "Put up a dialog allowing the user to specify the author's initials. Inform the user about collisions with known contributors. See SystemNavigation class >> #authors. " | newInitials newName | newInitials := Project uiManager request: 'Please type your initials:' translated initialAnswer: AuthorInitials. newInitials ifEmpty: [^ self "No Change"]. (SystemNavigation authorsInverted at: newInitials ifPresent: [:existingNames | newName := existingNames sorted joinSeparatedBy: '/'. + (self confirm: ('Hello, {1}!! :-)

Our
list of known contributors associates the initials you have entered with this name. If this is not you, please consider alternative initials, preferably more than just a few characters, to avoid collisions.

Do you want to use these author initials?

{2}' translated format: { - (self confirm: ('Hello, {1}!! :-)

Our
list of known contributors associates the initials you have entered with this name. If this is not you, please consider alternative initials, preferably more than just a few characters, to avoid collisions.

Do you want to use these author initials?

{2}' translated format: { newName ifNil: [newInitials]. newInitials. 'SystemReporter open model categoryAt: 1 put: true'. "mt: Avoid triggering the Windows Defender. See http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-December/217346.html" 'a' }) asTextFromHtml) ] ifAbsent: [true]) ifTrue: [self authorInitials: newInitials].! From christoph.thiede at student.hpi.uni-potsdam.de Sat Nov 26 14:49:14 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Sat, 26 Nov 2022 15:49:14 +0100 Subject: [squeak-dev] The Inbox: Morphic-ct.2051.mcz In-Reply-To: References: <20221119193609.AB3AA14D7C5@mail.squeak.org>, Message-ID: <99b480f3-9917-4df3-b1a1-63d582536ec5@MX2018-DAG2.hpi.uni-potsdam.de> Hi Marcel, > If you care for it, go ahead and merge it. I really think that the invalidated instruction text provides a poor experience ... > You should also mention that you also decided on some visual updates in the form of border etc. I'm sorry, I forgot that. My goal was to align the look with regular pluggable text morphs & Co. > Yet, notice the extra complexity in the form of two new instVars etc. That was one of the reasons I did not do it. :-) Hm ... that touches on our common conflict between "minimal implementation" and "convenient UI" again, I think. Would there be frameworks in a perfect world where these two aspects would not contradict each other at all? In some previous discussions, I opted for prioritizing "convenient UI" because the main usage of any tool or widget still is to be *use* it, not to study its implementation. If we want to have simple exemplary implementations for teaching and documentation purposes, maybe we should maintain them separately from "production code"? Apart from that, the most interesting documentational aspect of the KeyboardExerciser seems to me to be its event handling implementation, which I did not touch. Best, Christoph --- Sent from Squeak Inbox Talk On 2022-11-21T11:04:24+01:00, marcel.taeumel at hpi.de wrote: > If you care for it, go ahead and merge it. Yet, notice the extra complexity in the form of two new instVars etc. That was one of the reasons I did not do it. :-) > > You should also mention that you also decided on some visual updates in the form of border etc. I did not use that by intention as well ;-) > > Best, > Marcel > Am 19.11.2022 20:36:17 schrieb commits at source.squeak.org : > Christoph Thiede uploaded a new version of Morphic to project The Inbox: > http://source.squeak.org/inbox/Morphic-ct.2051.mcz > > ==================== Summary ==================== > > Name: Morphic-ct.2051 > Author: ct > Time: 19 November 2022, 8:35:59.299387 pm > UUID: 6d037f4d-9ad4-8f48-8a0b-b40df261c00c > Ancestors: Morphic-mt.2049 > > Makes keyboard exerciser scale-factor-aware. Fixes layout of instruction text, which was previously not wrapped within the morph, overlapped the check buttons, and caused invalidations when moving or closing the exerciser. For this, uses a classical row-based tabel layout. > > =============== Diff against Morphic-mt.2049 =============== > > Item was changed: > Morph subclass: #KeyboardExerciser > + instanceVariableNames: 'checkButtons eventPane' > - instanceVariableNames: '' > classVariableNames: '' > poolDictionaries: '' > category: 'Morphic-Demo'! > > Item was added: > + ----- Method: KeyboardExerciser>>addCheckButtons (in category 'initialization') ----- > + addCheckButtons > + > + | buttonPane | > + buttonPane := Morph new > + beTransparent; > + changeTableLayout; > + hResizing: #spaceFill; > + vResizing: #shrinkWrap; > + listDirection: #leftToRight; > + wrapDirection: #topToBottom; > + cellGap: 10 px; > + yourself. > + > + checkButtons := OrderedCollection new. > + #(processKeyStroke 'Test key stroke' > + processKeyDown 'Test key down' > + processKeyUp 'Test key up') > + groupsDo: [:selector :label | > + | button | > + button := ThreePhaseButtonMorph checkBox > + target: self; > + actionSelector: selector; > + label: label; > + yourself. > + checkButtons addLast: button. > + buttonPane addMorphBack: button]. > + > + self addMorphBack: buttonPane. > + ^ buttonPane! > > Item was added: > + ----- Method: KeyboardExerciser>>addEventPane (in category 'initialization') ----- > + addEventPane > + > + eventPane := Morph new > + beTransparent; > + changeTableLayout; > + listDirection: #leftToRight; > + wrapDirection: #topToBottom; > + hResizing: #spaceFill; > + vResizing: #shrinkWrap; > + cellGap: 10 px; > + height: 0; > + yourself. > + > + self addMorphBack: eventPane. > + ^ eventPane! > > Item was added: > + ----- Method: KeyboardExerciser>>addTitle (in category 'initialization') ----- > + addTitle > + > + | title | > + title := TextMorph new > + contents: 'Move your mouse cursor to here and start typing. Try modifiers, too.' translated; > + font: Preferences standardButtonFont; > + color: Color gray; > + hResizing: #spaceFill; > + lock; > + yourself. > + > + self addMorphBack: title. > + ^ title! > > Item was changed: > ----- Method: KeyboardExerciser>>checkButton: (in category 'initialization') ----- > checkButton: checkIndex > > + self checkButtons do: [:button | > + button state: #off]. > - 1 to: 3 do: [:index | > - (self submorphs at: index) > - state: #off]. > > + (self checkButtons at: checkIndex) state: #on.! > - (self submorphs at: checkIndex) state: #on.! > > Item was added: > + ----- Method: KeyboardExerciser>>checkButtons (in category 'accessing') ----- > + checkButtons > + > + ^ checkButtons! > > Item was changed: > ----- Method: KeyboardExerciser>>clear (in category 'initialization') ----- > clear > > + eventPane removeAllMorphs. > + eventPane height: 0.! > - (self submorphs allButFirst: 3) do: [:m | m delete].! > > Item was removed: > - ----- 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.' translated > - at: self topLeft > - font: Preferences standardButtonFont > - color: Color gray.! > > Item was added: > + ----- Method: KeyboardExerciser>>eventMorphs (in category 'accessing') ----- > + eventMorphs > + > + ^ eventPane submorphs! > > Item was changed: > ----- Method: KeyboardExerciser>>handleEvent:inspect: (in category 'actions') ----- > handleEvent: mouseEvent inspect: morph > > + mouseEvent shiftPressed > - mouseEvent shiftPressed > ifTrue: [(morph valueOfProperty: #event) explore] > ifFalse: [(morph valueOfProperty: #event) inspect].! > > Item was changed: > ----- Method: KeyboardExerciser>>initialize (in category 'initialization') ----- > initialize > > super initialize. > > self > + color: ((self userInterfaceTheme get: #color for: #ScrollPane) ifNil: [Color white]); > + borderStyle: ((self userInterfaceTheme get: #borderStyle for: #ScrollPane) ifNil: [BorderStyle simple]) copy; > + borderColor: ((self userInterfaceTheme get: #borderColor for: #ScrollPane) ifNil: [Color gray: 0.6]); > + borderWidth: (((self userInterfaceTheme get: #borderWidth for: #ScrollPane) ifNil: [1]) * RealEstateAgent scaleFactor) truncated; > + extent: 300 px @ 50 px; > - color: (self userInterfaceTheme get: #color for: #ScrollPane); > - extent: 300 at 50; > layoutPolicy: TableLayout new; > + listDirection: #topToBottom; > - listDirection: #leftToRight; > - wrapDirection: #topToBottom; > hResizing: #rigid; > vResizing: #shrinkWrap; > + cellGap: 10 px; > + layoutInset: 20 px; > - cellGap: 10; > - layoutInset: 20; > yourself. > > + self addTitle. > + self addCheckButtons. > + self addEventPane. > - #(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>>instructionMorph (in category 'accessing') ----- > + instructionMorph > + > + ^ self hasSubmorphs ifTrue: [self firstSubmorph]! > > Item was changed: > ----- Method: KeyboardExerciser>>lastEvent (in category 'accessing') ----- > lastEvent > > | view event | > + view := (self eventMorphs ifEmpty: [^ nil]) last. > - view := self submorphs last. > (view hasProperty: #event) ifFalse: [^ nil]. > event := view valueOfProperty: #event. > event isCollection ifTrue: [event := event last]. > ^ event! > > Item was changed: > ----- Method: KeyboardExerciser>>logEvent: (in category 'event handling') ----- > logEvent: evt > > | eventMorph | > evt = self lastEvent > ifTrue: [^ self logEventRepetition: evt]. > > eventMorph := evt asMorph. > eventMorph > setProperty: #event toValue: evt copy; > balloonText: ('Click to inspect. Shift+click to explore.\\Virtual key: {8}\Virtual modifiers: {5}\\Physical key: {9}\Physical modifiers: {6}\\Key value: 0x{1} ({2}) \Key character: {3}\Key string: {4}\\{7}' translated withCRs format: { > evt keyValue printPaddedWith: $0 to: 2 base: 16. > evt keyValue. > evt isKeystroke ifTrue: [evt keyCharacter printString] ifFalse: ['-']. > evt isKeystroke ifTrue: [evt keyString printString] ifFalse: ['-']. > (evt virtualModifiers joinSeparatedBy: ' ') asUppercase. > (evt physicalModifiers joinSeparatedBy: ' ') asUppercase. > evt printString. > evt virtualKey printString. > evt physicalKey asString printString}). > > eventMorph > on: #mouseEnter send: #handleEvent:emphasize: to: self; > on: #mouseLeave send: #handleEvent:deemphasize: to: self; > on: #mouseDown send: #handleEvent:inspect: to: self. > > + eventPane addMorphBack: eventMorph.! > - self addMorphBack: eventMorph.! > > Item was changed: > ----- Method: KeyboardExerciser>>logEventRepetition: (in category 'event handling') ----- > logEventRepetition: evt > > | label lastEvents box | > + (self eventMorphs last hasProperty: #repetition) > + ifTrue: [box := self eventMorphs last. label := box submorphs first] > - (self submorphs last hasProperty: #repetition) > - ifTrue: [box := self submorphs last. label := box submorphs first] > ifFalse: [ > box := Morph new > setProperty: #repetition toValue: true; > color: Color transparent; > layoutPolicy: TableLayout new; > hResizing: #shrinkWrap; > vResizing:#shrinkWrap; > yourself. > label := '' asText asMorph lock. > box addMorph: label. > box setProperty: #event toValue: (OrderedCollection with: self lastEvent). > + eventPane addMorphBack: box]. > - self addMorphBack: box]. > > lastEvents := box valueOfProperty: #event. > lastEvents add: evt copy. > box setProperty: #event toValue: lastEvents. > > label newContents: (('x ', (lastEvents size)) asText > addAttribute: (TextFontReference toFont: Preferences standardButtonFont); > yourself). > box balloonText: ('{1}{2}' format: { > lastEvents size > 10 ifTrue: ['... {1} older events and:\' translated withCRs format: {lastEvents size - 10}] ifFalse: ['']. > (lastEvents last: (10 min: lastEvents size)) joinSeparatedBy: String cr. > }). > > box > on: #mouseEnter send: #handleEvent:emphasize: to: self; > on: #mouseLeave send: #handleEvent:deemphasize: to: self; > on: #mouseDown send: #handleEvent:inspect: to: self.! > > > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Sat Nov 26 16:57:41 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sat, 26 Nov 2022 08:57:41 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <093B4101-F5ED-4136-ABD8-2AD705722929@gmx.de> References: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> <093B4101-F5ED-4136-ABD8-2AD705722929@gmx.de> Message-ID: Hi Tobi, On Thu, Nov 24, 2022 at 12:18 PM Tobias Pape wrote: > Hi Eliot > > First things first, I did not raise objections in my admittedly short quip. > > > > On 24. Nov 2022, at 20:23, Eliot Miranda > wrote: > > > > Hi Tobi, > > > > let me try again (https://youtu.be/Cj8n4MfhjUc)… > > :D > > I already got my comfy chair! > > > > >> On Nov 23, 2022, at 12:23 PM, Tobias Pape wrote: > >> > >> Yet, nil is only seldom a good domain object. > > > > Precisely. Being disjoint from any domain it is the ideal “I am not a > domain object” marker. So when one wants a variable to range over a domain > and the singleton “not a member of the domain” nil is a great choice. And > that’s exactly how I use it below. > > Second things second, I got that. > > > > > There is another excellent marker of a non-domain object, and that is a > newly instantiated object. That object is known to not be any other object, > since objects are unique. So if code is searching for something (eg > applying a block to every literal in the system), having the newly > instantiated object that implements the search use itself as the “I’m not > in the domain of all pre-existing objects” is a sensible choice. This is > the pattern InstructionStream uses when scanning for selectors. > > And #someObject/#nextObject. > I get that. And it is actually a beautiful thing you cannot do > everywhere[0]. > > My fear is as follows: > > I hope we can agree that "nil" is part of the "system domain" of > Smalltalk, or - said differently - the meta-level. > > So are the concepts of variables, classes etc. > Yes, and equally, for example, collections. The Set instance in a set of accounts is not part of the domain because it's not specific to the domain. It comes from the Smalltalk library. But so what? This feels like a straw man to me. One could argue that an account object itself is not part of the domain, but part of the model of the domain, etc. In the end nil is an object that is useful and well-defined. It isn't special, just like true & false aren;t special, or that classes being objects aren't special. Instead these are all functional relationships that allow us to construct a system that is malleable and comprehensible. > The non-meta, base, or "domain proper" layer can be anything you want to > computationally achieve.[1] > Let's arbitrarily chose finance[2]. > > A domain object would be an account, a transaction, an account holder, etc. > (Note that we can chose how to represent each, and we do not necessarily > need objects for each, but I digress). > > My take: in code dealing with such domain objects, nil should appear next > to never, because it is an object from the Metalevel. > I don't agree. nil can serve as an absence, and absences are important. In any query which can yield no results we have three choices: - answer nil (e.g. at end of stream) - raise an exception - require passing in a continuation to take in the event of an error (e.g. the block argument to at:ifAbsent: or the second one to detect:ifNone: etc) Often nil is lighter-weight, much more concise, and hence more comprehensible, hence to be preferred. The problems with accepting nil as the general "nothing to see" marker > include: > > - There are too many. > In our example, an account holder could have an instVar "account" which > could be nil when not having an account yet, BUT ALSO > an account could have a "closingDate" for when the account folded, which > is "nil" when the account is still open, AND ALSO, a transaction could have > an "auditor" which is nil as long as no audit has taken place etc. > Just like that, nil takes _different roles_ just by being convenient. > As do the integers, symbols, collections. As do classes. Should we have different kinds of classes for the class library, the meta level, the domain model? Or is it sufficient to have classes, metaclasses and traits? i.e. do we need to label things according to their use, or is it sufficient to differentiate them purely by function? I think the latter. - Nil has problematic provenance. > When somewhere during debugging (the all-known MNU for UndefinedObject) > a nil pops up, it is often reallllly hard to say whence it came from. > So dealing with a lot of nil-bearing code will send you down rabbit > holes after the other. > Whereas NaN doesn't have problematical provenance? Or getting an identically-valued instance with a different identity, or a host of other potential evils.... These are not specific to nil, and not specific to using nuil as a marker of absence, or as bottom. Programming is tricky; we have lots of ways of doping things; things happen very fast; code does what tou tell it, not what you want it to do. We find we make mistakes all the time. This is not specific to the use of nil in our domain models. > - Nil begets polymorphism, nil defies polymorphism. > It is one of the most awesome feats of Smalltalk that nil is NOT like > NULL, in that it can respond to messages. That is exceptionally powerful > and has given Smalltalk a lot of resilience. > But cluttering UndefinedObject with custom, even domain-specifc methods > is a really bad idea. However, that means > it is often unwise to just have object that could be nil be sent > arbitrary messages. > Hence a multitude of #isNil/#ifNil-Checks. Proper domain objects that > model absence, pre-valid state, or error conditions can deal much better > with that. > When it's possible then fine. But in the query example above we must be able to deal with absence/have an element disjoint from a domain. And nil functions ideally for this case. - Nil is in a collection-superposition (just like your good old USB-A plug > which you have to turn at least twice to fit). > You only know whether nil _actually_ could be a collection when you know > that a non-nil object in its place is a collection [3]. > Said differently: in contrast to LISPy languages, our nil is _by design_ > no collection, while LISPy null _by design_ IS the empty list. > This makes for funny messages like #isEmptyOrNil, which bails on > non-nil-non-collection objects. > So every time you have to deal with nil, you automatically at lease > once have to answer the question "could the non-nil version of this object > be a collection"? > Many uses of isEmptyOrNil are in response to FillInTheBlank which can return nil on cancel or an empty string if the user doesn't type anything. This is a natural consequence of the affordances of FillInTheBlank, and isEmptyOrNil is simply a pragmatic response, hardly a symptom of some deep problem. > There are a lot of interesting approaches to each or combinations of these > issues. > This includes Null-Object patterns, Sane-default-initializers, exceptions, > or explicit models of multiplicity[4]. > > But back to the beginning. > > In code that does, for example > > blaFooAnAccount > > | fooAccount | > self accounts processBla: > [:ea | > fooAccount ifNil: [fooAccount := ea]. > fooAccount := (ea doesBork: fooAccount) > ifTrue: [fooAccount] > ifFalse: [ea]] > ^ fooAccount > > we find two things: > I think we find three things. The things you8 list below, plus the fact that this should have been written using detect:ifNone: ;-) > > First, we could inadvertently return nil from that method. But this is > technical and I think most here can deal with that. > > But second, the line "fooAccount ifNil: [fooAccount := ea]." ACTUALLY says > > "if fooAccount is an uninitialized temporary variable, populate it". > > This is technically correct, but conflates domains. > In our world of finance, the idea of a "temporary variable" does no make > sense. It is part of the meta-level domain, the system. > > I don't say this is wrong _per se_ but people reading, and even more so, > people writing such code > MUST be aware that they are crossing domains, and especially, entering a > meta level. > > That's why I think these warnings are really ok. > I won't fight the commit "Compiler-eem.480.mcz", especially since it more > or less is descriptive of a pervasive style of writing Smalltalk of Squeak > Core contributors. > > I hope people find theses ideas useful. > > Best regards > -Tobias > > > [0]: I've used it in Python code to much joy. > [1]: Caveat lector: the "domain layer" can surely be the "system layer". > In fact that is what a lot of system code deals with. > But this is messy for our considerations above and lets treat it as > _exceptional_. > [2]: Semi-arbitrarly, just because I received my tax returns :P > [3]: yes, that is a strange sentence. It's late. Also, Ardbeg. > [4]: For example, as in the work of Steimann ( > https://dl.acm.org/doi/10.1145/2509578.2509582 ). It seems they had a > Smalltalk implementation in 2017. > > > > > >> -t > >> > >>> On 23. Nov 2022, at 19:34, tim Rowledge wrote: > >>> > >>> I won't quote it all again but what Eliot wrote is important. There > are good solid reasons why Smalltalk has a rigorously defined > UndefinedObject. We demand rigorously defined areas of doubt and > uncertainty! > >>> > >>> tim > > > > > > _,,,^..^,,,_ (phone) > > > > > > -- _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Sat Nov 26 17:37:09 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sat, 26 Nov 2022 09:37:09 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: <4121d105-f261-4a85-82ef-68201168cbb4@MX2018-DAG2.hpi.uni-potsdam.de> References: <20221123031033.E174A14D821@mail.squeak.org> <4121d105-f261-4a85-82ef-68201168cbb4@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: Hi Christoph, On Fri, Nov 25, 2022 at 7:47 AM wrote: > Hi Eliot, > > thanks for the great discussion. Your reply cleared a lot of things up for > me -- I very much agree that the default value of any variable is not > "undefined", but specifically nil. > > What I still find an interesting trade-off is that of "implicit vs > explicit" aka "terseness vs readability". I think its solution depends on > the typical readers of the code I am writing. If they are Squeak Core > developers or VM developers, I can assume that they know the default value > for any variable. For unexperienced programmers, I hope they do know. > Still, it's easier for anyone to forget if it's not explicitly written > down. Yes, I can translate | a | to | a *:= nil* | in my head, but that > also might be a tiny portion of mental overhead. > Right. One of the design principles of Smalltalk, one of its more important design principles, is to use the least amount of rules possible (but no fewer) and apply them consistently. This applies, for example, to Maxwell's equations, right? It is a critical attribute of good scientific models, good legal systems, good road traffic laws, not just good programming languages. Finding a small set of easily memorable rules, or principles, that are orthogonal and cohere to provide a calculus which can be used to construct or predict behaviour or consequence, is a delight and a blessing. There was one rule in Smalltalk that was awful; that was a result of the implementation showing through, (that IIRC got into the ANSI standard), that we fixed. That was that the value of an empty block that took arguments, was the value of the last argument. So [:a :b|] value: 1 value: 2 would evaluate to 2. Thankfully this has been fixed and the value of an empty block is always nil, irrespective of its arguments. ColorArray new: n is not something that needs to be fixed, or alarmed at. It can be experienced (I discovered it this last week, I was not astonished). I wager you will never forget that the default value of a ColorArray indexed instance variable is Color transparent. You may even use it in your teaching as an amusing and interesting example for the initialization rule. I doubt that it would tax any new Smalltalker that has already encountered bits collections, and would serve to help them remember the initialize-with-zero sub-rule. Example 2, ColorArray: My first take would be indeed be to favor ColorArray > new: 256 withAll: Color transparent over ColorArray new: 256, because I > have never used this class before and would not be sure whether the values > default to black or transparent or anything else. I could look it up, but I > would likely forget it several times before remembering. Why should I do > this to myself (and to any other non-ColorArray expert)? > The thing about ColorArray that's important to our discussion is that a new instance is initialized; it doesn't contain random crap. This is the point about initialization that applies to all Smalltalk variables, temporary, global, named instance, and indexed instance. We have one rule, if the variable holds pointers it is initialized by nil, if the variable holds bits it is initialized with the all-zeros bit string. This has some unexpected consequences such as (ColorArray new: 10) anyOne = Color transparent, but the nice thing is that the rule is very easy to learn, and so when one discovers (ColorArray new: 10) anyOne = Color transparent one is not astonished. [the principle of least astonishment) > Example 3, point arithmetic: Here I'm completely with you, but maybe I'm > also biased because I have already spent some time working with visual > domains in Squeak. :-) > :-) indeed! > Example 4, coreutils: ls, cat, and less are all lisping, catastrophic, or > at least less intuitive names IMHO. Most of us will have got familiar with > them, but from a Smalltalk perspective that is seeking for readability, I > still would favor them to be named ListFiles, PrintFile, and > OpenFileForRead. On the contrary, many people who are used the present > nomenclature would dismiss these proposals as hard to write and maybe even > hard to read. Is "terseness vs readability" as this syntactical point > really a matter of data (code) quality (that must be ensured by the > writer), or more a matter of the right tooling (that can be adjusted by the > editor/reader)? > Learning to play a musical instrument, learning to wield a golf club, learning to drive a car, ride a bike, accumulate any useful skill, involves a tradeoff. Masterful use always drops the training wheels. Eventually we always advance to using a functionally efficient interface and/or set of skills. This makes like hard for the learner. They have to acquire the skills that allow them to reach competence on their way to mastery. But we do not serve ourselves by preventing mastery, by protecting us against mastery. If we do, we end up with inexpressive music, shirt and unexciting drives, 30 kph autobahns, 70 kg bikes that don;'t lean in the corners. The Prussian Model of Education was set up under Bismark, its intent being to produce a generation of easily ruled consumers and cannon fodder. Its means were to teach badly, to render its subjects insecure, consciously inferior to those educated in elite private schools. This model was adopted by th eUS senate immediately after the civil war as the blueprint for the US's public education system. It serves as the ideal instrument of oppression in faux democracies. [I was incredibly fortunate that it was not used in my public primary school; unsurprisingly, teachers that love children hate the Prussian Model]. Driving a child to school, rather than having them walk, and/or catch a bus, results in an adult less at ease moving around the city. It infantilises them. It constrains them their whole lives. Wittgenstein's realisation was that language means what we collectively decide it means, not what it is defined to mean, and the fact that a substantial number of American adults think that "inflammable" means the opposite of "flammable" is alarming, an example that militates for better teaching, not Newspeak. If we are to live meaningful, rich, lives that enrich those of others, we must enculturate, we must take off the training wheels, we must fashion that which is concise, powerful and call it elegant. --- > > > I want a warning for the usage of b in "c := b", "d" in "#(1 2 3) > sorted: d", g in "g perform: #ifNotNil: with: [b := g]". I *don't* want to > be told about a in "a ifNil: [a := 1]", c in "c ifNil: [c := 3]", or e & f > in "(e isNil or: [f isNil]) ifTrue: [e := f := 6]". > > Thank you for clarification. So the idea of #queryUndefined (will rename > that) is to fix human forgetfulness. Yes. > In the second group of examples, you explicitly consider these variables > being nil, so you don't need a reminder from the compiler (or with regards > to Tobi's argument, you're already dealing with the meta-level). In the > first group of examples, one could say that you are covering tracks of your > own possible forgetfulness and spreading possibly unsassigned values, so > it's more important for the tooling to point you to that possible slip. > Yes, I guess now that makes more sense to me. :-) > Cool. > > Still, the scope of this warning remains a bit blurry for me. Maybe that's > because we are approximating a type analysis engine here with a *very* > rough heuristic. I think that's exactly why. > For instance: > > | a | > a ifNotNil: [a *:=* a + 1]. > ^ a > > In this example, I do *not* want a warning for "a + 1" but I *do* want a > warning for "^ a" as a still might be unassigned. Currently, the reality > is just the other way around. But that is probably out of scope for the > current architecture ... > I love the pragmatic design principle from the LRG/SCG at PARC that I was taught on arrival at ParcPlace Systems: don't let the perfect be the enemy of the good. It's ok to have 95% of the solution. (As a side note, some other confusing thing around this notification for me > is the fact that our compiler essentially integrates a few rudimentary > linter tools (namely, UndefinedVariable and UnknownSelector) and forces the > user to interact with them in a modal fashion. To be honest, I never liked > that "modal linter style" and often wish we had some more contemporary > annotation-/wiggle-line-based tooling for that. +1000 !!!!! Thanks for pointing this out. This is an excellent suggestion. I *hate* clicking on the "declare as a foo variable" dialog for a sequence of as-yet-undeclared temp vars, only to hit a lint rule, or syntax error, and have all those declarations discarded. > My typical interaction with #queryUndefined looks like this: me: accept > new code, compiler: you did not assign foobar, me: oops, you're right, let > me fix that; or alternatively: yes, that was intended, let me explicate > that. Ignoring and proceeding from this warning has never felt acceptable > for me as this would put the same confusion on any future editor of the > method.) > > > :-) Hope I'm not too strident :-) > > No problem, it was very interesting and I learn a lot from your replies. > :-) > > Best, > Christoph > > --- > *Sent from **Squeak Inbox Talk > * > > On 2022-11-22T23:36:09-08:00, eliot.miranda at gmail.com wrote: > > > Hi Christoph, Hi Marcel, > > > > apologies about the font size mismatches... > > > > On Wed, Nov 23, 2022 at 2:25 AM Marcel Taeumel > > > wrote: > > > > > Hi Christoph -- > > > > > > > IMHO, it unnecessarily complicates the simple Smalltalk syntax. [...] > > > > > > Nah, this is just a tooling change, not a syntactical one. > > > > > > > +1 > > > > > > > > Yes, I would like to have this info skipped for #isNil as well. Note > that one > > > should not use #ifNotNilDo: anymore. > > > > > > > Good idea. I'll include it. > > > > > > > > Best, > > > Marcel > > > > > > Am 23.11.2022 11:00:43 schrieb Thiede, Christoph < > > > christoph.thiede at student.hpi.uni-potsdam.de>: > > > > > > Hi Eliot, hi all, > > > > > > > > > I'm skeptical about this change, as it creates or expands a special > role > > > of the selectors #ifNil:, #ifNotNil:, and their combinations. IMHO, it > > > unnecessarily complicates the simple Smalltalk syntax. While I know and > > > sometimes dislike these UndefinedVariable notifications, too, I don't > know > > > whether differentiating them by the selector is the right strategy > > > to improve this situation. > > > > > > Please indulge me. It's f***ing irritating to be told by the compiler > > that as temp var appears to be uninitialized when one is intentionally > > using the fact that temps are initialized to nil. And that temp vars are > > initialized to nil is a) essential knowledge and b) a good thing (no > > uninitialized local variables a la C, a sensible value to initialize a > > variable with). > > > > BTW, I find it more than sad (a little alarming in fact) that > > someSmalltalkers don't know that the value of several conditionals that > > take blocks is nil when the condition doesn't select the block. e.g. > false > > ifTrue: [self anything] is nil. I see "expr ifNotNil: [...] ifNil: [nil]" > > and it strikes me as illiterate. I recently visited code written by a > > strong programmer who open coded a lot of point arithmetic, decomposing > > e.g. a * b into (a x * b x) @ (a y * b y). It's bad. It gradually > > degrades the code base in that it isn't always an exemplar of best > > practice, > > > > > > > > Consider the following examples: > > > > > > > > > | a b c d e f g h | > > > a ifNil: [a := 1]. > > > c := b. > > > c ifNil: [c := 3]. > > > #(1 2 3) sorted: d. > > > e := 5. > > > (e isNil or: [f isNil]) ifTrue: [e := f := 6]. > > > g perform: #ifNotNil: with: [b := g]. > > > h ifNotNilDo: [h := 8]. > > > > > > How would you explain to a naive Smalltalker which of these variables > will > > > be marked as undefined at this point and why? (Of course, you can > explain > > > it by pointing to the implementation, but I think that's a > significantly > > > less intuitive explanation than just saying "you must declare any > variable > > > before using it".) > > > > > > > > No. It's a hard-and-fast rule that all temp vars are initialized to nil. > > And initializing a variable (to other than nil) is done by assigning it. > > In the above a through h are declared within the vertical bars.n They are > > initialized in the assignments. I want a warning for the usage of b in "c > > := b", "d" in "#(1 2 3) sorted: d", g in "g perform: #ifNotNil: with: [b > := > > g]". I *don't* want to be told about a in "a ifNil: [a := 1]", c in "c > > ifNil: [c := 3]", or e & f in "(e isNil or: [f isNil]) ifTrue: [e := f := > > 6]". I never want to see "ifNotNilDo", ever ;-) > > (* note that a couple of years back we fixed a bad bug in the compiler > > where block local temps were not (re)initialized to nil on each > iteration, > > leaking their values from previous iterations, breaking the "all temp > vars > > are initialized to nil rule, and revealing implementation details in the > > compiler's inlining of to:[by:]do: forms) > > > > > This behavior leads to a mental model that disambiguates between null > and > > > undefined similar to JavaScript which I never have found helpful. > > > > > > > > I don't see how that applies. Smalltalk has no undefined. It has nil & > > zero, and these values are used to initialize any and all variables. This > > is not an artifact of the implementation. It is a fundamental part of the > > language design. It results in no dangling referents or > > uninitialized variables. The language used in Parser>>#queryUndefined is > > problematic. It should be "unassigned", not "undefined". There is nothing > > undefined about these variables. But they are indeed unassigned. In some > > cases (see my i=diomatic implementation of subsequences: and substrings) > > this can (and *should*) be used to advantage. And all Smalltalk > > programming courses should explain that variables are always initialized > > (either to nil or zero, & hence by extension 0.0, Character null, Color > > transparent, et al), and may need assignment before their referents get > > sent messages. > > > > I see the same kind of sloppiness in people not knowing that conditionals > > that take blocks typically evaluate to nil when the condition doesn;t > > select the block. So always "expr ifNotNil: [...]", never "expr ifNotNil: > > [...] ifNil: [nil]", or "expr ifNotNil: [...] ifNil: []". I recently > > cleaned up code by as string programmer who had open coded point > arithmetic > > (e.g. a * b written as (a x * b x) @ (a y * b y) ). This is really bad: > > it's exemplifying poor practice, it's verbose, it takes away at least as > > much understanding as it conveys, it leads to more difficult to manage > code. > > > > If we fail to teach the language properly we start on a slippery slope to > > duplication (which is an awful evil, leading to much increased > maintennance > > effort, and brittleness), and rendering perfectly good, well thought-out > > idioms mysterious. It;'s not like Smalltalk has a lot of rules; the > > number, compared to C & C++ et al is tiny. And terseness has not just > > aesthetic benefit, but real practical benefit in terms of readability & > > maintainability. > > > > > Also, with this change, the compiler leaks the default value of any > > > temporary variable, which we previously were able to hide at least > > > partially. > > > > > > > > But that is a MISTAKE!! The language designers didn't arrange for temps > to > > be initialized to nil just because that's the only default. They did it > to > > ensure that there is no such thing as an uninitialized variable in > > Smalltalk. That's why nil ids an object, with a class, not just nil. > > That's why nil ~~ false. It's carefully thought out and not just some > > artifact of the implementation. And that rationale (read the blue book > > carefully) and its implications, should be taught/learned/known, and > > especially exemplified by the core code of Squeak trunk, and hence > > supported by the compiler. > > > > > In many cases, I think explicitly setting a temporary variable to nil > > > before it is initialized within some non-trivial conditional complex > would > > > be more explicit, thus more readable, and something which we should > > > generally encourage programmers to do. > > > > > > > > I disagree. You're advocating for absurdities such as > > > > | colors | > > colors :=- ColorArray new: 256. > > colors atAllPut: Color transparent > > > > This is the kind of thinking that leads to cycling wearing American > > Football clothes. It won't keep you from being run over by a truck, but > > it'll make you so slow and reduce your peripheral vision so much, not to > > mention give you a false sense of security, that you'll be much more > likely > > to be run over by a truck... > > > > > Looking forward to your opinion! > > > > > > > > :-) Hope I'm not too strident :-) > > > > > Best, > > > > > > Christoph > > > ------------------------------ > > > *Von:* Squeak-dev > im > > > Auftrag von commits at source.squeak.org > > > > *Gesendet:* Mittwoch, 23. November 2022 04:10:30 > > > *An:* squeak-dev at lists.squeakfoundation.org; > > > packages at lists.squeakfoundation.org > > > *Betreff:* [squeak-dev] The Trunk: Compiler-eem.480.mcz > > > > > > Eliot Miranda uploaded a new version of Compiler to project The Trunk: > > > http://source.squeak.org/trunk/Compiler-eem.480.mcz > > > > > > ==================== Summary ==================== > > > > > > Name: Compiler-eem.480 > > > Author: eem > > > Time: 22 November 2022, 7:10:27.324796 pm > > > UUID: 3e5ba19e-c44a-4390-9004-de1246736cbc > > > Ancestors: Compiler-eem.479 > > > > > > Do not warn of an uninitialized temporary if it is being sent ifNil: or > > > ifNotNil:. > > > > > > =============== Diff against Compiler-eem.479 =============== > > > > > > Item was changed: > > > ----- Method: Parser>>primaryExpression (in category 'expression > types') > > > ----- > > > primaryExpression > > > hereType == #word > > > ifTrue: > > > [parseNode := self variable. > > > + (parseNode isUndefTemp > > > + and: [(#('ifNil:' 'ifNotNil:') includes: here) > > > not > > > + and: [self interactive]]) > > > + ifTrue: > > > + [self queryUndefined]. > > > - (parseNode isUndefTemp and: [self interactive]) > > > - ifTrue: [self queryUndefined]. > > > parseNode nowHasRef. > > > ^ true]. > > > hereType == #leftBracket > > > ifTrue: > > > [self advance. > > > self blockExpression. > > > ^true]. > > > hereType == #leftBrace > > > ifTrue: > > > [self braceExpression. > > > ^true]. > > > hereType == #leftParenthesis > > > ifTrue: > > > [self advance. > > > self expression ifFalse: [^self expected: > > > 'expression']. > > > (self match: #rightParenthesis) > > > ifFalse: [^self expected: 'right > > > parenthesis']. > > > ^true]. > > > (hereType == #string or: [hereType == #number or: [hereType == > > > #literal or: [hereType == #character]]]) > > > ifTrue: > > > [parseNode := encoder encodeLiteral: self advance. > > > ^true]. > > > (here == #- and: [tokenType == #number and: [1 + hereEnd = mark]]) > > > ifTrue: > > > [self advance. > > > parseNode := encoder encodeLiteral: self advance > > > negated. > > > ^true]. > > > ^false! > > > > > _,,,^..^,,,_ > > best, Eliot > > -------------- next part -------------- > > An HTML attachment was scrubbed... > > URL: < > http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20221123/dfd355fa/attachment.html > > > _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Sat Nov 26 18:50:21 2022 From: tim at rowledge.org (tim Rowledge) Date: Sat, 26 Nov 2022 10:50:21 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> <093B4101-F5ED-4136-ABD8-2AD705722929@gmx.de> Message-ID: <8F663BFE-6ABB-46F9-B5B8-389BDCDEB04D@rowledge.org> > On Thu, Nov 24, 2022 at 12:18 PM Tobias Pape wrote: > > [0]: I've used it in Python code to much joy. I have to wave my little flag of disagreement here; having had to do a bunch of Python stuff recently I claim with some emphasis that nothing about Python could possibly bring much joy. Really - it's so disappointingly meh. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim If you never try anything new, you'll miss out on many of life's great disappointments From tim at rowledge.org Sat Nov 26 18:58:35 2022 From: tim at rowledge.org (tim Rowledge) Date: Sat, 26 Nov 2022 10:58:35 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <20221123031033.E174A14D821@mail.squeak.org> <4121d105-f261-4a85-82ef-68201168cbb4@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: <5CF14B56-FD85-49DA-A3DA-7FEB78EBA1C1@rowledge.org> > On 2022-11-26, at 9:37 AM, Eliot Miranda wrote: > > a new instance is initialized; it doesn't contain random crap. This is a really, really, important fact that gets far too little appreciation. We (as in those of us that have done significant amounts of living in the bowels of VM implementations) had to put non-trivial effort into making that happen correctly and efficiently, because in the Olden Times (when computers did maybe one million instructions a second if you could afford a professional workstation class machine) it was *painful* to spend that time and we had to cheat in creative ways. The pay-off is that we get to not worry about the potential for horrifying things happening in the way it can with so many other programming systems. It makes garbage collection more practical, which in turn makes other parts of programming life nicer. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- If she was any dumber, she'd be a green plant. From squeaklist at gmail.com Sat Nov 26 20:01:38 2022 From: squeaklist at gmail.com (Kjell Godo) Date: Sat, 26 Nov 2022 12:01:38 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: <3239961F-C30C-433F-AE0D-D0CC1BDAF2DE@gmx.de> <093B4101-F5ED-4136-ABD8-2AD705722929@gmx.de> Message-ID: if you could dump obj1 or ( Error something )<—-[ you create it and fill it but you do not signal it you just return it ] or some notNil into the data pathway which could be tested at some one single place or a few places like if the pathway was like a channel in a water shed with all the channels coming together in a river at the sea and then you check for isError or something at the mouth of the river like More and Just in Haskell but way more expressive than More and Just then you know exactly what went wrong and where maybe and that could be good maybe better than signal in this case if there would be a lot of signals deprecated and a lot of on:do:s all gone into one testing at the river ending if you put all your UndefinedObject>>methods into a Category named by the name of your Package or Project that should be ok it’s easy to hide it all then. Like Category KEGGenerator in UndefinedObject hey that’s a good idea i will do that nil is an empty KEGGenerator and that is convenient but if nil is an empty Collection also then is nil a Gen or a Coll so then you better use #( )asGen instead if that is a problem or maybe it’s fine sometimes it is fine sometimes it is not Object>>asGen ^self asGenerator if KEGGenerator g and g next isNil then any g next later isNil also until ( g reset ). This is essential to KEGGenerator if not the whole thing quits. But i use KEGFooArray as a not nil end of something also. Probably KEGFooArray could get a way better name because i just named it with out thinking and it stuck. i guess i could use KEGGeneratorTail or something instead of nil but nil is central and has a lot of testers which would have to be isomorphically recreated slow so just use nil I guess i could just rename KEGFooArray and the refactoring would change it everywhere in one single stroke so probably i should do this try this but what name should i choose and then the #fooArray local variables would look funny so but what could it be called instead of KEGFooArray that means nil like terminator Array in case you want to stick things into it like you do with Errors but without creating another Error Class or something KEGnotNilTerminator ? although KEGFooArray can be used for more than just terminating sequences and once you know it it sticks in your craw in your brain and you never forget it at least i never did so but KEGFooArray has a nil like quality to it. i could look at all the KEGFooArray references and see if it is mostly a not nil subsequence terminator does anybody want KEGGenerator besides me i remember telling a co worker you should use Generators by Timothy Budd for that and he said i don’t want to use Generators for anything i just want to use to:do: to:by:do: do: collect: select: reject: and detect: ok? Generators away. So i am guessing that this is the general censure. the general opinion. Actually Generators don’t do to:do: and to:by:do: as far as i know yet but some could do. Otherwise they are similar to Collections and you can do aCollection asGen or anObject asGen or aStream asGen etc. they are between Collections and Streams so you do not have a lot of intermediate Collections created when you do ((((( aCollection asGen ) collect: […] ) select: […] ) reject: […] ) detect: […] ifNone: […] ) ifNotNil: [ :g | g asArray ] there are no intermediate Collections created none and asArray sends ( g next ) over and over so execution proceeds g next collect: select: reject: reject: detect:ifNone: etc g next collect: select: reject: detect:ifNone: etc etc etc sort of and there is a new semaphore SharedQueue thing which does the java or something version of Generators from inside of regular loops whileTrue: and so you can have the […] above communicating with each other in very convenient ways which come up a lot once you know to look and this highly collapses the code as versus the Collection way is my opinion. But KEGGenerators has got as big or bigger than Xtreams i believe i know nothing and the combination of KEGGenerators and Xtreams aught to be pretty good although i haven’t tried it yet pretty good i would think but nobody wants it and nobody is me just me alone apparently i use it a lot just like LittleSmalltalk uses its predecessor Generator a lot also look at the Icon language book and the implementation of n Queens therein it’s like one line or something because everything in Icon is a Generator practically or something oh god another thing to learn by spelunking no well actually KEGGenerators is highly documented by Package comments Class comments and Method comments completely Not corporate or consistent. well it may be consistent mostly but not wholly and it’s definitely not corporate or the ancient IBM standard accounting to which i say : what me worry? oh god another huge pile up of pages to read yes and the older comments are highly convoluted i have found unfortunately but the newer ones are pretty good clear i am hoping well future me is hoping i want to put the latest versions of KEGGenerators into Github but it is rather large with many optional addon Packages and there are many Experimental Methods as well which could be Categorized KEGExperimental and or KEGUnfinished and it’s Dolphin so there are Methods in multiple Categories. So i was going to try to break it up into more Packages so you just get what you want like a Core and some addons or something or should i just dump the whole thing now and break it up later if i live that long well seeing as nobody wants it and nobody is just me only then dump it otherwise it should be highly portable to all different ANSI Smalltalk just as soon as the other Smalltalks stop the prehistoric insanity and allow Method M to be in multiple Categories or something and then allow system wide searching on a Category i could attempt allowing M in multiple Categories in Squeak if i could get some help from somebody or something it should be easy why isn’t it easy? is some prehistoric rubble is blocking? SSSSSSS HOCK people hate the idea? Now why in hell would you do that unless i wake up and go oh no i can’t do that I’ve got to do all of this clean the gutters watch a million hours of tv etc On Sat, Nov 26, 2022 at 08:58 Eliot Miranda wrote: > Hi Tobi, > > On Thu, Nov 24, 2022 at 12:18 PM Tobias Pape wrote: > >> Hi Eliot >> >> First things first, I did not raise objections in my admittedly short >> quip. >> >> >> > On 24. Nov 2022, at 20:23, Eliot Miranda >> wrote: >> > >> > Hi Tobi, >> > >> > let me try again (https://youtu.be/Cj8n4MfhjUc)… >> >> :D >> >> I already got my comfy chair! >> >> > >> >> On Nov 23, 2022, at 12:23 PM, Tobias Pape wrote: >> >> >> >> Yet, nil is only seldom a good domain object. >> > >> > Precisely. Being disjoint from any domain it is the ideal “I am not a >> domain object” marker. So when one wants a variable to range over a domain >> and the singleton “not a member of the domain” nil is a great choice. And >> that’s exactly how I use it below. >> >> Second things second, I got that. >> >> > >> > There is another excellent marker of a non-domain object, and that is a >> newly instantiated object. That object is known to not be any other object, >> since objects are unique. So if code is searching for something (eg >> applying a block to every literal in the system), having the newly >> instantiated object that implements the search use itself as the “I’m not >> in the domain of all pre-existing objects” is a sensible choice. This is >> the pattern InstructionStream uses when scanning for selectors. >> >> And #someObject/#nextObject. >> I get that. And it is actually a beautiful thing you cannot do >> everywhere[0]. >> >> My fear is as follows: >> >> I hope we can agree that "nil" is part of the "system domain" of >> Smalltalk, or - said differently - the meta-level. >> >> So are the concepts of variables, classes etc. >> > > Yes, and equally, for example, collections. The Set instance in a set of > accounts is not part of the domain because it's not specific to the > domain. It comes from the Smalltalk library. > > But so what? This feels like a straw man to me. One could argue that an > account object itself is not part of the domain, but part of the model of > the domain, etc. > > In the end nil is an object that is useful and well-defined. It isn't > special, just like true & false aren;t special, or that classes being > objects aren't special. Instead these are all functional relationships > that allow us to construct a system that is malleable and comprehensible. > > >> The non-meta, base, or "domain proper" layer can be anything you want to >> computationally achieve.[1] >> Let's arbitrarily chose finance[2]. >> >> A domain object would be an account, a transaction, an account holder, >> etc. >> (Note that we can chose how to represent each, and we do not necessarily >> need objects for each, but I digress). >> >> My take: in code dealing with such domain objects, nil should appear next >> to never, because it is an object from the Metalevel. >> > > I don't agree. nil can serve as an absence, and absences are important. > > In any query which can yield no results we have three choices: > - answer nil (e.g. at end of stream) > - raise an exception > - require passing in a continuation to take in the event of an error (e.g. > the block argument to at:ifAbsent: or the second one to detect:ifNone: etc) > > Often nil is lighter-weight, much more concise, and hence more > comprehensible, hence to be preferred. > > The problems with accepting nil as the general "nothing to see" marker >> include: >> >> - There are too many. >> In our example, an account holder could have an instVar "account" which >> could be nil when not having an account yet, BUT ALSO >> an account could have a "closingDate" for when the account folded, >> which is "nil" when the account is still open, AND ALSO, a transaction >> could have >> an "auditor" which is nil as long as no audit has taken place etc. >> Just like that, nil takes _different roles_ just by being convenient. >> > > As do the integers, symbols, collections. As do classes. Should we have > different kinds of classes for the class library, the meta level, the > domain model? Or is it sufficient to have classes, metaclasses and traits? > i.e. do we need to label things according to their use, or is it > sufficient to differentiate them purely by function? I think the latter. > > - Nil has problematic provenance. >> When somewhere during debugging (the all-known MNU for UndefinedObject) >> a nil pops up, it is often reallllly hard to say whence it came from. >> So dealing with a lot of nil-bearing code will send you down rabbit >> holes after the other. >> > > Whereas NaN doesn't have problematical provenance? Or getting an > identically-valued instance with a different identity, or a host of other > potential evils.... These are not specific to nil, and not specific to > using nuil as a marker of absence, or as bottom. Programming is tricky; we > have lots of ways of doping things; things happen very fast; code does what > tou tell it, not what you want it to do. We find we make mistakes all the > time. This is not specific to the use of nil in our domain models. > >> - Nil begets polymorphism, nil defies polymorphism. >> It is one of the most awesome feats of Smalltalk that nil is NOT like >> NULL, in that it can respond to messages. That is exceptionally powerful >> and has given Smalltalk a lot of resilience. >> But cluttering UndefinedObject with custom, even domain-specifc >> methods is a really bad idea. However, that means >> it is often unwise to just have object that could be nil be sent >> arbitrary messages. >> Hence a multitude of #isNil/#ifNil-Checks. Proper domain objects that >> model absence, pre-valid state, or error conditions can deal much better >> with that. >> > > When it's possible then fine. But in the query example above we must be > able to deal with absence/have an element disjoint from a domain. And nil > functions ideally for this case. > > - Nil is in a collection-superposition (just like your good old USB-A plug >> which you have to turn at least twice to fit). >> You only know whether nil _actually_ could be a collection when you >> know that a non-nil object in its place is a collection [3]. >> Said differently: in contrast to LISPy languages, our nil is _by >> design_ no collection, while LISPy null _by design_ IS the empty list. >> This makes for funny messages like #isEmptyOrNil, which bails on >> non-nil-non-collection objects. >> So every time you have to deal with nil, you automatically at lease >> once have to answer the question "could the non-nil version of this object >> be a collection"? >> > > Many uses of isEmptyOrNil are in response to FillInTheBlank which can > return nil on cancel or an empty string if the user doesn't type anything. > This is a natural consequence of the affordances of FillInTheBlank, and > isEmptyOrNil is simply a pragmatic response, hardly a symptom of some deep > problem. > > >> There are a lot of interesting approaches to each or combinations of >> these issues. >> This includes Null-Object patterns, Sane-default-initializers, >> exceptions, or explicit models of multiplicity[4]. >> >> But back to the beginning. >> >> In code that does, for example >> >> blaFooAnAccount >> >> | fooAccount | >> self accounts processBla: >> [:ea | >> fooAccount ifNil: [fooAccount := ea]. >> fooAccount := (ea doesBork: fooAccount) >> ifTrue: [fooAccount] >> ifFalse: [ea]] >> ^ fooAccount >> >> we find two things: >> > > I think we find three things. The things you8 list below, plus the fact > that this should have been written using detect:ifNone: ;-) > >> >> First, we could inadvertently return nil from that method. But this is >> technical and I think most here can deal with that. >> >> But second, the line "fooAccount ifNil: [fooAccount := ea]." ACTUALLY says >> >> "if fooAccount is an uninitialized temporary variable, populate it". >> >> This is technically correct, but conflates domains. >> In our world of finance, the idea of a "temporary variable" does no make >> sense. It is part of the meta-level domain, the system. >> >> I don't say this is wrong _per se_ but people reading, and even more so, >> people writing such code >> MUST be aware that they are crossing domains, and especially, entering a >> meta level. >> >> That's why I think these warnings are really ok. >> I won't fight the commit "Compiler-eem.480.mcz", especially since it more >> or less is descriptive of a pervasive style of writing Smalltalk of Squeak >> Core contributors. >> >> I hope people find theses ideas useful. >> >> Best regards >> -Tobias >> >> >> [0]: I've used it in Python code to much joy. >> [1]: Caveat lector: the "domain layer" can surely be the "system layer". >> In fact that is what a lot of system code deals with. >> But this is messy for our considerations above and lets treat it as >> _exceptional_. >> [2]: Semi-arbitrarly, just because I received my tax returns :P >> [3]: yes, that is a strange sentence. It's late. Also, Ardbeg. >> [4]: For example, as in the work of Steimann ( >> https://dl.acm.org/doi/10.1145/2509578.2509582 ). It seems they had a >> Smalltalk implementation in 2017. >> >> >> > >> >> -t >> >> >> >>> On 23. Nov 2022, at 19:34, tim Rowledge wrote: >> >>> >> >>> I won't quote it all again but what Eliot wrote is important. There >> are good solid reasons why Smalltalk has a rigorously defined >> UndefinedObject. We demand rigorously defined areas of doubt and >> uncertainty! >> >>> >> >>> tim >> > >> > >> > _,,,^..^,,,_ (phone) >> > >> >> >> >> > > -- > _,,,^..^,,,_ > best, Eliot > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Sat Nov 26 20:44:04 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Sat, 26 Nov 2022 12:44:04 -0800 Subject: [squeak-dev] The Trunk: Compiler-eem.480.mcz In-Reply-To: References: Message-ID: <03A0C364-EE01-4354-AEF7-8B09C932E20F@gmail.com> Hi Kjell, > On Nov 26, 2022, at 12:01 PM, Kjell Godo wrote: > >  > if you could dump obj1 or ( Error something )<—-[ you create it and fill it but you do not signal it you just return it ] or some notNil into the data pathway which could be tested at some one single place or a few places like if the pathway was like a channel in a water shed with all the channels coming together in a river at the sea and then you check for isError or something at the mouth of the river like More and Just in Haskell but way more expressive than More and Just then you know exactly what went wrong and where maybe and that could be good maybe better than signal in this case if there would be a lot of signals deprecated and a lot of on:do:s all gone into one testing at the river ending Yes, that’s a great pattern too. Sort of related to sentinels right? > > if you put all your UndefinedObject>>methods into a Category named by the name of your Package or Project that should be ok it’s easy to hide it all then. I agree. And if we had selector namespaces then collisions would be avoidable. > Like Category KEGGenerator in UndefinedObject hey that’s a good idea i will do that > nil is an empty KEGGenerator and that is convenient but if nil is an empty Collection also then is nil a Gen or a Coll so then you better use #( )asGen instead if that is a problem or maybe it’s fine sometimes it is fine sometimes it is not > Object>>asGen ^self asGenerator > > if KEGGenerator g and g next isNil then any g next later isNil also until ( g reset ). > This is essential to KEGGenerator if not the whole thing quits. But i use KEGFooArray as a not nil end of something also. Probably KEGFooArray could get a way better name because i just named it with out thinking and it stuck. i guess i could use KEGGeneratorTail or something instead of nil but nil is central and has a lot of testers which would have to be isomorphically recreated slow so just use nil > > I guess i could just rename KEGFooArray and the refactoring would change it everywhere in one single stroke so probably i should do this try this but what name should i choose and then the #fooArray local variables would look funny so but what could it be called instead of KEGFooArray that means nil like terminator Array in case you want to stick things into it like you do with Errors but without creating another Error Class or something KEGnotNilTerminator ? although KEGFooArray can be used for more than just terminating sequences and once you know it it sticks in your craw in your brain and you never forget it at least i never did so but KEGFooArray has a nil like quality to it. i could look at all the KEGFooArray references and see if it is mostly a not nil subsequence terminator > > does anybody want KEGGenerator besides me i remember telling a co worker you should use Generators by Timothy Budd for that and he said i don’t want to use Generators for anything i just want to use to:do: to:by:do: do: collect: select: reject: and detect: ok? Generators away. So i am guessing that this is the general censure. the general opinion. Actually Generators don’t do to:do: and to:by:do: as far as i know yet but some could do. Otherwise they are similar to Collections and you can do aCollection asGen or anObject asGen or aStream asGen etc. they are between Collections and Streams so you do not have a lot of intermediate Collections created when you do > ((((( aCollection asGen > ) collect: […] > ) select: […] > ) reject: […] > ) detect: […] ifNone: […] > ) ifNotNil: [ :g | g asArray ] > there are no intermediate Collections created none and asArray sends ( g next ) over and over so execution proceeds > g next > collect: select: reject: reject: detect:ifNone: etc > g next > collect: select: reject: detect:ifNone: etc etc etc Yes, great to avoid this kind of thing. > sort of > and there is a new semaphore SharedQueue thing which does the java > or something version of Generators from inside of regular loops whileTrue: > and so you can have the […] above communicating with each other in very convenient ways which come up a lot once you know to look and this highly collapses the code as versus the Collection way is my opinion. But KEGGenerators has got as big or bigger than Xtreams i believe i know nothing and the combination of KEGGenerators and Xtreams aught to be pretty good although i haven’t tried it yet pretty good i would think but nobody wants it and nobody is me just me alone apparently Having objects that encode functions/transformations/operations is also very much Smalltalk style (related to “every noun can be verbed”). BitBlt is one such. In VisualWorks we did compounds for querying. So instead of brosdeAllCallsOn:and:localToPackage: you could do (((query allCallsOn: a) | (query allCallsOn: b)) & (query localToPackage: p)) browse Very powerful. > > i use it a lot just like LittleSmalltalk uses its predecessor Generator a lot > also look at the Icon language book and the implementation of n Queens therein it’s like one line or something because everything in Icon is a Generator practically or something > > oh god another thing to learn by spelunking no > > well actually KEGGenerators is highly documented by Package comments Class comments and Method comments completely Not corporate or consistent. well it may be consistent mostly but not wholly and it’s definitely not corporate or the ancient IBM standard accounting to which i say : what me worry? > > oh god another huge pile up of pages to read yes > > and the older comments are highly convoluted i have found unfortunately but the newer ones are pretty good clear i am hoping well future me is hoping > > i want to put the latest versions of KEGGenerators into Github but it is rather large with many optional addon Packages and there are many Experimental Methods as well which could be Categorized KEGExperimental and or KEGUnfinished and it’s Dolphin so there are Methods in multiple Categories. So i was going to try to break it up into more Packages so you just get what you want like a Core and some addons or something or should i just dump the whole thing now and break it up later if i live that long > well seeing as nobody wants it and nobody is just me only then > dump it > otherwise it should be highly portable to all different ANSI Smalltalk > just as soon as the other Smalltalks stop the prehistoric insanity and allow Method M to be in multiple Categories > or something > and then allow system wide searching on a Category > > i could attempt allowing M in multiple Categories in Squeak > if i could get some help from somebody > or something > it should be easy why isn’t it easy? > is some prehistoric rubble is blocking? > SSSSSSS HOCK people hate the idea? Now why in hell would you do that > unless i wake up and go oh no i can’t do that I’ve got to do all of this > clean the gutters watch a million hours of tv etc > >> On Sat, Nov 26, 2022 at 08:58 Eliot Miranda wrote: >> Hi Tobi, >> >>> On Thu, Nov 24, 2022 at 12:18 PM Tobias Pape wrote: >>> Hi Eliot >>> >>> First things first, I did not raise objections in my admittedly short quip. >>> >>> >>> > On 24. Nov 2022, at 20:23, Eliot Miranda wrote: >>> > >>> > Hi Tobi, >>> > >>> > let me try again (https://youtu.be/Cj8n4MfhjUc)… >>> >>> :D >>> >>> I already got my comfy chair! >>> >>> > >>> >> On Nov 23, 2022, at 12:23 PM, Tobias Pape wrote: >>> >> >>> >> Yet, nil is only seldom a good domain object. >>> > >>> > Precisely. Being disjoint from any domain it is the ideal “I am not a domain object” marker. So when one wants a variable to range over a domain and the singleton “not a member of the domain” nil is a great choice. And that’s exactly how I use it below. >>> >>> Second things second, I got that. >>> >>> > >>> > There is another excellent marker of a non-domain object, and that is a newly instantiated object. That object is known to not be any other object, since objects are unique. So if code is searching for something (eg applying a block to every literal in the system), having the newly instantiated object that implements the search use itself as the “I’m not in the domain of all pre-existing objects” is a sensible choice. This is the pattern InstructionStream uses when scanning for selectors. >>> >>> And #someObject/#nextObject. >>> I get that. And it is actually a beautiful thing you cannot do everywhere[0]. >>> >>> My fear is as follows: >>> >>> I hope we can agree that "nil" is part of the "system domain" of Smalltalk, or - said differently - the meta-level. >>> >>> So are the concepts of variables, classes etc. >> >> Yes, and equally, for example, collections. The Set instance in a set of accounts is not part of the domain because it's not specific to the domain. It comes from the Smalltalk library. >> >> But so what? This feels like a straw man to me. One could argue that an account object itself is not part of the domain, but part of the model of the domain, etc. >> >> In the end nil is an object that is useful and well-defined. It isn't special, just like true & false aren;t special, or that classes being objects aren't special. Instead these are all functional relationships that allow us to construct a system that is malleable and comprehensible. >> >>> >>> The non-meta, base, or "domain proper" layer can be anything you want to computationally achieve.[1] >>> Let's arbitrarily chose finance[2]. >>> >>> A domain object would be an account, a transaction, an account holder, etc. >>> (Note that we can chose how to represent each, and we do not necessarily need objects for each, but I digress). >>> >>> My take: in code dealing with such domain objects, nil should appear next to never, because it is an object from the Metalevel. >> >> I don't agree. nil can serve as an absence, and absences are important. >> >> In any query which can yield no results we have three choices: >> - answer nil (e.g. at end of stream) >> - raise an exception >> - require passing in a continuation to take in the event of an error (e.g. the block argument to at:ifAbsent: or the second one to detect:ifNone: etc) >> >> Often nil is lighter-weight, much more concise, and hence more comprehensible, hence to be preferred. >> >>> The problems with accepting nil as the general "nothing to see" marker include: >>> >>> - There are too many. >>> In our example, an account holder could have an instVar "account" which could be nil when not having an account yet, BUT ALSO >>> an account could have a "closingDate" for when the account folded, which is "nil" when the account is still open, AND ALSO, a transaction could have >>> an "auditor" which is nil as long as no audit has taken place etc. >>> Just like that, nil takes _different roles_ just by being convenient. >> >> As do the integers, symbols, collections. As do classes. Should we have different kinds of classes for the class library, the meta level, the domain model? Or is it sufficient to have classes, metaclasses and traits? i.e. do we need to label things according to their use, or is it sufficient to differentiate them purely by function? I think the latter. >> >>> - Nil has problematic provenance. >>> When somewhere during debugging (the all-known MNU for UndefinedObject) a nil pops up, it is often reallllly hard to say whence it came from. >>> So dealing with a lot of nil-bearing code will send you down rabbit holes after the other. >> >> Whereas NaN doesn't have problematical provenance? Or getting an identically-valued instance with a different identity, or a host of other potential evils.... These are not specific to nil, and not specific to using nuil as a marker of absence, or as bottom. Programming is tricky; we have lots of ways of doping things; things happen very fast; code does what tou tell it, not what you want it to do. We find we make mistakes all the time. This is not specific to the use of nil in our domain models. >>> - Nil begets polymorphism, nil defies polymorphism. >>> It is one of the most awesome feats of Smalltalk that nil is NOT like NULL, in that it can respond to messages. That is exceptionally powerful >>> and has given Smalltalk a lot of resilience. >>> But cluttering UndefinedObject with custom, even domain-specifc methods is a really bad idea. However, that means >>> it is often unwise to just have object that could be nil be sent arbitrary messages. >>> Hence a multitude of #isNil/#ifNil-Checks. Proper domain objects that model absence, pre-valid state, or error conditions can deal much better with that. >> >> When it's possible then fine. But in the query example above we must be able to deal with absence/have an element disjoint from a domain. And nil functions ideally for this case. >> >>> - Nil is in a collection-superposition (just like your good old USB-A plug which you have to turn at least twice to fit). >>> You only know whether nil _actually_ could be a collection when you know that a non-nil object in its place is a collection [3]. >>> Said differently: in contrast to LISPy languages, our nil is _by design_ no collection, while LISPy null _by design_ IS the empty list. >>> This makes for funny messages like #isEmptyOrNil, which bails on non-nil-non-collection objects. >>> So every time you have to deal with nil, you automatically at lease once have to answer the question "could the non-nil version of this object be a collection"? >> >> Many uses of isEmptyOrNil are in response to FillInTheBlank which can return nil on cancel or an empty string if the user doesn't type anything. This is a natural consequence of the affordances of FillInTheBlank, and isEmptyOrNil is simply a pragmatic response, hardly a symptom of some deep problem. >> >>> >>> There are a lot of interesting approaches to each or combinations of these issues. >>> This includes Null-Object patterns, Sane-default-initializers, exceptions, or explicit models of multiplicity[4]. >>> >>> But back to the beginning. >>> >>> In code that does, for example >>> >>> blaFooAnAccount >>> >>> | fooAccount | >>> self accounts processBla: >>> [:ea | >>> fooAccount ifNil: [fooAccount := ea]. >>> fooAccount := (ea doesBork: fooAccount) >>> ifTrue: [fooAccount] >>> ifFalse: [ea]] >>> ^ fooAccount >>> >>> we find two things: >> >> I think we find three things. The things you8 list below, plus the fact that this should have been written using detect:ifNone: ;-) >>> >>> First, we could inadvertently return nil from that method. But this is technical and I think most here can deal with that. >>> >>> But second, the line "fooAccount ifNil: [fooAccount := ea]." ACTUALLY says >>> >>> "if fooAccount is an uninitialized temporary variable, populate it". >>> >>> This is technically correct, but conflates domains. >>> In our world of finance, the idea of a "temporary variable" does no make sense. It is part of the meta-level domain, the system. >>> >>> I don't say this is wrong _per se_ but people reading, and even more so, people writing such code >>> MUST be aware that they are crossing domains, and especially, entering a meta level. >>> >>> That's why I think these warnings are really ok. >>> I won't fight the commit "Compiler-eem.480.mcz", especially since it more or less is descriptive of a pervasive style of writing Smalltalk of Squeak Core contributors. >>> >>> I hope people find theses ideas useful. >>> >>> Best regards >>> -Tobias >>> >>> >>> [0]: I've used it in Python code to much joy. >>> [1]: Caveat lector: the "domain layer" can surely be the "system layer". In fact that is what a lot of system code deals with. >>> But this is messy for our considerations above and lets treat it as _exceptional_. >>> [2]: Semi-arbitrarly, just because I received my tax returns :P >>> [3]: yes, that is a strange sentence. It's late. Also, Ardbeg. >>> [4]: For example, as in the work of Steimann (https://dl.acm.org/doi/10.1145/2509578.2509582 ). It seems they had a Smalltalk implementation in 2017. >>> >>> >>> > >>> >> -t >>> >> >>> >>> On 23. Nov 2022, at 19:34, tim Rowledge wrote: >>> >>> >>> >>> I won't quote it all again but what Eliot wrote is important. There are good solid reasons why Smalltalk has a rigorously defined UndefinedObject. We demand rigorously defined areas of doubt and uncertainty! >>> >>> >>> >>> tim >>> > >>> > >>> > _,,,^..^,,,_ (phone) >>> > >>> >>> >>> >> >> >> -- >> _,,,^..^,,,_ >> best, Eliot >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vanessa at codefrau.net Sat Nov 26 21:10:06 2022 From: vanessa at codefrau.net (Vanessa Freudenberg) Date: Sat, 26 Nov 2022 13:10:06 -0800 Subject: [squeak-dev] Squeak 6 on SqueakJS In-Reply-To: <3c9d0c6b9f4b4600859c98bb1e32e225@student.hpi.uni-potsdam.de> References: <3c9d0c6b9f4b4600859c98bb1e32e225@student.hpi.uni-potsdam.de> Message-ID: Oh yes I noticed that. I guess the 32MB headroom is not enough with a high res display … https://github.com/codefrau/SqueakJS/blob/a947f96a3fdf7473582d6b359cadd89db96cea72/vm.image.js#L70 SqueakJS artificially limits the amount of memory used, like old Squeak VMs used to do, partly because there’s no way to query the actual available memory size via JavaScript. Not sure what the best way is to deal with that. Maybe if we run out of room we should do a full GC, and if that didn’t help, increase the headroom? Vanessa On Wed, Nov 23, 2022 at 06:31 Thiede, Christoph < Christoph.Thiede at student.hpi.uni-potsdam.de> wrote: > Thank you Vanessa! > > > If I open Marcel's link > https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip&highdpi=true on > my high-dpi device (250%), it loads about one minute and then > reproducibly says: > > > > > But I have more than 1 GB free RAM. If open the link on a low-DPI screen > instead, and move it to the other screen afterward, everything works fine. > :-) > > > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Taeumel, Marcel > *Gesendet:* Montag, 21. November 2022 09:50:25 > *An:* squeak-dev; vm-dev > *Betreff:* Re: [squeak-dev] Squeak 6 on SqueakJS > > Hi Vanessa -- > > Thank you!! :-D > > High-DPI also works: > > https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip&highdpi=true > > Best, > Marcel > > Am 21.11.2022 06:29:19 schrieb Vanessa Freudenberg : > ... works now with release 1.0.5 of SqueakJS: > > > https://squeak.js.org/run/#zip=https://files.squeak.org/6.0/Squeak6.0-22104-64bit/Squeak6.0-22104-64bit.zip > > We only had to recognize the new image format – sorry it took me so long. > Thank you, Christoph Tiede and Dave Lewis! > (https://github.com/codefrau/SqueakJS/pull/138) > > TODO: actually implement primitive 578 (but then, quite a few > non-essential prims are still missing) > > Enjoy! > Vanessa > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Sun Nov 27 01:49:41 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Sun, 27 Nov 2022 02:49:41 +0100 Subject: [squeak-dev] Please ignore | Encoding test for squeak-dev pipermail archive Message-ID: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> Sometimes tab characters seem to be encoded as U+FFFD, does this depend on the mail client from which I am sending my messages? Tab    tab    tab Ümläutß Sorry for the noisé! Best, Christoph From LEnglish5 at cox.net Mon Nov 28 10:58:44 2022 From: LEnglish5 at cox.net (LawsonEnglish) Date: Mon, 28 Nov 2022 03:58:44 -0700 Subject: [squeak-dev] Full block closure return value testing/using in workspace? Message-ID: <3711F01C-950D-4BAE-B992-4EFC8C1BE408@cox.net> I was trying to test some ideas and was using the new FullBlockClosure to return values for further use in a workspace. This works with “print it”: [Transcript show: 2;cr. ^2] value => 2 This does not work: test := [Transcript show: 2;cr. ^2] value test => nil. nor does this: test :=( [Transcript show: 2;cr. ^2] value) test => nil print it still works: test := ([Transcript show: 2;cr. ^2] value) => 2 test => nil. In all cases, a 2 appears in the Transcript window, so I know that *something* is happening. I would have thought that if print-it and do-it work, then the returned value would be put in the test variable, but that is not the case. I can use a workspace global variable to access the output, but that kinda makes the ^ a one-trick-pony: useful for breaking out of loops, but not giving me access to the return value. [test := 2. Transcript show: test;cr. ^test] value => 2 test => 2 Is this an oversight or bug or feature for workspaces, or is it working as intended? Lawson From Das.Linux at gmx.de Mon Nov 28 11:15:14 2022 From: Das.Linux at gmx.de (Tobias Pape) Date: Mon, 28 Nov 2022 12:15:14 +0100 Subject: [squeak-dev] Full block closure return value testing/using in workspace? In-Reply-To: <3711F01C-950D-4BAE-B992-4EFC8C1BE408@cox.net> References: <3711F01C-950D-4BAE-B992-4EFC8C1BE408@cox.net> Message-ID: Hi Lawson good to see you. > On 28. Nov 2022, at 11:58, LawsonEnglish wrote: > > I was trying to test some ideas and was using the new FullBlockClosure to return values for further use in a workspace. > > This works with “print it”: > > [Transcript show: 2;cr. ^2] value => 2 > > This does not work: > > test := [Transcript show: 2;cr. ^2] value > > test => nil. Yes, and that is expected. Two things: First, it seems you want to assign the _return value_ of a block to a variable. To achieve this, do test := [Transcript show: 2;cr. 2] value "Note the missing caret/return" This is because the last statement of a block will be its return value. Second, yes, the return/caret in the block does something but apparently not the thing you expected. The effect for caret/^/return is: ^ statement "Returns the value from statement from the method" The last word is crucial. You return from the method, regardless of the block you are in. Like so: fooo Transcript showln: 'foo 1'. self bar: [Transcript showln: 'block 1'. ^ 1]. Transcript showln: 'foo 2'. ^ 2. bar: aBlock Transcript showln: 'bar 1'. aBlock value. Transcript showln: 'bar 2'. If you send #foo, transcript will contain foo 1 bar 1 block 1 an the return value will be 1. This is because the Return in the block will return form the _method #foo_ (where the block is defined) and not only from the block. What does that have to do with the Workspace??? Workspaces create artificial methods for doIts and PrintIts. Hence, your actually sent method looks like that: DoIt test := [Transcript show: 2;cr. ^2] value If you run that method as print-it, "^2" returns form the DoIt method and the workspace can print the 2. If you run that method as print-it, "^2" returns form the DoIt method but the assignment has never taken place, so test remains at its previous value, wich is nil. I hope this helps. Best regards -Tobias > > nor does this: > > test :=( [Transcript show: 2;cr. ^2] value) > > test => nil > > print it still works: > > test := ([Transcript show: 2;cr. ^2] value) => 2 > > test => nil. > > In all cases, a 2 appears in the Transcript window, so I know that *something* is happening. > > I would have thought that if print-it and do-it work, then the returned value would be put in the test variable, but that is not the case. > > I can use a workspace global variable to access the output, but that kinda makes the ^ a one-trick-pony: useful for breaking out of loops, but not giving me access to the return value. > > > [test := 2. Transcript show: test;cr. ^test] value => 2 > > test => 2 > > Is this an oversight or bug or feature for workspaces, or is it working as intended? > > > Lawson > > > From LEnglish5 at cox.net Mon Nov 28 11:32:43 2022 From: LEnglish5 at cox.net (LawsonEnglish) Date: Mon, 28 Nov 2022 04:32:43 -0700 Subject: [squeak-dev] Full block closure return value testing/using in workspace? In-Reply-To: References: <3711F01C-950D-4BAE-B992-4EFC8C1BE408@cox.net> Message-ID: OK, thanks. I had thought perhaps it would act more like a break and take one to the outside of the block, but instead it returns to the caller, as I should have realized. Stilly me. L > On Nov 28, 2022, at 04:15, Tobias Pape wrote: > > Hi Lawson > > good to see you. > >> On 28. Nov 2022, at 11:58, LawsonEnglish wrote: >> >> I was trying to test some ideas and was using the new FullBlockClosure to return values for further use in a workspace. >> >> This works with “print it”: >> >> [Transcript show: 2;cr. ^2] value => 2 >> >> This does not work: >> >> test := [Transcript show: 2;cr. ^2] value >> >> test => nil. > > Yes, and that is expected. > > Two things: > First, it seems you want to assign the _return value_ of a block to a variable. > To achieve this, do > test := [Transcript show: 2;cr. 2] value "Note the missing caret/return" > > This is because the last statement of a block will be its return value. > > Second, yes, the return/caret in the block does something but apparently not the thing you expected. > The effect for caret/^/return is: > > ^ statement "Returns the value from statement from the method" > > The last word is crucial. You return from the method, regardless of the block you are in. > > Like so: > > fooo > > Transcript showln: 'foo 1'. > self bar: > [Transcript showln: 'block 1'. > ^ 1]. > Transcript showln: 'foo 2'. > ^ 2. > > > bar: aBlock > > Transcript showln: 'bar 1'. > aBlock value. > Transcript showln: 'bar 2'. > > > If you send #foo, transcript will contain > > foo 1 > bar 1 > block 1 > > an the return value will be 1. > > This is because the Return in the block will return form the _method #foo_ (where the block is defined) and not only from the block. > > What does that have to do with the Workspace??? > > Workspaces create artificial methods for doIts and PrintIts. > > Hence, your actually sent method looks like that: > > DoIt > test := [Transcript show: 2;cr. ^2] value > > If you run that method as print-it, "^2" returns form the DoIt method and the workspace can print the 2. > If you run that method as print-it, "^2" returns form the DoIt method but the assignment has never taken place, so test remains at its previous value, wich is nil. > > I hope this helps. > > Best regards > -Tobias > >> >> nor does this: >> >> test :=( [Transcript show: 2;cr. ^2] value) >> >> test => nil >> >> print it still works: >> >> test := ([Transcript show: 2;cr. ^2] value) => 2 >> >> test => nil. >> >> In all cases, a 2 appears in the Transcript window, so I know that *something* is happening. >> >> I would have thought that if print-it and do-it work, then the returned value would be put in the test variable, but that is not the case. >> >> I can use a workspace global variable to access the output, but that kinda makes the ^ a one-trick-pony: useful for breaking out of loops, but not giving me access to the return value. >> >> >> [test := 2. Transcript show: test;cr. ^test] value => 2 >> >> test => 2 >> >> Is this an oversight or bug or feature for workspaces, or is it working as intended? >> >> >> Lawson >> >> >> > > > From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Nov 28 12:31:19 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 28 Nov 2022 12:31:19 +0000 Subject: [squeak-dev] Please ignore | Encoding test for squeak-dev pipermail archive In-Reply-To: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> References: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> Message-ID: This is another test. Sorry ... Sent from OWA. Ümläutß, sorry for the noisé! Tab tab tab RxMatcher>>matchAgainstLookbehind:positive:nextLink: {matching} · ct 3/6/2020 20:09 (changed) Best, Christoph From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 12:31:31 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (Christoph Thiede) Date: Mon, 28 Nov 2022 13:31:31 +0100 Subject: [squeak-dev] Please ignore | Encoding test for squeak-dev pipermail archive In-Reply-To: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> References: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> Message-ID: <5b88aab7-3c0b-c13f-930e-b78ba4ae367f@student.hpi.uni-potsdam.de> This is another test. Sorry ... Sent from Thunderbird. Ümläutß, sorry for the noisé! Tab    tab    tab RxMatcher>>matchAgainstLookbehind:positive:nextLink: {matching} · ct 3/6/2020 20:09 (changed) Best, Christoph From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 12:25:55 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 13:25:55 +0100 Subject: [squeak-dev] Please ignore | Encoding test for squeak-dev pipermail archive In-Reply-To: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> References: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> Message-ID: This is another test. Sorry ... Sent from SMTPClient. Ümläutß, sorry for the noisé! Tab tab tab RxMatcher>>matchAgainstLookbehind:positive:nextLink: {matching} · ct 3/6/2020 20:09 (changed) Best, Christoph From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 12:34:26 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 13:34:26 +0100 Subject: [squeak-dev] Please ignore | Encoding test for squeak-dev pipermail archive In-Reply-To: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> References: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> Message-ID: <2193a6b2-e5d5-498b-95f4-adb7f7f27979@MX2018-DAG2.hpi.uni-potsdam.de> This is another test. Sorry ... Sent from SIT. �ml�ut�, sorry for the nois�! Tab tab tab RxMatcher>>matchAgainstLookbehind:positive:nextLink: {matching} � ct 3/6/2020 20:09 (changed) Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 12:55:06 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 13:55:06 +0100 Subject: [squeak-dev] Please ignore | Encoding test for squeak-dev pipermail archive In-Reply-To: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> References: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de> Message-ID: This is another test. Sorry ... Sent from SIT (3). Ümläutß, sorry for the noisé! Tab tab tab RxMatcher>>matchAgainstLookbehind:positive:nextLink: {matching} · ct 3/6/2020 20:09 (changed) Best, Christoph -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 12:57:49 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 13:57:49 +0100 Subject: [squeak-dev] Please ignore | Encoding test for squeak-dev pipermail archive In-Reply-To: References: <10f62088-2b22-0a05-fdf4-86c36274e40f@student.hpi.uni-potsdam.de>, Message-ID: <6d82f79d-d65d-4fe3-b297-999e802a08c7@MX2018-DAG2.hpi.uni-potsdam.de> Yahoo, fixed! For anyone interested: When sending a message with content-type multipart/alternative, the charset must of be specified for each part separately, otherwise MIMEDocument will encode them incorrectly, and in turn, the recipient (here: mailman/pipermail (?)) will convert the unknown characters such as ümläutß, âccénts, and even tabs into Character value: 16rfffd (Unicode replacement character) � for the representation in the monthly archive files (even though the single HTML files look well). :-) On 2022-11-28T13:55:06+01:00, christoph.thiede at student.hpi.uni-potsdam.de wrote: > This is another test. Sorry ... > > Sent from SIT (3). > > Ümläutß, sorry for the noisé! > Tab tab tab > > RxMatcher>>matchAgainstLookbehind:positive:nextLink: {matching} · ct 3/6/2020 20:09 (changed) > > Best, > Christoph > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > > From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 13:07:55 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 14:07:55 +0100 Subject: [squeak-dev] Encoding issue with pipermail archives Message-ID: <93b6e64d-92d3-4063-8257-e95e5f944cde@MX2018-DAG2.hpi.uni-potsdam.de> Hi all, while debugging some encoding issues in Squeak Inbox Talk, I observed a possible encoding issues with the pipermail archives for squeak-dev. Specifically, I'm referring to the downloadable versions, e.g., http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November.txt or http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November.txt.gz. When I retrieve such a file which is encoded as UTF-8 using the WebClient, the Content-Type header of the server response does not include the charset used, so Squeak does not decode the UTF-8 again. I'm not sure, but shouldn't the server indicate this? Of course, I can work around, just wanted to document this here. :-) (Note that this bug report is independent of the multipart encoding issue I analyzed in http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November/222729.html which turned out to be my fault.) Best, Christoph --- Sent from Squeak Inbox Talk -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 13:39:19 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 14:39:19 +0100 Subject: [squeak-dev] Encoding issue with pipermail archives In-Reply-To: <93b6e64d-92d3-4063-8257-e95e5f944cde@MX2018-DAG2.hpi.uni-potsdam.de> References: <93b6e64d-92d3-4063-8257-e95e5f944cde@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: <151e7b54-520e-4c63-a617-6748d26c1784@MX2018-DAG2.hpi.uni-potsdam.de> Hi, > (Note that this bug report is independent of the multipart encoding issue I analyzed in http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November/222729.html which turned out to be my fault.) Here is a second, slightly related issue: The notification mails by commits at source.squeak.org itself does not describe the charset of its messages, for instance in this message: http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-November/217286.html#:~:text=Same%20as%20in%20CodeHolder This leads to exactly the problem described above, that is, in the monthly archive files, the special character in the patch is replaced by a U+FFFD replacement char. Best, Christoph --- Sent from Squeak Inbox Talk On 2022-11-28T15:07:55+01:00, christoph.thiede at student.hpi.uni-potsdam.de wrote: > Hi all, > > while debugging some encoding issues in Squeak Inbox Talk, I observed a possible encoding issues with the pipermail archives for squeak-dev. Specifically, I'm referring to the downloadable versions, e.g., http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November.txt or http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November.txt.gz. > > When I retrieve such a file which is encoded as UTF-8 using the WebClient, the Content-Type header of the server response does not include the charset used, so Squeak does not decode the UTF-8 again. I'm not sure, but shouldn't the server indicate this? Of course, I can work around, just wanted to document this here. :-) > > (Note that this bug report is independent of the multipart encoding issue I analyzed in http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-November/222729.html which turned out to be my fault.) > > Best, > Christoph > > --- > Sent from Squeak Inbox Talk > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 15:09:45 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 16:09:45 +0100 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: References: Message-ID: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> Note for future self: This is a breaking change that should be documented in the next release notes. :-) Best, Christoph On 2022-09-06T16:03:35+00:00, commits at source.squeak.org wrote: > David T. Lewis uploaded a new version of Chronology-Core to project The Trunk: > http://source.squeak.org/trunk/Chronology-Core-dtl.80.mcz > > ==================== Summary ==================== > > Name: Chronology-Core-dtl.80 > Author: dtl > Time: 19 May 2022, 12:03:05.720962 pm > UUID: 1b1b97c4-bc35-408d-b548-f0d0376a0808 > Ancestors: Chronology-Core-dtl.79 > > Change DateAndTime>>offset: to be compliant with the ANSI draft spec. The offset: method should answer an instance equivalent to the receiver, where equivalent means having the same UTC time. > > Let #offset: adopt the prior behavior of #utcOffset: and let #utcOffset: be a compatibility synonym for #offset:. Add #asLocalAt: to the squeak protocol and let it implement the prior behavior of #offset: Change existing code and tests to use #asLocalAt: but otherwise retain existing behavior. > > Issue reported at https://github.com/squeak-smalltalk/squeak-object-memory/issues/23 > > =============== Diff against Chronology-Core-dtl.79 =============== > > Item was added: > + ----- Method: DateAndTime>>asLocalAt: (in category 'squeak protocol') ----- > + asLocalAt: anOffset > + "Answer a DateAndTime for a different time zone offset that has the same > + year, month, day, hour, minute, and second as this instance, and with > + printString that matches except for time zone offset." > + > + | newOffset newMicros | > + newOffset := anOffset asDuration asSeconds. > + newMicros := localOffsetSeconds - newOffset * 1000000 + utcMicroseconds. > + ^ self class utcMicroseconds: newMicros offset: newOffset > + ! > > Item was changed: > ----- Method: DateAndTime>>offset: (in category 'ansi protocol') ----- > offset: anOffset > + "Answer a equivalent to the receiver but with its local time > + being offset from UTC by offset. > - "Answer a DateAndTime for a different time zone offset that has the same > - year, month, day, hour, minute, and second as this instance, and with > - printString that matches except for time zone offset." > > + See asLocalAt: for the earlier behavior of this method." > + > + ^ self class > + utcMicroseconds: utcMicroseconds > + offset: anOffset asDuration asSeconds! > - | newOffset newMicros | > - newOffset := anOffset asDuration asSeconds. > - newMicros := localOffsetSeconds - newOffset * 1000000 + utcMicroseconds. > - ^ self class utcMicroseconds: newMicros offset: newOffset > - ! > > Item was changed: > ----- Method: DateAndTime>>utcOffset: (in category 'squeak protocol') ----- > utcOffset: anOffset > + "Compatiblity. Answer a DateAndTime equivalent to the receiver but offset from UTC by anOffset." > + > + ^ self offset: anOffset! > - "Answer a DateAndTime equivalent to the receiver but offset from UTC by anOffset" > - ^ self class > - utcMicroseconds: utcMicroseconds > - offset: anOffset asDuration asSeconds! > > Item was changed: > ----- Method: Timespan class>>current (in category 'squeak protocol') ----- > current > + ^ self starting: (DateAndTime now asLocalAt: self defaultOffset)! > - ^ self starting: (DateAndTime now offset: self defaultOffset)! > > From jakres+squeak at gmail.com Mon Nov 28 15:21:25 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 28 Nov 2022 16:21:25 +0100 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: Hi Christoph, Question to present you: do you have any means to definitively retrieve this note when you or anyone else actually writes the release notes? ;-) If there is a practical means to do so, maybe initialize these release notes right now and already write it down. Kind regards, Jakob Am Mo., 28. Nov. 2022 um 16:10 Uhr schrieb < christoph.thiede at student.hpi.uni-potsdam.de>: > Note for future self: This is a breaking change that should be documented > in the next release notes. :-) > > Best, > Christoph > > On 2022-09-06T16:03:35+00:00, commits at source.squeak.org wrote: > > > David T. Lewis uploaded a new version of Chronology-Core to project The > Trunk: > > http://source.squeak.org/trunk/Chronology-Core-dtl.80.mcz > > > > ==================== Summary ==================== > > > > Name: Chronology-Core-dtl.80 > > Author: dtl > > Time: 19 May 2022, 12:03:05.720962 pm > > UUID: 1b1b97c4-bc35-408d-b548-f0d0376a0808 > > Ancestors: Chronology-Core-dtl.79 > > > > Change DateAndTime>>offset: to be compliant with the ANSI draft spec. > The offset: method should answer an instance equivalent to the receiver, > where equivalent means having the same UTC time. > > > > Let #offset: adopt the prior behavior of #utcOffset: and let #utcOffset: > be a compatibility synonym for #offset:. Add #asLocalAt: to the squeak > protocol and let it implement the prior behavior of #offset: Change > existing code and tests to use #asLocalAt: but otherwise retain existing > behavior. > > > > Issue reported at > https://github.com/squeak-smalltalk/squeak-object-memory/issues/23 > > > > =============== Diff against Chronology-Core-dtl.79 =============== > > > > Item was added: > > + ----- Method: DateAndTime>>asLocalAt: (in category 'squeak protocol') > ----- > > + asLocalAt: anOffset > > + "Answer a DateAndTime for a different time zone offset that has > the same > > + year, month, day, hour, minute, and second as this instance, and > with > > + printString that matches except for time zone offset." > > + > > + | newOffset newMicros | > > + newOffset := anOffset asDuration asSeconds. > > + newMicros := localOffsetSeconds - newOffset * 1000000 + > utcMicroseconds. > > + ^ self class utcMicroseconds: newMicros offset: newOffset > > + ! > > > > Item was changed: > > ----- Method: DateAndTime>>offset: (in category 'ansi protocol') ----- > > offset: anOffset > > + "Answer a equivalent to the receiver but with its > local time > > + being offset from UTC by offset. > > - "Answer a DateAndTime for a different time zone offset that has > the same > > - year, month, day, hour, minute, and second as this instance, and > with > > - printString that matches except for time zone offset." > > > > + See asLocalAt: for the earlier behavior of this method." > > + > > + ^ self class > > + utcMicroseconds: utcMicroseconds > > + offset: anOffset asDuration asSeconds! > > - | newOffset newMicros | > > - newOffset := anOffset asDuration asSeconds. > > - newMicros := localOffsetSeconds - newOffset * 1000000 + > utcMicroseconds. > > - ^ self class utcMicroseconds: newMicros offset: newOffset > > - ! > > > > Item was changed: > > ----- Method: DateAndTime>>utcOffset: (in category 'squeak protocol') > ----- > > utcOffset: anOffset > > + "Compatiblity. Answer a DateAndTime equivalent to the receiver but > offset from UTC by anOffset." > > + > > + ^ self offset: anOffset! > > - "Answer a DateAndTime equivalent to the receiver but offset from > UTC by anOffset" > > - ^ self class > > - utcMicroseconds: utcMicroseconds > > - offset: anOffset asDuration asSeconds! > > > > Item was changed: > > ----- Method: Timespan class>>current (in category 'squeak protocol') > ----- > > current > > + ^ self starting: (DateAndTime now asLocalAt: self defaultOffset)! > > - ^ self starting: (DateAndTime now offset: self defaultOffset)! > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From drurowin at gmail.com Mon Nov 28 16:09:40 2022 From: drurowin at gmail.com (Lauren P) Date: Mon, 28 Nov 2022 09:09:40 -0700 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: List, Could we flag #breaking the way we flag #deprecated? I think we should hold off deleting the old implementation for at least one version... Is Squeak's debugger advanced enough to run the old code during the transition period? I was thinking #breaking:legacy: or similar to invoke the old implementation. User flexibility to not need to debug someone else's library, yaknow? On Mon, Nov 28, 2022, 08:21 Jakob Reschke wrote: > Hi Christoph, > > Question to present you: do you have any means to definitively retrieve > this note when you or anyone else actually writes the release notes? ;-) > > If there is a practical means to do so, maybe initialize these > release notes right now and already write it down. > > Kind regards, > Jakob > > > Am Mo., 28. Nov. 2022 um 16:10 Uhr schrieb < > christoph.thiede at student.hpi.uni-potsdam.de>: > >> Note for future self: This is a breaking change that should be documented >> in the next release notes. :-) >> >> Best, >> Christoph >> >> On 2022-09-06T16:03:35+00:00, commits at source.squeak.org wrote: >> >> > David T. Lewis uploaded a new version of Chronology-Core to project The >> Trunk: >> > http://source.squeak.org/trunk/Chronology-Core-dtl.80.mcz >> > >> > ==================== Summary ==================== >> > >> > Name: Chronology-Core-dtl.80 >> > Author: dtl >> > Time: 19 May 2022, 12:03:05.720962 pm >> > UUID: 1b1b97c4-bc35-408d-b548-f0d0376a0808 >> > Ancestors: Chronology-Core-dtl.79 >> > >> > Change DateAndTime>>offset: to be compliant with the ANSI draft spec. >> The offset: method should answer an instance equivalent to the receiver, >> where equivalent means having the same UTC time. >> > >> > Let #offset: adopt the prior behavior of #utcOffset: and let >> #utcOffset: be a compatibility synonym for #offset:. Add #asLocalAt: to the >> squeak protocol and let it implement the prior behavior of #offset: Change >> existing code and tests to use #asLocalAt: but otherwise retain existing >> behavior. >> > >> > Issue reported at >> https://github.com/squeak-smalltalk/squeak-object-memory/issues/23 >> > >> > =============== Diff against Chronology-Core-dtl.79 =============== >> > >> > Item was added: >> > + ----- Method: DateAndTime>>asLocalAt: (in category 'squeak protocol') >> ----- >> > + asLocalAt: anOffset >> > + "Answer a DateAndTime for a different time zone offset that has >> the same >> > + year, month, day, hour, minute, and second as this instance, and >> with >> > + printString that matches except for time zone offset." >> > + >> > + | newOffset newMicros | >> > + newOffset := anOffset asDuration asSeconds. >> > + newMicros := localOffsetSeconds - newOffset * 1000000 + >> utcMicroseconds. >> > + ^ self class utcMicroseconds: newMicros offset: newOffset >> > + ! >> > >> > Item was changed: >> > ----- Method: DateAndTime>>offset: (in category 'ansi protocol') ----- >> > offset: anOffset >> > + "Answer a equivalent to the receiver but with its >> local time >> > + being offset from UTC by offset. >> > - "Answer a DateAndTime for a different time zone offset that has >> the same >> > - year, month, day, hour, minute, and second as this instance, and >> with >> > - printString that matches except for time zone offset." >> > >> > + See asLocalAt: for the earlier behavior of this method." >> > + >> > + ^ self class >> > + utcMicroseconds: utcMicroseconds >> > + offset: anOffset asDuration asSeconds! >> > - | newOffset newMicros | >> > - newOffset := anOffset asDuration asSeconds. >> > - newMicros := localOffsetSeconds - newOffset * 1000000 + >> utcMicroseconds. >> > - ^ self class utcMicroseconds: newMicros offset: newOffset >> > - ! >> > >> > Item was changed: >> > ----- Method: DateAndTime>>utcOffset: (in category 'squeak protocol') >> ----- >> > utcOffset: anOffset >> > + "Compatiblity. Answer a DateAndTime equivalent to the receiver >> but offset from UTC by anOffset." >> > + >> > + ^ self offset: anOffset! >> > - "Answer a DateAndTime equivalent to the receiver but offset from >> UTC by anOffset" >> > - ^ self class >> > - utcMicroseconds: utcMicroseconds >> > - offset: anOffset asDuration asSeconds! >> > >> > Item was changed: >> > ----- Method: Timespan class>>current (in category 'squeak protocol') >> ----- >> > current >> > + ^ self starting: (DateAndTime now asLocalAt: self defaultOffset)! >> > - ^ self starting: (DateAndTime now offset: self defaultOffset)! >> > >> > >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 16:10:47 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 17:10:47 +0100 Subject: [squeak-dev] Release Notes Process (was: The Trunk: Chronology-Core-dtl.80.mcz) In-Reply-To: References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de>, Message-ID: <231f783f-32e6-4f60-9f8c-a649d424998a@MX2018-DAG2.hpi.uni-potsdam.de> Hi Jakob, > do you have any means to definitively retrievethis note when you or anyone else actually writes the release notes? ;-) Thank you for raising this question! For the last release notes, I did a quick search in Squeak Inbox Talk for "breaking change" in the timespan of the previous alpha version and skimmed the results quickly, which yielded 17 conversations that I was able to skim pretty quickly. However, this step is not documented anywhere. The entire process of writing release notes could benefit from some better documentation. (I also have too many other changes lying around in my working copy of SIT, one of them is a filter to search for versions for a particular release only which I used for the 6.0 release. I should really find some time to commit all of this stuff ...) > maybe initialize these release notes right now As already mentioned earlier [1], I wanted to propose that we migrate the release notes into the image using the HelpBrowser (similar to Help-Squeak-Project, maybe create another package for it?). Serializing, versioning, and deploying them through the squeak-app repository really felt unconvenient for me. We still could maintain a generated HTML version of them if we feel a need for this. Best, Christoph [1] http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-June/221167.html --- Sent from Squeak Inbox Talk On 2022-11-28T17:21:25+01:00, jakres+squeak at gmail.com wrote: > Hi Christoph, > > Question to present you: do you have any means to definitively retrieve > this note when you or anyone else actually writes the release notes? ;-) > > If there is a practical means to do so, maybe initialize these > release notes right now and already write it down. > > Kind regards, > Jakob > > > Am Mo., 28. Nov. 2022 um 16:10 Uhr schrieb < > christoph.thiede at student.hpi.uni-potsdam.de>: > > > Note for future self: This is a breaking change that should be documented > > in the next release notes. :-) > > > > Best, > > Christoph > > > > On 2022-09-06T16:03:35+00:00, commits at source.squeak.org wrote: > > > > > David T. Lewis uploaded a new version of Chronology-Core to project The > > Trunk: > > > http://source.squeak.org/trunk/Chronology-Core-dtl.80.mcz > > > > > > ==================== Summary ==================== > > > > > > Name: Chronology-Core-dtl.80 > > > Author: dtl > > > Time: 19 May 2022, 12:03:05.720962 pm > > > UUID: 1b1b97c4-bc35-408d-b548-f0d0376a0808 > > > Ancestors: Chronology-Core-dtl.79 > > > > > > Change DateAndTime>>offset: to be compliant with the ANSI draft spec. > > The offset: method should answer an instance equivalent to the receiver, > > where equivalent means having the same UTC time. > > > > > > Let #offset: adopt the prior behavior of #utcOffset: and let #utcOffset: > > be a compatibility synonym for #offset:. Add #asLocalAt: to the squeak > > protocol and let it implement the prior behavior of #offset: Change > > existing code and tests to use #asLocalAt: but otherwise retain existing > > behavior. > > > > > > Issue reported at > > https://github.com/squeak-smalltalk/squeak-object-memory/issues/23 > > > > > > =============== Diff against Chronology-Core-dtl.79 =============== > > > > > > Item was added: > > > + ----- Method: DateAndTime>>asLocalAt: (in category 'squeak protocol') > > ----- > > > + asLocalAt: anOffset > > > + "Answer a DateAndTime for a different time zone offset that has > > the same > > > + year, month, day, hour, minute, and second as this instance, and > > with > > > + printString that matches except for time zone offset." > > > + > > > + | newOffset newMicros | > > > + newOffset := anOffset asDuration asSeconds. > > > + newMicros := localOffsetSeconds - newOffset * 1000000 + > > utcMicroseconds. > > > + ^ self class utcMicroseconds: newMicros offset: newOffset > > > + ! > > > > > > Item was changed: > > > ----- Method: DateAndTime>>offset: (in category 'ansi protocol') ----- > > > offset: anOffset > > > + "Answer a equivalent to the receiver but with its > > local time > > > + being offset from UTC by offset. > > > - "Answer a DateAndTime for a different time zone offset that has > > the same > > > - year, month, day, hour, minute, and second as this instance, and > > with > > > - printString that matches except for time zone offset." > > > > > > + See asLocalAt: for the earlier behavior of this method." > > > + > > > + ^ self class > > > + utcMicroseconds: utcMicroseconds > > > + offset: anOffset asDuration asSeconds! > > > - | newOffset newMicros | > > > - newOffset := anOffset asDuration asSeconds. > > > - newMicros := localOffsetSeconds - newOffset * 1000000 + > > utcMicroseconds. > > > - ^ self class utcMicroseconds: newMicros offset: newOffset > > > - ! > > > > > > Item was changed: > > > ----- Method: DateAndTime>>utcOffset: (in category 'squeak protocol') > > ----- > > > utcOffset: anOffset > > > + "Compatiblity. Answer a DateAndTime equivalent to the receiver but > > offset from UTC by anOffset." > > > + > > > + ^ self offset: anOffset! > > > - "Answer a DateAndTime equivalent to the receiver but offset from > > UTC by anOffset" > > > - ^ self class > > > - utcMicroseconds: utcMicroseconds > > > - offset: anOffset asDuration asSeconds! > > > > > > Item was changed: > > > ----- Method: Timespan class>>current (in category 'squeak protocol') > > ----- > > > current > > > + ^ self starting: (DateAndTime now asLocalAt: self defaultOffset)! > > > - ^ self starting: (DateAndTime now offset: self defaultOffset)! > > > > > > > > > > > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From drurowin at gmail.com Mon Nov 28 16:49:01 2022 From: drurowin at gmail.com (Lauren P) Date: Mon, 28 Nov 2022 09:49:01 -0700 Subject: [squeak-dev] wrt debugger flexibility Message-ID: Hi List, In reference to my question about the debugger in regards to Chronology-Core-dtl.80, I have a proposal. I am halfway or so to stealing RESTART from Common Lisp for Squeak. It lets the programmer define alternatives for exception handling. Restarts would be responsible for making the Proceed, Abandon, etc. buttons in the debugger window, with every #on:offer: defining a button. It's an extra layer of indirection and complexity in the evaluator, but it is an extremely powerful tool for writing clean code. If I had to choose one of an interactive debugger or restarts I'd pick restarts. Implementation is easy but tedious... restarts have lots of optional parameters. If List thinks RESTART would be a good thing to have I will prioritize it. PS: Whoever wrote the signalling code, thank you. It is very clean and easy to read. I learned everything about dynamic extent in Smalltalk from reading it. -- Obviously, I vote yes, and the effort to not proselytize the Cult Of Restart here is great indeed. -------------- next part -------------- An HTML attachment was scrubbed... URL: From drurowin at gmail.com Mon Nov 28 17:01:42 2022 From: drurowin at gmail.com (Lauren P) Date: Mon, 28 Nov 2022 10:01:42 -0700 Subject: [squeak-dev] Full block closure return value testing/using in workspace? In-Reply-To: References: <3711F01C-950D-4BAE-B992-4EFC8C1BE408@cox.net> Message-ID: I read somewhere to never write ^ in a block you intend to give out. I use it to abandon methods in assertions and never any other time. One thing I do know from experimentation is it marks the method finished, so you can't call the block twice. You'll get BlockCannotReturn nowadays. It used to be a segmentation fault. On Mon, Nov 28, 2022, 04:33 LawsonEnglish wrote: > OK, thanks. > > I had thought perhaps it would act more like a break and take one to the > outside of the block, but instead it returns to the caller, as I should > have realized. > > Stilly me. > > L > > > > On Nov 28, 2022, at 04:15, Tobias Pape wrote: > > > > Hi Lawson > > > > good to see you. > > > >> On 28. Nov 2022, at 11:58, LawsonEnglish wrote: > >> > >> I was trying to test some ideas and was using the new FullBlockClosure > to return values for further use in a workspace. > >> > >> This works with “print it”: > >> > >> [Transcript show: 2;cr. ^2] value => 2 > >> > >> This does not work: > >> > >> test := [Transcript show: 2;cr. ^2] value > >> > >> test => nil. > > > > Yes, and that is expected. > > > > Two things: > > First, it seems you want to assign the _return value_ of a block to a > variable. > > To achieve this, do > > test := [Transcript show: 2;cr. 2] value "Note the missing > caret/return" > > > > This is because the last statement of a block will be its return value. > > > > Second, yes, the return/caret in the block does something but apparently > not the thing you expected. > > The effect for caret/^/return is: > > > > ^ statement "Returns the value from statement from the method" > > > > The last word is crucial. You return from the method, regardless of the > block you are in. > > > > Like so: > > > > fooo > > > > Transcript showln: 'foo 1'. > > self bar: > > [Transcript showln: 'block 1'. > > ^ 1]. > > Transcript showln: 'foo 2'. > > ^ 2. > > > > > > bar: aBlock > > > > Transcript showln: 'bar 1'. > > aBlock value. > > Transcript showln: 'bar 2'. > > > > > > If you send #foo, transcript will contain > > > > foo 1 > > bar 1 > > block 1 > > > > an the return value will be 1. > > > > This is because the Return in the block will return form the _method > #foo_ (where the block is defined) and not only from the block. > > > > What does that have to do with the Workspace??? > > > > Workspaces create artificial methods for doIts and PrintIts. > > > > Hence, your actually sent method looks like that: > > > > DoIt > > test := [Transcript show: 2;cr. ^2] value > > > > If you run that method as print-it, "^2" returns form the DoIt method > and the workspace can print the 2. > > If you run that method as print-it, "^2" returns form the DoIt method > but the assignment has never taken place, so test remains at its previous > value, wich is nil. > > > > I hope this helps. > > > > Best regards > > -Tobias > > > >> > >> nor does this: > >> > >> test :=( [Transcript show: 2;cr. ^2] value) > >> > >> test => nil > >> > >> print it still works: > >> > >> test := ([Transcript show: 2;cr. ^2] value) => 2 > >> > >> test => nil. > >> > >> In all cases, a 2 appears in the Transcript window, so I know that > *something* is happening. > >> > >> I would have thought that if print-it and do-it work, then the > returned value would be put in the test variable, but that is not the case. > >> > >> I can use a workspace global variable to access the output, but that > kinda makes the ^ a one-trick-pony: useful for breaking out of loops, but > not giving me access to the return value. > >> > >> > >> [test := 2. Transcript show: test;cr. ^test] value => 2 > >> > >> test => 2 > >> > >> Is this an oversight or bug or feature for workspaces, or is it working > as intended? > >> > >> > >> Lawson > >> > >> > >> > > > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Nov 28 17:24:43 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 28 Nov 2022 17:24:43 +0000 Subject: [squeak-dev] Full block closure return value testing/using in workspace? In-Reply-To: References: <3711F01C-950D-4BAE-B992-4EFC8C1BE408@cox.net> , Message-ID: <3baa4426adea4bc7bdec68c7452970fa@student.hpi.uni-potsdam.de> If you want to return from the block directly (but not from the containing method), here are some options: [:x | x ifNil: [#plonk] ifNotNil: [x + 1]]. [:x | x ifNil: [thisContext return: #plonk] ifNotNil: [x + 1]]. "metaprogramming, usually disregarded!" Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Lauren P Gesendet: Montag, 28. November 2022 18:01:42 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] Full block closure return value testing/using in workspace? I read somewhere to never write ^ in a block you intend to give out. I use it to abandon methods in assertions and never any other time. One thing I do know from experimentation is it marks the method finished, so you can't call the block twice. You'll get BlockCannotReturn nowadays. It used to be a segmentation fault. On Mon, Nov 28, 2022, 04:33 LawsonEnglish > wrote: OK, thanks. I had thought perhaps it would act more like a break and take one to the outside of the block, but instead it returns to the caller, as I should have realized. Stilly me. L > On Nov 28, 2022, at 04:15, Tobias Pape > wrote: > > Hi Lawson > > good to see you. > >> On 28. Nov 2022, at 11:58, LawsonEnglish > wrote: >> >> I was trying to test some ideas and was using the new FullBlockClosure to return values for further use in a workspace. >> >> This works with “print it”: >> >> [Transcript show: 2;cr. ^2] value => 2 >> >> This does not work: >> >> test := [Transcript show: 2;cr. ^2] value >> >> test => nil. > > Yes, and that is expected. > > Two things: > First, it seems you want to assign the _return value_ of a block to a variable. > To achieve this, do > test := [Transcript show: 2;cr. 2] value "Note the missing caret/return" > > This is because the last statement of a block will be its return value. > > Second, yes, the return/caret in the block does something but apparently not the thing you expected. > The effect for caret/^/return is: > > ^ statement "Returns the value from statement from the method" > > The last word is crucial. You return from the method, regardless of the block you are in. > > Like so: > > fooo > > Transcript showln: 'foo 1'. > self bar: > [Transcript showln: 'block 1'. > ^ 1]. > Transcript showln: 'foo 2'. > ^ 2. > > > bar: aBlock > > Transcript showln: 'bar 1'. > aBlock value. > Transcript showln: 'bar 2'. > > > If you send #foo, transcript will contain > > foo 1 > bar 1 > block 1 > > an the return value will be 1. > > This is because the Return in the block will return form the _method #foo_ (where the block is defined) and not only from the block. > > What does that have to do with the Workspace??? > > Workspaces create artificial methods for doIts and PrintIts. > > Hence, your actually sent method looks like that: > > DoIt > test := [Transcript show: 2;cr. ^2] value > > If you run that method as print-it, "^2" returns form the DoIt method and the workspace can print the 2. > If you run that method as print-it, "^2" returns form the DoIt method but the assignment has never taken place, so test remains at its previous value, wich is nil. > > I hope this helps. > > Best regards > -Tobias > >> >> nor does this: >> >> test :=( [Transcript show: 2;cr. ^2] value) >> >> test => nil >> >> print it still works: >> >> test := ([Transcript show: 2;cr. ^2] value) => 2 >> >> test => nil. >> >> In all cases, a 2 appears in the Transcript window, so I know that *something* is happening. >> >> I would have thought that if print-it and do-it work, then the returned value would be put in the test variable, but that is not the case. >> >> I can use a workspace global variable to access the output, but that kinda makes the ^ a one-trick-pony: useful for breaking out of loops, but not giving me access to the return value. >> >> >> [test := 2. Transcript show: test;cr. ^test] value => 2 >> >> test => 2 >> >> Is this an oversight or bug or feature for workspaces, or is it working as intended? >> >> >> Lawson >> >> >> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Nov 28 17:30:19 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 28 Nov 2022 17:30:19 +0000 Subject: [squeak-dev] wrt debugger flexibility In-Reply-To: References: Message-ID: <647b6dfacfde438a816c37e4105c64fa@student.hpi.uni-potsdam.de> Hi Lauren, Squeak Exceptions have a resumption mechanism. See Exception>>#resume:, or ProvideAnswerNotification and BlockClosure>>#valueSupplyingAnswers: for a common example. There is no UI integration for this, yet. However, this idea already has been mentioned on the list earlier, this would definitely be a sweet feature. Note that for #notYetImplemented, #doesNotUnderstand:, et al., the debugger already defines a variable button. See senders of #createImplementingMethod. However, this mechanism has not yet been generalized, i.e., by dispatching it to the original exception. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Lauren P Gesendet: Montag, 28. November 2022 17:49:01 An: The general-purpose Squeak developers list Betreff: [squeak-dev] wrt debugger flexibility Hi List, In reference to my question about the debugger in regards to Chronology-Core-dtl.80, I have a proposal. I am halfway or so to stealing RESTART from Common Lisp for Squeak. It lets the programmer define alternatives for exception handling. Restarts would be responsible for making the Proceed, Abandon, etc. buttons in the debugger window, with every #on:offer: defining a button. It's an extra layer of indirection and complexity in the evaluator, but it is an extremely powerful tool for writing clean code. If I had to choose one of an interactive debugger or restarts I'd pick restarts. Implementation is easy but tedious... restarts have lots of optional parameters. If List thinks RESTART would be a good thing to have I will prioritize it. PS: Whoever wrote the signalling code, thank you. It is very clean and easy to read. I learned everything about dynamic extent in Smalltalk from reading it. -- Obviously, I vote yes, and the effort to not proselytize the Cult Of Restart here is great indeed. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Nov 28 17:34:10 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 28 Nov 2022 17:34:10 +0000 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> , Message-ID: <956828c56ffe4f7ebe9da5738b691897@student.hpi.uni-potsdam.de> Hi Lauren, > Could we flag #breaking the way we flag #deprecated? This is an interesting idea, but I think that the concept of change mismatches the static concept of source code here. IMHO we should not start documenting changelogs in every single method again. :-) > I think we should hold off deleting the old implementation for at least one version... Is Squeak's debugger advanced enough to run the old code during the transition period? So many fancy ideas, but probably too fancy for a "production" system. :D Most likely, this would ultimately lead us to versioning hell, I think. However, some mechanisms that could be used for this would be layered methods (e.g. Context/S) or multiple environments to that one could install different versions of a package. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von Lauren P Gesendet: Montag, 28. November 2022 17:09:40 An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz List, Could we flag #breaking the way we flag #deprecated? I think we should hold off deleting the old implementation for at least one version... Is Squeak's debugger advanced enough to run the old code during the transition period? I was thinking #breaking:legacy: or similar to invoke the old implementation. User flexibility to not need to debug someone else's library, yaknow? On Mon, Nov 28, 2022, 08:21 Jakob Reschke > wrote: Hi Christoph, Question to present you: do you have any means to definitively retrieve this note when you or anyone else actually writes the release notes? ;-) If there is a practical means to do so, maybe initialize these release notes right now and already write it down. Kind regards, Jakob Am Mo., 28. Nov. 2022 um 16:10 Uhr schrieb >: Note for future self: This is a breaking change that should be documented in the next release notes. :-) Best, Christoph On 2022-09-06T16:03:35+00:00, commits at source.squeak.org wrote: > David T. Lewis uploaded a new version of Chronology-Core to project The Trunk: > http://source.squeak.org/trunk/Chronology-Core-dtl.80.mcz > > ==================== Summary ==================== > > Name: Chronology-Core-dtl.80 > Author: dtl > Time: 19 May 2022, 12:03:05.720962 pm > UUID: 1b1b97c4-bc35-408d-b548-f0d0376a0808 > Ancestors: Chronology-Core-dtl.79 > > Change DateAndTime>>offset: to be compliant with the ANSI draft spec. The offset: method should answer an instance equivalent to the receiver, where equivalent means having the same UTC time. > > Let #offset: adopt the prior behavior of #utcOffset: and let #utcOffset: be a compatibility synonym for #offset:. Add #asLocalAt: to the squeak protocol and let it implement the prior behavior of #offset: Change existing code and tests to use #asLocalAt: but otherwise retain existing behavior. > > Issue reported at https://github.com/squeak-smalltalk/squeak-object-memory/issues/23 > > =============== Diff against Chronology-Core-dtl.79 =============== > > Item was added: > + ----- Method: DateAndTime>>asLocalAt: (in category 'squeak protocol') ----- > + asLocalAt: anOffset > + "Answer a DateAndTime for a different time zone offset that has the same > + year, month, day, hour, minute, and second as this instance, and with > + printString that matches except for time zone offset." > + > + | newOffset newMicros | > + newOffset := anOffset asDuration asSeconds. > + newMicros := localOffsetSeconds - newOffset * 1000000 + utcMicroseconds. > + ^ self class utcMicroseconds: newMicros offset: newOffset > + ! > > Item was changed: > ----- Method: DateAndTime>>offset: (in category 'ansi protocol') ----- > offset: anOffset > + "Answer a equivalent to the receiver but with its local time > + being offset from UTC by offset. > - "Answer a DateAndTime for a different time zone offset that has the same > - year, month, day, hour, minute, and second as this instance, and with > - printString that matches except for time zone offset." > > + See asLocalAt: for the earlier behavior of this method." > + > + ^ self class > + utcMicroseconds: utcMicroseconds > + offset: anOffset asDuration asSeconds! > - | newOffset newMicros | > - newOffset := anOffset asDuration asSeconds. > - newMicros := localOffsetSeconds - newOffset * 1000000 + utcMicroseconds. > - ^ self class utcMicroseconds: newMicros offset: newOffset > - ! > > Item was changed: > ----- Method: DateAndTime>>utcOffset: (in category 'squeak protocol') ----- > utcOffset: anOffset > + "Compatiblity. Answer a DateAndTime equivalent to the receiver but offset from UTC by anOffset." > + > + ^ self offset: anOffset! > - "Answer a DateAndTime equivalent to the receiver but offset from UTC by anOffset" > - ^ self class > - utcMicroseconds: utcMicroseconds > - offset: anOffset asDuration asSeconds! > > Item was changed: > ----- Method: Timespan class>>current (in category 'squeak protocol') ----- > current > + ^ self starting: (DateAndTime now asLocalAt: self defaultOffset)! > - ^ self starting: (DateAndTime now offset: self defaultOffset)! > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From LEnglish5 at cox.net Mon Nov 28 17:34:07 2022 From: LEnglish5 at cox.net (LawsonEnglish) Date: Mon, 28 Nov 2022 10:34:07 -0700 Subject: [squeak-dev] Any progress on a GridLayout LayoutPolicy? Message-ID: Or if it is working in any substantial way, are there any working examples? Thanks. Lawson From jakres+squeak at gmail.com Mon Nov 28 17:49:04 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 28 Nov 2022 18:49:04 +0100 Subject: [squeak-dev] wrt debugger flexibility In-Reply-To: <647b6dfacfde438a816c37e4105c64fa@student.hpi.uni-potsdam.de> References: <647b6dfacfde438a816c37e4105c64fa@student.hpi.uni-potsdam.de> Message-ID: Hi Christoph, Note that restarts are more flexible than just resuming an exception because they can unwind the stack and restart at a different site than where signal was sent to the exception. Say, after a download failed, you could not only resume in the place after it has already happened, but you could restart at the point before the connection is made or change the URL... Kind regards, Jakob Thiede, Christoph schrieb am Mo., 28. Nov. 2022, 18:30: > Hi Lauren, > > > Squeak Exceptions have a resumption mechanism. See Exception>>#resume:, or > ProvideAnswerNotification and BlockClosure>>#valueSupplyingAnswers: for a > common example. > > > There is no UI integration for this, yet. However, this idea already has > been mentioned on the list earlier, this would definitely be a > sweet feature. Note that for #notYetImplemented, #doesNotUnderstand:, et > al., the debugger already defines a variable button. See senders of #createImplementingMethod. > However, this mechanism has not yet been generalized, i.e., by dispatching > it to the original exception. > > > Best, > > Christoph > ------------------------------ > *Von:* Squeak-dev im > Auftrag von Lauren P > *Gesendet:* Montag, 28. November 2022 17:49:01 > *An:* The general-purpose Squeak developers list > *Betreff:* [squeak-dev] wrt debugger flexibility > > Hi List, > > In reference to my question about the debugger in regards to > Chronology-Core-dtl.80, I have a proposal. > > I am halfway or so to stealing RESTART from Common Lisp for Squeak. It > lets the programmer define alternatives for exception handling. Restarts > would be responsible for making the Proceed, Abandon, etc. buttons in the > debugger window, with every #on:offer: defining a button. > > It's an extra layer of indirection and complexity in the evaluator, but it > is an extremely powerful tool for writing clean code. If I had to choose > one of an interactive debugger or restarts I'd pick restarts. > > Implementation is easy but tedious... restarts have lots of optional > parameters. If List thinks RESTART would be a good thing to have I will > prioritize it. > > PS: Whoever wrote the signalling code, thank you. It is very clean and > easy to read. I learned everything about dynamic extent in Smalltalk from > reading it. > > -- > Obviously, I vote yes, and the effort to not proselytize the Cult Of > Restart here is great indeed. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Mon Nov 28 18:05:51 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Mon, 28 Nov 2022 19:05:51 +0100 Subject: [squeak-dev] wrt debugger flexibility In-Reply-To: References: Message-ID: Hi Lauren, I am a big fan of Common Lisp conditions and restarts. Just as mentioned I too already mused on the list once that the debugger notifier buttons like Proceed and Abandon could be generalized in this way. However, they are not Smalltalk "standard" (not even de facto), therefore not portable, and you must expect that they do not get widely adopted even in the Squeak community (how many of us use Traits?!). I could see them being used as a Squeak-internal feature though, like for the debugger buttons... And I would like to use them for some error recovery cases in the Git Browser if they were already there. About increasing the complexity of the system, I am torn. In Cuis, restarts would probably have no place for that reason, unless the learning/understanding impact is really small. Maybe it would be good to see first how much more complicated things get with a restarts mechanism in place. But that may be well after you or anyone else has already invested most of the work. So, I would be delighted to see this happen. But I also do not want to incite any illusions. ;-) Kind regards, Jakob Lauren P schrieb am Mo., 28. Nov. 2022, 17:49: > Hi List, > > In reference to my question about the debugger in regards to > Chronology-Core-dtl.80, I have a proposal. > > I am halfway or so to stealing RESTART from Common Lisp for Squeak. It > lets the programmer define alternatives for exception handling. Restarts > would be responsible for making the Proceed, Abandon, etc. buttons in the > debugger window, with every #on:offer: defining a button. > > It's an extra layer of indirection and complexity in the evaluator, but it > is an extremely powerful tool for writing clean code. If I had to choose > one of an interactive debugger or restarts I'd pick restarts. > > Implementation is easy but tedious... restarts have lots of optional > parameters. If List thinks RESTART would be a good thing to have I will > prioritize it. > > PS: Whoever wrote the signalling code, thank you. It is very clean and > easy to read. I learned everything about dynamic extent in Smalltalk from > reading it. > > -- > Obviously, I vote yes, and the effort to not proselytize the Cult Of > Restart here is great indeed. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From christoph.thiede at student.hpi.uni-potsdam.de Mon Nov 28 18:10:25 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Mon, 28 Nov 2022 19:10:25 +0100 Subject: [squeak-dev] Review Request: browseMethodReference.1.cs Message-ID: =============== Summary =============== Change Set:        browseMethodReference Date:            28 November 2022 Author:            Christoph Thiede Adds support for method references in editors's 'Browse it' and 'iMplmentors' shortcuts. Method references can have different formats such as String findMethodReference or String>>#findMethodReference. Includes tests and proper support for message traces. Performance: <1.1 ms per run if you select an entire line, which should be fine. :-) Also makes sure that no debuggers opens up when you browse the iMplementors of an incomplete literal such as a single quote. =============== Diff =============== MessageTrace>>browseMethod:requestor: {actions} · ct 11/28/2022 18:00 + browseMethod: aMethodReference requestor: requestor +     "Overwritten to modify the trace if the request origins from a model-menu command such as the message-list menu (shortcut)." + +     (Preferences traceMessages and: [ self hasUnacceptedEdits not ]) +         ifTrue: [ self +             addChildMessages: (OrderedCollection with: aMethodReference) +             autoSelectString: '' ] +         ifFalse: [ super browseAllImplementorsOf: aMethodReference requestor: requestor ]. Model>>browseMethod: {*Tools-MessageSets} · ct 11/28/2022 18:58 + browseMethod: aMethodReference +     "A tool's widget/view (i.e., 'requestor') requested to browse aMethodReference. By default, dispatch back to the reference." + +     ^ aMethodReference browse Model>>browseMethod:requestor: {*Tools-MessageSets} · ct 11/28/2022 18:58 + browseMethod: aMethodReference requestor: requestor +     "A tool's widget/view (i.e., 'requestor') requested to browse aMethodReference. By default, dispatch back to the reference." + +     ^ self browseMethod: aMethodReference ParagraphEditor>>selectedLiteral {menu messages} · ct 11/28/2022 18:18 (changed) selectedLiteral     "Try to make a Smalltalk literal out of the current text selection." -     ^ self selection string findLiteral +     ^ [self selection string findLiteral] ifError: ["e.g., incomplete string"] String>>findMethodReference {converting} · ct 11/28/2022 19:03 + findMethodReference +     "Find and parse a method reference within the receiver. Answer a MethodReference or nil if none is found. Heuristic." + +     | str substrings | +     str := self copyReplaceAll: '>>' with: ' >> '. +     str := str copyWithRegex: '(?=(?>') asBit clampHigh: substrings size) to: classIndex + 1 by: -1 do: [:selIndex | +                 | ref selStr | +                 selStr := substrings at: selIndex. +                 (selStr size > 1 and: [selStr first = $#]) ifTrue: [selStr := selStr allButFirst]. +                 (Symbol lookup: selStr) ifNotNil: [:sel | +                     ref := MethodReference +                         class: class +                         selector: sel. +                     ref isValid ifTrue: [^ ref]]]]]. +     ^ nil StringTest>>testFindMethodReference {tests - finding} · ct 11/28/2022 18:11 + testFindMethodReference + +     { +         Number >> #negated. 'Number negated'. +         Number >> #negated. 'Number>>negated'. +         Number >> #negated. 'Number>>#negated'. +         Number >> #negated. 'Number >> #negated'. +          +         Number >> #negated. 'Number >> #negated.'. +         Number >> #negated. '"Number >> #negated"'. +         Number >> #negated. 'For more information, see Number>>#negated or run the tests.'. +          +         nil. 'Number absentSelector'. +         nil. ''. +          +         Morph >> #drawOn:. 'Morph drawOn:'. +         nil. 'Morph drawOn'. "Do not add colons." +          +         Number >> #+. 'Number +'. +         Number >> #+. 'Number>>+'. +         Number >> #+. 'Number>>#+'. +         Number >> #+. 'Number+'. +          +         Behavior >> #>>. 'Behavior >>'. +         Behavior >> #>>. 'Behavior>>'. +         Behavior >> #>>. 'Behavior>> >>'. +     } pairsDo: [:method :string | +         self +             assert: (method ifNotNil: [method asCodeReference]) +             equals: string findMethodReference]. TextEditor>>browseIt {menu messages} · ct 11/28/2022 17:53 (changed) browseIt     "Launch a browser for the current selection, if appropriate." +     self selectedMethodReference ifNotNil: +         [:methodReference | ^self model browseMethod: methodReference requestor: morph].     Preferences alternativeBrowseIt ifTrue: [^ self browseClassFromIt].     self lineSelectAndEmptyCheck: [^ morph flash].     "First, try to show all accesses to instance or class variables."     self selectedInstanceVariable ifNotNil:         [:nameToClass | self systemNavigation             browseAllAccessesTo: nameToClass key             from: nameToClass value].     self selectedClassVariable ifNotNil:         [:binding | self model browseAllCallsOn: binding].     "Then, either browse the class (from a binding) or all implementors of a selector."     self selectedBinding ifNotNil:         [:binding | ^ self systemNavigation browseClass: binding].     self selectedSelector ifNotNil:         [:selector | ^ self model browseAllImplementorsOf: selector requestor: morph].          morph flash TextEditor>>implementorsOfIt {menu messages} · ct 11/28/2022 17:05 (changed) implementorsOfIt     "Open an implementors browser on the selected selector"     self lineSelectAndEmptyCheck: [^ self]. +     self selectedMethodReference ifNotNil: +         [:methodReference | ^self model browseMethod: methodReference requestor: morph].     self selectedSelector ifNotNil:         [:aSelector| ^self model browseAllImplementorsOf: aSelector requestor: morph].     self selectedLiteral ifNotNil:         [:aLiteral| ^self model browseAllImplementorsOf: aLiteral requestor: morph].     morph flash. TextEditor>>selectedLiteral {menu messages} · ct 11/28/2022 18:18 (changed) selectedLiteral     "Try to make a Smalltalk literal out of the current text selection." -     ^ self selection string findLiteral +     ^ [self selection string findLiteral] ifError: ["e.g., incomplete string"] TextEditor>>selectedMethodReference {menu messages} · ct 11/28/2022 17:06 + selectedMethodReference +     "Try to make a method reference out of the current text selection." + +     ^ self selection string findMethodReference --- Sent from Squeak Inbox Talk ["browseMethodReference.1.cs"] -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: browseMethodReference.1.cs Type: application/octet-stream Size: 5980 bytes Desc: not available URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Mon Nov 28 18:35:01 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Mon, 28 Nov 2022 18:35:01 +0000 Subject: [squeak-dev] Any progress on a GridLayout LayoutPolicy? In-Reply-To: References: Message-ID: <69901122243446b7b5a1c1b90164c303@student.hpi.uni-potsdam.de> Hi Lawson, to my knowledge, GridLayout is working. Marcel (mt) could you tell you more. You can enable it for the entire world through the "Snap Morphs to World Grid" preference. As a quick pointer, you can find some examples in see GridLayoutTest, which looks like pretty solid documentation to me. :-) Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von LawsonEnglish Gesendet: Montag, 28. November 2022 18:34:07 An: The general-purpose Squeak developers list Betreff: [squeak-dev] Any progress on a GridLayout LayoutPolicy? Or if it is working in any substantial way, are there any working examples? Thanks. Lawson -------------- next part -------------- An HTML attachment was scrubbed... URL: From asqueaker at gmail.com Mon Nov 28 23:49:39 2022 From: asqueaker at gmail.com (Chris Muller) Date: Mon, 28 Nov 2022 17:49:39 -0600 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: Release Note reminders are already initialized as a side-effect of our normal development process. The way I wrote them for one or two 4.x releases was by literally reading the notes of all MCVersions since the previous production release. It's not hard to get all this pasted together in our IDE, and then it was just a matter of sitting down and reading and digesting them into which bits were important enough to include, and also re-written in a less-technical way for the Release Notes audience. I have since remembered to keep this use-case in mind when writing my MCVersion notes, e.g., I ask myself, "what verbiage will be helpful to future consumers of this note..?" while being as clear and terse as possible, because... ... going through all of them is a laborious one-time chore per release, but the best way to not miss anything. - Chris On Mon, Nov 28, 2022 at 9:21 AM Jakob Reschke wrote: > Hi Christoph, > > Question to present you: do you have any means to definitively retrieve > this note when you or anyone else actually writes the release notes? ;-) > > If there is a practical means to do so, maybe initialize these > release notes right now and already write it down. > > Kind regards, > Jakob > > > Am Mo., 28. Nov. 2022 um 16:10 Uhr schrieb < > christoph.thiede at student.hpi.uni-potsdam.de>: > >> Note for future self: This is a breaking change that should be documented >> in the next release notes. :-) >> >> Best, >> Christoph >> >> On 2022-09-06T16:03:35+00:00, commits at source.squeak.org wrote: >> >> > David T. Lewis uploaded a new version of Chronology-Core to project The >> Trunk: >> > http://source.squeak.org/trunk/Chronology-Core-dtl.80.mcz >> > >> > ==================== Summary ==================== >> > >> > Name: Chronology-Core-dtl.80 >> > Author: dtl >> > Time: 19 May 2022, 12:03:05.720962 pm >> > UUID: 1b1b97c4-bc35-408d-b548-f0d0376a0808 >> > Ancestors: Chronology-Core-dtl.79 >> > >> > Change DateAndTime>>offset: to be compliant with the ANSI draft spec. >> The offset: method should answer an instance equivalent to the receiver, >> where equivalent means having the same UTC time. >> > >> > Let #offset: adopt the prior behavior of #utcOffset: and let >> #utcOffset: be a compatibility synonym for #offset:. Add #asLocalAt: to the >> squeak protocol and let it implement the prior behavior of #offset: Change >> existing code and tests to use #asLocalAt: but otherwise retain existing >> behavior. >> > >> > Issue reported at >> https://github.com/squeak-smalltalk/squeak-object-memory/issues/23 >> > >> > =============== Diff against Chronology-Core-dtl.79 =============== >> > >> > Item was added: >> > + ----- Method: DateAndTime>>asLocalAt: (in category 'squeak protocol') >> ----- >> > + asLocalAt: anOffset >> > + "Answer a DateAndTime for a different time zone offset that has >> the same >> > + year, month, day, hour, minute, and second as this instance, and >> with >> > + printString that matches except for time zone offset." >> > + >> > + | newOffset newMicros | >> > + newOffset := anOffset asDuration asSeconds. >> > + newMicros := localOffsetSeconds - newOffset * 1000000 + >> utcMicroseconds. >> > + ^ self class utcMicroseconds: newMicros offset: newOffset >> > + ! >> > >> > Item was changed: >> > ----- Method: DateAndTime>>offset: (in category 'ansi protocol') ----- >> > offset: anOffset >> > + "Answer a equivalent to the receiver but with its >> local time >> > + being offset from UTC by offset. >> > - "Answer a DateAndTime for a different time zone offset that has >> the same >> > - year, month, day, hour, minute, and second as this instance, and >> with >> > - printString that matches except for time zone offset." >> > >> > + See asLocalAt: for the earlier behavior of this method." >> > + >> > + ^ self class >> > + utcMicroseconds: utcMicroseconds >> > + offset: anOffset asDuration asSeconds! >> > - | newOffset newMicros | >> > - newOffset := anOffset asDuration asSeconds. >> > - newMicros := localOffsetSeconds - newOffset * 1000000 + >> utcMicroseconds. >> > - ^ self class utcMicroseconds: newMicros offset: newOffset >> > - ! >> > >> > Item was changed: >> > ----- Method: DateAndTime>>utcOffset: (in category 'squeak protocol') >> ----- >> > utcOffset: anOffset >> > + "Compatiblity. Answer a DateAndTime equivalent to the receiver >> but offset from UTC by anOffset." >> > + >> > + ^ self offset: anOffset! >> > - "Answer a DateAndTime equivalent to the receiver but offset from >> UTC by anOffset" >> > - ^ self class >> > - utcMicroseconds: utcMicroseconds >> > - offset: anOffset asDuration asSeconds! >> > >> > Item was changed: >> > ----- Method: Timespan class>>current (in category 'squeak protocol') >> ----- >> > current >> > + ^ self starting: (DateAndTime now asLocalAt: self defaultOffset)! >> > - ^ self starting: (DateAndTime now offset: self defaultOffset)! >> > >> > >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lewis at mail.msen.com Tue Nov 29 00:02:31 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Mon, 28 Nov 2022 19:02:31 -0500 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> Message-ID: <20221129000231.GA38117@shell.msen.com> On Mon, Nov 28, 2022 at 09:09:40AM -0700, Lauren P wrote: > List, > > Could we flag #breaking the way we flag #deprecated? > Let's not over-engineer this. I'm the person who was worried about potentially breaking some external packages with the change in Chronology-Core-dtl. But it turned out to be a non-issue, nothing got broken and nobody had any problems with it at all. So it was just me being worried about something that was not a problem. We don't need to engineer a solution for my excessive worrying, I'll try to just stop doing that :-) Dave From LEnglish5 at cox.net Tue Nov 29 00:50:26 2022 From: LEnglish5 at cox.net (LawsonEnglish) Date: Mon, 28 Nov 2022 17:50:26 -0700 Subject: [squeak-dev] What it is the expected behavior of Rectangle (class) #intersect: if there is no interesection? Message-ID: <2E9BB6C5-E815-4369-BD9A-62FEC16CAAA4@cox.net> I did this and created 2 small rectangles quite far from each other trying to figure out what the method returns when there is no intersection: r1 := Rectangle fromUser. r2 := Rectangle fromUser. r2 3072 at 993 corner: 3203 at 1136 r1 2710 at 632 corner: 2835 at 752 r2 intersect: r1 3072 at 993 corner: 2835 at 752 r1 intersect: r2 3072 at 993 corner: 2835 at 752 Could someone explain these results? Not in terms of the math involved (I assume that there’s no math bug as the routine was last edited 22 years ago and it is used everywhere in Morphic), but what the LOGIC is for returning what is returned and what it means in the context of the comments: intersect: aRectangle "Answer a Rectangle that is the area in which the receiver overlaps with aRectangle…. “ I was trying to figure out how to look to identify when there is no intersection, and that isn’t at all obvious here. Thanks. L From drurowin at gmail.com Tue Nov 29 02:50:31 2022 From: drurowin at gmail.com (Lauren Pullen) Date: Tue, 29 Nov 2022 02:50:31 +0000 Subject: [squeak-dev] wrt debugger flexibility In-Reply-To: References: Message-ID: <028cacb5-f9e3-4ad6-91c1-4898897ed2c6@gmail.com> Jakob, On 11/28/22 18:05, Jakob Reschke wrote: > However, they are not Smalltalk "standard" (not even de facto), therefore > not portable, and you must expect that they do not get widely adopted even > in the Squeak community (how many of us use Traits?!). I could see them > being used as a Squeak-internal feature though, like for the debugger > buttons... And I would like to use them for some error recovery cases in > the Git Browser if they were already there. I wouldn't even care if it was unique to Squeak. I'm not really sure how much they get used in Common Lisp... I stayed away from them for a long time because I just never needed them, and, honestly, the example in the hyperspec lacks illustration. The normal HANDLER- macros were enough. Christoph's comment and my initial reaction to them are basically the same. > About increasing the complexity of the system, I am torn. In Cuis, restarts > would probably have no place for that reason, unless the > learning/understanding impact is really small. Maybe it would be good to > see first how much more complicated things get with a restarts mechanism in > place. But that may be well after you or anyone else has already invested > most of the work. Right? Hard to tell what the complexity will look like until after it's finished. And the ice cream sundae example... well... Sure, you'll learn, but you won't get. > So, I would be delighted to see this happen. But I also do not want to > incite any illusions. ;-) I mean, I'm half done. What's another half? ;3 From drurowin at gmail.com Tue Nov 29 03:45:32 2022 From: drurowin at gmail.com (Lauren Pullen) Date: Tue, 29 Nov 2022 03:45:32 +0000 Subject: [squeak-dev] wrt debugger flexibility In-Reply-To: <647b6dfacfde438a816c37e4105c64fa@student.hpi.uni-potsdam.de> References: <647b6dfacfde438a816c37e4105c64fa@student.hpi.uni-potsdam.de> Message-ID: <0aa85ac2-0db6-2703-b9e1-ecb1fa5802c1@gmail.com> Christoph (and anyone else with this reaction), On 11/28/22 17:30, Thiede, Christoph wrote: > Squeak Exceptions have a resumption mechanism. See Exception>>#resume:, or ProvideAnswerNotification and BlockClosure>>#valueSupplyingAnswers: for a common example. The name RESTART took me a couple tries to figure out. Obviously, there is a #resume: function in the exception system. I like 'restart normal evaluation after handling an exception' better, but it doesn't roll off the tongue, and I didn't write the Common Lisp spec, so we're stuck with it. Let me see if I can explain it better than ice cream sundaes with Jakob's download example... ~ ~ ~ ~ ~ ~ The short version: exception handlers let signallers talk to callers, and restarts let the callers talk back. ~ ~ ~ ~ ~ ~ You write a package that downloads a file. The download can fail, so what should you have the package do? Some users want to give up, others try again, and even others resume it where it left off, so which option do you pick? All three, of course! There's a method that knows how far into the download it's gotten. From there you offer 'Resume Download' that works the HTTP 2 magic. Maybe the internet had a hiccup. Maybe your cat sat on your laptop lid because she learned you need what's on the bottom and she wants attention. But first you need to reopen the TCP socket. We all know Abandon. Abandon is provided for you. But there's another Abandon: if you're loading that download into an instance and the user wants to 'Abandon Loading' you null out whatever incomplete state you were building so that some later check will see, 'Ya... this is null... It never got fetched.' and not 'What is ''828734t9tg9g9ubiuviub3r''?...'. Then comes Retry. In a different package that works with git, the user sees the reason it failed is they missed the last character during copy-paste. After a duh moment they change the URL and tell it to try that again. Just like Abandon, there are also two Retry options. 'Is it plugged in?' is an amazing question... no wonder it didn't work! Restarts are all about giving those options. That's why I named the message #on:OFFER:. It's an offer of some action to take. What's more, since these options cause branches in different methods... in different packages... and might be at the whim of the person in front of the screen... they go beyond the capabilities of only condition handlers. Sadly, that's more complicated than making a yummy ice cream sundae, but it's a good use case. > There is no UI integration for this, yet. However, this idea already has been mentioned on the list earlier, this would definitely be a sweet feature.Two sweets is better than, 'Oh yea... Trait...'. ;3 From karlramberg at gmail.com Tue Nov 29 05:50:18 2022 From: karlramberg at gmail.com (karl ramberg) Date: Tue, 29 Nov 2022 06:50:18 +0100 Subject: [squeak-dev] What it is the expected behavior of Rectangle (class) #intersect: if there is no interesection? In-Reply-To: <2E9BB6C5-E815-4369-BD9A-62FEC16CAAA4@cox.net> References: <2E9BB6C5-E815-4369-BD9A-62FEC16CAAA4@cox.net> Message-ID: Hi, I think you must use this method with a very similar name intersects: aRectangle "Answer whether aRectangle intersects the receiver anywhere." "Optimized; old code answered: (origin max: aRectangle origin) < (corner min: aRectangle corner)" Best, Karl On Tue, Nov 29, 2022 at 1:50 AM LawsonEnglish wrote: > I did this and created 2 small rectangles quite far from each other trying > to figure out what the method returns when there is no intersection: > > r1 := Rectangle fromUser. > r2 := Rectangle fromUser. > > r2 3072 at 993 corner: 3203 at 1136 > r1 2710 at 632 corner: 2835 at 752 > > r2 intersect: r1 3072 at 993 corner: 2835 at 752 > > r1 intersect: r2 3072 at 993 corner: 2835 at 752 > > Could someone explain these results? > > Not in terms of the math involved (I assume that there’s no math bug as > the routine was last edited 22 years ago and it is used everywhere in > Morphic), but what the LOGIC is for returning what is returned and what it > means in the context of the comments: > > intersect: aRectangle > "Answer a Rectangle that is the area in which the receiver > overlaps with > aRectangle…. “ > > I was trying to figure out how to look to identify when there is no > intersection, and that isn’t at all obvious here. > > Thanks. > > > L > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From karlramberg at gmail.com Tue Nov 29 06:01:26 2022 From: karlramberg at gmail.com (karl ramberg) Date: Tue, 29 Nov 2022 07:01:26 +0100 Subject: [squeak-dev] What it is the expected behavior of Rectangle (class) #intersect: if there is no interesection? In-Reply-To: References: <2E9BB6C5-E815-4369-BD9A-62FEC16CAAA4@cox.net> Message-ID: Doh, ignore my answer. Its to early in the morning :-D Best, Karl On Tue, Nov 29, 2022 at 6:50 AM karl ramberg wrote: > Hi, > I think you must use this method with a very similar name > > intersects: aRectangle > "Answer whether aRectangle intersects the receiver anywhere." > "Optimized; old code answered: > (origin max: aRectangle origin) < (corner min: aRectangle corner)" > > Best, > Karl > > On Tue, Nov 29, 2022 at 1:50 AM LawsonEnglish wrote: > >> I did this and created 2 small rectangles quite far from each other >> trying to figure out what the method returns when there is no intersection: >> >> r1 := Rectangle fromUser. >> r2 := Rectangle fromUser. >> >> r2 3072 at 993 corner: 3203 at 1136 >> r1 2710 at 632 corner: 2835 at 752 >> >> r2 intersect: r1 3072 at 993 corner: 2835 at 752 >> >> r1 intersect: r2 3072 at 993 corner: 2835 at 752 >> >> Could someone explain these results? >> >> Not in terms of the math involved (I assume that there’s no math bug as >> the routine was last edited 22 years ago and it is used everywhere in >> Morphic), but what the LOGIC is for returning what is returned and what it >> means in the context of the comments: >> >> intersect: aRectangle >> "Answer a Rectangle that is the area in which the receiver >> overlaps with >> aRectangle…. “ >> >> I was trying to figure out how to look to identify when there is no >> intersection, and that isn’t at all obvious here. >> >> Thanks. >> >> >> L >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From LEnglish5 at cox.net Tue Nov 29 07:09:02 2022 From: LEnglish5 at cox.net (LawsonEnglish) Date: Tue, 29 Nov 2022 00:09:02 -0700 Subject: [squeak-dev] What it is the expected behavior of Rectangle (class) #intersect: if there is no interesection? In-Reply-To: References: <2E9BB6C5-E815-4369-BD9A-62FEC16CAAA4@cox.net> Message-ID: <79E6B350-9683-477B-A245-0D48F988554A@cox.net> I think you’re right. Im trying to see if a selection rectangle for cells in a spreadsheet-like thing is selecting anything, so FIRST I do r1 intersects: rectangleList and then I guess iterate through again with #intersects: or perhaps I can combine. I’m guessing I need to go look at some python spreadsheet code or something. I’m working on the interface for the MorphleLogic simulator/programming app for the first gen SiliconSqueak chip due out first half of next year. It will allow one to manually (or programmatically) program an array of ML cells as they they were simple logical elements, which allows optimization of simple aspects of a software algorithm to be implemented in reprogrammable hardware, so this will give folks a feel for what the chip can do and hopefully inspire people to buy bunches of them for applications as yet unknown. Projected cost of the chip will be in the $0.03 - $0.15 range in bulk, depending on how cheap they can design it to be. It’s an SOC with circuitry designed for control of battery charging builtin, with an eye to extending the life of EV battery packs by disabling charging of individual batteries so you don’t have to recycle the entire pack to still safely recharge the rest of the pack. Secondary usecase is to keep track of solar cell viability in a solar panel, to extend solar panel life. The SiSq CPU won’t have enough memory to hold the Squeak IDE so you’ll need to program it from a laptop-based squeak (or perhaps a smartphone-based Squeak), but it should be the first commercial chip running the Smalltalk VM as the native ISA (it can also be switched to use almost any other stack-based interpreter if you want to use it as a SiliconPython chip or SiliconLua chip or whatever). The MorphleLogic part simply allows one to optimize special bits of code in hardware, so I’m working on the simulator/programmer for that part (the Squeak IDE is already done, afterall). L > On Nov 28, 2022, at 22:50, karl ramberg wrote: > > Hi, > I think you must use this method with a very similar name > > intersects: aRectangle > "Answer whether aRectangle intersects the receiver anywhere." > "Optimized; old code answered: > (origin max: aRectangle origin) < (corner min: aRectangle corner)" > > Best, > Karl > > On Tue, Nov 29, 2022 at 1:50 AM LawsonEnglish > wrote: >> I did this and created 2 small rectangles quite far from each other trying to figure out what the method returns when there is no intersection: >> >> r1 := Rectangle fromUser. >> r2 := Rectangle fromUser. >> >> r2 3072 at 993 corner: 3203 at 1136 >> r1 2710 at 632 corner: 2835 at 752 >> >> r2 intersect: r1 3072 at 993 corner: 2835 at 752 >> >> r1 intersect: r2 3072 at 993 corner: 2835 at 752 >> >> Could someone explain these results? >> >> Not in terms of the math involved (I assume that there’s no math bug as the routine was last edited 22 years ago and it is used everywhere in Morphic), but what the LOGIC is for returning what is returned and what it means in the context of the comments: >> >> intersect: aRectangle >> "Answer a Rectangle that is the area in which the receiver overlaps with >> aRectangle…. “ >> >> I was trying to figure out how to look to identify when there is no intersection, and that isn’t at all obvious here. >> >> Thanks. >> >> >> L >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jakres+squeak at gmail.com Tue Nov 29 07:54:01 2022 From: jakres+squeak at gmail.com (Jakob Reschke) Date: Tue, 29 Nov 2022 08:54:01 +0100 Subject: [squeak-dev] wrt debugger flexibility In-Reply-To: <0aa85ac2-0db6-2703-b9e1-ecb1fa5802c1@gmail.com> References: <647b6dfacfde438a816c37e4105c64fa@student.hpi.uni-potsdam.de> <0aa85ac2-0db6-2703-b9e1-ecb1fa5802c1@gmail.com> Message-ID: Lauren Pullen schrieb am Di., 29. Nov. 2022, 04:45: > What's > more, since these options cause branches in different methods... in > different packages... and might be at the whim of the person in front of > the screen... they go beyond the capabilities of only condition handlers. > Yup. But in case anyone of the readership wonders: restarts can also be invoked automatically by exception handlers. In case you don't want (or need) to leave the choice to the human with the cat on their laptop in some case. Thus restarts should be considered part of the interface of a solution, just like the exception types to be expected. In a game I wrote 12 years ago I used restarts to put a request that arrived in an untimely manner (peer to peer communication between three parties) into a waiting queue of the messaging component to be redelivered later. That was in response to the exception of the game logic component that the request could not be processed by the state machine at this time. -------------- next part -------------- An HTML attachment was scrubbed... URL: From giovanni at corriga.net Tue Nov 29 09:03:29 2022 From: giovanni at corriga.net (Giovanni Corriga) Date: Tue, 29 Nov 2022 09:03:29 +0000 Subject: [squeak-dev] UK Smalltalk User Group meeting - 30 November 2022 Message-ID: For this month's UKSTUG meeting, Dave Mason will talk about Zag Smalltalk, a new Smalltalk VM written in Zig. Dave Mason ( http://sarg.ryerson.ca/dmason/ ) has been a professor of Computer Science at Toronto Metropolitan University (previously known as Ryerson) for 41 years. He has done research on operating systems, software reliability and programming languages. Current research is mostly around Smalltalk and other dynamic languages. If forced to program very low level projects such as virtual machines, he is willing to use Zig or Rust, but for any other purpose, he insists on using higher productivity languages - primarily Smalltalk. Zag Smalltalk ( https://github.com/dvmason/Zag-Smalltalk ) is a principle-based Smalltalk VM. "Principled" means that the only 3 operations are: message send, assignment, and return. 1) it is designed from the ground up to use multi-processing, to leverage multi-core systems. 2) There is no special-casing of methods like ifTrue:ifFalse or whileTrue:, although of course some methods are implemented by primitive methods. It does aggressive inlining of methods and blocks. 3) “Source” code is maintained as ASTs. 4) Compiled code runs in a dual form of threaded code and JIT’ed machine code that seamlessly interoperate. 5) It has a partially-copying and partially-non-moving garbage collector. 6) It keeps many more values as immediate, including symbols. 7) It uses a single-level dispatch mechanism to implement Smalltalk dispatch semantics The research question is, "Can this be made fast enough to be competitive?” Preliminary results are encouraging. 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/290036186 ) to receive the meeting details. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Christoph.Thiede at student.hpi.uni-potsdam.de Tue Nov 29 12:03:46 2022 From: Christoph.Thiede at student.hpi.uni-potsdam.de (Thiede, Christoph) Date: Tue, 29 Nov 2022 12:03:46 +0000 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: <20221129000231.GA38117@shell.msen.com> References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> , <20221129000231.GA38117@shell.msen.com> Message-ID: > But it turned out to be a non-issue, nothing got broken and nobody had any problems with it at all. Well, Squeak Inbox Talk displayed dates in the wrong timezone since then until I noticed, but I have fixed that now. :-) What I want to say with that is, I would not assume that everyone who detects a bug or a breaking change will report it to the mailing list. I think (at least I hope?) that there is a notable part of the community that does not actively engage on the mailing list. Maybe someone also will update a package five years from now from Squeak 6.0 to Squeak 7.0 and stumble about that breaking change. But as mentioned earlier, I think that a simple entry in the release notes will be fine. Best, Christoph ________________________________ Von: Squeak-dev im Auftrag von David T. Lewis Gesendet: Dienstag, 29. November 2022 01:02 Uhr An: The general-purpose Squeak developers list Betreff: Re: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz On Mon, Nov 28, 2022 at 09:09:40AM -0700, Lauren P wrote: > List, > > Could we flag #breaking the way we flag #deprecated? > Let's not over-engineer this. I'm the person who was worried about potentially breaking some external packages with the change in Chronology-Core-dtl. But it turned out to be a non-issue, nothing got broken and nobody had any problems with it at all. So it was just me being worried about something that was not a problem. We don't need to engineer a solution for my excessive worrying, I'll try to just stop doing that :-) Dave -------------- next part -------------- An HTML attachment was scrubbed... URL: From fweimer at redhat.com Tue Nov 29 12:10:45 2022 From: fweimer at redhat.com (Florian Weimer) Date: Tue, 29 Nov 2022 13:10:45 +0100 Subject: [squeak-dev] Building with a strict(er) C99 compiler Message-ID: <87cz967ygq.fsf@oldenburg.str.redhat.com> I'm trying to build the VM with a C compiler which does not accept implicit function declarations or implici int. This is in preparation for a future change in GCC and Clang defaults. More information is here: (The second link points to a container image with an instrumented GCC that can be used for experiments, or you can just inject -Werror=implicit-function-declaration -Werror=implicit-int into the build, which has the same results if compiler flags injection works reliably throughout the build environment.) According to Fedora's records Squeak-4.10.2.2614-src-no-mp3 was downloaded from . I got passed the first obstacle with these little changes: diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/CroquetPlugin.h Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/CroquetPlugin.h --- Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/CroquetPlugin.h 2006-09-14 19:52:45.000000000 +0200 +++ Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/CroquetPlugin.h 2022-11-29 12:30:00.834158643 +0100 @@ -20,4 +20,6 @@ */ int ioGatherEntropy(char *bufPtr, int bufSize); +int triBoxOverlap(float *a, float *b, float *c, float *d, float *e); + #endif /* CROQUET_PLUGIN_H */ diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/TriBoxStub.c Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/TriBoxStub.c --- Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/TriBoxStub.c 2009-05-26 23:15:18.000000000 +0200 +++ Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/TriBoxStub.c 2022-11-29 12:30:10.184066148 +0100 @@ -1,3 +1,5 @@ +#include "CroquetPlugin.h" + /* a stub for triboxoverlap */ int triBoxOverlap(float *a, float *b, float *c, float *d, float *e) { return 0; diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/SerialPlugin/SerialPlugin.h Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/SerialPlugin/SerialPlugin.h --- Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/SerialPlugin/SerialPlugin.h 2009-08-27 03:48:06.000000000 +0200 +++ Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/SerialPlugin/SerialPlugin.h 2022-11-29 13:02:56.418443376 +0100 @@ -6,9 +6,13 @@ #pragma export on int serialPortClose(int portNum); +int serialPortCloseByName(const char *portName); + int serialPortCount(void); int serialPortOpen(int portNum, int baudRate, int stopBitsType, int parityType, int dataBits, int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar); +int serialPortOpenByName(char *portName, int dataRate, int stopBitsType, int parityType, int dataBits, + int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar); int serialPortReadInto(int portNum, int count, void *bufferPtr); int serialPortReadIntoByName(const char *portName, int count, void *bufferPtr); int serialPortWriteFrom(int portNum, int count, void *bufferPtr); diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c Squeak-4.10.2.2614-src-no-mp3/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c --- Squeak-4.10.2.2614-src-no-mp3.orig/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c 2006-10-18 19:10:25.000000000 +0200 +++ Squeak-4.10.2.2614-src-no-mp3/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c 2022-11-29 12:30:44.062730997 +0100 @@ -142,7 +142,7 @@ return fp; } -INLINE static allocateBuffer(struct FileBuf *buf, int size) +INLINE static int allocateBuffer(struct FileBuf *buf, int size) { if (buf->capacity >= size) return 1; A few more changes like these seem to be needed. But now I'm hitting this error: …/unix/src/vm/intplugins/MiscPrimitivePlugin/MiscPrimitivePlugin.c:118: implicit function declaration: isBytes This error is harder to deal with because it seems to be a bug in the code generator. There probably should be a macro definition for isBytes similar to arrayValueOf, like this: #define isBytes(oop) (interpreterProxy->isBytes(oop)) Otherwise, the global function definition is picked up instead, and that does not seem to be the right pattern. Thanks, Florian From karlramberg at gmail.com Tue Nov 29 18:05:45 2022 From: karlramberg at gmail.com (karl ramberg) Date: Tue, 29 Nov 2022 19:05:45 +0100 Subject: [squeak-dev] What it is the expected behavior of Rectangle (class) #intersect: if there is no interesection? In-Reply-To: <79E6B350-9683-477B-A245-0D48F988554A@cox.net> References: <2E9BB6C5-E815-4369-BD9A-62FEC16CAAA4@cox.net> <79E6B350-9683-477B-A245-0D48F988554A@cox.net> Message-ID: Here is a quite old spreadsheet like program. (2004) http://languagegame.org:8080/ggame/11 Maybe you get some inspiration from that :-D Best, Karl On Tue, Nov 29, 2022 at 8:09 AM LawsonEnglish wrote: > I think you’re right. Im trying to see if a selection rectangle for cells > in a spreadsheet-like thing is selecting anything, so FIRST I do r1 > intersects: rectangleList > > and then I guess iterate through again with #intersects: or perhaps I can > combine. > > I’m guessing I need to go look at some python spreadsheet code or > something. > > I’m working on the interface for the MorphleLogic simulator/programming > app for the first gen SiliconSqueak chip due out first half of next year. > It will allow one to manually (or programmatically) program an array of ML > cells as they they were simple logical elements, which allows optimization > of simple aspects of a software algorithm to be implemented in > reprogrammable hardware, so this will give folks a feel for what the chip > can do and hopefully inspire people to buy bunches of them for applications > as yet unknown. Projected cost of the chip will be in the $0.03 - $0.15 > range in bulk, depending on how cheap they can design it to be. It’s an SOC > with circuitry designed for control of battery charging builtin, with an > eye to extending the life of EV battery packs by disabling charging of > individual batteries so you don’t have to recycle the entire pack to still > safely recharge the rest of the pack. Secondary usecase is to keep track > of solar cell viability in a solar panel, to extend solar panel life. > > The SiSq CPU won’t have enough memory to hold the Squeak IDE so you’ll > need to program it from a laptop-based squeak (or perhaps a > smartphone-based Squeak), but it should be the first commercial chip > running the Smalltalk VM as the native ISA (it can also be switched to use > almost any other stack-based interpreter if you want to use it as a > SiliconPython chip or SiliconLua chip or whatever). The MorphleLogic part > simply allows one to optimize special bits of code in hardware, so I’m > working on the simulator/programmer for that part (the Squeak IDE is > already done, afterall). > > > L > > On Nov 28, 2022, at 22:50, karl ramberg wrote: > > Hi, > I think you must use this method with a very similar name > > intersects: aRectangle > "Answer whether aRectangle intersects the receiver anywhere." > "Optimized; old code answered: > (origin max: aRectangle origin) < (corner min: aRectangle corner)" > > Best, > Karl > > On Tue, Nov 29, 2022 at 1:50 AM LawsonEnglish wrote: > >> I did this and created 2 small rectangles quite far from each other >> trying to figure out what the method returns when there is no intersection: >> >> r1 := Rectangle fromUser. >> r2 := Rectangle fromUser. >> >> r2 3072 at 993 corner: 3203 at 1136 >> r1 2710 at 632 corner: 2835 at 752 >> >> r2 intersect: r1 3072 at 993 corner: 2835 at 752 >> >> r1 intersect: r2 3072 at 993 corner: 2835 at 752 >> >> Could someone explain these results? >> >> Not in terms of the math involved (I assume that there’s no math bug as >> the routine was last edited 22 years ago and it is used everywhere in >> Morphic), but what the LOGIC is for returning what is returned and what it >> means in the context of the comments: >> >> intersect: aRectangle >> "Answer a Rectangle that is the area in which the receiver >> overlaps with >> aRectangle…. “ >> >> I was trying to figure out how to look to identify when there is no >> intersection, and that isn’t at all obvious here. >> >> Thanks. >> >> >> L >> >> > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From commits at source.squeak.org Tue Nov 29 21:48:55 2022 From: commits at source.squeak.org (commits at source.squeak.org) Date: Tue, 29 Nov 2022 21:48:55 0000 Subject: [squeak-dev] The Trunk: Compiler-eem.483.mcz Message-ID: <20221129214859.1730214D692@mail.squeak.org> Eliot Miranda uploaded a new version of Compiler to project The Trunk: http://source.squeak.org/trunk/Compiler-eem.483.mcz ==================== Summary ==================== Name: Compiler-eem.483 Author: eem Time: 29 November 2022, 1:46:01.772575 pm UUID: 08cfac57-1240-4bff-bfc9-4af67efb8a5f Ancestors: Compiler-eem.482 Oops! The SistaV1 encoder has been including unnecessarily in the literal frame literals that are encoded in bytecodes (integers and characters in the -32k/32k, 0/64k range). Fix this and recompile. =============== Diff against Compiler-eem.482 =============== Item was changed: ----- Method: LiteralNode>>sizeCodeForValue: (in category 'code generation') ----- sizeCodeForValue: encoder - self reserve: encoder. ^(encoder isSpecialLiteralForPush: key) ifTrue: [encoder sizePushSpecialLiteral: key] + ifFalse: + [self reserve: encoder. + encoder sizePushLiteral: index]! - ifFalse: [encoder sizePushLiteral: index]! Item was changed: (PackageInfo named: 'Compiler') postscript: '"below, add code to be run after the loading of this package" + "recompile any and all SistaV1 compiled methods that refer to special literals. These literals were mistakenly included in the literal frame. saves about 200k bytes in a normal 64-bit Squeak image" + | e nm | + e := EncoderForSistaV1 new. + nm := 0. + ''Recompiling'' + displayProgressFrom: 1 + to: CompiledMethod instanceCount + during: + [:bar| + self systemNavigation allSelect: + [:m| | r | + bar value: (nm := nm + 1). + m encoderClass == EncoderForSistaV1 ifTrue: + [ + r := false. + m codeLiteralsDo: + [:cl| + cl literalsDo: [:l| (e isSpecialLiteralForPush: l) ifTrue: [r := true]]]. + r ifTrue: + [nm := nm + 1. + m methodClass recompile: m selector]]. + false]]'! - "Recompile senders of caseOf:" - self systemNavigation allSelectorsAndMethodsDo: [ :behavior :selector :method | - (method hasLiteral: #caseOf:) - ifTrue: [behavior recompile: selector]]. - - "Treat non-breaking space (16ra0) as delimiter in parser/scanner (Compiler-ct.473)." - Scanner initialize.'! From eliot.miranda at gmail.com Tue Nov 29 22:19:47 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue, 29 Nov 2022 14:19:47 -0800 Subject: [squeak-dev] Can anyone add me as a committer to http://www.squeaksource.com/INIFile? Message-ID: The package contains underscore assignments. _,,,^..^,,,_ best, Eliot -------------- next part -------------- An HTML attachment was scrubbed... URL: From lewis at mail.msen.com Tue Nov 29 22:46:24 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Tue, 29 Nov 2022 17:46:24 -0500 Subject: [squeak-dev] Can anyone add me as a committer to http://www.squeaksource.com/INIFile? In-Reply-To: References: Message-ID: <20221129224624.GA83821@shell.msen.com> On Tue, Nov 29, 2022 at 02:19:47PM -0800, Eliot Miranda wrote: > The package contains underscore assignments. > _,,,^..^,,,_ > best, Eliot > I set the access to this repository to global read and write, which should allow commits from the community (please let me know if it does not work). For the record: The project was created by Julian Fitzell, with administrators Julian Fitzell and Cees de Groot. License is MIT and the last commit was September 2005. Previously the access was global read, not is is set to global read/write to permit community support. Dave From lewis at mail.msen.com Tue Nov 29 22:48:10 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Tue, 29 Nov 2022 17:48:10 -0500 Subject: [squeak-dev] Can anyone add me as a committer to http://www.squeaksource.com/INIFile? In-Reply-To: <20221129224624.GA83821@shell.msen.com> References: <20221129224624.GA83821@shell.msen.com> Message-ID: <20221129224810.GB83821@shell.msen.com> On Tue, Nov 29, 2022 at 05:46:24PM -0500, David T. Lewis wrote: > On Tue, Nov 29, 2022 at 02:19:47PM -0800, Eliot Miranda wrote: > > The package contains underscore assignments. > > _,,,^..^,,,_ > > best, Eliot > > > > I set the access to this repository to global read and write, which > should allow commits from the community (please let me know if it > does not work). > > For the record: > > The project was created by Julian Fitzell, with administrators Julian > Fitzell and Cees de Groot. License is MIT and the last commit was > September 2005. Previously the access was global read, not is is > set to global read/write to permit community support. > I should get a spell checker. I meant to say "now it is set to global read/write". Dave From lewis at mail.msen.com Tue Nov 29 22:52:35 2022 From: lewis at mail.msen.com (David T. Lewis) Date: Tue, 29 Nov 2022 17:52:35 -0500 Subject: [squeak-dev] The Trunk: Chronology-Core-dtl.80.mcz In-Reply-To: References: <63387545-5ed3-40de-9dc0-4a8d52549ef3@MX2018-DAG2.hpi.uni-potsdam.de> <20221129000231.GA38117@shell.msen.com> Message-ID: <20221129225235.GC83821@shell.msen.com> On Tue, Nov 29, 2022 at 12:03:46PM +0000, Thiede, Christoph wrote: > > But it turned out to be a non-issue, nothing got broken and nobody had any problems with it at all. > > Well, Squeak Inbox Talk displayed dates in the wrong timezone since then until I noticed, but I have fixed that now. :-) Oh dear, I stand corrected! > What I want to say with that is, I would not assume that everyone who detects a bug or a breaking change will report it to the mailing list. I think (at least I hope?) that there is a notable part of the community that does not actively engage on the mailing list. Maybe someone also will update a package five years from now from Squeak 6.0 to Squeak 7.0 and stumble about that breaking change. But as mentioned earlier, I think that a simple entry in the release notes will be fine. > I agree. And your work on release notes is very much appreciated. Dave From eliot.miranda at gmail.com Wed Nov 30 02:33:43 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Tue, 29 Nov 2022 18:33:43 -0800 Subject: [squeak-dev] Building with a strict(er) C99 compiler In-Reply-To: <87cz967ygq.fsf@oldenburg.str.redhat.com> References: <87cz967ygq.fsf@oldenburg.str.redhat.com> Message-ID: <0FBCA268-ACCC-4A48-B62C-120741C23A37@gmail.com> Hi Florian, which vm are you trying to build? https://github.com/OpenSmalltalk/opensmalltalk-vm or some other vm? _,,,^..^,,,_ (phone) > On Nov 29, 2022, at 4:10 AM, Florian Weimer wrote: > > I'm trying to build the VM with a C compiler which does not accept > implicit function declarations or implici int. > > This is in preparation for a future change in GCC and Clang defaults. > More information is here: > > > > > (The second link points to a container image with an instrumented GCC > that can be used for experiments, or you can just inject > -Werror=implicit-function-declaration -Werror=implicit-int into the > build, which has the same results if compiler flags injection works > reliably throughout the build environment.) > > According to Fedora's records Squeak-4.10.2.2614-src-no-mp3 was > downloaded from . > > I got passed the first obstacle with these little changes: > > diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/CroquetPlugin.h Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/CroquetPlugin.h > --- Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/CroquetPlugin.h 2006-09-14 19:52:45.000000000 +0200 > +++ Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/CroquetPlugin.h 2022-11-29 12:30:00.834158643 +0100 > @@ -20,4 +20,6 @@ > */ > int ioGatherEntropy(char *bufPtr, int bufSize); > > +int triBoxOverlap(float *a, float *b, float *c, float *d, float *e); > + > #endif /* CROQUET_PLUGIN_H */ > diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/TriBoxStub.c Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/TriBoxStub.c > --- Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/CroquetPlugin/TriBoxStub.c 2009-05-26 23:15:18.000000000 +0200 > +++ Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/CroquetPlugin/TriBoxStub.c 2022-11-29 12:30:10.184066148 +0100 > @@ -1,3 +1,5 @@ > +#include "CroquetPlugin.h" > + > /* a stub for triboxoverlap */ > int triBoxOverlap(float *a, float *b, float *c, float *d, float *e) { > return 0; > diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/SerialPlugin/SerialPlugin.h Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/SerialPlugin/SerialPlugin.h > --- Squeak-4.10.2.2614-src-no-mp3.orig/Cross/plugins/SerialPlugin/SerialPlugin.h 2009-08-27 03:48:06.000000000 +0200 > +++ Squeak-4.10.2.2614-src-no-mp3/Cross/plugins/SerialPlugin/SerialPlugin.h 2022-11-29 13:02:56.418443376 +0100 > @@ -6,9 +6,13 @@ > > #pragma export on > int serialPortClose(int portNum); > +int serialPortCloseByName(const char *portName); > + > int serialPortCount(void); > int serialPortOpen(int portNum, int baudRate, int stopBitsType, int parityType, int dataBits, > int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar); > +int serialPortOpenByName(char *portName, int dataRate, int stopBitsType, int parityType, int dataBits, > + int inFlowCtrl, int outFlowCtrl, int xOnChar, int xOffChar); > int serialPortReadInto(int portNum, int count, void *bufferPtr); > int serialPortReadIntoByName(const char *portName, int count, void *bufferPtr); > int serialPortWriteFrom(int portNum, int count, void *bufferPtr); > diff -ur Squeak-4.10.2.2614-src-no-mp3.orig/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c Squeak-4.10.2.2614-src-no-mp3/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c > --- Squeak-4.10.2.2614-src-no-mp3.orig/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c 2006-10-18 19:10:25.000000000 +0200 > +++ Squeak-4.10.2.2614-src-no-mp3/unix/plugins/AsynchFilePlugin/sqUnixAsynchFile.c 2022-11-29 12:30:44.062730997 +0100 > @@ -142,7 +142,7 @@ > return fp; > } > > -INLINE static allocateBuffer(struct FileBuf *buf, int size) > +INLINE static int allocateBuffer(struct FileBuf *buf, int size) > { > if (buf->capacity >= size) > return 1; > > A few more changes like these seem to be needed. > > But now I'm hitting this error: > > …/unix/src/vm/intplugins/MiscPrimitivePlugin/MiscPrimitivePlugin.c:118: implicit function declaration: isBytes > > This error is harder to deal with because it seems to be a bug in the > code generator. There probably should be a macro definition for isBytes > similar to arrayValueOf, like this: > > #define isBytes(oop) (interpreterProxy->isBytes(oop)) > > Otherwise, the global function definition is picked up instead, and that > does not seem to be the right pattern. > > Thanks, > Florian > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fweimer at redhat.com Wed Nov 30 08:56:24 2022 From: fweimer at redhat.com (Florian Weimer) Date: Wed, 30 Nov 2022 09:56:24 +0100 Subject: [squeak-dev] Building with a strict(er) C99 compiler In-Reply-To: <0FBCA268-ACCC-4A48-B62C-120741C23A37@gmail.com> (Eliot Miranda's message of "Tue, 29 Nov 2022 18:33:43 -0800") References: <87cz967ygq.fsf@oldenburg.str.redhat.com> <0FBCA268-ACCC-4A48-B62C-120741C23A37@gmail.com> Message-ID: <87k03c95xj.fsf@oldenburg.str.redhat.com> * Eliot Miranda: > Hi Florian, > > which vm are you trying to build? > https://github.com/OpenSmalltalk/opensmalltalk-vm or > some other vm? I don't really know. I have this piece of information: > According to Fedora's records Squeak-4.10.2.2614-src-no-mp3 was > downloaded from . There seems to be some overlap with opensmalltalk/opensmalltalk-vm, but it's not the same code base. Is Fedora using outdated sources? Thanks, Florian From christoph.thiede at student.hpi.uni-potsdam.de Wed Nov 30 14:58:24 2022 From: christoph.thiede at student.hpi.uni-potsdam.de (christoph.thiede at student.hpi.uni-potsdam.de) Date: Wed, 30 Nov 2022 15:58:24 +0100 Subject: [squeak-dev] Review Request: noUNCPaths Message-ID: Repairs FileDirectory>>#exists for long paths (> 260 characters) on Windows by well-defining an edge case in the Windows implementation of the FilePlugin primitiveDirectoryEntry, that is, to specify a single dot (.) as the file name. Documents the present limitations to syntactic sugar in long file paths in the platform code, the relevant plugin methods, and on the image side of Squeak Trunk. An alternative consideration was to rewrite FileDirectory>>#exists to pass an empty string as file name to the primitive instead of modifying the VM, but strictly speaking, even this would have exploited an undefined behavior in the VM plugin, and an empty file name would be less idiomatic than a single dot. For the original bug report, see: https://github.com/hpi-swa-teaching/Morphic-Testing-Framework/issues/13 Thanks to Marcel (mt) for his support! Signed-off-by: Christoph Thiede --- Note that this mail contains both a git diff for the changes in the opensmalltalk-vm repository and a changeset for the changes in the Squeak Trunk so that they may be reviewed together. Any feedback on this formatting approach will be appreciated. Excited to receive your review! platforms/win32/vm/sqWin32Directory.c | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/platforms/win32/vm/sqWin32Directory.c b/platforms/win32/vm/sqWin32Directory.c index 2b3d090ec..0aa5c2108 100644 --- a/platforms/win32/vm/sqWin32Directory.c +++ b/platforms/win32/vm/sqWin32Directory.c @@ -196,6 +196,15 @@ sqInt dir_Lookup(char *pathString, sqInt pathLength, sqInt index, /* Lookup the index-th entry of the directory with the given path, starting at the root of the file system. Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). + + Note that, due to restrictions by the operating system, this method only + has limited support for paths longer than 260 characters. In the case of + longer paths, they must not contain syntactic sugar such as ".", "..", or + "a/b".* For more details, see: + https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#paths + *) Long paths are automatically converted into UNC paths, which only + support a subset of the normal path syntax. + Return: 0 if a entry is found at the given index 1 if the directory has fewer than index entries @@ -354,6 +363,20 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathLength, char* nameString, sqIn /* Lookup a given file in a given named directory. Set the name, name length, creation date, creation time, directory flag, and file size (if the entry is a file). + + Note that, due to restrictions by the operating system, this method only + has limited support for paths longer than 260 characters (for the full + path concatenated from the directory path, a backslash, and the file + name). In the case of longer paths, neither the path nor the file name + must contain syntactic sugar such as ".", "..", or "a/b".* However, this + method defines a single (!) convention for passing nameString as ".", + which is also supported for long paths. This convention is provided for + an efficient existence check of the directory (e.g., + FileDirectory>>#exists). For more details, see: + https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#paths + *) Long paths are automatically converted into UNC paths, which only + support a subset of the normal path syntax. + Return: 0 if found (a file or directory 'nameString' exists in directory 'pathString') 1 if the directory has no such entry @@ -416,6 +439,12 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathLength, char* nameString, sqIn fullPath=(char *)calloc(fullPathLength,sizeof(char)); memcpy(fullPath,pathString,pathLength); if (pathString[pathLength-1] != '\\') fullPath[pathLength]='\\'; + if (nameStringLength == 1 && nameString[0] == '.') { + /* special syntax: "." is the current directory. Trim it from the full + path to avoid generating a UNC path with an unresolved ".", which is + not supported there. See comment above. */ + nameStringLength = 0; + } memcpy(fullPath+fullPathLength-nameStringLength,nameString,nameStringLength); /* convert the path name into a null-terminated C string */ -- 2.37.3.windows.1 =============== Summary =============== Change Set:        noUNCPaths Date:            30 November 2022 Author:            Christoph Thiede Documents the present limitations to syntactic sugar in long file paths in the relevant plugin methods and on the image side. For the original bug report, see: https://github.com/hpi-swa-teaching/Morphic-Testing-Framework/issues/13 Thanks to Marcel (mt) for his support! =============== Diff =============== FileDirectory>>primLookupEntryIn:index: {private} · ct 11/29/2022 20:24 (changed) primLookupEntryIn: fullPath index: index     "Look up the index-th entry of the directory with the given fully-qualified path (i.e., starting from the root of the file hierarchy) and return an array containing:          The empty string enumerates the top-level files or drives. (For example, on Unix, the empty path enumerates the contents of '/'. On Macs and PCs, it enumerates the mounted volumes/drives.) +     Note that in general, fullPath must not contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters. See the comment in the primitive implementation for more details.     The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given path is bad."          ^ #badDirectoryPath FileDirectory>>primLookupEntryIn:name: {private} · ct 11/30/2022 15:38 (changed) primLookupEntryIn: fullPath name: fName -     "Look up (a simple file name) in the directory identified by      and return an array containing:          On Unix, the empty path denotes '/'. On Macs and PCs, it is the container of the system volumes.) +     Note that in general, neither fullPath nor fName must contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters (for the full path concatenated from the directory path, a backslash, and the file name). As a single (!) exception, the file name may always be a single dot ('.'), which is supported for an efficient existence test of the directory path (e.g., FileDirectory>>#exists). See the comment in the primitive implementation for more details.     The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given path is bad."          ^ #primFailed        "to distinguish from nil" FilePlugin>>primitiveDirectoryEntry {directory primitives} · ct 11/30/2022 15:13 (changed) primitiveDirectoryEntry     "Two arguments - directory path, and simple file name;      returns an array (see primitiveDirectoryLookup) describing the file or directory,      or nil if it does not exist. +      +      Note that in general, neither the directory path nor the file name must +      contain syntactic sugar for the current platform (e.g., '.' or '..', or on +      Windows, forward slashes instead of backslashes). These conventions are +      only fully supported on Unix platforms; on Windows, they are only +      supported for short non-UNC file paths containing max 260 characters (for +      the full path concatenated from the directory path, a backslash, and the +      file name). As a single (!) exception, the file name may always be a +      single dot ('.'), which is supported for an efficient existence test of +      the directory path (e.g., FileDirectory>>#exists). See the comment in +      sqWin32Directory.c for more details. +           Primitive fails if the outer path does not identify a readable directory.      (This is a lookup-by-name variant of primitiveDirectoryLookup.)"     | requestedName pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag posixPermissions symlinkFlag fileSize okToList reqNameIndex reqNameSize |                                   requestedName := interpreterProxy stackValue: 0.     pathName := interpreterProxy stackValue: 1.     (interpreterProxy isBytes: pathName) ifFalse:         [^interpreterProxy primitiveFail].     "Outbound string parameters"     pathNameIndex := interpreterProxy firstIndexableField: pathName.     pathNameSize := interpreterProxy byteSizeOf: pathName.     reqNameIndex := interpreterProxy firstIndexableField: requestedName.     reqNameSize := interpreterProxy byteSizeOf: requestedName.     self cCode: '' inSmalltalk:         [entryName := ByteString new: 256.          entryNameSize := createDate := modifiedDate := dirFlag := fileSize := posixPermissions := symlinkFlag := nil].     "If the security plugin can be loaded, use it to check for permission.      If not, assume it's ok"     okToList := sCLPfn ~= 0                     ifTrue: [self cCode: '((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize)' inSmalltalk: [true]]                     ifFalse: [true].     status := okToList         ifTrue:             [self dir_EntryLookup: pathNameIndex _: pathNameSize                     _: reqNameIndex _: reqNameSize                     _: entryName _: (self addressOf: entryNameSize put: [:v| entryNameSize := v])                     _: (self addressOf: createDate put: [:v| createDate := v])                     _: (self addressOf: modifiedDate put: [:v| modifiedDate := v])                     _: (self addressOf: dirFlag put: [:v| dirFlag := v])                     _: (self addressOf: fileSize put: [:v| fileSize := v])                     _: (self addressOf: posixPermissions put: [:v| posixPermissions := v])                     _: (self addressOf: symlinkFlag put: [:v| symlinkFlag := v])]         ifFalse:             [DirNoMoreEntries].     interpreterProxy failed ifTrue:         [^nil].     status = DirNoMoreEntries ifTrue: "no entry; return nil"         [interpreterProxy "pop pathName, index, rcvr"             pop: 3 thenPush: interpreterProxy nilObject.             ^nil].     status = DirBadPath ifTrue:         [^interpreterProxy primitiveFail]."bad path"     interpreterProxy         pop: 3    "pop pathName, index, rcvr"         thenPush:             (self                 cppIf: PharoVM                 ifTrue:                     [self                         makeDirEntryName: entryName                         size: entryNameSize                         createDate: createDate                         modDate: modifiedDate                         isDir: dirFlag                         fileSize: fileSize                         posixPermissions: posixPermissions                         isSymlink: symlinkFlag]                 ifFalse:                     [self                         makeDirEntryName: entryName                         size: entryNameSize                         createDate: createDate                         modDate: modifiedDate                         isDir: dirFlag                         fileSize: fileSize]) FilePlugin>>primitiveDirectoryLookup {directory primitives} · ct 11/30/2022 15:00 (changed) primitiveDirectoryLookup +     "Two arguments - directory path, and an index to an item; returns an array (see primitiveDirectoryLookup) describing the file or directory, or nil if it does not exist. +      +     Note that in general, the directory path must not contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters. See the comment in sqWin32Directory.c for more details. +      +     Primitive fails if the outer path does not identify a readable directory. (For a lookup-by-name variant, see primitiveDirectoryEntry.)"     | index pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag symlinkFlag posixPermissions fileSize okToList |                              index := interpreterProxy stackIntegerValue: 0.     pathName := interpreterProxy stackValue: 1.     (interpreterProxy isBytes: pathName)         ifFalse: [^interpreterProxy primitiveFail].     pathNameIndex := interpreterProxy firstIndexableField: pathName.     pathNameSize := interpreterProxy byteSizeOf: pathName.     self cCode: '' inSmalltalk:         [entryName := ByteString new: 256.          entryNameSize := createDate := modifiedDate := dirFlag := fileSize := posixPermissions := symlinkFlag := nil].     "If the security plugin can be loaded, use it to check for permission.     If not, assume it's ok"     okToList := sCLPfn ~= 0                     ifTrue: [self cCode: '((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize)' inSmalltalk: [true]]                     ifFalse: [true].     status := okToList         ifTrue:             [self dir_Lookup: pathNameIndex _: pathNameSize                     _: index                     _: entryName _: (self addressOf: entryNameSize put: [:v| entryNameSize := v])                     _: (self addressOf: createDate put: [:v| createDate := v])                     _: (self addressOf: modifiedDate put: [:v| modifiedDate := v])                     _: (self addressOf: dirFlag put: [:v| dirFlag := v])                     _: (self addressOf: fileSize put: [:v| fileSize := v])                     _: (self addressOf: posixPermissions put: [:v| posixPermissions := v])                     _: (self addressOf: symlinkFlag put: [:v| symlinkFlag := v])]         ifFalse: [DirNoMoreEntries].     interpreterProxy failed ifTrue:         [^nil].     status = DirNoMoreEntries ifTrue: "no more entries; return nil"         [interpreterProxy "pop pathName, index, rcvr"             pop: 3 thenPush: interpreterProxy nilObject.         ^nil].     status = DirBadPath ifTrue:         [^interpreterProxy primitiveFail]."bad path"     interpreterProxy         pop: 3    "pop pathName, index, rcvr"         thenPush:             (self                 cppIf: PharoVM                 ifTrue:                     [self                         makeDirEntryName: entryName                         size: entryNameSize                         createDate: createDate                         modDate: modifiedDate                         isDir: dirFlag                         fileSize: fileSize                         posixPermissions: posixPermissions                         isSymlink: symlinkFlag]                 ifFalse:                     [self                         makeDirEntryName: entryName                         size: entryNameSize                         createDate: createDate                         modDate: modifiedDate                         isDir: dirFlag                         fileSize: fileSize]) --- Sent from Squeak Inbox Talk ["noUNCPaths.3.cs"] -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: noUNCPaths.3.cs Type: application/octet-stream Size: 11726 bytes Desc: not available URL: From eliot.miranda at gmail.com Wed Nov 30 15:16:07 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed, 30 Nov 2022 07:16:07 -0800 Subject: [squeak-dev] Review Request: noUNCPaths In-Reply-To: References: Message-ID: Hi Christoph, looks good. Please cc messages like this which are relevant to the vm to vm-dev (aka opensmalltalk-vm). I would love to see some example paths in the comments below rather than just “don’t include ‘..’ ‘.’). Show a path that would be converted to unc path vs a proper windows path. People coming to the vm may not have experience with all platforms. Over commenting is a much better evil than overcommenting :-) Sorry for top posting _,,,^..^,,,_ (phone) > On Nov 30, 2022, at 6:58 AM, Christoph.Thiede at student.hpi.uni-potsdam.de wrote: > > Repairs FileDirectory>>#exists for long paths (> 260 characters) on Windows by well-defining an edge case in the Windows implementation of the FilePlugin primitiveDirectoryEntry, that is, to specify a single dot (.) as the file name. Documents the present limitations to syntactic sugar in long file paths in the platform code, the relevant plugin methods, and on the image side of Squeak Trunk. > > An alternative consideration was to rewrite FileDirectory>>#exists to pass an empty string as file name to the primitive instead of modifying the VM, but strictly speaking, even this would have exploited an undefined behavior in the VM plugin, and an empty file name would be less idiomatic than a single dot. > > For the original bug report, see: https://github.com/hpi-swa-teaching/Morphic-Testing-Framework/issues/13 Thanks to Marcel (mt) for his support! > > Signed-off-by: Christoph Thiede > --- > Note that this mail contains both a git diff for the changes in the opensmalltalk-vm repository and a changeset for the changes in the Squeak Trunk so that they may be reviewed together. Any feedback on this formatting approach will be appreciated. Excited to receive your review! > > platforms/win32/vm/sqWin32Directory.c | 29 +++++++++++++++++++++++++++ > 1 file changed, 29 insertions(+) > > diff --git a/platforms/win32/vm/sqWin32Directory.c b/platforms/win32/vm/sqWin32Directory.c > index 2b3d090ec..0aa5c2108 100644 > --- a/platforms/win32/vm/sqWin32Directory.c > +++ b/platforms/win32/vm/sqWin32Directory.c > @@ -196,6 +196,15 @@ sqInt dir_Lookup(char *pathString, sqInt pathLength, sqInt index, > /* Lookup the index-th entry of the directory with the given path, starting > at the root of the file system. Set the name, name length, creation date, > creation time, directory flag, and file size (if the entry is a file). > + > + Note that, due to restrictions by the operating system, this method only > + has limited support for paths longer than 260 characters. In the case of > + longer paths, they must not contain syntactic sugar such as ".", "..", or > + "a/b".* For more details, see: > + https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#paths > + *) Long paths are automatically converted into UNC paths, which only > + support a subset of the normal path syntax. > + > Return: > 0 if a entry is found at the given index > 1 if the directory has fewer than index entries > @@ -354,6 +363,20 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathLength, char* nameString, sqIn > /* Lookup a given file in a given named directory. > Set the name, name length, creation date, > creation time, directory flag, and file size (if the entry is a file). > + > + Note that, due to restrictions by the operating system, this method only > + has limited support for paths longer than 260 characters (for the full > + path concatenated from the directory path, a backslash, and the file > + name). In the case of longer paths, neither the path nor the file name > + must contain syntactic sugar such as ".", "..", or "a/b".* However, this > + method defines a single (!) convention for passing nameString as ".", > + which is also supported for long paths. This convention is provided for > + an efficient existence check of the directory (e.g., > + FileDirectory>>#exists). For more details, see: > + https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#paths > + *) Long paths are automatically converted into UNC paths, which only > + support a subset of the normal path syntax. > + > Return: > 0 if found (a file or directory 'nameString' exists in directory 'pathString') > 1 if the directory has no such entry > @@ -416,6 +439,12 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathLength, char* nameString, sqIn > fullPath=(char *)calloc(fullPathLength,sizeof(char)); > memcpy(fullPath,pathString,pathLength); > if (pathString[pathLength-1] != '\\') fullPath[pathLength]='\\'; > + if (nameStringLength == 1 && nameString[0] == '.') { > + /* special syntax: "." is the current directory. Trim it from the full > + path to avoid generating a UNC path with an unresolved ".", which is > + not supported there. See comment above. */ > + nameStringLength = 0; > + } > memcpy(fullPath+fullPathLength-nameStringLength,nameString,nameStringLength); > > /* convert the path name into a null-terminated C string */ > -- > 2.37.3.windows.1 > > =============== Summary =============== > > Change Set: noUNCPaths > Date: 30 November 2022 > Author: Christoph Thiede > > Documents the present limitations to syntactic sugar in long file paths in the relevant plugin methods and on the image side. > > For the original bug report, see: https://github.com/hpi-swa-teaching/Morphic-Testing-Framework/issues/13 Thanks to Marcel (mt) for his support! > > =============== Diff =============== > > FileDirectory>>primLookupEntryIn:index: {private} · ct 11/29/2022 20:24 (changed) > primLookupEntryIn: fullPath index: index > "Look up the index-th entry of the directory with the given fully-qualified path (i.e., starting from the root of the file hierarchy) and return an array containing: > > > > The empty string enumerates the top-level files or drives. (For example, on Unix, the empty path enumerates the contents of '/'. On Macs and PCs, it enumerates the mounted volumes/drives.) > + Note that in general, fullPath must not contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters. See the comment in the primitive implementation for more details. > > The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given path is bad." > > > ^ #badDirectoryPath > > > > FileDirectory>>primLookupEntryIn:name: {private} · ct 11/30/2022 15:38 (changed) > primLookupEntryIn: fullPath name: fName > - > "Look up (a simple file name) in the directory identified by > and return an array containing: > > > > On Unix, the empty path denotes '/'. > On Macs and PCs, it is the container of the system volumes.) > + Note that in general, neither fullPath nor fName must contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters (for the full path concatenated from the directory path, a backslash, and the file name). As a single (!) exception, the file name may always be a single dot ('.'), which is supported for an efficient existence test of the directory path (e.g., FileDirectory>>#exists). See the comment in the primitive implementation for more details. > > The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given path is bad." > > > > ^ #primFailed "to distinguish from nil" > > > > FilePlugin>>primitiveDirectoryEntry {directory primitives} · ct 11/30/2022 15:13 (changed) > primitiveDirectoryEntry > > "Two arguments - directory path, and simple file name; > returns an array (see primitiveDirectoryLookup) describing the file or directory, > or nil if it does not exist. > + > + Note that in general, neither the directory path nor the file name must > + contain syntactic sugar for the current platform (e.g., '.' or '..', or on > + Windows, forward slashes instead of backslashes). These conventions are > + only fully supported on Unix platforms; on Windows, they are only > + supported for short non-UNC file paths containing max 260 characters (for > + the full path concatenated from the directory path, a backslash, and the > + file name). As a single (!) exception, the file name may always be a > + single dot ('.'), which is supported for an efficient existence test of > + the directory path (e.g., FileDirectory>>#exists). See the comment in > + sqWin32Directory.c for more details. > + > Primitive fails if the outer path does not identify a readable directory. > (This is a lookup-by-name variant of primitiveDirectoryLookup.)" > > | requestedName pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag posixPermissions symlinkFlag fileSize okToList reqNameIndex reqNameSize | > > > > > > > > requestedName := interpreterProxy stackValue: 0. > pathName := interpreterProxy stackValue: 1. > (interpreterProxy isBytes: pathName) ifFalse: > [^interpreterProxy primitiveFail]. > > "Outbound string parameters" > pathNameIndex := interpreterProxy firstIndexableField: pathName. > pathNameSize := interpreterProxy byteSizeOf: pathName. > > reqNameIndex := interpreterProxy firstIndexableField: requestedName. > reqNameSize := interpreterProxy byteSizeOf: requestedName. > self cCode: '' inSmalltalk: > [entryName := ByteString new: 256. > entryNameSize := createDate := modifiedDate := dirFlag := fileSize := posixPermissions := symlinkFlag := nil]. > "If the security plugin can be loaded, use it to check for permission. > If not, assume it's ok" > okToList := sCLPfn ~= 0 > ifTrue: [self cCode: '((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize)' inSmalltalk: [true]] > ifFalse: [true]. > status := okToList > ifTrue: > [self dir_EntryLookup: pathNameIndex _: pathNameSize > _: reqNameIndex _: reqNameSize > _: entryName _: (self addressOf: entryNameSize put: [:v| entryNameSize := v]) > _: (self addressOf: createDate put: [:v| createDate := v]) > _: (self addressOf: modifiedDate put: [:v| modifiedDate := v]) > _: (self addressOf: dirFlag put: [:v| dirFlag := v]) > _: (self addressOf: fileSize put: [:v| fileSize := v]) > _: (self addressOf: posixPermissions put: [:v| posixPermissions := v]) > _: (self addressOf: symlinkFlag put: [:v| symlinkFlag := v])] > ifFalse: > [DirNoMoreEntries]. > > interpreterProxy failed ifTrue: > [^nil]. > status = DirNoMoreEntries ifTrue: "no entry; return nil" > [interpreterProxy "pop pathName, index, rcvr" > pop: 3 thenPush: interpreterProxy nilObject. > ^nil]. > status = DirBadPath ifTrue: > [^interpreterProxy primitiveFail]."bad path" > > interpreterProxy > pop: 3 "pop pathName, index, rcvr" > thenPush: > (self > cppIf: PharoVM > ifTrue: > [self > makeDirEntryName: entryName > size: entryNameSize > createDate: createDate > modDate: modifiedDate > isDir: dirFlag > fileSize: fileSize > posixPermissions: posixPermissions > isSymlink: symlinkFlag] > ifFalse: > [self > makeDirEntryName: entryName > size: entryNameSize > createDate: createDate > modDate: modifiedDate > isDir: dirFlag > fileSize: fileSize]) > > FilePlugin>>primitiveDirectoryLookup {directory primitives} · ct 11/30/2022 15:00 (changed) > primitiveDirectoryLookup > + "Two arguments - directory path, and an index to an item; returns an array (see primitiveDirectoryLookup) describing the file or directory, or nil if it does not exist. > + > + Note that in general, the directory path must not contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters. See the comment in sqWin32Directory.c for more details. > + > + Primitive fails if the outer path does not identify a readable directory. (For a lookup-by-name variant, see primitiveDirectoryEntry.)" > > | index pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag symlinkFlag posixPermissions fileSize okToList | > > > > > > > index := interpreterProxy stackIntegerValue: 0. > pathName := interpreterProxy stackValue: 1. > (interpreterProxy isBytes: pathName) > ifFalse: [^interpreterProxy primitiveFail]. > pathNameIndex := interpreterProxy firstIndexableField: pathName. > pathNameSize := interpreterProxy byteSizeOf: pathName. > self cCode: '' inSmalltalk: > [entryName := ByteString new: 256. > entryNameSize := createDate := modifiedDate := dirFlag := fileSize := posixPermissions := symlinkFlag := nil]. > "If the security plugin can be loaded, use it to check for permission. > If not, assume it's ok" > okToList := sCLPfn ~= 0 > ifTrue: [self cCode: '((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize)' inSmalltalk: [true]] > ifFalse: [true]. > status := okToList > ifTrue: > [self dir_Lookup: pathNameIndex _: pathNameSize > _: index > _: entryName _: (self addressOf: entryNameSize put: [:v| entryNameSize := v]) > _: (self addressOf: createDate put: [:v| createDate := v]) > _: (self addressOf: modifiedDate put: [:v| modifiedDate := v]) > _: (self addressOf: dirFlag put: [:v| dirFlag := v]) > _: (self addressOf: fileSize put: [:v| fileSize := v]) > _: (self addressOf: posixPermissions put: [:v| posixPermissions := v]) > _: (self addressOf: symlinkFlag put: [:v| symlinkFlag := v])] > ifFalse: [DirNoMoreEntries]. > interpreterProxy failed ifTrue: > [^nil]. > status = DirNoMoreEntries ifTrue: "no more entries; return nil" > [interpreterProxy "pop pathName, index, rcvr" > pop: 3 thenPush: interpreterProxy nilObject. > ^nil]. > status = DirBadPath ifTrue: > [^interpreterProxy primitiveFail]."bad path" > > interpreterProxy > pop: 3 "pop pathName, index, rcvr" > thenPush: > (self > cppIf: PharoVM > ifTrue: > [self > makeDirEntryName: entryName > size: entryNameSize > createDate: createDate > modDate: modifiedDate > isDir: dirFlag > fileSize: fileSize > posixPermissions: posixPermissions > isSymlink: symlinkFlag] > ifFalse: > [self > makeDirEntryName: entryName > size: entryNameSize > createDate: createDate > modDate: modifiedDate > isDir: dirFlag > fileSize: fileSize]) > > --- > Sent from Squeak Inbox Talk > ["noUNCPaths.3.cs"] -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: noUNCPaths.3.cs Type: application/octet-stream Size: 11726 bytes Desc: not available URL: -------------- next part -------------- An HTML attachment was scrubbed... URL: From eliot.miranda at gmail.com Wed Nov 30 15:16:49 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed, 30 Nov 2022 07:16:49 -0800 Subject: [squeak-dev] Review Request: noUNCPaths In-Reply-To: References: Message-ID: Oops! I see you did cc. I should stop reading email in my phone. The letterbox is too small. _,,,^..^,,,_ (phone) > On Nov 30, 2022, at 7:16 AM, Eliot Miranda wrote: > > Hi Christoph, > > looks good. Please cc messages like this which are relevant to the vm to vm-dev (aka opensmalltalk-vm). I would love to see some example paths in the comments below rather than just “don’t include ‘..’ ‘.’). Show a path that would be converted to unc path vs a proper windows path. People coming to the vm may not have experience with all platforms. Over commenting is a much better evil than overcommenting :-) > > Sorry for top posting > _,,,^..^,,,_ (phone) > >>> On Nov 30, 2022, at 6:58 AM, Christoph.Thiede at student.hpi.uni-potsdam.de wrote: >>> >> Repairs FileDirectory>>#exists for long paths (> 260 characters) on Windows by well-defining an edge case in the Windows implementation of the FilePlugin primitiveDirectoryEntry, that is, to specify a single dot (.) as the file name. Documents the present limitations to syntactic sugar in long file paths in the platform code, the relevant plugin methods, and on the image side of Squeak Trunk. >> >> An alternative consideration was to rewrite FileDirectory>>#exists to pass an empty string as file name to the primitive instead of modifying the VM, but strictly speaking, even this would have exploited an undefined behavior in the VM plugin, and an empty file name would be less idiomatic than a single dot. >> >> For the original bug report, see: https://github.com/hpi-swa-teaching/Morphic-Testing-Framework/issues/13 Thanks to Marcel (mt) for his support! >> >> Signed-off-by: Christoph Thiede >> --- >> Note that this mail contains both a git diff for the changes in the opensmalltalk-vm repository and a changeset for the changes in the Squeak Trunk so that they may be reviewed together. Any feedback on this formatting approach will be appreciated. Excited to receive your review! >> >> platforms/win32/vm/sqWin32Directory.c | 29 +++++++++++++++++++++++++++ >> 1 file changed, 29 insertions(+) >> >> diff --git a/platforms/win32/vm/sqWin32Directory.c b/platforms/win32/vm/sqWin32Directory.c >> index 2b3d090ec..0aa5c2108 100644 >> --- a/platforms/win32/vm/sqWin32Directory.c >> +++ b/platforms/win32/vm/sqWin32Directory.c >> @@ -196,6 +196,15 @@ sqInt dir_Lookup(char *pathString, sqInt pathLength, sqInt index, >> /* Lookup the index-th entry of the directory with the given path, starting >> at the root of the file system. Set the name, name length, creation date, >> creation time, directory flag, and file size (if the entry is a file). >> + >> + Note that, due to restrictions by the operating system, this method only >> + has limited support for paths longer than 260 characters. In the case of >> + longer paths, they must not contain syntactic sugar such as ".", "..", or >> + "a/b".* For more details, see: >> + https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#paths >> + *) Long paths are automatically converted into UNC paths, which only >> + support a subset of the normal path syntax. >> + >> Return: >> 0 if a entry is found at the given index >> 1 if the directory has fewer than index entries >> @@ -354,6 +363,20 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathLength, char* nameString, sqIn >> /* Lookup a given file in a given named directory. >> Set the name, name length, creation date, >> creation time, directory flag, and file size (if the entry is a file). >> + >> + Note that, due to restrictions by the operating system, this method only >> + has limited support for paths longer than 260 characters (for the full >> + path concatenated from the directory path, a backslash, and the file >> + name). In the case of longer paths, neither the path nor the file name >> + must contain syntactic sugar such as ".", "..", or "a/b".* However, this >> + method defines a single (!) convention for passing nameString as ".", >> + which is also supported for long paths. This convention is provided for >> + an efficient existence check of the directory (e.g., >> + FileDirectory>>#exists). For more details, see: >> + https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#paths >> + *) Long paths are automatically converted into UNC paths, which only >> + support a subset of the normal path syntax. >> + >> Return: >> 0 if found (a file or directory 'nameString' exists in directory 'pathString') >> 1 if the directory has no such entry >> @@ -416,6 +439,12 @@ sqInt dir_EntryLookup(char *pathString, sqInt pathLength, char* nameString, sqIn >> fullPath=(char *)calloc(fullPathLength,sizeof(char)); >> memcpy(fullPath,pathString,pathLength); >> if (pathString[pathLength-1] != '\\') fullPath[pathLength]='\\'; >> + if (nameStringLength == 1 && nameString[0] == '.') { >> + /* special syntax: "." is the current directory. Trim it from the full >> + path to avoid generating a UNC path with an unresolved ".", which is >> + not supported there. See comment above. */ >> + nameStringLength = 0; >> + } >> memcpy(fullPath+fullPathLength-nameStringLength,nameString,nameStringLength); >> >> /* convert the path name into a null-terminated C string */ >> -- >> 2.37.3.windows.1 >> >> =============== Summary =============== >> >> Change Set: noUNCPaths >> Date: 30 November 2022 >> Author: Christoph Thiede >> >> Documents the present limitations to syntactic sugar in long file paths in the relevant plugin methods and on the image side. >> >> For the original bug report, see: https://github.com/hpi-swa-teaching/Morphic-Testing-Framework/issues/13 Thanks to Marcel (mt) for his support! >> >> =============== Diff =============== >> >> FileDirectory>>primLookupEntryIn:index: {private} · ct 11/29/2022 20:24 (changed) >> primLookupEntryIn: fullPath index: index >> "Look up the index-th entry of the directory with the given fully-qualified path (i.e., starting from the root of the file hierarchy) and return an array containing: >> >> >> >> The empty string enumerates the top-level files or drives. (For example, on Unix, the empty path enumerates the contents of '/'. On Macs and PCs, it enumerates the mounted volumes/drives.) >> + Note that in general, fullPath must not contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters. See the comment in the primitive implementation for more details. >> >> The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given path is bad." >> >> >> ^ #badDirectoryPath >> >> >> >> FileDirectory>>primLookupEntryIn:name: {private} · ct 11/30/2022 15:38 (changed) >> primLookupEntryIn: fullPath name: fName >> - >> "Look up (a simple file name) in the directory identified by >> and return an array containing: >> >> >> >> On Unix, the empty path denotes '/'. >> On Macs and PCs, it is the container of the system volumes.) >> + Note that in general, neither fullPath nor fName must contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters (for the full path concatenated from the directory path, a backslash, and the file name). As a single (!) exception, the file name may always be a single dot ('.'), which is supported for an efficient existence test of the directory path (e.g., FileDirectory>>#exists). See the comment in the primitive implementation for more details. >> >> The creation and modification times are in seconds since the start of the Smalltalk time epoch. DirFlag is true if the entry is a directory. FileSize the file size in bytes or zero for directories. The primitive returns nil when index is past the end of the directory. It fails if the given path is bad." >> >> >> >> ^ #primFailed "to distinguish from nil" >> >> >> >> FilePlugin>>primitiveDirectoryEntry {directory primitives} · ct 11/30/2022 15:13 (changed) >> primitiveDirectoryEntry >> >> "Two arguments - directory path, and simple file name; >> returns an array (see primitiveDirectoryLookup) describing the file or directory, >> or nil if it does not exist. >> + >> + Note that in general, neither the directory path nor the file name must >> + contain syntactic sugar for the current platform (e.g., '.' or '..', or on >> + Windows, forward slashes instead of backslashes). These conventions are >> + only fully supported on Unix platforms; on Windows, they are only >> + supported for short non-UNC file paths containing max 260 characters (for >> + the full path concatenated from the directory path, a backslash, and the >> + file name). As a single (!) exception, the file name may always be a >> + single dot ('.'), which is supported for an efficient existence test of >> + the directory path (e.g., FileDirectory>>#exists). See the comment in >> + sqWin32Directory.c for more details. >> + >> Primitive fails if the outer path does not identify a readable directory. >> (This is a lookup-by-name variant of primitiveDirectoryLookup.)" >> >> | requestedName pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag posixPermissions symlinkFlag fileSize okToList reqNameIndex reqNameSize | >> >> >> >> >> >> >> >> requestedName := interpreterProxy stackValue: 0. >> pathName := interpreterProxy stackValue: 1. >> (interpreterProxy isBytes: pathName) ifFalse: >> [^interpreterProxy primitiveFail]. >> >> "Outbound string parameters" >> pathNameIndex := interpreterProxy firstIndexableField: pathName. >> pathNameSize := interpreterProxy byteSizeOf: pathName. >> >> reqNameIndex := interpreterProxy firstIndexableField: requestedName. >> reqNameSize := interpreterProxy byteSizeOf: requestedName. >> self cCode: '' inSmalltalk: >> [entryName := ByteString new: 256. >> entryNameSize := createDate := modifiedDate := dirFlag := fileSize := posixPermissions := symlinkFlag := nil]. >> "If the security plugin can be loaded, use it to check for permission. >> If not, assume it's ok" >> okToList := sCLPfn ~= 0 >> ifTrue: [self cCode: '((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize)' inSmalltalk: [true]] >> ifFalse: [true]. >> status := okToList >> ifTrue: >> [self dir_EntryLookup: pathNameIndex _: pathNameSize >> _: reqNameIndex _: reqNameSize >> _: entryName _: (self addressOf: entryNameSize put: [:v| entryNameSize := v]) >> _: (self addressOf: createDate put: [:v| createDate := v]) >> _: (self addressOf: modifiedDate put: [:v| modifiedDate := v]) >> _: (self addressOf: dirFlag put: [:v| dirFlag := v]) >> _: (self addressOf: fileSize put: [:v| fileSize := v]) >> _: (self addressOf: posixPermissions put: [:v| posixPermissions := v]) >> _: (self addressOf: symlinkFlag put: [:v| symlinkFlag := v])] >> ifFalse: >> [DirNoMoreEntries]. >> >> interpreterProxy failed ifTrue: >> [^nil]. >> status = DirNoMoreEntries ifTrue: "no entry; return nil" >> [interpreterProxy "pop pathName, index, rcvr" >> pop: 3 thenPush: interpreterProxy nilObject. >> ^nil]. >> status = DirBadPath ifTrue: >> [^interpreterProxy primitiveFail]."bad path" >> >> interpreterProxy >> pop: 3 "pop pathName, index, rcvr" >> thenPush: >> (self >> cppIf: PharoVM >> ifTrue: >> [self >> makeDirEntryName: entryName >> size: entryNameSize >> createDate: createDate >> modDate: modifiedDate >> isDir: dirFlag >> fileSize: fileSize >> posixPermissions: posixPermissions >> isSymlink: symlinkFlag] >> ifFalse: >> [self >> makeDirEntryName: entryName >> size: entryNameSize >> createDate: createDate >> modDate: modifiedDate >> isDir: dirFlag >> fileSize: fileSize]) >> >> FilePlugin>>primitiveDirectoryLookup {directory primitives} · ct 11/30/2022 15:00 (changed) >> primitiveDirectoryLookup >> + "Two arguments - directory path, and an index to an item; returns an array (see primitiveDirectoryLookup) describing the file or directory, or nil if it does not exist. >> + >> + Note that in general, the directory path must not contain syntactic sugar for the current platform (e.g., '.' or '..', or on Windows, forward slashes instead of backslashes). These conventions are only fully supported on Unix platforms; on Windows, they are only supported for short non-UNC file paths containing max 260 characters. See the comment in sqWin32Directory.c for more details. >> + >> + Primitive fails if the outer path does not identify a readable directory. (For a lookup-by-name variant, see primitiveDirectoryEntry.)" >> >> | index pathName pathNameIndex pathNameSize status entryName entryNameSize createDate modifiedDate dirFlag symlinkFlag posixPermissions fileSize okToList | >> >> >> >> >> >> >> index := interpreterProxy stackIntegerValue: 0. >> pathName := interpreterProxy stackValue: 1. >> (interpreterProxy isBytes: pathName) >> ifFalse: [^interpreterProxy primitiveFail]. >> pathNameIndex := interpreterProxy firstIndexableField: pathName. >> pathNameSize := interpreterProxy byteSizeOf: pathName. >> self cCode: '' inSmalltalk: >> [entryName := ByteString new: 256. >> entryNameSize := createDate := modifiedDate := dirFlag := fileSize := posixPermissions := symlinkFlag := nil]. >> "If the security plugin can be loaded, use it to check for permission. >> If not, assume it's ok" >> okToList := sCLPfn ~= 0 >> ifTrue: [self cCode: '((sqInt (*)(char *, sqInt))sCLPfn)(pathNameIndex, pathNameSize)' inSmalltalk: [true]] >> ifFalse: [true]. >> status := okToList >> ifTrue: >> [self dir_Lookup: pathNameIndex _: pathNameSize >> _: index >> _: entryName _: (self addressOf: entryNameSize put: [:v| entryNameSize := v]) >> _: (self addressOf: createDate put: [:v| createDate := v]) >> _: (self addressOf: modifiedDate put: [:v| modifiedDate := v]) >> _: (self addressOf: dirFlag put: [:v| dirFlag := v]) >> _: (self addressOf: fileSize put: [:v| fileSize := v]) >> _: (self addressOf: posixPermissions put: [:v| posixPermissions := v]) >> _: (self addressOf: symlinkFlag put: [:v| symlinkFlag := v])] >> ifFalse: [DirNoMoreEntries]. >> interpreterProxy failed ifTrue: >> [^nil]. >> status = DirNoMoreEntries ifTrue: "no more entries; return nil" >> [interpreterProxy "pop pathName, index, rcvr" >> pop: 3 thenPush: interpreterProxy nilObject. >> ^nil]. >> status = DirBadPath ifTrue: >> [^interpreterProxy primitiveFail]."bad path" >> >> interpreterProxy >> pop: 3 "pop pathName, index, rcvr" >> thenPush: >> (self >> cppIf: PharoVM >> ifTrue: >> [self >> makeDirEntryName: entryName >> size: entryNameSize >> createDate: createDate >> modDate: modifiedDate >> isDir: dirFlag >> fileSize: fileSize >> posixPermissions: posixPermissions >> isSymlink: symlinkFlag] >> ifFalse: >> [self >> makeDirEntryName: entryName >> size: entryNameSize >> createDate: createDate >> modDate: modifiedDate >> isDir: dirFlag >> fileSize: fileSize]) >> >> --- >> Sent from Squeak Inbox Talk >> ["noUNCPaths.3.cs"] > >> -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: noUNCPaths.3.cs Type: application/octet-stream Size: 11726 bytes Desc: not available URL: -------------- next part -------------- An HTML attachment was scrubbed... URL: From tim at rowledge.org Wed Nov 30 17:55:54 2022 From: tim at rowledge.org (tim Rowledge) Date: Wed, 30 Nov 2022 09:55:54 -0800 Subject: [squeak-dev] Building with a strict(er) C99 compiler In-Reply-To: <87k03c95xj.fsf@oldenburg.str.redhat.com> References: <87cz967ygq.fsf@oldenburg.str.redhat.com> <0FBCA268-ACCC-4A48-B62C-120741C23A37@gmail.com> <87k03c95xj.fsf@oldenburg.str.redhat.com> Message-ID: > On 2022-11-30, at 12:56 AM, Florian Weimer wrote: > > Is Fedora using outdated sources? Yes, very much so. Just like Debian etc. PhilB was working on solving the problem but ran out of time and so far nobody has been able to take up the challenge. tim -- tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim Useful random insult:- Teflon brain -- nothing sticks. From fweimer at redhat.com Wed Nov 30 19:41:03 2022 From: fweimer at redhat.com (Florian Weimer) Date: Wed, 30 Nov 2022 20:41:03 +0100 Subject: [squeak-dev] Building with a strict(er) C99 compiler In-Reply-To: (tim Rowledge's message of "Wed, 30 Nov 2022 09:55:54 -0800") References: <87cz967ygq.fsf@oldenburg.str.redhat.com> <0FBCA268-ACCC-4A48-B62C-120741C23A37@gmail.com> <87k03c95xj.fsf@oldenburg.str.redhat.com> Message-ID: <87zgc82ptc.fsf@oldenburg.str.redhat.com> * tim Rowledge: >> On 2022-11-30, at 12:56 AM, Florian Weimer wrote: >> >> Is Fedora using outdated sources? > > Yes, very much so. Just like Debian etc. PhilB was working on solving > the problem but ran out of time and so far nobody has been able to > take up the challenge. Should I propose to retire the Fedora package (i.e., remove it from future Fedora releases)? It's really ancient, and I'm worried we do the community a disservice here by misrepresenting the current state of the project. Anyway, I built the real sources with the instrumented compiler and submitted configure.ac: Fix tzet typo for tzset and it already got merged. Thanks! I found a couple of other places where implicit function declarations were involved, but don't really know what to do with these. diff --git a/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h b/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h index d21984e0c..2726be3cb 100755 --- a/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h +++ b/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h @@ -44,6 +44,8 @@ typedef struct #endif } mpeg3_slice_t; +void mpeg3_slice_loop(mpeg3_slice_t *slice); + #define mpeg3slice_fillbits(buffer, nbits) \ while(((mpeg3_slice_buffer_t*)(buffer))->bits_size < (nbits)) \ { \ That is probably an okay as a fix? diff --git a/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c b/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c index 5a68ec982..ddd733dc8 100644 --- a/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c +++ b/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c @@ -42,6 +42,8 @@ #include "FilePlugin.h" #include "DropPlugin.h" +extern usqIntptr_t fileRecordSize(void); + extern struct VirtualMachine *interpreterProxy; extern int uxDropFileCount; extern char **uxDropFileNames; This is way more questionable. I couldn't find the right header for this declaration. diff --git a/platforms/unix/vm-display-X11/sqUnixX11.c b/platforms/unix/vm-display-X11/sqUnixX11.c index 09b3f03f9..a07377ee9 100644 --- a/platforms/unix/vm-display-X11/sqUnixX11.c +++ b/platforms/unix/vm-display-X11/sqUnixX11.c @@ -4144,7 +4144,9 @@ void initPixmap(void) for (b= 0; b < 6; b++) { int i= 40 + ((36 * r) + (6 * b) + g); - if (i > 255) error("index out of range in color table compuation"); + if (i > 255) + fprintf(stderr, + "index out of range in color table compuation\n"); initColourmap(i, (r * 65535) / 5, (g * 65535) / 5, (b * 65535) / 5); } } I think the call goes to the error function in platforms/unix/vm/sqUnixMain.c, but its name is unfortunate because it interposes the function of the same name in glibc (which as a different prototype). diff --git a/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c b/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c index 64c384ba6..48372180f 100644 --- a/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c +++ b/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c @@ -33,6 +33,10 @@ static char __buildInfo[] = "XDisplayControlPlugin VMConstruction-Plugins-XDispl # define INT_EXT "(e)" #endif +void openXDisplay(void); +void forgetXDisplay(void); +void synchronizeXDisplay(void); +void disconnectXDisplay(void); /*** Function Prototypes ***/ EXPORT(const char*) getModuleName(void); This is obviously the wrong fix because it's in generated code, but it gets the build to pass. The logged errors are: …/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/getpicture.c:695: implicit function declaration: mpeg3_slice_loop …/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c:120: implicit function declaration: fileRecordSize …/platforms/unix/vm-display-X11/sqUnixX11.c:4147: implicit function declaration: error …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:188: implicit function declaration: forgetXDisplay …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:200: implicit function declaration: synchronizeXDisplay …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:259: implicit function declaration: disconnectXDisplay …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:284: implicit function declaration: openXDisplay You should be able to replicate this with unpatched GCC by building with -Werror=implicit-function-declaration. The instrumentation is only really needed for cases where errors do not fail the build and tend to be hidden (such as configure scripts). Thanks, Florian From eliot.miranda at gmail.com Wed Nov 30 23:57:30 2022 From: eliot.miranda at gmail.com (Eliot Miranda) Date: Wed, 30 Nov 2022 15:57:30 -0800 Subject: [squeak-dev] Building with a strict(er) C99 compiler In-Reply-To: <87zgc82ptc.fsf@oldenburg.str.redhat.com> References: <87zgc82ptc.fsf@oldenburg.str.redhat.com> Message-ID: <9F66599F-9780-4630-BF63-93B164048C51@gmail.com> > On Nov 30, 2022, at 11:41 AM, Florian Weimer wrote: > > * tim Rowledge: > >>>> On 2022-11-30, at 12:56 AM, Florian Weimer wrote: >>> >>> Is Fedora using outdated sources? >> >> Yes, very much so. Just like Debian etc. PhilB was working on solving >> the problem but ran out of time and so far nobody has been able to >> take up the challenge. > > Should I propose to retire the Fedora package (i.e., remove it from > future Fedora releases)? It's really ancient, and I'm worried we do the > community a disservice here by misrepresenting the current state of the > project. +1 > > Anyway, I built the real sources with the instrumented compiler and > submitted > > configure.ac: Fix tzet typo for tzset > > > and it already got merged. Thanks! Wow, thanks Florian! > > I found a couple of other places where implicit function declarations > were involved, but don't really know what to do with these. > > diff --git a/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h b/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h > index d21984e0c..2726be3cb 100755 > --- a/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h > +++ b/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/slice.h > @@ -44,6 +44,8 @@ typedef struct > #endif > } mpeg3_slice_t; > > +void mpeg3_slice_loop(mpeg3_slice_t *slice); > + > #define mpeg3slice_fillbits(buffer, nbits) \ > while(((mpeg3_slice_buffer_t*)(buffer))->bits_size < (nbits)) \ > { \ > > > That is probably an okay as a fix? > > diff --git a/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c b/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c > index 5a68ec982..ddd733dc8 100644 > --- a/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c > +++ b/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c > @@ -42,6 +42,8 @@ > #include "FilePlugin.h" > #include "DropPlugin.h" > > +extern usqIntptr_t fileRecordSize(void); > + > extern struct VirtualMachine *interpreterProxy; > extern int uxDropFileCount; > extern char **uxDropFileNames; > > This is way more questionable. I couldn't find the right header for > this declaration. > > > diff --git a/platforms/unix/vm-display-X11/sqUnixX11.c b/platforms/unix/vm-display-X11/sqUnixX11.c > index 09b3f03f9..a07377ee9 100644 > --- a/platforms/unix/vm-display-X11/sqUnixX11.c > +++ b/platforms/unix/vm-display-X11/sqUnixX11.c > @@ -4144,7 +4144,9 @@ void initPixmap(void) > for (b= 0; b < 6; b++) > { > int i= 40 + ((36 * r) + (6 * b) + g); > - if (i > 255) error("index out of range in color table compuation"); > + if (i > 255) > + fprintf(stderr, > + "index out of range in color table compuation\n"); > initColourmap(i, (r * 65535) / 5, (g * 65535) / 5, (b * 65535) / 5); > } > } > > > I think the call goes to the error function in > platforms/unix/vm/sqUnixMain.c, but its name is unfortunate because it > interposes the function of the same name in glibc (which as a different > prototype). > > diff --git a/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c b/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c > index 64c384ba6..48372180f 100644 > --- a/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c > +++ b/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c > @@ -33,6 +33,10 @@ static char __buildInfo[] = "XDisplayControlPlugin VMConstruction-Plugins-XDispl > # define INT_EXT "(e)" > #endif > > +void openXDisplay(void); > +void forgetXDisplay(void); > +void synchronizeXDisplay(void); > +void disconnectXDisplay(void); > > /*** Function Prototypes ***/ > EXPORT(const char*) getModuleName(void); > > This is obviously the wrong fix because it's in generated code, but it > gets the build to pass. > > The logged errors are: > > …/platforms/Cross/plugins/Mpeg3Plugin/libmpeg/video/getpicture.c:695: implicit function declaration: mpeg3_slice_loop > …/platforms/unix/plugins/DropPlugin/sqUnixDragDrop.c:120: implicit function declaration: fileRecordSize > …/platforms/unix/vm-display-X11/sqUnixX11.c:4147: implicit function declaration: error > …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:188: implicit function declaration: forgetXDisplay > …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:200: implicit function declaration: synchronizeXDisplay > …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:259: implicit function declaration: disconnectXDisplay > …/src/plugins/XDisplayControlPlugin/XDisplayControlPlugin.c:284: implicit function declaration: openXDisplay > > You should be able to replicate this with unpatched GCC by building with > -Werror=implicit-function-declaration. The instrumentation is only > really needed for cases where errors do not fail the build and tend to > be hidden (such as configure scripts). > > Thanks, > Florian > >