On Tue, Oct 4, 2016 at 4:23 AM, CodeDmitry <[email protected]> wrote:
> I am trying to study Pharo's internals and I am now curious how it stores
> class variables.
>
> I notice that in order to have a class `Greeter` with a "static" variable
> `greeting`,


I guess you are referring to...
http://www.learncpp.com/cpp-tutorial/811-static-member-variables/

So its fair to analogize to a familiar concept, but you need to remember...

Rule 1: *Everything* is an object.

which includes class definitions, being instances of Metaclass. So try...
  Metaclass allInstances inspect.
then select one and compare its 'methodDict' and 'thisClass' ==> 'methodDict'
with what you see for that class in the System Browser.

Notice the ClassDescription superclass to Metaclass has an instance
variable 'instanceVariables'.
Now one thing that confused me for a moment just now is, if you try...
  Metaclass allInstances select: [ :mc | mc instanceVariables size > 0 ].
then look at that instance variable 'instanceVariables'
it is always nil due to the implementation in Pharo 5 of instance
variables as Slots.  In Pharo 4 you see actual names of instance
variables.   btw I'm curious now, does that ivar 'instanceVariables'
planned to be removed some time?

Now actually (IIUC) a C++ static member variable is most like a "Class
Variable" which is defined on the instance side of a class.  There are
three main variable types to consider when defining a class in Pharo:
Instance variables - scoped to instance methods, unique per instance
Class Variables - scoped to instance methods & class methods, common
to the class and all subclasses and all their instances
Class Instance Variables - scoped to class methods, unique per class
(i.e. instance of Metaclass)

To experience the finer points of these you might try the experiment I
describe here...
http://forum.world.st/Class-vars-and-inst-vars-of-a-class-tp4749910p4749914.html


> I need to make `greeting` an instance variable under "show
> the class side" and create a "Getter" and "Setter" for this "instance
> variable".
>
> First thing that confuses me is, why is this called an instance variable if
> this particular "static" method is not bound to any particular instance?


The method is bound to an instance of Metaclass, being the class
definition.  When you add methods or instance variables to the
class-side in the Browser, you are adding them to this instance.
There is one instance of Metaclass for each class in the system.


> Is
> it just because it is defined in an "instance" of a "ProtoClass"?

I don't understand this question.  Can you rephrase after doing the
experiment linked above?

>
> Second thing that confuses me is, where are these pairs of ("instance
> variable name" => "instance variable value") stored? I know that I can call
>
> Transcript show:
>     ((Greeter class) instanceVariables at: 1).
>
> which prints "greeting".
>
> and
>
> Transcript show:
>   Greeter instanceVariables class.
>
> which prints "Array"(curious, i expected a Dictionary mapping Strings to
> Object).


What you are seeing is a copy of the core representation. Try debugging into....
    (Greeter class instanceVariables at: 1)
paying particular attention to...
LayoutClassScope>>visibleSlots
LayoutClassScope>>do:


>
> Transcript show:
>     ((Greeter class) instanceVariables at: 1) class.
>
> prints "ByteSymbol".
>
> Now I am confused, where are the actual values of the "static variables"
> stored? I can find the names, but  can't understand where  the values are
> hidden.

You are looking at a copy of the core representation.

To work through a quick example... take the Morph class definition's
first two instanceVariables: 'bounds owner...'
and for each of their accessors #bounds and #owner
right-click and choose <Inspect Method>
then compare each [Bytecode] tab
with the first line showing "callPrimitive: 264" or "callPrimitive:
265" respectively.
These (and similar) primitives provide the *real* "compiled" access to
the instance variables.

So that demostration is the equivalent of asking "where are the values
in variables stored" for C++
and reviewing its generated assembler code - although our VM provides
a level of abstraction.  Hopefully the ease of digging from source
code down to its compiled bytecode demonstrates another aspect of the
power of the Pharo environment.


btw, you can see the list of VM primitives here...
https://github.com/pharo-project/pharo-vm/blob/36079d9be14542ea9e0d72e5ef57b596bd8aab52/mc/VMMaker.oscog.package/StackInterpreter.class/class/initializePrimitiveTable.st


cheers -ben

Reply via email to