[squeak-dev] Environment declarations vs bindings

H. Hirzel hannes.hirzel at gmail.com
Thu Sep 29 17:42:45 UTC 2016


On 9/29/16, Frank Shearar <frank.shearar at gmail.com> wrote:
> On 29 September 2016 at 10:10, Nicolas Cellier <
> nicolas.cellier.aka.nice at gmail.com> wrote:
>
>>
>>
>> 2016-09-29 18:39 GMT+02:00 Jakob Reschke <jakob.reschke at student.hpi.de>:
>>
>>> Many questions should be answered with tooling here, but in the
>>> particular case I mentioned, IMHO it is not about tooling. Until now,
>>> code that does `Smalltalk at: something` wants to look up something
>>> dynamically or it can't be sure that this class is actually loaded. As
>>> there was only one place to do such lookups, no differentiation about
>>> visibility or the source of a binding was necessary.
>>>
>>> Instances of `Smalltalk at: something` should either be replaced by an
>>> environment aware equivalent that makes clear if a name should be
>>> looked up *only* in the receiving environment (in its declarations),
>>> or if a name should be resolved, looking also in imported environments
>>> (in the bindings).
>>
>>
>> Agree
>>
>>
>>> As it is inconvenient to find all these pieces of
>>> code and change them all, `Smalltalk (globals)` could be the "active"
>>> environment (currently via dynamic scoping with `on:
>>> CurrentEnvironment do: ...`), not the original global environment.
>>
>>
>> I don't like the idea of CurrentEnvironment at all. IMO global state
>> stinks.
>> It would mean that a lotta behavior would change by simply switching one
>> shared variable...
>> I see it more like a not so clever workaround to make tools still work in
>> presence of environments with minimal changes.
>>
>
> Global state does indeed stink, which is why Environments is so nice,
> because "global" isn't global anymore.
>
> But that's the whole point of CurrentEnvironment - it's a _delimited
> dynamic variable_, turning formerly actually global state into something
> context sensitive.

     Environment current

is parallel to

     Project current

I think this is OK.

@Frank, could you elaborate please what you mean with '_delimited
dynamic variable_' ?

--Hannes

