Christoph Thiede uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-ct.1442.mcz
==================== Summary ====================
Name: Kernel-ct.1442
Author: ct
Time: 3 January 2022, 9:25:00.293397 pm
UUID: 1c8eb404-f420-9f48-99fa-32c965fb5491
Ancestors: Kernel-mt.1441
Improves multilingual support in common error messages on Object.
Uploaded to the inbox because I am not sure whether any of these places should NOT invoke Get-Text to avoid infinite recursions. I already excluded the error selectors in the private category and #primitiveFailed: for this reason. How far do we want to go with multilingual support in low-level Kernel?
=============== Diff against Kernel-mt.1441 ===============
Item was changed:
----- Method: AdditionalMethodState>>copyWith: (in category 'copying') -----
copyWith: aPropertyOrPragma "<Association|Pragma>"
"Answer a copy of the receiver which includes aPropertyOrPragma"
| bs copy |
(Association == aPropertyOrPragma class
or: [Pragma == aPropertyOrPragma class]) ifFalse:
+ [self error: ('{1} instances should hold only Associations or Pragmas.' translated format: {self class name})].
- [self error: self class name, ' instances should hold only Associations or Pragmas.'].
"no need to initialize here; we're copying all inst vars"
copy := self class basicNew: (bs := self basicSize) + 1.
1 to: bs do:
[:i|
copy basicAt: i put: (self basicAt: i) shallowCopy].
copy basicAt: bs + 1 put: aPropertyOrPragma.
1 to: self class instSize do:
[:i| copy instVarAt: i put: (self instVarAt: i)].
^copy!
Item was changed:
----- Method: Object>>assert: (in category 'error handling') -----
assert: aBlock
"Throw an assertion error if aBlock does not evaluates to true."
+ aBlock value ifFalse: [AssertionFailure signal: 'Assertion failed' translated]!
- aBlock value ifFalse: [AssertionFailure signal: 'Assertion failed']!
Item was changed:
----- Method: Object>>backwardCompatibilityOnly: (in category 'error handling') -----
backwardCompatibilityOnly: explanationString
"Warn that the sending method has been deprecated. Methods that are tagt with #backwardCompatibility:
are kept for compatibility."
Deprecation
signalForContext: thisContext sender
+ message: ' (but will be kept for compatibility)' translated
- message: ' (but will be kept for compatibility)'
explanation: explanationString!
Item was changed:
----- Method: Object>>caseError (in category 'error handling') -----
caseError
"Report an error from an in-line or explicit case statement."
+ self error: ('Case not found ({1}), and no otherwise clause' translated format: {self printString})!
- self error: ('Case not found ({1}), and no otherwise clause' format: {self printString})!
Item was changed:
----- Method: Object>>doesNotUnderstand: (in category 'error handling') -----
doesNotUnderstand: aMessage
"Handle the fact that there was an attempt to send the given
message to the receiver but the receiver does not understand
this message (typically sent from the machine when a message
is sent to the receiver and no method is defined for that selector).
Raise the MessageNotUnderstood signal. If it is caught, answer
the result supplied by the exception handler. If it is not caught,
answer the result of resending the message within a guard for
infinite recursion. This allows, for example, the programmer to
implement the method and continue."
"Testing: (3 activeProcess)"
| exception resumeValue |
(exception := MessageNotUnderstood new)
message: aMessage;
receiver: self.
resumeValue := exception signal.
^exception reachedDefaultHandler "i.e. exception was not caught..."
ifTrue:
[[aMessage sentTo: self]
on: MessageNotUnderstood
do: [:ex|
(self == ex receiver
and: [aMessage hasIdenticalContentsAs: ex message]) ifFalse:
[ex pass].
+ self error: 'infinite recursion in doesNotUnderstand:' translated]]
- self error: 'infinite recursion in doesNotUnderstand:']]
ifFalse: [resumeValue]!
Item was changed:
----- Method: Object>>error (in category 'error handling') -----
error
"Throw a generic Error exception."
+ ^self error: 'Error!!' translated.!
- ^self error: 'Error!!'.!
Item was changed:
----- Method: Object>>shouldBeImplemented (in category 'error handling') -----
shouldBeImplemented
"Announce that this message should be implemented"
+ ^ NotImplemented signal: ('{1} or a superclass should implement {2}' translated format: {self className. thisContext sender selector})!
- ^ NotImplemented signal: ('{1} or a superclass should implement {2}' format: {self className. thisContext sender selector})!
Item was changed:
----- Method: Object>>shouldNotImplement (in category 'error handling') -----
shouldNotImplement
"Announce that, although the receiver inherits this message, it should
not implement it."
+ NotImplemented signal: ('{1} is not a message appropriate for a {2}' translated format: {thisContext sender selector. self className}).!
- NotImplemented signal: ('{1} is not a message appropriate for a {2}' format: {thisContext sender selector. self className}).!
Item was changed:
----- Method: Object>>subclassResponsibility (in category 'error handling') -----
subclassResponsibility
"This message sets up a framework for the behavior of the class' subclasses.
Announce that the subclass should have implemented this message."
^ SubclassResponsibility
signal: ('My {1} subclass should have overridden {2}'
+ translated format: {self className. thisContext sender selector}).!
- format: {self className. thisContext sender selector}).!
Item was changed:
----- Method: Object>>traitConflict (in category 'error handling') -----
traitConflict
+ self error: 'A class or trait does not properly resolve a conflict between multiple traits it uses.' translated!
- self error: 'A class or trait does not properly resolve a conflict between multiple traits it uses.'!
Christoph Thiede uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-ct.1557.mcz
==================== Summary ====================
Name: Kernel-ct.1557
Author: ct
Time: 2 March 2024, 6:57:26.957512 pm
UUID: 6f373fc9-2314-3c4b-b252-07eb1d5e1f4b
Ancestors: Kernel-ct.1556, Kernel-ct.1442, Kernel-ct.1410, Kernel-ct.1385
Merge commit.
Kernel-ct.1410:
Makes IllegalResumeAttempt an error.
Revision: Makes IllegalResumeAttempt resumable. See: http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-May/215520.html
Kernel-ct.1385 & Kernel-ct.1442:
Improves multilingual support in common error messages on Object & others.
=============== Diff against Kernel-ct.1556 ===============
Item was changed:
----- Method: AdditionalMethodState>>copyWith: (in category 'copying') -----
copyWith: aPropertyOrPragma "<Association|Pragma>"
"Answer a copy of the receiver which includes aPropertyOrPragma"
| bs copy |
(Association == aPropertyOrPragma class
or: [Pragma == aPropertyOrPragma class]) ifFalse:
+ [self error: ('{1} instances should hold only Associations or Pragmas.' translated format: {self class name})].
- [self error: self class name, ' instances should hold only Associations or Pragmas.'].
"no need to initialize here; we're copying all inst vars"
copy := self class basicNew: (bs := self basicSize) + 1.
1 to: bs do:
[:i|
copy basicAt: i put: (self basicAt: i) shallowCopy].
copy basicAt: bs + 1 put: aPropertyOrPragma.
1 to: self class instSize do:
[:i| copy instVarAt: i put: (self instVarAt: i)].
^copy!
Item was changed:
+ Error subclass: #IllegalResumeAttempt
- Exception subclass: #IllegalResumeAttempt
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Kernel-Exceptions'!
!IllegalResumeAttempt commentStamp: '<historical>' prior: 0!
This class is private to the EHS implementation. An instance of it is signaled whenever an attempt is made to resume from an exception which answers false to #isResumable.!
Item was removed:
- ----- Method: IllegalResumeAttempt>>defaultAction (in category 'handling') -----
- defaultAction
- "No one has handled this error, but now give them a chance to decide how to debug it. If none handle this either then open debugger (see UnhandedError-defaultAction)"
-
- UnhandledError signalForException: self!
Item was changed:
+ ----- Method: IllegalResumeAttempt>>isResumable (in category 'priv handling') -----
- ----- Method: IllegalResumeAttempt>>isResumable (in category 'handling') -----
isResumable
+
+ ^ true!
-
- ^ false!
Item was removed:
- ----- Method: IllegalResumeAttempt>>readMe (in category 'comment') -----
- readMe
-
- "Never handle this exception!!"!
Item was changed:
----- Method: Object>>assert: (in category 'error handling') -----
assert: aBlock
"Throw an assertion error if aBlock does not evaluates to true."
+ aBlock value ifFalse: [AssertionFailure signal: 'Assertion failed' translated]!
- aBlock value ifFalse: [AssertionFailure signal: 'Assertion failed']!
Item was changed:
----- Method: Object>>backwardCompatibilityOnly: (in category 'error handling') -----
backwardCompatibilityOnly: explanationString
"Warn that the sending method has been deprecated. Methods that are tagt with #backwardCompatibility:
are kept for compatibility."
Deprecation
signalForContext: thisContext sender
+ message: ' (but will be kept for compatibility)' translated
- message: ' (but will be kept for compatibility)'
explanation: explanationString!
Item was changed:
----- Method: Object>>caseError (in category 'error handling') -----
caseError
"Report an error from an in-line or explicit case statement."
+ self error: ('Case not found ({1}), and no otherwise clause' translated format: {self printString})!
- self error: ('Case not found ({1}), and no otherwise clause' format: {self printString})!
Item was changed:
----- Method: Object>>doesNotUnderstand: (in category 'error handling') -----
doesNotUnderstand: aMessage
"Handle the fact that there was an attempt to send the given
message to the receiver but the receiver does not understand
this message (typically sent from the machine when a message
is sent to the receiver and no method is defined for that selector).
Raise the MessageNotUnderstood signal. If it is caught, answer
the result supplied by the exception handler. If it is not caught,
answer the result of resending the message within a guard for
infinite recursion. This allows, for example, the programmer to
implement the method and continue."
"Testing: (3 activeProcess)"
| exception resumeValue |
(exception := MessageNotUnderstood new)
message: aMessage;
receiver: self.
resumeValue := exception signal.
^exception reachedDefaultHandler "i.e. exception was not caught..."
ifTrue:
[[aMessage sentTo: self]
on: MessageNotUnderstood
do: [:ex|
(self == ex receiver
and: [aMessage hasIdenticalContentsAs: ex message]) ifFalse:
[ex pass].
+ self error: 'infinite recursion in doesNotUnderstand:' translated]]
- self error: 'infinite recursion in doesNotUnderstand:']]
ifFalse: [resumeValue]!
Item was changed:
----- Method: Object>>error (in category 'error handling') -----
error
"Throw a generic Error exception."
+ ^self error: 'Error!!' translated.!
- ^self error: 'Error!!'.!
Item was changed:
----- Method: Object>>errorImproperStore (in category 'private') -----
errorImproperStore
"Create an error notification that an improper store was attempted."
+ ^ self error: 'Improper store into indexable object' translated!
- self error: 'Improper store into indexable object'!
Item was changed:
----- Method: Object>>errorNonIntegerIndex (in category 'private') -----
errorNonIntegerIndex
"Create an error notification that an improper object was used as an index."
+ ^ self error: 'Only integers should be used as indices' translated!
- self error: 'only integers should be used as indices'!
Item was changed:
----- Method: Object>>errorSubscriptBounds: (in category 'private') -----
errorSubscriptBounds: index
"Create an error notification that an improper integer was used as an index."
+ ^ self error: ('Subscript is out of bounds: {1}' translated format: {index})!
- self error: 'subscript is out of bounds: ' , index printString!
Item was changed:
----- Method: Object>>instVarNamed: (in category 'system primitives') -----
instVarNamed: aString
"Return the value of the instance variable in me with that name. Slow and unclean, but very useful. "
^ self instVarAt: (self class
instVarIndexFor: aString asString
+ ifAbsent: [self error: 'no such inst var' translated])
- ifAbsent: [self error: 'no such inst var'])
!
Item was changed:
----- Method: Object>>instVarNamed:put: (in category 'system primitives') -----
instVarNamed: aString put: aValue
"Store into the value of the instance variable in me of that name. Slow and unclean, but very useful. "
^self
instVarAt: (self class
instVarIndexFor: aString asString
+ ifAbsent: [self error: 'no such inst var' translated])
- ifAbsent: [self error: 'no such inst var'])
put: aValue
!
Item was changed:
----- Method: Object>>shouldBeImplemented (in category 'error handling') -----
shouldBeImplemented
"Announce that this message should be implemented"
+ ^ NotImplemented signal: ('{1} or a superclass should implement {2}' translated format: {self className. thisContext sender selector})!
- ^ NotImplemented signal: ('{1} or a superclass should implement {2}' format: {self className. thisContext sender selector})!
Item was changed:
----- Method: Object>>shouldNotImplement (in category 'error handling') -----
shouldNotImplement
"Announce that, although the receiver inherits this message, it should
not implement it."
+ NotImplemented signal: ('{1} is not a message appropriate for a {2}' translated format: {thisContext sender selector. self className}).!
- NotImplemented signal: ('{1} is not a message appropriate for a {2}' format: {thisContext sender selector. self className}).!
Item was changed:
----- Method: Object>>subclassResponsibility (in category 'error handling') -----
subclassResponsibility
"This message sets up a framework for the behavior of the class' subclasses.
Announce that the subclass should have implemented this message."
^ SubclassResponsibility
signal: ('My {1} subclass should have overridden {2}'
+ translated format: {self className. thisContext sender selector}).!
- format: {self className. thisContext sender selector}).!
Item was changed:
----- Method: Object>>traitConflict (in category 'error handling') -----
traitConflict
+ self error: 'A class or trait does not properly resolve a conflict between multiple traits it uses.' translated!
- self error: 'A class or trait does not properly resolve a conflict between multiple traits it uses.'!
Christoph Thiede uploaded a new version of Kernel to project The Treated Inbox:
http://source.squeak.org/treated/Kernel-ct.1405.mcz
==================== Summary ====================
Name: Kernel-ct.1405
Author: ct
Time: 15 May 2021, 3:56:24.713389 pm
UUID: 9a92be9b-d778-b54f-b659-713451a2ddb2
Ancestors: Kernel-nice.1402
Counterproposal to Kernel-jar.1404 for fixing VM crashes when resuming from a BlockCannotReturn. Instead of enforcing retrial, repair the context stack if the receiver has ended. There are two reasons for that:
1. Not in all situations, the receiver of #cannotReturn: is actually unable to resume. Consider this example for a disproof:
a := [true ifTrue: [^ 1]. 2].
"Both statements need to be executed separately in a Workspace so that [a outerContext sender] becomes nil!"
a value.
In this situation, it is valid to resume from BlockCannotReturn and currently also possible in the Trunk. Note that BlockCannotReturn even overrides #isResumable to answer true, though the class comment discrecommends resuming it.
2. The pattern proposed by Jaromir reminds me of the current implementation of Object >> #doesNotUnderstand: or Object >> #at:, that is, when the error was resumed, just try it again in the manner of a (potentially) infinite recursion. While the issue with infinite debuggers (which was eventually tripped by exactly this pattern) has been solved some time ago [1], I do not really agree with the pattern in general - it makes it unnecessarily hard for ToolSet implementors to consciously resume from an error instead of retrying it (which we have an extra selector on Exception for).
[1] http://forum.world.st/Please-try-out-Fixes-for-debugger-invocation-during-c…
=============== Diff against Kernel-nice.1402 ===============
Item was added:
+ ----- Method: BlockCannotReturn>>defaultResumeValue (in category 'defaults') -----
+ defaultResumeValue
+
+ ^ self result!
Item was changed:
----- Method: Context>>cannotReturn: (in category 'private-exceptions') -----
cannotReturn: result
+ closureOrNil ifNotNil: [
+ | resumptionValue |
+ resumptionValue := self cannotReturn: result to: self home sender.
+ self pc > self endPC ifTrue: [
+ "This block has ended, continue with sender"
+ thisContext privSender: self sender].
+ ^ resumptionValue].
- closureOrNil ifNotNil: [^ self cannotReturn: result to: self home sender].
Processor debugWithTitle: 'Computation has been terminated!!' translated full: false.!
Nicolas Cellier uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-nice.1059.mcz
==================== Summary ====================
Name: Collections-nice.1059
Author: nice
Time: 8 February 2024, 12:57:43.861987 am
UUID: a61087ae-f9ac-4e43-89d1-837d3edb7493
Ancestors: Collections-mt.1058
Provide the ability to reverse the endianness of a RawBitsArray. Spur platforms are all little-endian so far, so this is for the case when we would want to exchange such an array in a big-endian format.
Example:
| w |
w := WordArray with: 16r01020304.
w reverseEndianness.
w first hex
Also provide the ability to access the underlying bytes of any collection of raw bits thru byteAt: and byteAt:put:, whatever the number of bytesPerBasicElement.
Examples:
| w b |
w := WordArray with: 16r01020304.
b := w copy changeClassTo: ByteArray.
1 to: 4 do: [:index |
self assert: (w byteAt: index) = (b byteAt: index)].
| w b |
w := WordArray with: 16r01020304.
b := w copy changeClassTo: ByteArray.
w byteAt: 3 put: 5.
b byteAt: 3 put: 5.
{w first hex. b}
This might be usefull for low level operations, like simulating a VM for example.
=============== Diff against Collections-mt.1058 ===============
Item was added:
+ ----- Method: RawBitsArray>>byteAt: (in category 'accessing') -----
+ byteAt: anIndex
+ "Access a byte of the receiver, considered as a raw sequence of bytes.
+ This is a memory efficient implementation of:
+ ((self copy changeClassTo: ByteArray) at: anIndex)"
+ | int mask stride index shift |
+ self class isBytes
+ ifTrue: [^ self basicAt: anIndex].
+ mask := 16rFF.
+ stride := self bytesPerBasicElement.
+ index := anIndex - 1 // stride + 1.
+ shift := anIndex - 1 \\ stride * -8.
+ Smalltalk isLittleEndian ifFalse: [shift := stride - 1 * 8 - shift].
+ int := self basicAt: index.
+ int := int bitShift: shift.
+ int := int bitAnd: mask.
+ ^int!
Item was added:
+ ----- Method: RawBitsArray>>byteAt:put: (in category 'accessing') -----
+ byteAt: anIndex put: aByte
+ "Modify a byte of the receiver, considered as a raw sequence of bytes.
+ This is a less scary implementation than:
+ ([:class | ((self changeClassTo: ByteArray) at: anIndex put: aByte) changeClassTo: class] value: self class)"
+ | int stride index shift mask |
+ self class isBytes
+ ifTrue: [^ self basicAt: anIndex put: aByte].
+ mask := 16rFF.
+ stride := self bytesPerBasicElement.
+ index := anIndex - 1 // stride + 1.
+ shift := anIndex - 1 \\ stride * 8.
+ Smalltalk isLittleEndian ifFalse: [shift := stride - 1 * 8 - shift].
+ int := self basicAt: index.
+ int := int bitClear: (mask bitShift: shift).
+ int := int bitOr: (aByte bitShift: shift).
+ self basicAt: index put: int.
+ ^aByte!
Item was added:
+ ----- Method: RawBitsArray>>reverseEndianness (in category 'converting') -----
+ reverseEndianness
+ "reverse the endianness for each element"
+
+ self class isBytes ifTrue: [^self].
+ self class isWords ifTrue: [^self swapWords].
+ self class isLongs ifTrue: [^self swapDoubleWords].
+ self class isShorts ifTrue: [^self swapDoubleBytes].
+ self error: 'this is not a collection of 1,2,4 or 8 bytes elements'!
Item was added:
+ ----- Method: RawBitsArray>>swap16pairs (in category 'private') -----
+ swap16pairs
+ "Swap every pair of double-bytes
+ Example: #[ 1 2 3 4 5 6 7 8 ] copy swap16pairs => #[ 3 4 1 2 7 8 5 6]
+ Implementation notes: this is the same as swapHalves, except that swapHalves only work for WordArray"
+
+ | hack blt |
+ "The implementation is a hack, but fast for large ranges"
+ hack := Form new hackBits: self.
+ blt := (BitBlt toForm: hack) sourceForm: hack.
+ blt combinationRule: Form reverse. "XOR"
+ blt sourceY: 0; destY: 0; height: self byteSize//4; width: 2.
+ blt sourceX: 0; destX: 2; copyBits. "Exchange double-bytes 0 and 1"
+ blt sourceX: 2; destX: 0; copyBits.
+ blt sourceX: 0; destX: 2; copyBits.!
Item was added:
+ ----- Method: RawBitsArray>>swap32pairs (in category 'private') -----
+ swap32pairs
+ "Swap every pair of words
+ Example: #[ 1 2 3 4 5 6 7 8 ] copy swap32pairs => #[ 5 6 7 8 1 2 3 4 ]"
+
+ | hack blt |
+ "The implementation is a hack, but fast for large ranges"
+ hack := Form new hackBits: self width: 8.
+ blt := (BitBlt toForm: hack) sourceForm: hack.
+ blt combinationRule: Form reverse. "XOR"
+ blt sourceY: 0; destY: 0; height: self byteSize//8; width: 4.
+ blt sourceX: 0; destX: 4; copyBits. "Exchange words 0 and 1"
+ blt sourceX: 4; destX: 0; copyBits.
+ blt sourceX: 0; destX: 4; copyBits.!
Item was added:
+ ----- Method: RawBitsArray>>swap8pairs (in category 'private') -----
+ swap8pairs
+ "Swap every pair of bytes
+ Example: #[ 1 2 3 4 5 6 ] copy swap8pairs => #[ 2 1 4 3 6 5 ]"
+
+ | hack blt |
+ "The implementation is a hack, but fast for large ranges"
+ hack := Form new hackBits: self.
+ blt := (BitBlt toForm: hack) sourceForm: hack.
+ blt combinationRule: Form reverse. "XOR"
+ blt sourceY: 0; destY: 0; height: self byteSize//4; width: 1.
+ blt sourceX: 0; destX: 1; copyBits. "Exchange bytes 0 and 1"
+ blt sourceX: 1; destX: 0; copyBits.
+ blt sourceX: 0; destX: 1; copyBits.
+ blt sourceX: 2; destX: 3; copyBits. "Exchange bytes 2 and 3"
+ blt sourceX: 3; destX: 2; copyBits.
+ blt sourceX: 2; destX: 3; copyBits.
+ self byteSize\\4 >= 2
+ ifTrue:
+ ["The lines in a From must fit on a Word boundary.
+ Handle the excess bytes"
+ | n tmp |
+ n := self byteSize // 4 * 4.
+ tmp := self byteAt: n + 1.
+ self byteAt: n + 1 put: (self byteAt: n + 2).
+ self byteAt: n + 2 put: tmp.]!
Item was added:
+ ----- Method: RawBitsArray>>swapDoubleBytes (in category 'private') -----
+ swapDoubleBytes
+ "Perform a bigEndian/littleEndian byte reversal of my double bytes.
+ Assume that our byte size is a multiple of souble byte size (2)
+ If it's not the case, trailing bytes would be left unchanged"
+
+ self swap8pairs!
Item was added:
+ ----- Method: RawBitsArray>>swapDoubleWords (in category 'private') -----
+ swapDoubleWords
+ "Perform a bigEndian/littleEndian byte reversal of my double words.
+ Assume that our byte size is a multiple of double word size (8)
+ If it's not the case, 4 trailing bytes might be altered"
+
+ self swap32pairs. "#[1 2 3 4 5 6 7 8] copy swap32pairs => #[5 6 7 8 1 2 3 4]"
+ self swapWords "#[5 6 7 8 1 2 3 4] copy swapWords => #[8 7 6 5 4 3 2 1]"!
Item was added:
+ ----- Method: RawBitsArray>>swapWords (in category 'private') -----
+ swapWords
+ "Perform a bigEndian/littleEndian byte reversal of my words.
+ Assume that our byte size is a multiple of word size (4)
+ If it's not the case, trailing bytes will remain unchanged"
+
+ | hack blt |
+ "The implementation is a hack, but fast for large ranges"
+ hack := Form new hackBits: self.
+ blt := (BitBlt toForm: hack) sourceForm: hack.
+ blt combinationRule: Form reverse. "XOR"
+ blt sourceY: 0; destY: 0; height: self byteSize//4; width: 1.
+ blt sourceX: 0; destX: 3; copyBits. "Exchange bytes 0 and 3"
+ blt sourceX: 3; destX: 0; copyBits.
+ blt sourceX: 0; destX: 3; copyBits.
+ blt sourceX: 2; destX: 1; copyBits. "Exchange bytes 1 and 2"
+ blt sourceX: 1; destX: 2; copyBits.
+ blt sourceX: 2; destX: 1; copyBits.!
Nicolas Cellier uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-nice.551.mcz
==================== Summary ====================
Name: Graphics-nice.551
Author: nice
Time: 27 February 2024, 11:04:54.187486 pm
UUID: 6687a9e4-2fa7-4981-8548-fa272b631eda
Ancestors: Graphics-mt.550, Graphics-nice.550
Merge Graphics-mt.550 & Graphics-nice.550
=============== Diff against Graphics-mt.550 ===============
Item was added:
+ ----- Method: Form>>hackBits:width: (in category 'private') -----
+ hackBits: bitThing width: anInteger
+ "This method provides an initialization so that BitBlt may be used, eg, to
+ copy ByteArrays and other non-pointer objects efficiently.
+ The resulting form looks anInteger wide, 8 bits deep, and height is adjusted to fit the bitThing size.
+ anInteger shall be a multiple of 4, because lines in a Form always fall on a Word boundary.
+ If not, some dead bytes will remain unaccessible to the BitBlt operations on each line.
+ That's also the case of trailing excess bytes"
+ width := anInteger.
+ depth := 8.
+ bitThing class isBits ifFalse: [self error: 'bitThing must be a non-pointer object'].
+ height := bitThing basicSize * bitThing bytesPerBasicElement // (width + 3 // 4 * 4).
+ bits := bitThing!
Nicolas Cellier uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-nice.550.mcz
==================== Summary ====================
Name: Graphics-nice.550
Author: nice
Time: 7 February 2024, 11:08:47.366987 pm
UUID: 9a845f0a-b60c-a740-93f9-d705b5b9b840
Ancestors: Graphics-mt.549
Provide a new Form hack of arbitrary width for bulk transfer of bytes.
This may be used for example for reversing the endianness of a DoubleWordArray.
=============== Diff against Graphics-mt.549 ===============
Item was added:
+ ----- Method: Form>>hackBits:width: (in category 'private') -----
+ hackBits: bitThing width: anInteger
+ "This method provides an initialization so that BitBlt may be used, eg, to
+ copy ByteArrays and other non-pointer objects efficiently.
+ The resulting form looks anInteger wide, 8 bits deep, and height is adjusted to fit the bitThing size.
+ anInteger shall be a multiple of 4, because lines in a Form always fall on a Word boundary.
+ If not, some dead bytes will remain unaccessible to the BitBlt operations on each line.
+ That's also the case of trailing excess bytes"
+ width := anInteger.
+ depth := 8.
+ bitThing class isBits ifFalse: [self error: 'bitThing must be a non-pointer object'].
+ height := bitThing basicSize * bitThing bytesPerBasicElement // (width + 3 // 4 * 4).
+ bits := bitThing!