Hi All,

I've submitted:

https://pharo.fogbugz.com/f/cases/21431/
https://github.com/pharo-project/pharo/pull/976

The issue has additional analysis of the problem, namely that
#classSide is a convenience method for retrieving the class from
either an instance or the class, so isn't appropriate for chunk file
out.

Cheers,
Alistair

On 26 February 2018 at 17:43, Alistair Grant <akgrant0...@gmail.com> wrote:
> Hi Everyone,
>
> The following demonstrates the problem (and will allow me to provide an
> automated test when I submit a patch):
>
>
> | stream definition writer diskStore nonExistent |
>
> definition := MCMethodDefinition
>     className: #DiskStore
>     classIsMeta: true
>     selector: #activeClass
>     category: 'current'
>     timeStamp: nil
>     source: 'activeClass
>     self allSubclassesDo: [:ea |
>         ea isActiveClass ifTrue: [^ ea]].
>     ^ self'.
> stream := String new writeStream.
> writer := MCStWriter new
>     stream: stream;
>     yourself.
>
> writer writeMethodPreamble: definition.
> diskStore := stream contents.
>
> definition := MCMethodDefinition
>     className: #NotALoadedClass
>     classIsMeta: true
>     selector: #reset
>     category: 'imagine'
>     timeStamp: nil
>     source: 'reset
>
>     ^self doReset'.
> stream := String new writeStream.
> writer := MCStWriter new
>     stream: stream;
>     yourself.
>
> writer writeMethodPreamble: definition.
> nonExistent := stream contents.
>
> { diskStore. nonExistent. }
>
> " #('
> !DiskStore class methodsFor: ''current'' stamp: ''nil''!
> ' '
> !NotALoadedClass classSide methodsFor: ''imagine'' stamp: ''nil''!
> ')"
>
>
> As can be seen, the DiskStore preamble is as expected, while the
> NotALoadedClass preamble uses "classSide" instead of "class".
>
>
> Modifying one method:
>
>
> MCStWriter>>
> writeMethodPreamble: definition
>     self chunkContents: [:str |
>        stream bang.
>        str nextPutAll: definition className asString.
>        definition classIsMeta ifTrue:
>           [ str nextPutAll: ' class' ].
>        str
>           nextPutAll: ' methodsFor: ';
>           nextPutAll: definition category asString printString;
>           nextPutAll: ' stamp: ';
>           nextPutAll: definition timeStamp asString printString
>        ]
>
>
> produces the correct result, i.e. running the test code above produces:
>
>
> " #('
> !DiskStore class methodsFor: ''current'' stamp: ''nil''!
> ' '
> !NotALoadedClass class methodsFor: ''imagine'' stamp: ''nil''!
> ')"
>
>
> The NotALoadedClass has the "class" keyword as expected.
>
>
> Cheers,
> Alistair
>
> On 26 February 2018 at 11:14, Alistair Grant <akgrant0...@gmail.com> wrote:
>> Hi Guille and Stef,
>>
>> Stef, thanks also for your reply.  All the information I was going to
>> put there I've included below, so please treat is a combined reply.
>>
>>
>> On 26 February 2018 at 09:51, Guillermo Polito
>> <guillermopol...@gmail.com> wrote:
>>> Hi Alistair,
>>>
>>> Can you provide some more context on what are you trying to do and how?
>>
>> I'm working on integrating the changes I've made to FileSystem to
>> properly support symbolic links and all the other attributes returned
>> by libc stat().
>>
>> There's a slightly dated but more detailed description of the changes
>> in 
>> http://forum.world.st/FileSystem-file-attributes-and-isSymlink-patch-tt4956517.html
>>
>> The patch introduces a number of new classes to the FileSystem package:
>>
>> - FileAttributesPluginPrims with Unx and Windows subclasses
>> - Subclasses of FileSystemDirectoryEntry for symbolic links
>> - FileAttributeNotSupported
>>
>>
>>> Generally you should not change anything in the bootstrap, just modify the
>>> classes you want to modify and commit them into the repository. The
>>> bootstrap will take care of it.
>>
>> That's true, but as mentioned this introduces new classes, which also
>> should be handled automatically, but there is a bug in the Monticello
>> file out code that is causing it to fail.
>>
>> I haven't gone through the bootstrap process in great detail, but my
>> understanding is that it reads in the Pharo 7 code from the repository
>> and writes out key classes to .st files to file in as part of the
>> build, i.e.:
>>
>> ${VM70} "${COMPILER_IMAGE_NAME}.image" st ${ST_CACHE}/Multilingual.st
>> ${ST_CACHE}/DeprecatedFileStream.st ${ST_CACHE}/FileSystem.st
>> --no-source --quit --save
>>
>> The bug is only triggered because the new classes, e.g.
>> FileAttributesPluginPrim, are not part of the running image.  You can
>> see the code here:
>>
>>
>> MCMethodDefinition>>fullClassName
>> "Using #class selector for classes for backwards compatibility"
>>
>>     ^ self classIsMeta
>>         ifFalse: [self className]
>>         ifTrue: [
>>             (self actualClass isNil or: [ self actualClass isTrait ])
>>                 ifFalse: [self className, ' class']
>>                 ifTrue: [self className, ' classSide']]
>>
>>
>> Because FileAttributesPluginPrims isn't in the image, #actualClass
>> returns nil, and the method answers "classSide" resulting in a chunk
>> that looks like:
>>
>>
>> !FileAttributesPluginPrims classSide methodsFor: 'initialize' stamp: 'nil'!
>> reset
>>     "Reload the masks"
>>
>>     Default := nil.! !
>>
>>
>> This then quietly fails to load, resulting in a DNU when the method is
>> called (later on in the bootstrap process).
>>
>> A quick test of filing out a trait suggests this code isn't called as
>> it uses "classTrait" in the chunk:
>>
>>
>> !TestTrait classTrait methodsFor: 'testing' stamp: 'AlistairGrant
>> 2/25/2018 15:37'!
>> testTrait
>>
>> ^'testing'! !
>>
>>
>> I'm not familiar with the monticello code base, but #fullClassName is
>> used in a number of different places, so I'm wondering whether it is
>> OK to change MCStWriter>>writeMethodPreamble to always use "class".
>>
>> The would solve this bootstrap issue (there's one more below).
>>
>>
>>> The only cases when you need to change bootstrap code are:
>>>  - your code modifies the API of the class builder, the binary
>>> representation of compiled methods, requires changing some class
>>> initialization or if it adds/removes some VM special object (as the ones in
>>> the special objects array)
>>>  - you want to add a new package to pharo. In this case you need to add your
>>> package to the repository and update the corresponding baseline so it is
>>> loaded in the image (otherwise it will be in disk but ignored...)
>>
>> Or the new code is dependent on functionality introduced in the Pharo 7 VM.
>>
>> The Pharo 7 image is currently built using the Pharo 6 VM.  Adding
>> FileAttributesPlugin to the VM will require the bootstrap to use the
>> Pharo 7 VM in build.sh.
>>
>>
>> Thanks!
>> Alistair
>>
>>
>>
>>
>>> Guille
>>>
>>> On Sun, Feb 25, 2018 at 9:47 PM, Stephane Ducasse <stepharo.s...@gmail.com>
>>> wrote:
>>>>
>>>> Now I do not understand what is this classSide here.
>>>> If we have a trait apparently we do not file out a class method as
>>>> class but as classSide.... Super strange.
>>>>
>>>> Stef
>>>>
>>>> On Sun, Feb 25, 2018 at 9:46 PM, Stephane Ducasse
>>>> <stepharo.s...@gmail.com> wrote:
>>>> > Apparently this method was like that in Pharo 60 so this is not my edit.
>>>> >
>>>> > fullClassName
>>>> >    "Using #class selector for classes for backwards compatibility"
>>>> >
>>>> >    ^ self classIsMeta
>>>> >           ifFalse: [self className]
>>>> >           ifTrue: [
>>>> >               (self actualClass isNil or: [ self actualClass isTrait ])
>>>> >                   ifFalse: [self className, ' class']
>>>> >                   ifTrue: [self className, ' classSide']]
>>>> >
>>>> > Now it does not mean that this is not a bug I introduced.
>>>> >
>>>> >
>>>> >
>>>> >
>>>> > On Sun, Feb 25, 2018 at 9:42 PM, Stephane Ducasse
>>>> > <stepharo.s...@gmail.com> wrote:
>>>> >> the problem is here of course but I need my mind back (In the train to
>>>> >> home). ...
>>>> >>
>>>> >>
>>>> >> MCMethodDefinition>>fullClassName
>>>> >> "Using #class selector for classes for backwards compatibility"
>>>> >>
>>>> >>     ^ self classIsMeta
>>>> >>         ifFalse: [self className]
>>>> >>         ifTrue: [
>>>> >>             (self actualClass isNil or: [ self actualClass isTrait ])
>>>> >>                 ifFalse: [self className, ' class']
>>>> >>                 ifTrue: [self className, ' classSide']]
>>>> >>
>>>> >>
>>>> >>
>>>> >>
>>>> >>
>>>> >> On Sun, Feb 25, 2018 at 9:41 PM, Stephane Ducasse
>>>> >> <stepharo.s...@gmail.com> wrote:
>>>> >>> Hi Alistair
>>>> >>>
>>>> >>> This is my mistake! I introduced this bug when I transformed
>>>> >>> theMetaClass to classSide
>>>> >>> Now I was paying super attention and I did not touch theMetaClass even
>>>> >>> when class would have been far enough.
>>>> >>> So do you have a scenario? So that I can try to have a look.
>>>> >>> Unfortunately I was away from home and lab since a week and I may have
>>>> >>> problem to allocate concentrated time.
>>>> >>> But I will try.
>>>> >>> Tx for reporting this!
>>>> >>>
>>>> >>> Stef
>>>> >>>
>>>> >>>
>>>> >>> On Sun, Feb 25, 2018 at 3:48 PM, Alistair Grant
>>>> >>> <akgrant0...@gmail.com> wrote:
>>>> >>>> Hi Everyone,
>>>> >>>>
>>>> >>>> I'm working on integrating the file attribute primitives in to the
>>>> >>>> main
>>>> >>>> code during bootstrap.
>>>> >>>>
>>>> >>>> Class methods for FileAttributesPluginPrims are written out as:
>>>> >>>>
>>>> >>>>
>>>> >>>>
>>>> >>>> !FileAttributesPluginPrims classSide methodsFor: 'initialize' stamp:
>>>> >>>> 'nil'!
>>>> >>>> reset
>>>> >>>> "Reload the masks"
>>>> >>>>
>>>> >>>> Default := nil.! !
>>>> >>>>
>>>> >>>>
>>>> >>>> As you can see, the class name is written with "classSide" instead of
>>>> >>>> "class", resulting in the method quietly being ignored during file
>>>> >>>> in.
>>>> >>>>
>>>> >>>> This comes about in:
>>>> >>>>
>>>> >>>>
>>>> >>>> MCStWriter>>writeMethodPreamble: definition
>>>> >>>>     self chunkContents: [:str |
>>>> >>>>         stream bang.
>>>> >>>>         str nextPutAll: definition fullClassName;
>>>> >>>>             nextPutAll: ' methodsFor: ';
>>>> >>>>             nextPutAll: definition category asString printString;
>>>> >>>>             nextPutAll: ' stamp: ';
>>>> >>>>             nextPutAll: definition timeStamp asString printString
>>>> >>>>         ]
>>>> >>>>
>>>> >>>>
>>>> >>>> which calls:
>>>> >>>>
>>>> >>>>
>>>> >>>> MCMethodDefinition>>fullClassName
>>>> >>>> "Using #class selector for classes for backwards compatibility"
>>>> >>>>
>>>> >>>>     ^ self classIsMeta
>>>> >>>>         ifFalse: [self className]
>>>> >>>>         ifTrue: [
>>>> >>>>             (self actualClass isNil or: [ self actualClass isTrait ])
>>>> >>>>                 ifFalse: [self className, ' class']
>>>> >>>>                 ifTrue: [self className, ' classSide']]
>>>> >>>>
>>>> >>>>
>>>> >>>>
>>>> >>>> Because FileAttributesPluginPrims doesn't exist in the image (the
>>>> >>>> code
>>>> >>>> is read in from the git repository and being written out to a .st
>>>> >>>> file),
>>>> >>>> #actualClass returns nil, resulting in "classSide" being used instead
>>>> >>>> of
>>>> >>>> "class".
>>>> >>>>
>>>> >>>> I've never seen "classSide" used in chunk format.  Is there any time
>>>> >>>> "classSide" is valid, and any suggestions on how this should be
>>>> >>>> fixed?
>>>> >>>> (My first thought is to just change MCStWriter>>writeMethodPreamble:
>>>> >>>> to
>>>> >>>> only write "class").
>>>> >>>>
>>>> >>>>
>>>> >>>>
>>>> >>>> Thanks,
>>>> >>>> Alistair
>>>> >>>>
>>>>
>>>
>>>
>>>
>>> --
>>>
>>>
>>>
>>> Guille Polito
>>>
>>> Research Engineer
>>>
>>> Centre de Recherche en Informatique, Signal et Automatique de Lille
>>>
>>> CRIStAL - UMR 9189
>>>
>>> French National Center for Scientific Research - http://www.cnrs.fr
>>>
>>>
>>> Web: http://guillep.github.io
>>>
>>> Phone: +33 06 52 70 66 13

Reply via email to