> frank
>
>
>
>> But
>>> then Environment>>at: must behave sensibly. I would expect that I can
>>> always do `Smalltalk at: #Object` to retrieve `Object` in any
>>> environment (under the assumption that every environment would import
>>> the "Kernel" or original environment). This is currently not the case,
>>> because Environment>>at: looks only into an environment's (own)
>>> declarations, not the imported bindings.
>>>
>>>
>> I don't know. Maybe (Smalltalk at: #Foo) is questionable by itself.
>> VW did introduce #{Foo} ifPresent: [:foo | ] or something like that for
>> deferred bindings.
>> I remind you that Smalltalk itself is a global variable created with a
>> different instance for each environment.
>>
>> Object is in the superclass chain, so we can still access with superclass
>> superclass ... environment.
>>
>>
>>
>>> 2016-09-29 17:30 GMT+02:00 Nicolas Cellier
>>> <nicolas.cellier.aka.nice at gmai
>>> l.com>:
>>> >
>>> >
>>> > 2016-09-29 15:15 GMT+02:00 Jakob Reschke
>>> > <jakob.reschke at student.hpi.de>
>>> :
>>> >>
>>> >> Hi,
>>> >>
>>> >> Environment>>associationAt: is part of the Smalltalk globals
>>> >> Dictionary compatibility interface, right? As a quick and dirty fix,
>>> >> I
>>> >> changed instances of Smalltalk at: xyz in Monticello code to
>>> >> CurrentEnvironment signal at: xyz, but #at: also only reads in the
>>> >> declarations, so myEnvironment at: #MCWriter or myEnvironment at:
>>> >> #Object returns nil by default. It would make more sense to perform a
>>> >> full lookup via #valueOf:ifAbsent: in #at: and its cousins, wouldn't
>>> >> it?
>>> >>
>>> >> Best,
>>> >> Jakob
>>> >>
>>> >
>>> > I imagine that the question is about tools.
>>> > For now Smalltalk importSelf, so bindings and declarations do agree.
>>> > If an Environment does not importSelf, then some variables will be
>>> > invisibles (unbounds). Do we still want to see them in some tool, or
>>> not?
>>> > What's going on if we play with Alias? Do we want to see the Alias in
>>> some
>>> > browser? If not, then we'd better stick with declarations.
>>> > There is no easy solution. A single facade for two dictionaries cannot
>>> fit
>>> > all, so we need several different messages.
>>> > But it's much about what we want to do with those environments.
>>> >
>>> >
>>> >>
>>> >> 2016-09-29 7:33 GMT+02:00 H. Hirzel <hannes.hirzel at gmail.com>:
>>> >> > On 9/28/16, Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com>
>>> wrote:
>>> >> >> Since we are at reviewing Environment, here is a small detail that
>>> >> >> bothers
>>> >> >> me. I already asked some months ago, but silence was the only
>>> response,
>>> >> >> so
>>> >> >> ping.
>>> >> >>
>>> >> >> Implementation of Environment is sometimes not obvious:
>>> >> >> - Environment>>associationAt: uses declarations inst.var..
>>> >> >> - Environment>>associationOrUndeclaredAt: uses bindings inst.var.
>>> >> >> How can it be so different, the selector does not speak, does it?
>>> >> >>
>>> >> >> OK, there is a flag: #review in one of them, but that does not
>>> >> >> make
>>> >> >> code
>>> >> >> clearer, it's just a smell of over-complexity or ill-naming.
>>> >> >>
>>> >> >> Whatever the reason (self explaining code?) Colin does not comment
>>> >> >> class/methods, that's a fact.
>>> >> >
>>> >> > Alternatively a description of the general ideas and the mechanism
>>> would
>>> >> > help.
>>> >> >
>>> >> > After all Environments is just a clever combination of a few
>>> >> > dictionaries  to look up class names? Isn't it?  ;-)
>>> >> >
>>> >> > However the fact that people did not move on much finalising the
>>> >> > implementation of environments  since 2012 shows that it is hard to
>>> >> > reverse-engineer the intentions from the (incomplete) code.
>>> >> >
>>> >> >
>>> >> >
>>> >> >
>>> >> >
>>> >> >> Chris made the effort of commenting Environment but then came this
>>> >> >> declarations/bindings split, and the comment did rapidly rot.
>>> >> >> We have here an un-healthy statu quo crying for change.
>>> >> >>
>>> >> >> So if we want to at least comment the class with the
>>> >> >> meaning/role/responsibility of inst vars, here is my
>>> >> >> understanding:
>>> >> >>
>>> >> >> environment bind: #Foo to: 0. just add to the declarations.
>>> >> >> (You see how names are not obvious: bind does not bind the new
>>> binding
>>> >> >> to
>>> >> >> bindings).
>>> >> >
>>> >> > Environments
>>> >> >
>>> >> > bind: aSymbol to: anObject
>>> >> >         | binding newBinding |
>>> >> >         newBinding := aSymbol => anObject.
>>> >> >
>>> >> >         binding := declarations associationAt: aSymbol ifAbsent:
>>> [nil].
>>> >> >         binding ifNotNil:
>>> >> >                 [binding class == newBinding class
>>> >> >                         ifTrue: [binding value: anObject]
>>> >> >                         ifFalse: [binding becomeForward:
>>> >> > newBinding].
>>> >> >                 ^anObject].
>>> >> >
>>> >> >         binding := undeclared associationAt: aSymbol ifAbsent:
>>> >> > [nil].
>>> >> >         binding
>>> >> >                 ifNil: [binding := newBinding]
>>> >> >                 ifNotNil:
>>> >> >                         [undeclared removeKey: aSymbol.
>>> >> >                         binding class == newBinding class
>>> >> >                                 ifTrue: [binding value: anObject]
>>> >> >                                 ifFalse: [binding becomeForward:
>>> >> > newBinding]].
>>> >> >
>>> >> >         declarations add: binding.
>>> >> >         self binding: binding addedTo: self.
>>> >> >         ^anObject
>>> >> >
>>> >> >
>>> >> > Could you elaborate a bit please?
>>> >> >
>>> >> >
>>> >> >
>>> >> >
>>> >> >> If the Environment importSelf, then the ClassBinding/Global also
>>> goes
>>> >> >> to
>>> >> >> bindings... (thru an observer pattern and the magic of naming
>>> policies)
>>> >> >>
>>> >> >> The bindings is what is used by the compiler, so what if an
>>> environment
>>> >> >> does not importSelf? It means that the variable it declares are
>>> >> >> not
>>> >> >> bound,
>>> >> >> so it is not reachable (kind of invisible class/Global).
>>> >> >>
>>> >> >> IOW, the bindings will contain all the imports, including
>>> self-imports.
>>> >> >> importSelf is generally what we want to do, unless weird cases of
>>> >> >> powerless
>>> >> >> environment for obfuscation or trustless sandboxing reason.
>>> >> >>
>>> >> >> Now, associationAt: does not speak for itself. It's too hard to
>>> decide
>>> >> >> if
>>> >> >> we're speaking of own declarations or bindings... Analyzing the
>>> usage
>>> >> >> is
>>> >> >> difficult. bindingAt: would be less ambiguous, so IMO we cannot
>>> >> >> fix
>>> >> >> without
>>> >> >> semantic shift.
>>> >> >
>>> >> > This would need as well elaboration as well a separate thread.
>>> >> >
>>> >> >
>>> >> >> The semantic will be carried by the senders (the Tools), and the
>>> tools
>>> >> >> by
>>> >> >> usage we want to make of Environment. So we first have to define
>>> that:
>>> >> >> what
>>> >> >> feature do we want to support? With which tool? That probably
>>> require
>>> >> >> yet
>>> >> >> another thread...
>>> >> >
>>> >> > Yes
>>> >> >
>>> >> > --Hannes
>>> >> >
>>> >>
>>> >
>>>
>>>
>>
>>
>>
>>
>


More information about the Squeak-dev mailing list