Making TDD in pharo work properly (aka - walkback on a missing class is nasty)
Hi guys - Iâve been hammering on the exercism project to get pharo shining over there⦠its been a good side distraction (there is lots of energy in that community to) and its made me really push my use of Iceberg & git as well as learn some fo the newish file reference stuff (still getting good at that - but like the approach), Anyway - Iâve got an Alpha working, and users can pull down a zero conf pharo image and eval a little script that will get them up and running (which is pretty slick). So the story then goes - Exercism is trying to simulate TDD and help you learn a new language (aka Pharo or Go or Python etc). To this end, theyâve got an active community building up little test exercises with suites of tests that new users can run to help them learn the syntax/essence of the language track theyâve signed up to. You run the tests, develop your solution and then submit it to a community to get feedback and then progress. Pretty standard - we can play in this pond too - and it turns out that Tonel actually makes it pretty easy to submit readable solutions that will fit on their website. YAY. The trouble is - when you pull down a new exercise - I use the TonelReader to pull the code into your image - and I thought it would be cute to just pull in the TestCase so that users can simulate the full TDD cycle - where you can create things in the debugger⦠this is where it all began right? So you hit a clanger when you do this - and in a way its a bit of a legacy thing weâve carried around (and possibly should fix better). When Tonel reads in the TesCase, it normally will reference a class this isnât there (Iâve deliberately left the solution out). It does the right thing and put a nil placeholder in the code so that it can read it in. HOWEVER - when you run your test and hit that nil class placeholder we do a very bad job of dealing with this in the debugger. And if you think about it - we also do a bad job when typing in code too - we essentially insist that declare a class then and there - unlike a selector which can happily be late bound. So back to my TDD example - user gets a debugger with a nil class error - the create button is actually not helpful for you as it only creates methods. So our âlive in the debuggerâ mantra is a bit less obvious here. What you had to do is make a change to the source (like a space) so that you can reserve the method - which then causes you to get the âcreate class promptâ. So we have the ability - just donât expose it very well - however now you have a missing method - but again its not so obvious that you have to resume your debugger (it hasnât resumed when you created the class) - and then you will get another error for the missing method that the create button will now resolve. This feels very clunky to me - and makes me feel like Iâm mis-selling smalltalk where we have a bullet point about âAmazing for debuggingâ¦â. This feels fixable though right? Iâm wondering about thoughts though before jumping in⦠Tim p.s. - weâre building some exercises for exercism and getting that process streamlined so hopefully many more people can help - and maybe we can augment the great learning courses/videos/books that we already have.
+1 On Tue, 7 Aug 2018 at 09:02 Tim Mackinnon <tim@testit.works> wrote:
Hi guys - Iâve been hammering on the exercism project to get pharo shining over there⦠its been a good side distraction (there is lots of energy in that community to) and its made me really push my use of Iceberg & git as well as learn some fo the newish file reference stuff (still getting good at that - but like the approach),
Anyway - Iâve got an Alpha working, and users can pull down a zero conf pharo image and eval a little script that will get them up and running (which is pretty slick).
So the story then goes - Exercism is trying to simulate TDD and help you learn a new language (aka Pharo or Go or Python etc). To this end, theyâve got an active community building up little test exercises with suites of tests that new users can run to help them learn the syntax/essence of the language track theyâve signed up to. You run the tests, develop your solution and then submit it to a community to get feedback and then progress.
Pretty standard - we can play in this pond too - and it turns out that Tonel actually makes it pretty easy to submit readable solutions that will fit on their website. YAY.
The trouble is - when you pull down a new exercise - I use the TonelReader to pull the code into your image - and I thought it would be cute to just pull in the TestCase so that users can simulate the full TDD cycle - where you can create things in the debugger⦠this is where it all began right?
So you hit a clanger when you do this - and in a way its a bit of a legacy thing weâve carried around (and possibly should fix better). When Tonel reads in the TesCase, it normally will reference a class this isnât there (Iâve deliberately left the solution out). It does the right thing and put a nil placeholder in the code so that it can read it in.
HOWEVER - when you run your test and hit that nil class placeholder we do a very bad job of dealing with this in the debugger. And if you think about it - we also do a bad job when typing in code too - we essentially insist that declare a class then and there - unlike a selector which can happily be late bound.
So back to my TDD example - user gets a debugger with a nil class error - the create button is actually not helpful for you as it only creates methods. So our âlive in the debuggerâ mantra is a bit less obvious here. What you had to do is make a change to the source (like a space) so that you can reserve the method - which then causes you to get the âcreate class promptâ. So we have the ability - just donât expose it very well - however now you have a missing method - but again its not so obvious that you have to resume your debugger (it hasnât resumed when you created the class) - and then you will get another error for the missing method that the create button will now resolve.
This feels very clunky to me - and makes me feel like Iâm mis-selling smalltalk where we have a bullet point about âAmazing for debuggingâ¦â.
This feels fixable though right? Iâm wondering about thoughts though before jumping inâ¦
Tim
p.s. - weâre building some exercises for exercism and getting that process streamlined so hopefully many more people can help - and maybe we can augment the great learning courses/videos/books that we already have.
-- Sent from the past
Feenk re-imagining aside (which I will pursue with them), it seems like our current tools can support this better right? I see two issues: 1) if we encounter a not present class can we fix the debugger to offer something like we do for a missing method so itâs less obtuse? 2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned) Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can. Tim Sent from my iPhone
On 9 Aug 2018, at 01:44, Francisco Ortiz Peñaloza <patchinko@gmail.com> wrote:
+1
On Tue, 7 Aug 2018 at 09:02 Tim Mackinnon <tim@testit.works> wrote: Hi guys - Iâve been hammering on the exercism project to get pharo shining over there⦠its been a good side distraction (there is lots of energy in that community to) and its made me really push my use of Iceberg & git as well as learn some fo the newish file reference stuff (still getting good at that - but like the approach),
Anyway - Iâve got an Alpha working, and users can pull down a zero conf pharo image and eval a little script that will get them up and running (which is pretty slick).
So the story then goes - Exercism is trying to simulate TDD and help you learn a new language (aka Pharo or Go or Python etc). To this end, theyâve got an active community building up little test exercises with suites of tests that new users can run to help them learn the syntax/essence of the language track theyâve signed up to. You run the tests, develop your solution and then submit it to a community to get feedback and then progress.
Pretty standard - we can play in this pond too - and it turns out that Tonel actually makes it pretty easy to submit readable solutions that will fit on their website. YAY.
The trouble is - when you pull down a new exercise - I use the TonelReader to pull the code into your image - and I thought it would be cute to just pull in the TestCase so that users can simulate the full TDD cycle - where you can create things in the debugger⦠this is where it all began right?
So you hit a clanger when you do this - and in a way its a bit of a legacy thing weâve carried around (and possibly should fix better). When Tonel reads in the TesCase, it normally will reference a class this isnât there (Iâve deliberately left the solution out). It does the right thing and put a nil placeholder in the code so that it can read it in.
HOWEVER - when you run your test and hit that nil class placeholder we do a very bad job of dealing with this in the debugger. And if you think about it - we also do a bad job when typing in code too - we essentially insist that declare a class then and there - unlike a selector which can happily be late bound.
So back to my TDD example - user gets a debugger with a nil class error - the create button is actually not helpful for you as it only creates methods. So our âlive in the debuggerâ mantra is a bit less obvious here. What you had to do is make a change to the source (like a space) so that you can reserve the method - which then causes you to get the âcreate class promptâ. So we have the ability - just donât expose it very well - however now you have a missing method - but again its not so obvious that you have to resume your debugger (it hasnât resumed when you created the class) - and then you will get another error for the missing method that the create button will now resolve.
This feels very clunky to me - and makes me feel like Iâm mis-selling smalltalk where we have a bullet point about âAmazing for debuggingâ¦â.
This feels fixable though right? Iâm wondering about thoughts though before jumping inâ¦
Tim
p.s. - weâre building some exercises for exercism and getting that process streamlined so hopefully many more people can help - and maybe we can augment the great learning courses/videos/books that we already have.
-- Sent from the past
On 9 Aug 2018, at 08:20, Tim Mackinnon <tim@testit.works> wrote:
Feenk re-imagining aside (which I will pursue with them), it seems like our current tools can support this better right?
I see two issues:
1) if we encounter a not present class can we fix the debugger to offer something like we do for a missing method so itâs less obtuse?
Right now we compile an âUndeclaredâ variable: a bining #name -> nil that lives in the Undeclareds dictionary. The result is that this variable is nil when read. This seems a good behaviour for non-interactive use, but not the right thing when doing development. In Pharo, these bindings are actually now not just Associations, but there is a class Hierarchy. The object describing the global binding is actually a UndeclaredVariable. You can see that like this: compile this with a non-existing âMyClassâ (see below, Pharo7 can do it even in interactive mode): test ^MyClass. then (TT>>#test) literals first class Now: the compiler actually asks that object to generate the code for the read. If you look at class UndeclaredVariable, it looks like this: emitValue: methodBuilder methodBuilder pushLiteralVariable: self So we could do an experiment: couldnât we generate code here that actually starts an interaction? Similar to the one (see below) that we do when the user tries to compile a method with an Undeclared in the first place (see below).
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option:
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
Tim
Sent from my iPhone
On 9 Aug 2018, at 01:44, Francisco Ortiz Peñaloza <patchinko@gmail.com <mailto:patchinko@gmail.com>> wrote:
+1
On Tue, 7 Aug 2018 at 09:02 Tim Mackinnon <tim@testit.works <mailto:tim@testit.works>> wrote: Hi guys - Iâve been hammering on the exercism project to get pharo shining over there⦠its been a good side distraction (there is lots of energy in that community to) and its made me really push my use of Iceberg & git as well as learn some fo the newish file reference stuff (still getting good at that - but like the approach),
Anyway - Iâve got an Alpha working, and users can pull down a zero conf pharo image and eval a little script that will get them up and running (which is pretty slick).
So the story then goes - Exercism is trying to simulate TDD and help you learn a new language (aka Pharo or Go or Python etc). To this end, theyâve got an active community building up little test exercises with suites of tests that new users can run to help them learn the syntax/essence of the language track theyâve signed up to. You run the tests, develop your solution and then submit it to a community to get feedback and then progress.
Pretty standard - we can play in this pond too - and it turns out that Tonel actually makes it pretty easy to submit readable solutions that will fit on their website. YAY.
The trouble is - when you pull down a new exercise - I use the TonelReader to pull the code into your image - and I thought it would be cute to just pull in the TestCase so that users can simulate the full TDD cycle - where you can create things in the debugger⦠this is where it all began right?
So you hit a clanger when you do this - and in a way its a bit of a legacy thing weâve carried around (and possibly should fix better). When Tonel reads in the TesCase, it normally will reference a class this isnât there (Iâve deliberately left the solution out). It does the right thing and put a nil placeholder in the code so that it can read it in.
HOWEVER - when you run your test and hit that nil class placeholder we do a very bad job of dealing with this in the debugger. And if you think about it - we also do a bad job when typing in code too - we essentially insist that declare a class then and there - unlike a selector which can happily be late bound.
So back to my TDD example - user gets a debugger with a nil class error - the create button is actually not helpful for you as it only creates methods. So our âlive in the debuggerâ mantra is a bit less obvious here. What you had to do is make a change to the source (like a space) so that you can reserve the method - which then causes you to get the âcreate class promptâ. So we have the ability - just donât expose it very well - however now you have a missing method - but again its not so obvious that you have to resume your debugger (it hasnât resumed when you created the class) - and then you will get another error for the missing method that the create button will now resolve.
This feels very clunky to me - and makes me feel like Iâm mis-selling smalltalk where we have a bullet point about âAmazing for debuggingâ¦â.
This feels fixable though right? Iâm wondering about thoughts though before jumping inâ¦
Tim
p.s. - weâre building some exercises for exercism and getting that process streamlined so hopefully many more people can help - and maybe we can augment the great learning courses/videos/books that we already have.
-- Sent from the past
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
An alternative could be to not show the menu at all. Instead just compile (I like the ideas that âeverything can be compiled and runâ). Just compile the Undeclared and instead of breaking the flow, we should add a menu to the editor to do the âdefine Classâ âDefine Traitâ⦠(with the gutter icons, we can provide a menu easily). I will make a small demo for that, too. Marcus
On 9 Aug 2018, at 10:06, Marcus Denker <marcus.denker@inria.fr> wrote:
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
An alternative could be to not show the menu at all. Instead just compile (I like the ideas that âeverything can be compiled and runâ).
Just compile the Undeclared and instead of breaking the flow, we should add a menu to the editor to do the âdefine Classâ âDefine Traitâ⦠(with the gutter icons, we can provide a menu easily).
I will make a small demo for that, too.
ah, and this fits well with the idea to show at runtime a dialog for fixing a Undeclared: The âfix toolâ would be the editor itself. It shows the menu in the gutter for the user to define a class, or the possibility to just edit and compile the method. Marcus
Marcus, I love this idea, not showing the menu at all would be more aligned to live coding. As you said in a later e-mail it must be fixed at runtime, while running the tests. Thanks! On Thu, Aug 9, 2018 at 5:07 AM Marcus Denker <marcus.denker@inria.fr> wrote:
2) when coding - if you want reference a missing class, why donât we
let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
An alternative could be to not show the menu at all. Instead just compile (I like the ideas that âeverything can be compiled and runâ).
Just compile the Undeclared and instead of breaking the flow, we should add a menu to the editor to do the âdefine Classâ âDefine Traitâ⦠(with the gutter icons, we can provide a menu easily).
I will make a small demo for that, too.
Marcus
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option: <leave undeclared.png>
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un... <https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un...> Marcus
Hi Marcus, Is it wise to backport things that may break things like this? I'd prefer to put the energy on backporting the workaround to avoid the infinite debuggers... On Thu, Aug 9, 2018 at 10:50 AM Marcus Denker <marcus.denker@inria.fr> wrote:
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option: <leave undeclared.png>
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un...
Marcus
-- 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 <http://www.cnrs.fr>* *Web:* *http://guillep.github.io* <http://guillep.github.io> *Phone: *+33 06 52 70 66 13
On 9 Aug 2018, at 10:59, Guillermo Polito <guillermopolito@gmail.com> wrote:
Hi Marcus,
Is it wise to backport things that may break things like this? maybe not, but it just took 5 minutes as it is very simple
I'd prefer to put the energy on backporting the workaround to avoid the infinite debuggers...
Yes.
On Thu, Aug 9, 2018 at 10:50 AM Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option: <leave undeclared.png>
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un... <https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un...>
Marcus
--
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 <http://www.cnrs.fr/>
Web: http://guillep.github.io <http://guillep.github.io/> Phone: +33 06 52 70 66 13
Guys - youâre awesome! It really shows why our environment is so powerful and why more people need to think this way! For back porting - you donât need to, as for exercism we are loading a script anyway, so I can load in some code until weâre ready for 7.0 I do agree that infinite debuggers is a pressing problem too (and sorry to distract on that one). Still - we want to present our best face when we go live on exercism - and the pharo features list I copied from Pharo.org (slightly tweaked) drove me to live up to the Hugh standards we set ourselves. Iâll definitely try out what youâve all proposed - I figured if was all possible . Tim Sent from my iPhone
On 9 Aug 2018, at 11:02, Marcus Denker <marcus.denker@inria.fr> wrote:
On 9 Aug 2018, at 10:59, Guillermo Polito <guillermopolito@gmail.com> wrote:
Hi Marcus,
Is it wise to backport things that may break things like this? maybe not, but it just took 5 minutes as it is very simple
I'd prefer to put the energy on backporting the workaround to avoid the infinite debuggers...
Yes.
On Thu, Aug 9, 2018 at 10:50 AM Marcus Denker <marcus.denker@inria.fr> wrote:
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option: <leave undeclared.png>
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un...
Marcus
--
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
Hey Marcus (or those knowledgable about stacks and contexts) - to self #1 - where the create button generates a class instead of a method, Iâm a bit out of my depth. I can see there is a DoesNotUnderstandDebugAction (which the create button calls). So to determine if the failure was due to a missing class or method - would this work? msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ⦠create a class E.g. if youâre trying to send a msg to nil (which is what got patched into the compiled method for a missing class) then you are dealing with a missing class? AND then for create a class - how do I extract the name? I can get the compiled method for msg - but how do I marry that up with what you were executing? Am I write in thinking that the AST nodes and there locations might line up with the stack pointer somehow (or something like that)⦠if I can get that - then I get the name of the missing class and can then create it and then rerun the method right? This is very neat stuff I âve never played with before. Tim
On 9 Aug 2018, at 11:02, Marcus Denker <marcus.denker@inria.fr> wrote:
On 9 Aug 2018, at 10:59, Guillermo Polito <guillermopolito@gmail.com <mailto:guillermopolito@gmail.com>> wrote:
Hi Marcus,
Is it wise to backport things that may break things like this? maybe not, but it just took 5 minutes as it is very simple
I'd prefer to put the energy on backporting the workaround to avoid the infinite debuggers...
Yes.
On Thu, Aug 9, 2018 at 10:50 AM Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option: <leave undeclared.png>
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un... <https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un...>
Marcus
--
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 <http://www.cnrs.fr/>
Web: http://guillep.github.io <http://guillep.github.io/> Phone: +33 06 52 70 66 13
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated) createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver. newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart. However that last line is wrong, as it doesnât restart with my newly defined class - I also tried aContext restartWithNewReceiver: newClass But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦) Tim
On 10 Aug 2018, at 16:30, Tim Mackinnon <tim@testit.works> wrote:
Hey Marcus (or those knowledgable about stacks and contexts) - to self #1 - where the create button generates a class instead of a method, Iâm a bit out of my depth.
I can see there is a DoesNotUnderstandDebugAction (which the create button calls).
So to determine if the failure was due to a missing class or method - would this work?
msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ⦠create a class
E.g. if youâre trying to send a msg to nil (which is what got patched into the compiled method for a missing class) then you are dealing with a missing class?
AND then for create a class - how do I extract the name?
I can get the compiled method for msg - but how do I marry that up with what you were executing? Am I write in thinking that the AST nodes and there locations might line up with the stack pointer somehow (or something like that)⦠if I can get that - then I get the name of the missing class and can then create it and then rerun the method right?
This is very neat stuff I âve never played with before.
Tim
On 9 Aug 2018, at 11:02, Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
On 9 Aug 2018, at 10:59, Guillermo Polito <guillermopolito@gmail.com <mailto:guillermopolito@gmail.com>> wrote:
Hi Marcus,
Is it wise to backport things that may break things like this? maybe not, but it just took 5 minutes as it is very simple
I'd prefer to put the energy on backporting the workaround to avoid the infinite debuggers...
Yes.
On Thu, Aug 9, 2018 at 10:50 AM Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option: <leave undeclared.png>
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un... <https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un...>
Marcus
--
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 <http://www.cnrs.fr/>
Web: http://guillep.github.io <http://guillep.github.io/> Phone: +33 06 52 70 66 13
I guess for a bit of historical record - I fixed the Pharo 6.1 image in exercism to properly handle the creation of a missing class. Not a lot of code (but you do need the right code - and it is slightly confusing how the debugger window is so tightly tied to the model which also has the stack and context - and thus getting rid of the window gets rid of the context - which in retrospect makes sense as closing the debugger should terminate everything). Iâll kick it around a bit with Exercism - and if it seems good Iâll make a PR for Pharo 7 as Think its worth having? It does raise an interesting point however - when you hit a missing class, the debugger says â#message was sent to nilâ - I would think we can do better than that given what Marcus discussed further below. If we were to save an UndefinedClass in the compiled method - then the error could be much better (not nil - but UndefinedClass, or UndefinedGlobal) - and equally the corrective action could be much better too. I think this is what Marcus was getting at - and I think it would be a much better thing for us to do. Having used one of his suggestions below (and tried it when coding some exercises) - I also think we should stop the disruptive prompting for missing classes or variables when you save and just show them as gutter warnings or squiggles in the editor. You could add some other key to walk you through fixes if you want to deal with them right at that moment. Anyway - this really shows how flexible our environment is (and the work we can keep doing). Tim
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
Tim
On 10 Aug 2018, at 16:30, Tim Mackinnon <tim@testit.works <mailto:tim@testit.works>> wrote:
Hey Marcus (or those knowledgable about stacks and contexts) - to self #1 - where the create button generates a class instead of a method, Iâm a bit out of my depth.
I can see there is a DoesNotUnderstandDebugAction (which the create button calls).
So to determine if the failure was due to a missing class or method - would this work?
msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ⦠create a class
E.g. if youâre trying to send a msg to nil (which is what got patched into the compiled method for a missing class) then you are dealing with a missing class?
AND then for create a class - how do I extract the name?
I can get the compiled method for msg - but how do I marry that up with what you were executing? Am I write in thinking that the AST nodes and there locations might line up with the stack pointer somehow (or something like that)⦠if I can get that - then I get the name of the missing class and can then create it and then rerun the method right?
This is very neat stuff I âve never played with before.
Tim
On 9 Aug 2018, at 11:02, Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
On 9 Aug 2018, at 10:59, Guillermo Polito <guillermopolito@gmail.com <mailto:guillermopolito@gmail.com>> wrote:
Hi Marcus,
Is it wise to backport things that may break things like this? maybe not, but it just took 5 minutes as it is very simple
I'd prefer to put the energy on backporting the workaround to avoid the infinite debuggers...
Yes.
On Thu, Aug 9, 2018 at 10:50 AM Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
This is fixed in Pharo7: we added a menu entry âleave undeclaredâ as the first option: <leave undeclared.png>
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
I will back port the fix for 2) to Pharo6 and will do a quick prototype for 1)
https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un... <https://pharo.fogbugz.com/f/cases/22305/Backport-to-Pharo6-Leave-Variable-Un...>
Marcus
--
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 <http://www.cnrs.fr/>
Web: http://guillep.github.io <http://guillep.github.io/> Phone: +33 06 52 70 66 13
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point. I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try? Marcus
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)? Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? Tim Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo <https://exercism.io/tracks/pharo>) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better?
I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works <mailto:tim@testit.works>> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation <https://exercism.io/tracks/pharo/installation> (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md <https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md>) Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works <mailto:tim@testit.works>> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo <https://exercism.io/tracks/pharo>) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better?
I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr <mailto:marcus.denker@inria.fr>> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works <mailto:tim@testit.works>> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome) Is this supposed to contain the code below (the createMissingClassActionFor:in:) ? It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem) Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better?
I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc). In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:) Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better?
I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Hi, I played with it, nice! I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases. Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better?
I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong? I will also put together a pr for this in Pharo 7 if you think itâs a decent fix. Tim Sent from my iPhone Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
On 22 Aug 2018, at 16:24, Tim Mackinnon <tim@testit.works> wrote:
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong?
In pharo7 we could easily do that (due to the âbindingâ, the meta class of the variable) being different. We could return a nil subclass or add code into the method directly. But the problem with that is that nil checks are always identity checks⦠Could you not in the case you now raise the error just fall back to the âdefine methodâ, the behaviour we have now? Marcus
I will also put together a pr for this in Pharo 7 if you think itâs a decent fix.
Tim
Sent from my iPhone
Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Hi Marcus - thatâs actually what I do - and âcreateâ in this case, creates a class and then restarts like the method case does. I guess I was wondering if we can do it more cleanly and also improve the debugger message. If Iâve understood you guys correctly- you try to remove the ambiguity around operations. Looking up a class and getting nil - seems like one of these holes you keep sorting out. I think the flaw in my solution is understanding if that message was being sent to a class, or some other global? I dont think I got that bit right (but itâs certainly better than nothing). e.g. in the debugger I am doing (in DoesNotUnderstandDebugAction) msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ^self createMissingClassIn: self interruptedContext ]. Iâm not totally convinced that lookupClass has to be a class - although maybe its good enough. But really, at the time this happened - we probably knew better than to get a DNU debug action in the the first place - and equally the title in the debugger could be something more akin to the kind of action its supposed to be. Anyway - this is all musing on my part - and I will assemble a proper PR for review by you guys (and at least it advances us forward - and maybe opens the door to better changes further on). Iâm just juggling another change at the moment - so it will be a few days. Tim Sent from my iPhone
On 23 Aug 2018, at 05:33, Marcus Denker <marcus.denker@inria.fr> wrote:
On 22 Aug 2018, at 16:24, Tim Mackinnon <tim@testit.works> wrote:
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong?
In pharo7 we could easily do that (due to the âbindingâ, the meta class of the variable) being different. We could return a nil subclass or add code into the method directly. But the problem with that is that nil checks are always identity checksâ¦
Could you not in the case you now raise the error just fall back to the âdefine methodâ, the behaviour we have now?
Marcus
I will also put together a pr for this in Pharo 7 if you think itâs a decent fix.
Tim
Sent from my iPhone
Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
On 23 Aug 2018, at 15:56, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - thatâs actually what I do - and âcreateâ in this case, creates a class and then restarts like the method case does.
Yes, that I saw. But I mean a different case: Imagine you do have code like nil doSomething or an expression that evaluates to nil, press âdefineâ and get a method definition dialog, not the error message? (it is, as I mentioned, not that important as nobody ever wants to define a method in UndefinedObject, but for consistency it would be nice)
I guess I was wondering if we can do it more cleanly and also improve the debugger message.
If Iâve understood you guys correctly- you try to remove the ambiguity around operations. Looking up a class and getting nil - seems like one of these holes you keep sorting out.
I think the flaw in my solution is understanding if that message was being sent to a class, or some other global? I dont think I got that bit right (but itâs certainly better than nothing).
e.g. in the debugger I am doing (in DoesNotUnderstandDebugAction)
msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ^self createMissingClassIn: self interruptedContext ].
Iâm not totally convinced that lookupClass has to be a class - although maybe its good enough. But really, at the time this happened - we probably knew better than to get a DNU debug action in the the first place - and equally the title in the debugger could be something more akin to the kind of action its supposed to be.
Anyway - this is all musing on my part - and I will assemble a proper PR for review by you guys (and at least it advances us forward - and maybe opens the door to better changes further on).
Iâm just juggling another change at the moment - so it will be a few days.
Tim
Sent from my iPhone
On 23 Aug 2018, at 05:33, Marcus Denker <marcus.denker@inria.fr> wrote:
On 22 Aug 2018, at 16:24, Tim Mackinnon <tim@testit.works> wrote:
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong?
In pharo7 we could easily do that (due to the âbindingâ, the meta class of the variable) being different. We could return a nil subclass or add code into the method directly. But the problem with that is that nil checks are always identity checksâ¦
Could you not in the case you now raise the error just fall back to the âdefine methodâ, the behaviour we have now?
Marcus
I will also put together a pr for this in Pharo 7 if you think itâs a decent fix.
Tim
Sent from my iPhone
Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Iâve submitted a PR for what I did, so at least it improves the situation (but potentially could get even more refined as you suggest) Tim
On 23 Aug 2018, at 11:26, Marcus Denker <marcus.denker@inria.fr> wrote:
On 23 Aug 2018, at 15:56, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - thatâs actually what I do - and âcreateâ in this case, creates a class and then restarts like the method case does.
Yes, that I saw.
But I mean a different case: Imagine you do have code like
nil doSomething
or an expression that evaluates to nil, press âdefineâ and get a method definition dialog, not the error message? (it is, as I mentioned, not that important as nobody ever wants to define a method in UndefinedObject, but for consistency it would be nice)
I guess I was wondering if we can do it more cleanly and also improve the debugger message.
If Iâve understood you guys correctly- you try to remove the ambiguity around operations. Looking up a class and getting nil - seems like one of these holes you keep sorting out.
I think the flaw in my solution is understanding if that message was being sent to a class, or some other global? I dont think I got that bit right (but itâs certainly better than nothing).
e.g. in the debugger I am doing (in DoesNotUnderstandDebugAction)
msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ^self createMissingClassIn: self interruptedContext ].
Iâm not totally convinced that lookupClass has to be a class - although maybe its good enough. But really, at the time this happened - we probably knew better than to get a DNU debug action in the the first place - and equally the title in the debugger could be something more akin to the kind of action its supposed to be.
Anyway - this is all musing on my part - and I will assemble a proper PR for review by you guys (and at least it advances us forward - and maybe opens the door to better changes further on).
Iâm just juggling another change at the moment - so it will be a few days.
Tim
Sent from my iPhone
On 23 Aug 2018, at 05:33, Marcus Denker <marcus.denker@inria.fr> wrote:
On 22 Aug 2018, at 16:24, Tim Mackinnon <tim@testit.works> wrote:
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong?
In pharo7 we could easily do that (due to the âbindingâ, the meta class of the variable) being different. We could return a nil subclass or add code into the method directly. But the problem with that is that nil checks are always identity checksâ¦
Could you not in the case you now raise the error just fall back to the âdefine methodâ, the behaviour we have now?
Marcus
I will also put together a pr for this in Pharo 7 if you think itâs a decent fix.
Tim
Sent from my iPhone
Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Thanks! I will have a look at the sprint tomorrow.
On 30 Aug 2018, at 07:11, Tim Mackinnon <tim@testit.works> wrote:
Iâve submitted a PR for what I did, so at least it improves the situation (but potentially could get even more refined as you suggest)
Tim
On 23 Aug 2018, at 11:26, Marcus Denker <marcus.denker@inria.fr> wrote:
On 23 Aug 2018, at 15:56, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - thatâs actually what I do - and âcreateâ in this case, creates a class and then restarts like the method case does.
Yes, that I saw.
But I mean a different case: Imagine you do have code like
nil doSomething
or an expression that evaluates to nil, press âdefineâ and get a method definition dialog, not the error message? (it is, as I mentioned, not that important as nobody ever wants to define a method in UndefinedObject, but for consistency it would be nice)
I guess I was wondering if we can do it more cleanly and also improve the debugger message.
If Iâve understood you guys correctly- you try to remove the ambiguity around operations. Looking up a class and getting nil - seems like one of these holes you keep sorting out.
I think the flaw in my solution is understanding if that message was being sent to a class, or some other global? I dont think I got that bit right (but itâs certainly better than nothing).
e.g. in the debugger I am doing (in DoesNotUnderstandDebugAction)
msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ^self createMissingClassIn: self interruptedContext ].
Iâm not totally convinced that lookupClass has to be a class - although maybe its good enough. But really, at the time this happened - we probably knew better than to get a DNU debug action in the the first place - and equally the title in the debugger could be something more akin to the kind of action its supposed to be.
Anyway - this is all musing on my part - and I will assemble a proper PR for review by you guys (and at least it advances us forward - and maybe opens the door to better changes further on).
Iâm just juggling another change at the moment - so it will be a few days.
Tim
Sent from my iPhone
On 23 Aug 2018, at 05:33, Marcus Denker <marcus.denker@inria.fr> wrote:
On 22 Aug 2018, at 16:24, Tim Mackinnon <tim@testit.works> wrote:
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong?
In pharo7 we could easily do that (due to the âbindingâ, the meta class of the variable) being different. We could return a nil subclass or add code into the method directly. But the problem with that is that nil checks are always identity checksâ¦
Could you not in the case you now raise the error just fall back to the âdefine methodâ, the behaviour we have now?
Marcus
I will also put together a pr for this in Pharo 7 if you think itâs a decent fix.
Tim
Sent from my iPhone
Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Hi, I had a look: this works nicely! I even found a way to automatically fall back to the method creation, so nil doSomething on create will create a method. I have merged your code and will do a PR with the improvement later. Marcus
On 30 Aug 2018, at 09:57, Marcus Denker <marcus.denker@inria.fr> wrote:
Thanks! I will have a look at the sprint tomorrow.
On 30 Aug 2018, at 07:11, Tim Mackinnon <tim@testit.works> wrote:
Iâve submitted a PR for what I did, so at least it improves the situation (but potentially could get even more refined as you suggest)
Tim
On 23 Aug 2018, at 11:26, Marcus Denker <marcus.denker@inria.fr> wrote:
On 23 Aug 2018, at 15:56, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - thatâs actually what I do - and âcreateâ in this case, creates a class and then restarts like the method case does.
Yes, that I saw.
But I mean a different case: Imagine you do have code like
nil doSomething
or an expression that evaluates to nil, press âdefineâ and get a method definition dialog, not the error message? (it is, as I mentioned, not that important as nobody ever wants to define a method in UndefinedObject, but for consistency it would be nice)
I guess I was wondering if we can do it more cleanly and also improve the debugger message.
If Iâve understood you guys correctly- you try to remove the ambiguity around operations. Looking up a class and getting nil - seems like one of these holes you keep sorting out.
I think the flaw in my solution is understanding if that message was being sent to a class, or some other global? I dont think I got that bit right (but itâs certainly better than nothing).
e.g. in the debugger I am doing (in DoesNotUnderstandDebugAction)
msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ^self createMissingClassIn: self interruptedContext ].
Iâm not totally convinced that lookupClass has to be a class - although maybe its good enough. But really, at the time this happened - we probably knew better than to get a DNU debug action in the the first place - and equally the title in the debugger could be something more akin to the kind of action its supposed to be.
Anyway - this is all musing on my part - and I will assemble a proper PR for review by you guys (and at least it advances us forward - and maybe opens the door to better changes further on).
Iâm just juggling another change at the moment - so it will be a few days.
Tim
Sent from my iPhone
On 23 Aug 2018, at 05:33, Marcus Denker <marcus.denker@inria.fr> wrote:
On 22 Aug 2018, at 16:24, Tim Mackinnon <tim@testit.works> wrote:
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong?
In pharo7 we could easily do that (due to the âbindingâ, the meta class of the variable) being different. We could return a nil subclass or add code into the method directly. But the problem with that is that nil checks are always identity checksâ¦
Could you not in the case you now raise the error just fall back to the âdefine methodâ, the behaviour we have now?
Marcus
I will also put together a pr for this in Pharo 7 if you think itâs a decent fix.
Tim
Sent from my iPhone
Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Here is the new PR: https://github.com/pharo-project/pharo/pull/1731
On 31 Aug 2018, at 11:17, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I had a look: this works nicely!
I even found a way to automatically fall back to the method creation, so
nil doSomething
on create will create a method.
I have merged your code and will do a PR with the improvement later.
Marcus
On 30 Aug 2018, at 09:57, Marcus Denker <marcus.denker@inria.fr> wrote:
Thanks! I will have a look at the sprint tomorrow.
On 30 Aug 2018, at 07:11, Tim Mackinnon <tim@testit.works> wrote:
Iâve submitted a PR for what I did, so at least it improves the situation (but potentially could get even more refined as you suggest)
Tim
On 23 Aug 2018, at 11:26, Marcus Denker <marcus.denker@inria.fr> wrote:
On 23 Aug 2018, at 15:56, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - thatâs actually what I do - and âcreateâ in this case, creates a class and then restarts like the method case does.
Yes, that I saw.
But I mean a different case: Imagine you do have code like
nil doSomething
or an expression that evaluates to nil, press âdefineâ and get a method definition dialog, not the error message? (it is, as I mentioned, not that important as nobody ever wants to define a method in UndefinedObject, but for consistency it would be nice)
I guess I was wondering if we can do it more cleanly and also improve the debugger message.
If Iâve understood you guys correctly- you try to remove the ambiguity around operations. Looking up a class and getting nil - seems like one of these holes you keep sorting out.
I think the flaw in my solution is understanding if that message was being sent to a class, or some other global? I dont think I got that bit right (but itâs certainly better than nothing).
e.g. in the debugger I am doing (in DoesNotUnderstandDebugAction)
msg := self interruptedContext tempAt: 1. (msg lookupClass == UndefinedObject ) ifTrue: [ ^self createMissingClassIn: self interruptedContext ].
Iâm not totally convinced that lookupClass has to be a class - although maybe its good enough. But really, at the time this happened - we probably knew better than to get a DNU debug action in the the first place - and equally the title in the debugger could be something more akin to the kind of action its supposed to be.
Anyway - this is all musing on my part - and I will assemble a proper PR for review by you guys (and at least it advances us forward - and maybe opens the door to better changes further on).
Iâm just juggling another change at the moment - so it will be a few days.
Tim
Sent from my iPhone
On 23 Aug 2018, at 05:33, Marcus Denker <marcus.denker@inria.fr> wrote:
On 22 Aug 2018, at 16:24, Tim Mackinnon <tim@testit.works> wrote:
Hi - but I guess my question is (and excuse my basic knowledge in this area) - when a class isnât found - can we do better than return nil so that the debugger can give a better msg and presumably the code Iâve written could live on that undefined object? Or am thinking about this wrong?
In pharo7 we could easily do that (due to the âbindingâ, the meta class of the variable) being different. We could return a nil subclass or add code into the method directly. But the problem with that is that nil checks are always identity checksâ¦
Could you not in the case you now raise the error just fall back to the âdefine methodâ, the behaviour we have now?
Marcus
I will also put together a pr for this in Pharo 7 if you think itâs a decent fix.
Tim
Sent from my iPhone
Sent from my iPhone
On 22 Aug 2018, at 09:51, Marcus Denker <marcus.denker@inria.fr> wrote:
Hi,
I played with it, nice!
I guess the case when you really get a DNU on nil (and want to create method there) does not really happen⦠extending nil is for special cases.
Marcus
On 22 Aug 2018, at 13:39, Tim Mackinnon <tim@testit.works> wrote:
Sorry Marcus - you needed to follow the exercism instructions and right click on the exercism package to get an exercism menu to fetch a new exercise (e.g. hello-world). The is then using the TonalReader to pull in code - and then you get a test class that can reference a class that isnât there yet. (But you need to have the exercism cli installed as per the instructions etc).
In retrospect I think it might be simpler to download this 6.1 image that already has done that - https://www.dropbox.com/s/x2ot9f8arbbvlyb/PharoExercism.zip?dl=0 It has TwoFerTest that is in that state. If you click on the TestWithName orb, you will see "#new was sent to nilâ - can you can see how my Create button has been fixed per you suggestions to create a class. (The code I wrote is in ExercismTools:DoesNotUnderstandDebugAction>>createMissingClassIn:)
Tim
On 22 Aug 2018, at 04:44, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 14:20, Tim Mackinnon <tim@testit.works> wrote:
The direct link to instructions is here: https://exercism.io/tracks/pharo/installation (not sure if you have to be signed up to see it otherwise its in the repo here: https://github.com/exercism/pharo/blob/master/docs/INSTALLATION.md)
Hm⦠AllExercismTests seems to not be there (just a green test in Welcome)
Is this supposed to contain the code below (the createMissingClassActionFor:in:) ?
It would be nice to have an image that shows exactly the problem (I do not have that much time sadly to work on it,but I do have some time to check if I have an image that is set up to the point where i can easily recreate the problem)
Marcus
Tim
On 17 Aug 2018, at 07:17, Marcus Denker <marcus.denker@inria.fr> wrote:
On 17 Aug 2018, at 13:00, Tim Mackinnon <tim@testit.works> wrote:
Hi Marcus - I can put an image somewhere if that helps (do you just need the .image and .changes)?
Or you can repro from a fresh 6.1 if you follow the exercism Pharo instructions (https://exercism.io/tracks/pharo) to load the first hello world-world example and run the tests. This has my code changes to make create work with a nil class - but maybe we can do better? I will do that and have a look!
Tim
Sent from my iPhone
On 17 Aug 2018, at 06:21, Marcus Denker <marcus.denker@inria.fr> wrote:
On 10 Aug 2018, at 23:16, Tim Mackinnon <tim@testit.works> wrote:
Actually I think I figured that bit out - a bit clumsily - (pointers appreciated)
createMissingClassActionFor: aMessage in: aContext |errorNode senderContext newClass variableNode | senderContext := aContext sender. errorNode := senderContext method sourceNodeExecutedForPC: senderContext pc. variableNode := errorNode receiver receiver.
newClass := OCUndeclaredVariableWarning new node: variableNode; defineClass: variableNode name. aContext restart.
However that last line is wrong, as it doesnât restart with my newly defined class - I also tried
aContext restartWithNewReceiver: newClass
But again, I get a debugger where my class is still bound to nil. So whatâs the trick to re-evaluate with the new class Iâve created? Or maybe Iâm totally on the wrong track (still its very interestingâ¦)
what is a bit bad is that you catch the problem âtoo lateâ (that is, the DNU to nil, not the read of nil), so nil is already pushed on the stack at this point.
I tried it in the inspector and at least the class binding was correct after defining the class⦠do you have an image with the whole code to try?
Marcus
Hi Tim, I can only tell you that I agree with you ^^. Last year we worked with Stef and Luc on the idea of undefined classes ( https://hal.archives-ouvertes.fr/hal-01585305/document). The code is available in smalltalkhub if I remember well (check the links in the paper). We did not integrate it because all the changes in Pharo were already a lot (new contribution process, moving to Git, new CI, and lots of other changes). It also means that it would require some more iterations, because we used it to download big and old projects, but never really tested it for TDD :) But if you would like, it's there to give it a try Guille On Thu, Aug 9, 2018 at 8:21 AM Tim Mackinnon <tim@testit.works> wrote:
Feenk re-imagining aside (which I will pursue with them), it seems like our current tools can support this better right?
I see two issues:
1) if we encounter a not present class can we fix the debugger to offer something like we do for a missing method so itâs less obtuse?
2) when coding - if you want reference a missing class, why donât we let you? TonelReader seems to do it, why canât the editor? (This probably applies to variables as well - show them broken, let me fix it when I choose. The iVar case is a little rarer - although I hate the way we prompt fix, prompt fix instead of doing it in one go - itâs very old fashioned)
Does anyone have tips on solving these? It spoils the exercism experience that I thought we could convey, so Iâd like to at least fix #1 in 6.1 if I can.
Tim
Sent from my iPhone
On 9 Aug 2018, at 01:44, Francisco Ortiz Peñaloza <patchinko@gmail.com> wrote:
+1
On Tue, 7 Aug 2018 at 09:02 Tim Mackinnon <tim@testit.works> wrote:
Hi guys - Iâve been hammering on the exercism project to get pharo shining over there⦠its been a good side distraction (there is lots of energy in that community to) and its made me really push my use of Iceberg & git as well as learn some fo the newish file reference stuff (still getting good at that - but like the approach),
Anyway - Iâve got an Alpha working, and users can pull down a zero conf pharo image and eval a little script that will get them up and running (which is pretty slick).
So the story then goes - Exercism is trying to simulate TDD and help you learn a new language (aka Pharo or Go or Python etc). To this end, theyâve got an active community building up little test exercises with suites of tests that new users can run to help them learn the syntax/essence of the language track theyâve signed up to. You run the tests, develop your solution and then submit it to a community to get feedback and then progress.
Pretty standard - we can play in this pond too - and it turns out that Tonel actually makes it pretty easy to submit readable solutions that will fit on their website. YAY.
The trouble is - when you pull down a new exercise - I use the TonelReader to pull the code into your image - and I thought it would be cute to just pull in the TestCase so that users can simulate the full TDD cycle - where you can create things in the debugger⦠this is where it all began right?
So you hit a clanger when you do this - and in a way its a bit of a legacy thing weâve carried around (and possibly should fix better). When Tonel reads in the TesCase, it normally will reference a class this isnât there (Iâve deliberately left the solution out). It does the right thing and put a nil placeholder in the code so that it can read it in.
HOWEVER - when you run your test and hit that nil class placeholder we do a very bad job of dealing with this in the debugger. And if you think about it - we also do a bad job when typing in code too - we essentially insist that declare a class then and there - unlike a selector which can happily be late bound.
So back to my TDD example - user gets a debugger with a nil class error - the create button is actually not helpful for you as it only creates methods. So our âlive in the debuggerâ mantra is a bit less obvious here. What you had to do is make a change to the source (like a space) so that you can reserve the method - which then causes you to get the âcreate class promptâ. So we have the ability - just donât expose it very well - however now you have a missing method - but again its not so obvious that you have to resume your debugger (it hasnât resumed when you created the class) - and then you will get another error for the missing method that the create button will now resolve.
This feels very clunky to me - and makes me feel like Iâm mis-selling smalltalk where we have a bullet point about âAmazing for debuggingâ¦â.
This feels fixable though right? Iâm wondering about thoughts though before jumping inâ¦
Tim
p.s. - weâre building some exercises for exercism and getting that process streamlined so hopefully many more people can help - and maybe we can augment the great learning courses/videos/books that we already have.
-- Sent from the past
-- 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 <http://www.cnrs.fr>* *Web:* *http://guillep.github.io* <http://guillep.github.io> *Phone: *+33 06 52 70 66 13
On 7 August 2018 at 20:01, Tim Mackinnon <tim@testit.works> wrote:
Hi guys - Iâve been hammering on the exercism project to get pharo shining over there⦠its been a good side distraction (there is lots of energy in that community to) and its made me really push my use of Iceberg & git as well as learn some fo the newish file reference stuff (still getting good at that - but like the approach),
Anyway - Iâve got an Alpha working, and users can pull down a zero conf pharo image and eval a little script that will get them up and running (which is pretty slick).
So the story then goes - Exercism is trying to simulate TDD and help you learn a new language (aka Pharo or Go or Python etc). To this end, theyâve got an active community building up little test exercises with suites of tests that new users can run to help them learn the syntax/essence of the language track theyâve signed up to. You run the tests, develop your solution and then submit it to a community to get feedback and then progress.
Pretty standard - we can play in this pond too - and it turns out that Tonel actually makes it pretty easy to submit readable solutions that will fit on their website. YAY.
The trouble is - when you pull down a new exercise - I use the TonelReader to pull the code into your image - and I thought it would be cute to just pull in the TestCase so that users can simulate the full TDD cycle - where you can create things in the debugger⦠this is where it all began right?
So you hit a clanger when you do this - and in a way its a bit of a legacy thing weâve carried around (and possibly should fix better). When Tonel reads in the TesCase, it normally will reference a class this isnât there (Iâve deliberately left the solution out). It does the right thing and put a nil placeholder in the code so that it can read it in.
For the purpose of Exercism, I think its reasonable for any class referenced by the TestCase to be loaded as an empty stub. Its not really giving the too much of a head start. If they miss seeing the magic of interactively auto-creating a class, oh well, there is plenty of other magic to show them. And if a solution needs a second class, then they might be exposed to it then. KISS. cheers -ben
participants (5)
-
Ben Coman -
Francisco Ortiz Peñaloza -
Guillermo Polito -
Marcus Denker -
Tim Mackinnon