2013/12/4 Nicolas Cellier <nicolas.cellier.aka.n...@gmail.com>

> I forgot to add that the OCUndeclaredVariableWarning was already handled
> at semantic analysis.
>

This is not the case. The OCUndeclaredVariableWarning is handled in the
default action. Therefore anyone can catch it.

In this case for instance:

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

The Semantic warning is caught outside of the semantic analysis and it
works perfectly fine. The only thing is that you need to retry the error
and not resume it to restart the semantic analysis (or you have an
inconsistent execution state in the semantic analysis visitor).


> Do you suggest that default behavior should be to handle and retry instead
> of handle and return?
>
One way to achieve what you are asking would be to initialize the
> Undeclared entry to some kind of ProtoObject that does not understand
> anything and rethrow a OCUndeclaredVariableWarning instead of a
> MessageNotUnderstood... (very uneasy to debug, since the Debugger itself is
> querying the receiver etc... - unless Debugger is using basic mirror
> primitives)
>
>
> 2013/12/4 Nicolas Cellier <nicolas.cellier.aka.n...@gmail.com>
>
>> Steph, each time you want to evaluate something, do you agree that this
>> involves
>> - a parse phase of the expression you want to evaluate to create an AST
>> - a code generation phase from AST -> bytecodes to generate a
>> CompiledMethod
>> - the evaluation phase itself which evaluates above CompiledMethod with
>> appropriate receiver (nil generally)
>>
>> I didn't check OPAL, but do you agree that the semantic analysis
>> determining which are those variables you called {'AnUnknownClass'.
>> 'OCUndeclaredVariableWarning'. 'self'} and how to bind them, must happen
>> somewhere between AST and CompiledMethod creation?
>>
>> So if there is a semantic exception, like UndeclaredVariable, how would
>> the CompiledMethod be generated in the first place?
>> If it's not generated, how would it be executed?
>> If it's not executed, how would the message on:do: be sent to a block
>> with 2 arguments?
>>
>> Unless you suggest to attempt executing a ParseTree which is known to be
>> defectuous...
>>
>>  2013/12/4 Stéphane Ducasse <stephane.duca...@inria.fr>
>>
>>> 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: *
>>>
>>>
>>> I do not understand why if an exception is raised why I cannot trap it.
>>>
>>> [AnUnknownClass subclass: #Adaptor1Example
>>>         instanceVariableNames: 'customers accountID address name
>>> phoneNumber'
>>>         classVariableNames: ''
>>>         poolDictionaries: ''
>>>         category: 'Examples-Cookbook'] on: OCUndeclaredVariableWarning
>>> do: [ self halt.]  does not halt.
>>>
>>> The fact that is is at compilation time does not mean anything to me. So
>>> why? I'm totally confused by this bad and unexpected behavior.
>>> Do you imply that the warning is already trapped and that I cannot take
>>> precedence? Probably but this has nothing to do with compilation time.
>>>
>>> Then to me OCSemanticWarning should be enhanced so that we do not get
>>> these silly menus. An exception should work and clients should be able to
>>> customise
>>> it to (for example introduce menu and dialog with the users but they
>>> should not be the only default.
>>> We see again this plague of interactive environment not being rethought
>>> in the 2013 age.
>>>
>>> defaultAction
>>>  self errorNotification ifFalse: [ ^nil ].
>>>  ^self openMenuIn:
>>> [:labels :lines :caption |
>>> UIManager default chooseFrom: labels lines: lines title: caption]
>>>
>>> but that we could specify the action to be executed instead.
>>>
>>>
>>> to me CompilerException should have nothing to do with UI and popup.
>>> Then we should be able to pass objects that knows how to handle
>>> the errors in interactive way or not.
>>>
>>> As a clear example, this is just bad that each time we want to change
>>> the UI message we have to change the compiler exception.
>>> ugly at wish.
>>>
>>> I have no cycle to fix that now. I will check if I can get something in
>>> UndefinedObject so that I can continue to work on my task.
>>>
>>> Stef
>>>
>>>
>>>
>>> [ 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.
>>>
>>>
>>>
>>
>

Reply via email to