do you know if the OCUndeclaredVariable is raised for unknown superclass?

this code:

AnUnknownClass subclass: #Adaptor1Example
� � � � instanceVariableNames: 'customers accountID address name phoneNumber'
� � � � classVariableNames: ''
� � � � poolDictionaries: ''
� � � � category: 'Examples-Cookbook'

is run as a Do It. In Do It, unknown variables (as here AnUnknownClass) raise an�OCUndeclaredVariableWarning.
For example, running:

AnUnknownClass subclass: #Adaptor1Example
� � � � instanceVariableNames: 'customers accountID address name phoneNumber'
� � � � classVariableNames: ''
� � � � poolDictionaries: ''
� � � � category: 'Examples-Cookbook'

executes the default action for�OCUndeclaredVariableWarning, which is opening a pop-up titled: "Unknown variable ...". Here the error is raised at compilation time, therefore it would have no effect to wrap this with a #on:do:�

[ AnUnknownClass subclass: #Adaptor1Example
� � � � instanceVariableNames: 'customers accountID address name phoneNumber'
� � � � classVariableNames: ''
� � � � poolDictionaries: ''
� � � � category: 'Examples-Cookbook' ] on:�OCSemanticWarning do: [ ]

==> same problem.

Now if you do:�

[ OpalCompiler new evaluate: 'AnUnknownClass subclass: #Adaptor1Example
� � � � instanceVariableNames: ''customers accountID address name phoneNumber''
� � � � classVariableNames: ''''
� � � � poolDictionaries: ''''
� � � � category: ''Examples-Cookbook''' ] on: OCSemanticWarning do: [ :e | e halt ]

Here we catch the error, and you can handle it.�
Now it is not easily possible to resume the error, because you want a global instead and Opal expects a temp (there are way to resume but with very deep stack manipulation that I do not want to show to young pharoers present on this mailing list). So the best is to retry it. One solution is therefore:

[ OpalCompiler new evaluate: 'AnUnknownClass subclass: #Adaptor1Example
� � � � instanceVariableNames: ''customers accountID address phoneNumber''
� � � � classVariableNames: ''''
� � � � poolDictionaries: ''''
� � � � category: ''Examples-Cookbook''' ]�
on: OCSemanticWarning do: [ :e |�
Smalltalk at: e node name put: StubRootClass.
e retry ]�

with e node name answering #AnUnknownClass here.
Now you need to make sure that the exception block is executed for the case of a missing superclass and not something else or you will end up creating loads of globals.

The exception block should be something similar to:

�[ :e |�
� � � � e node name first isUppercase and: [ "some condition" ] ifTrue: [
Smalltalk at: e node name put: StubRootClass.
^ e retry ].
� � � � e pass ]�

How to undefined and�OCUndeclaredVariableWarning relate?

In your case, while loading from Monticello the code is compiled and evaluated in non interactive mode. Therefore it cannot trigger the default action of OCUndeclaredVariableWarning which is a UI event. So it sets by default the unknown global to:

Undeclared at: varName asSymbol put: nil.
OCUndeclaredVariable new name: varName asSymbol

in: OCUndeclaredVariableWarning >>defaultAction

which then later triggers the code in UndefinedObject.



2013/12/3 St�phane Ducasse <stephane.ducasse@inria.fr>

On Dec 3, 2013, at 11:20 AM, Cl�ment Bera <bera.clement@gmail.com> wrote:

Then for your project replace ProtoObject by�StubRootClass in�UndefinedObject>>subclass:instanceVariableNames:classVariableNames:poolDictionaries:category: it will work.

yes but this is ugly because I do not want override.
So I will introduce an exception so that we can do that in a clean way.


An alternative is to catch�OCSemanticWarning or its subclass OCUndeclaredVariableWarning while loading the new classes and execute another code instead of the default action in the exception handling block


do you know if the OCUndeclaredVariable is raised for unknown superclass?
How to undefined and�OCUndeclaredVariableWarning relate?

Stef


2013/12/3 St�phane Ducasse <stephane.ducasse@inria.fr>
> Well if the class does not exists it calls the method on UndefinedObject (UndeclaredBinding). And you have:

I will check and see if I can set up a hook because having classes subclasses of protoobject is not a good idea
when loading broken code.

> UndefinedObject>>subclass: nameOfClass
> � � � instanceVariableNames: instVarNames
> � � � classVariableNames: classVarNames
> � � � poolDictionaries: poolDictnames
> � � � category: category
> � � � "Calling this method is now considered an accident. �If you really want to create a class with a nil superclass, then create the class and then set the superclass using #superclass:"
> � � � self traceCr: ('Attempt to create ', nameOfClass, ' as a subclass of nil. �Possibly a class is being loaded before its superclass.').
> � � � ^ProtoObject
> � � � � � � � subclass: nameOfClass
> � � � � � � � instanceVariableNames: instVarNames
> � � � � � � � classVariableNames: classVarNames
> � � � � � � � poolDictionaries: poolDictnames
> � � � � � � � category: category
>
> The best is to set manually the superclass after with #superclass:

No because I have no idea what are the classes whose superclasses are not in the image.
With a proper hook I could just say
� � � � if the superclass is unknow please use the "StubRootClass" of my framework.
� � � � else let the system handles it.

Stef