Bert Freudenberg uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-hjh.967.mcz
==================== Summary ====================
Name: System-hjh.967
Author: hjh
Time: 14 October 2017, 4:33:41.102157 pm
UUID: ba832c58-398d-431e-b40c-fb01421606cf
Ancestors: System-bf.966
Update class comment with note how
'*Morphic-conversion'
methods are constructed.
=============== Diff against System-bf.966 ===============
Item was changed:
ReferenceStream subclass: #SmartRefStream
instanceVariableNames: 'structures steady reshaped renamed renamedConv superclasses progressBar objCount classInstVars'
classVariableNames: 'ScannedObject'
poolDictionaries: ''
category: 'System-Object Storage'!
+ !SmartRefStream commentStamp: 'hjh 10/14/2017 16:30' prior: 0!
- !SmartRefStream commentStamp: 'nice 3/25/2010 23:03' prior: 0!
Ordinary ReferenceStreams assume that the names and order of instance variables is exactly the same when an object file is written and read.
SmartRefStream allows object files to be read even after instance variables have changed or the entire class has been renamed.
When an object file is written, no one knows how the classes will change in the future. Therefore, all conversion must be done when the file is read. The key is to store enough information in the file about the names of the instance variables of all outgoing classes.
SmartRefStream works best with only one tree of objects per file. You can nextPut: more than once, but each object tree gets its own class structure description, which is big.
+ Conversion of old objects is done by a method in each class called (convertToCurrentVersion: varDict refStream: smartRefStrm). At fileOut time, ChangeSet>>checkForConversionMethods creates a prototype of this method (if Preference #conversionMethodsAtFileOut is true). The programmer must edit this method to
+ (1) test if the incoming object needs conversion,
+ (2) put non-nil values into any new inst vars that need them, and
+ (3) save the data of any inst vars that are being deleted.
- Conversion of old objects is done by a method in each class called (convertToCurrentVersion: varDict refStream: smartRefStrm). At fileOut time, ChangeSet>>checkForConversionMethods creates a prototype of this method (if Preference #conversionMethodsAtFileOut is true). The programmer must edit this method to (1) test if the incoming object needs conversion, (2) put non-nil values into any new inst vars that need them, and (3) save the data of any inst vars that are being deleted.
+ Determining which old version is represented by the incoming object can be done in several ways:
+ - noticing that a current inst var is nil when it should have data,
+ - noticing that there is an older inst var name in the variable dictionary (varDict),
+ - checking kinds of objects in one or more inst vars, or
+ - retrieving the classVersion of the incoming object from the ref stream.
- Determining which old version is represented by the incoming object can be done in several ways: noticing that a current inst var is nil when it should have data, noticing that there is an older inst var name in the variable dictionary (varDict), checking kinds of objects in one or more inst vars, or retrieving the classVersion of the incoming object from the ref stream.
+ If a class is renamed, a method goes into SmartRefStream telling the new name.
- If a class is renamed, a method goes into SmartRefStream telling the new name. The conversion method of the new class must be prepared to accept instances of the old class also. If no inst var names have changed, the conversion method does nothing.
+ The conversion method of the new class must be prepared to accept instances of the old class also. If no inst var names have changed, the conversion method does nothing.
+
+
+
+
An example:
+ Suppose we change the representation of class Rectangle from ('origin' 'corner') to ('origin' 'extent'). Suppose lots of Rectangle instances are already out on files (in .pr project files, especially).
- Suppose we change the representation of class Rectangle from ('origin' 'corner') to ('origin' 'extent'). Suppose lots of Rectangle instances are already out on files (in .pr project files, especially).
- The programmer changes the class definition, modifies all the methods, and filesOut. A series of dialogs appear, asking if instances Rectangle might be in an object file, if 'extent' needs to be non-nil (yes), and if the info in 'corner' needs to be preserved (yes). This method appears:
+ The programmer changes the class definition, modifies all the methods, and filesOut. A series of dialogs appear, asking if instances Rectangle might be in an object file, if 'extent' needs to be non-nil (yes), and if the info in 'corner' needs to be preserved (yes). This method appears:
+
Rectangle >> convertToCurrentVersion: varDict refStream: smartRefStrm
"These variables are automatically stored into the new instance: #('origin').
Test for this particular conversion. Get values using expressions like (varDict at: 'foo')."
"New variables: #('extent'). If a non-nil value is needed, please assign it."
"These are going away #('corner'). Possibly store their info in some other variable?"
"Move your code above the ^ super... Delete extra comments."
^ super convertToCurrentVersion: varDict refStream: smartRefStrm
The programmer modifies it to be:
Rectangle >> convertToCurrentVersion: varDict refStream: smartRefStrm
(varDict includesKey: 'extent') ifFalse: ["old version!!"
"Create the new extent, and preserve the info from the old corner"
extent := (varDict at: 'corner') - origin.
].
^ super convertToCurrentVersion: varDict refStream: smartRefStrm
This conversion method stays in the system and is ready to convert the old format of Rectangle whenever one is encountered in an object file. Note that the subclasses of Rectangle, (B3DViewport, CharacterBlock, and Quadrangle) do not need conversion methods. Their instances will be converted by the code in Rectangle.
+
Files written by SmartRefStream are in standard fileout format. You can mix raw objects with code to be filed in. The file starts out in the normal fileOut format. Definitions of new classes on the front.
structures Dictionary of (#Rectangle -> #(<classVersionInteger> 'origin' 'corner')). Inst
var names are strings.
steady Set of Classes who have the same structure now as on the incoming file.
Includes classes with same inst vars except for new ones added on the end.
reshaped Dictionary of Classes who have a different structure now from the incoming file.
Includes those with same inst vars but new version number.
(old class name -> method selector to fill in data for version to version)
renamed Dictionary of Classes who have a different name. Make an instance of the new
class, and send it the conversion call.
(old class name symbol -> new class name).
renamedConv Dictionary of conversion selector for Classes who have a different name.
(old class name symbol -> conversion selector).
topCall Tells if next or nextPut: are working on the top object in the tree.
nil if outside, the top object if deep inside.
See DataStream.typeIDFor: for where the tangle of objects is clipped, so the whole system will not be written on the file.
No object that is written on the file is ever a class. All class definitions are filed in. A class may be stored inside an ImageSegment that itself is stored in a SmartRefStream.
+
+
+
UniClasses are classes for the instance specific behavior of just one instance. Subclasses of Player are an example. When a UniClass is read in, and a class of the same name already exists, the incoming one is renamed. ObjectScanner converts the filed-in code.
Values in instance variables of UniClasses are stored in the array that tells the class structure. It is the fourth of the four top level objects. #(version (class-structure) the-object ((#Player25 scripts slotInfo costumeDictionary) (#Player26 scripts slotInfo costumeDictionary))).
There is a separate subclass for doing veryDeepCopy (in memory). Currently, any object for which objectToStoreOnDataStream return an object other than self, does this: The new object (a DiskProxy) is traced. When it comes time to go through the fields of the old object, they are not found as keys in references (DiskProxies are there instead). So the old field value is left in the new object. That is OK for StrikeFont, Class, MetaClass, DisplayScreen. But the DiskProxies are evaluated, which takes a lot of time.
Some metaclasses are put into the structures table. This is for when a block has a receiver that is a class. See checkFatalReshape:.
ImageSegments:
A ReferenceStream is used to enumerate objects to put inside an ImageSegment. If an instance of a UniClass is seen, the class is put in also.
A SmartRefStream is used to store the ImageSegment. Roots are nil, and the segment is a wordArray. We are encoding the outPointers. Structures contains all classes from both places. Must filter out UniClasses for some things, and do include them for putting source code at end of file. Do not write any class inst vars in file.
+
--Ted Kaehler and Bob Arning.
+
+
+
+ How are the selectors in the '*Morphic-conversion' protocol ending with something like
+
+ ttfclpomsswfpp0
+
+ constructed and what does it mean?
+
+
+ Answer:
+ It is the initials of all instance variables followed by the class version integer. The initials allow to detect most changes to the instance variables, but if this is not sufficient (perhaps because the new var had the same initial, or the vars did not change in name at all) we still have the class version.
+
+ Most classes are still at version 0, but if you check implementers of classVersion you can find a few that were incremented to force a conversion on load.!
- !
Bert Freudenberg uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-bf.966.mcz
==================== Summary ====================
Name: System-bf.966
Author: bf
Time: 14 October 2017, 2:30:57.487381 pm
UUID: be22259c-73c6-4721-86a9-f17059c77ebf
Ancestors: System-dtl.965
Mark SmartRefStream>>mapClass: as sender of all conversion methods.
=============== Diff against System-dtl.965 ===============
Item was added:
+ ----- Method: SmartRefStream class>>isConversionSelector: (in category 'browsing support') -----
+ isConversionSelector: aSelector
+ "Let mapClass: be found as sender of our conversion methods"
+ ^aSelector last isDigit and: [self includesSelector: aSelector]
+ !
Item was changed:
----- Method: SmartRefStream>>mapClass: (in category 'read write') -----
mapClass: incoming
"See if the old class named nm exists. If so, return it. If not, map it to a new class, and save the mapping in renamed. "
+ <hasLiteralTest: #isConversionSelector:>
+ "To find this method as sender of all conversion methods"
+
| cls oldVer sel nm |
self flag: #bobconv.
nm := renamed at: incoming ifAbsent: [incoming]. "allow pre-mapping around collisions"
(nm endsWith: ' class')
ifFalse: [cls := Smalltalk at: nm ifAbsent: [nil].
cls ifNotNil: [^ cls]] "Known class. It will know how to translate the instance."
ifTrue: [cls := Smalltalk at: nm substrings first asSymbol ifAbsent: [nil].
cls ifNotNil: [^ cls class]]. "Known class. It will know how to translate the instance."
oldVer := self versionSymbol: (structures at: nm).
sel := nm asString.
sel at: 1 put: (sel at: 1) asLowercase.
sel := sel, oldVer. "i.e. #rectangleoc4"
- self flag: #multiNewParagraphttfclpomsswfpp0. "identify senders of multiNewParagraphttfclpomsswfpp0"
Symbol hasInterned: sel ifTrue: [:symb |
(self class canUnderstand: sel asSymbol) ifTrue: [
reshaped ifNil: [reshaped := Dictionary new].
cls := self perform: sel asSymbol]]. "This class will take responsibility"
cls ifNil: [cls := self writeClassRenameMethod: sel was: nm
fromInstVars: (structures at: nm).
cls isString ifTrue: [cls := nil]].
cls ifNotNil: [renamed at: nm put: cls name].
^ cls
!
Tobias Pape uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-topa.764.mcz
==================== Summary ====================
Name: Collections-topa.764
Author: topa
Time: 14 October 2017, 1:30:58.746815 pm
UUID: 8b1c780c-c4fb-4a8c-baac-050c5a3e67c2
Ancestors: Collections-pre.763
Improve #initializedInstance and #empty for certain collections
=============== Diff against Collections-pre.763 ===============
Item was added:
+ ----- Method: Bitset class>>initializedInstance (in category 'instance creation') -----
+ initializedInstance
+
+ ^ self new: 0!
Item was added:
+ ----- Method: ByteArray class>>empty (in category 'instance creation') -----
+ empty
+ "A canonicalized empty ByteArray instance."
+ ^ #[]!
Item was added:
+ ----- Method: NonPointersOrderedCollection class>>initializedInstance (in category 'instance creation') -----
+ initializedInstance
+ " There are no instances of me, just my subclasses "
+ ^ self ~~ NonPointersOrderedCollection ifTrue: [super initializedInstance]
+ !
Item was added:
+ ----- Method: Symbol class>>empty (in category 'instance creation') -----
+ empty
+ "A canonicalized empty symbol."
+ ^ #''!
David T. Lewis uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-dtl.965.mcz
==================== Summary ====================
Name: System-dtl.965
Author: dtl
Time: 13 October 2017, 11:38:38.184812 pm
UUID: 710f2f23-7e87-4fbf-9a16-9b6df253f5bd
Ancestors: System-tpr.964
Add flag to identify sender of composed selector #multiNewParagraphttfclpomsswfpp0
=============== Diff against System-tpr.964 ===============
Item was changed:
----- Method: SmartRefStream>>mapClass: (in category 'read write') -----
mapClass: incoming
"See if the old class named nm exists. If so, return it. If not, map it to a new class, and save the mapping in renamed. "
| cls oldVer sel nm |
self flag: #bobconv.
nm := renamed at: incoming ifAbsent: [incoming]. "allow pre-mapping around collisions"
(nm endsWith: ' class')
ifFalse: [cls := Smalltalk at: nm ifAbsent: [nil].
cls ifNotNil: [^ cls]] "Known class. It will know how to translate the instance."
ifTrue: [cls := Smalltalk at: nm substrings first asSymbol ifAbsent: [nil].
cls ifNotNil: [^ cls class]]. "Known class. It will know how to translate the instance."
oldVer := self versionSymbol: (structures at: nm).
sel := nm asString.
sel at: 1 put: (sel at: 1) asLowercase.
sel := sel, oldVer. "i.e. #rectangleoc4"
+ self flag: #multiNewParagraphttfclpomsswfpp0. "identify senders of multiNewParagraphttfclpomsswfpp0"
Symbol hasInterned: sel ifTrue: [:symb |
(self class canUnderstand: sel asSymbol) ifTrue: [
reshaped ifNil: [reshaped := Dictionary new].
cls := self perform: sel asSymbol]]. "This class will take responsibility"
cls ifNil: [cls := self writeClassRenameMethod: sel was: nm
fromInstVars: (structures at: nm).
cls isString ifTrue: [cls := nil]].
cls ifNotNil: [renamed at: nm put: cls name].
^ cls
!
David T. Lewis uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-dtl.1352.mcz
==================== Summary ====================
Name: Morphic-dtl.1352
Author: dtl
Time: 13 October 2017, 11:34:58.074107 pm
UUID: 3b94e551-617d-40d5-b742-195b31393966
Ancestors: Morphic-hjh.1351, Morphic-hjh.1349
Merge Morphic-hjh.1349, add a comment to explain selector generation
=============== Diff against Morphic-hjh.1351 ===============
Item was added:
+ ----- Method: SmartRefStream>>multiNewParagraphttfclpomsswfpp0 (in category '*Morphic-conversion') -----
+ multiNewParagraphttfclpomsswfpp0
+ "Selector composed in SmartRefStream>>mapClass:"
+ ^ NewParagraph!
David T. Lewis uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-hjh.1349.mcz
==================== Summary ====================
Name: Morphic-hjh.1349
Author: hjh
Time: 9 October 2017, 9:45:19.910726 pm
UUID: 15492c5f-dfb8-43f5-b6c9-7b91b963907c
Ancestors: Morphic-tpr.1348
Fix in SmartRefStream
MultiNewParagraph
instances have to be converted to
NewParagraph
instances.
Example: Load Etoys project file
http://etoys.laptop.org/src/Content/ExampleEtoys/CarAndPen.014.pr
=============== Diff against Morphic-tpr.1348 ===============
Item was added:
+ ----- Method: SmartRefStream>>multiNewParagraphttfclpomsswfpp0 (in category '*Morphic-conversion') -----
+ multiNewParagraphttfclpomsswfpp0
+
+ ^ NewParagraph!
Marcel Taeumel uploaded a new version of EToys to project The Trunk:
http://source.squeak.org/trunk/EToys-hjh.279.mcz
==================== Summary ====================
Name: EToys-hjh.279
Author: hjh
Time: 22 February 2017, 11:23:24.984746 am
UUID: 3f908905-74c3-4c1c-931c-7b440b143602
Ancestors: EToys-dtl.278
Two steps towards loading an EToys projects dropped on to the desktop.
Change
StandardScriptingSystem>>baseColor
StandardScriptingSystem>>borderColor
to use UserInterfaceTheme current instead of the old direct access to Preferences.
=============== Diff against EToys-dtl.278 ===============
Item was changed:
----- Method: StandardScriptingSystem>>baseColor (in category '*Etoys-Squeakland-tile colors') -----
baseColor
+ ^ (UserInterfaceTheme current get: #titleColor for: #MenuMorph) ifNil: [ Color transparent]!
- ^ Preferences menuTitleColor!
Item was changed:
----- Method: StandardScriptingSystem>>borderColor (in category '*Etoys-Squeakland-tile colors') -----
borderColor
+ ^ (UserInterfaceTheme current get: #borderColor for: #MenuMorph) ifNil: [(Color r: 0.2 g: 0.3 b: 0.9)]!
- ^ Preferences menuBorderColor!