[squeak-dev] [Masters of Squeak] Have fun figuring this out

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[squeak-dev] [Masters of Squeak] Have fun figuring this out

Bert Freudenberg
If you evaluate the following two statements together
       
         
10
+
11
+
12
+
13
+
14
+
15
+
16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39.
        [:a :b :c | self halt] value: 0 value: 0 value: 0.

you are dropped into an emergency evaluator (in a non-closure image  
anyway). Evaluating each statement individually is no problem.

If you have fun figuring out puzzling behavior or want to prove your  
Squeak Skillz you might try to investigate it. If you need hints,  
scroll down to (*).

For the rest, a fix and explanation is on Mantis:

http://bugs.squeak.org/view.php?id=7355

- Bert -










































































(*) These lines

         
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40.
        [:a :b :c | ] decompile

let you debug the issue. Full explanation below (**)













































































































(**) The decompiler fails because the #blockCopy: argument is the 33rd  
literal and hence uses an extended byte code to push. This is not  
anticipated by the decompiler which assumes a single-byte instruction  
is used to push the argument. And if this explanation does not make  
sense to you ... you've got a lot to learn about the inner workings of  
Squeak ;)


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] [Masters of Squeak] Have fun figuring this out

Igor Stasenko
I prefer a more shorter way to get puzzled:

type:
0

and then use 'debug it' from menu

:)


2009/6/25 Bert Freudenberg <[hidden email]>
If you evaluate the following two statements together
       
       10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39.
       [:a :b :c | self halt] value: 0 value: 0 value: 0.

you are dropped into an emergency evaluator (in a non-closure image anyway). Evaluating each statement individually is no problem.

If you have fun figuring out puzzling behavior or want to prove your Squeak Skillz you might try to investigate it. If you need hints, scroll down to (*).

For the rest, a fix and explanation is on Mantis:

http://bugs.squeak.org/view.php?id=7355

- Bert -










































































(*) These lines

       10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40.
       [:a :b :c | ] decompile

let you debug the issue. Full explanation below (**)













































































































(**) The decompiler fails because the #blockCopy: argument is the 33rd literal and hence uses an extended byte code to push. This is not anticipated by the decompiler which assumes a single-byte instruction is used to push the argument. And if this explanation does not make sense to you ... you've got a lot to learn about the inner workings of Squeak ;)





--
Best regards,
Igor Stasenko AKA sig.


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] [Masters of Squeak] Have fun figuring this out

Stéphane Rollandin
In reply to this post by Bert Freudenberg
I'm glad I've never be bitten by that one :) right into the madhouse...

Stef


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] [Masters of Squeak] Have fun figuring this out

Bert Freudenberg
In reply to this post by Igor Stasenko

Am 25.06.2009 um 17:28 schrieb Igor Stasenko:

> I prefer a more shorter way to get puzzled:
>
> type:
> 0
>
> and then use 'debug it' from menu

That just locks up the image. Thanks for no warning.

(though I wonder why the Mac VM recently does not allow me to break  
into this kind of errors)

- Bert -

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] [Masters of Squeak] Have fun figuring this out

Igor Stasenko
2009/6/25 Bert Freudenberg <[hidden email]>:

>
> Am 25.06.2009 um 17:28 schrieb Igor Stasenko:
>
>> I prefer a more shorter way to get puzzled:
>>
>> type:
>> 0
>>
>> and then use 'debug it' from menu
>
> That just locks up the image. Thanks for no warning.
>
Gotcha!! :)

In fact, it was reported a few months ago, and sits on Mantis. Not
sure if fix is available.

> (though I wonder why the Mac VM recently does not allow me to break into
> this kind of errors)
>
> - Bert -
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Andreas.Raab
In reply to this post by Igor Stasenko
Igor Stasenko wrote:
> I prefer a more shorter way to get puzzled:
>
> type:
> 0
>
> and then use 'debug it' from menu
>
> :)

There is an easy fix for it, just change one expression in

    ParagraphEditor>>debug:receiver:in:

from this

   [debugger interruptedContext method == aCompiledMethod]
       whileFalse: [debugger send].

to instead

   [debugger interruptedContext method == aCompiledMethod or:[guineaPig
isTerminated]]
       whileFalse: [debugger send].

The issue is that because the expression has no send the simulation runs
away and causes a bunch of problems.

BTW, since this thread is about mastering Squeak, if you can explain why
the runaway simulation suspends the simulator process I will personally
acknowledge your mastery of Squeak. I couldn't figure out why that
happens :-)

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Bert Freudenberg
Am 25.06.2009 um 18:15 schrieb Andreas Raab:

> BTW, since this thread is about mastering Squeak, if you can explain  
> why the runaway simulation suspends the simulator process I will  
> personally acknowledge your mastery of Squeak. I couldn't figure out  
> why that happens :-)


I know why :)

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Igor Stasenko
In reply to this post by Andreas.Raab
2009/6/25 Andreas Raab <[hidden email]>:

> Igor Stasenko wrote:
>>
>> I prefer a more shorter way to get puzzled:
>>
>> type:
>> 0
>>
>> and then use 'debug it' from menu
>>
>> :)
>
> There is an easy fix for it, just change one expression in
>
>   ParagraphEditor>>debug:receiver:in:
>
> from this
>
>  [debugger interruptedContext method == aCompiledMethod]
>      whileFalse: [debugger send].
>
> to instead
>
>  [debugger interruptedContext method == aCompiledMethod or:[guineaPig
> isTerminated]]
>      whileFalse: [debugger send].
>
> The issue is that because the expression has no send the simulation runs
> away and causes a bunch of problems.
>
> BTW, since this thread is about mastering Squeak, if you can explain why the
> runaway simulation suspends the simulator process I will personally
> acknowledge your mastery of Squeak. I couldn't figure out why that happens
> :-)
>

1. The compiled method '0' looks like following:
all bytecodes: Quick return 0
header: 261 "primitive: 261
 numArgs: 0
 numTemps: 0
 numLiterals: 0
 frameSize: 16
 isClosureCompiled: false"

2.  stepToSendOrReturn doesn't treat this as return:

  stepToSendOrReturn
        "Simulate the execution of bytecodes until either sending a message or
        returning a value to the receiver (that is, until switching contexts)."

        | ctxt |
        [self willReallySend | self willReturn | self willStore]
                whileFalse: [
                        ctxt _ self step.
                        ctxt == self ifFalse: [self halt.
                                "Caused by mustBeBoolean handling"
                                ^ctxt]]
neither 'willStore' nor 'willReallySend' nor 'willReturn'
checks that method contains no bytecode, but an primitive which does
quick return of literal value.
I think a #willReturn need to be modified to check against this
primitive number.
Another way - is to force compiler to not optimize the 'doit' method.
Unfortunately squeak's compiler having no option to turn off all
optimizations.

3. because of 2. the process continue simulation and returns to a
#newProcess: method
newProcess
        "Answer a Process running the code in the receiver. The process is not
        scheduled."
        <primitive: 19> "Simulation guard"
        ^Process
                forContext:
                        [self value.
                        Processor terminateActive]
                priority: Processor activePriority

where "Processor terminateActive" effectively kills/suspends the
debugger process, because active process is not the simulated process,
as this method thinking :)

This could be fixed like following:

newProcess
        "Answer a Process running the code in the receiver. The process is not
        scheduled."
        <primitive: 19> "Simulation guard"
 | process |
        ^process := Process
                forContext:
                        [self value.
                        process terminate]
                priority: Processor activePriority

---
It seems works at first try, not sure about side effects. I'm letting
you to explore :)
On debug '0' its now spawns another error: subscript out of bounds.
But its not hangs anymore.



> Cheers,
>  - Andreas
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Igor Stasenko
In reply to this post by Bert Freudenberg
2009/6/25 Bert Freudenberg <[hidden email]>:

> Am 25.06.2009 um 18:15 schrieb Andreas Raab:
>
>> BTW, since this thread is about mastering Squeak, if you can explain why
>> the runaway simulation suspends the simulator process I will personally
>> acknowledge your mastery of Squeak. I couldn't figure out why that happens
>> :-)
>
>
> I know why :)
>
Please tell us :)

> - Bert -
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Igor Stasenko
In reply to this post by Igor Stasenko
2009/6/25 Igor Stasenko <[hidden email]>:

> 2009/6/25 Andreas Raab <[hidden email]>:
>> Igor Stasenko wrote:
>>>
>>> I prefer a more shorter way to get puzzled:
>>>
>>> type:
>>> 0
>>>
>>> and then use 'debug it' from menu
>>>
>>> :)
>>
>> There is an easy fix for it, just change one expression in
>>
>>   ParagraphEditor>>debug:receiver:in:
>>
>> from this
>>
>>  [debugger interruptedContext method == aCompiledMethod]
>>      whileFalse: [debugger send].
>>
>> to instead
>>
>>  [debugger interruptedContext method == aCompiledMethod or:[guineaPig
>> isTerminated]]
>>      whileFalse: [debugger send].
>>
>> The issue is that because the expression has no send the simulation runs
>> away and causes a bunch of problems.
>>
>> BTW, since this thread is about mastering Squeak, if you can explain why the
>> runaway simulation suspends the simulator process I will personally
>> acknowledge your mastery of Squeak. I couldn't figure out why that happens
>> :-)
>>
>
> 1. The compiled method '0' looks like following:
> all bytecodes: Quick return 0
> header: 261 "primitive: 261
>  numArgs: 0
>  numTemps: 0
>  numLiterals: 0
>  frameSize: 16
>  isClosureCompiled: false"
>
> 2.  stepToSendOrReturn doesn't treat this as return:
>
>  stepToSendOrReturn
>        "Simulate the execution of bytecodes until either sending a message or
>        returning a value to the receiver (that is, until switching contexts)."
>
>        | ctxt |
>        [self willReallySend | self willReturn | self willStore]
>                whileFalse: [
>                        ctxt _ self step.
>                        ctxt == self ifFalse: [self halt.
>                                "Caused by mustBeBoolean handling"
>                                ^ctxt]]
> neither 'willStore' nor 'willReallySend' nor 'willReturn'
> checks that method contains no bytecode, but an primitive which does
> quick return of literal value.
> I think a #willReturn need to be modified to check against this
> primitive number.
> Another way - is to force compiler to not optimize the 'doit' method.
> Unfortunately squeak's compiler having no option to turn off all
> optimizations.
>
> 3. because of 2. the process continue simulation and returns to a
> #newProcess: method

ah, forgot to add:

and because debugger waits a method's context to be activated:

        [debugger interruptedContext method == aCompiledMethod]
                whileFalse: [debugger send].

but its never is, because its having no chance to iterrupt inside that
method  - '0' .
That's why its going to 'Processor terminateActive' without any clues
that something went wrong.

> newProcess
>        "Answer a Process running the code in the receiver. The process is not
>        scheduled."
>        <primitive: 19> "Simulation guard"
>        ^Process
>                forContext:
>                        [self value.
>                        Processor terminateActive]
>                priority: Processor activePriority
>
> where "Processor terminateActive" effectively kills/suspends the
> debugger process, because active process is not the simulated process,
> as this method thinking :)
>
> This could be fixed like following:
>
> newProcess
>        "Answer a Process running the code in the receiver. The process is not
>        scheduled."
>        <primitive: 19> "Simulation guard"
>  | process |
>        ^process := Process
>                forContext:
>                        [self value.
>                        process terminate]
>                priority: Processor activePriority
>
> ---
> It seems works at first try, not sure about side effects. I'm letting
> you to explore :)
> On debug '0' its now spawns another error: subscript out of bounds.
> But its not hangs anymore.
>
>
>
>> Cheers,
>>  - Andreas
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Bert Freudenberg
In reply to this post by Igor Stasenko

On 25.06.2009, at 19:19, Igor Stasenko wrote:

> 2009/6/25 Bert Freudenberg <[hidden email]>:
>> Am 25.06.2009 um 18:15 schrieb Andreas Raab:
>>
>>> BTW, since this thread is about mastering Squeak, if you can  
>>> explain why
>>> the runaway simulation suspends the simulator process I will  
>>> personally
>>> acknowledge your mastery of Squeak. I couldn't figure out why that  
>>> happens
>>> :-)
>>
>>
>> I know why :)
>>
> Please tell us :)


I told Andreas privately, didn't want to spoil the fun for the others.  
But your analysis is correct.

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Igor Stasenko
In reply to this post by Igor Stasenko
Btw, this inability to interrupt in all such methods is the reason of
another annoying and confusing debugger behavior:

try debug:

1 isNumber

and when debugger opens, press 'into'.
Debugger not shows the method, but instead immediately shows as if
method already returns.
Now you have to spend time figuring out, what its returned, even if
there is constant - sometimes you need to know exact value.
But because of this , you can't. All you can do is modify method which
sends this message to see returned result, like:

| temp |

temp := 1 isNumber.

and then check it in temps.

Besides another issues, it would be good if debugger would display a
stack top somewhere (so we can always see a value(s) returned from
method(s) or primitives or whatever).

2009/6/25 Igor Stasenko <[hidden email]>:

> 2009/6/25 Igor Stasenko <[hidden email]>:
>> 2009/6/25 Andreas Raab <[hidden email]>:
>>> Igor Stasenko wrote:
>>>>
>>>> I prefer a more shorter way to get puzzled:
>>>>
>>>> type:
>>>> 0
>>>>
>>>> and then use 'debug it' from menu
>>>>
>>>> :)
>>>
>>> There is an easy fix for it, just change one expression in
>>>
>>>   ParagraphEditor>>debug:receiver:in:
>>>
>>> from this
>>>
>>>  [debugger interruptedContext method == aCompiledMethod]
>>>      whileFalse: [debugger send].
>>>
>>> to instead
>>>
>>>  [debugger interruptedContext method == aCompiledMethod or:[guineaPig
>>> isTerminated]]
>>>      whileFalse: [debugger send].
>>>
>>> The issue is that because the expression has no send the simulation runs
>>> away and causes a bunch of problems.
>>>
>>> BTW, since this thread is about mastering Squeak, if you can explain why the
>>> runaway simulation suspends the simulator process I will personally
>>> acknowledge your mastery of Squeak. I couldn't figure out why that happens
>>> :-)
>>>
>>
>> 1. The compiled method '0' looks like following:
>> all bytecodes: Quick return 0
>> header: 261 "primitive: 261
>>  numArgs: 0
>>  numTemps: 0
>>  numLiterals: 0
>>  frameSize: 16
>>  isClosureCompiled: false"
>>
>> 2.  stepToSendOrReturn doesn't treat this as return:
>>
>>  stepToSendOrReturn
>>        "Simulate the execution of bytecodes until either sending a message or
>>        returning a value to the receiver (that is, until switching contexts)."
>>
>>        | ctxt |
>>        [self willReallySend | self willReturn | self willStore]
>>                whileFalse: [
>>                        ctxt _ self step.
>>                        ctxt == self ifFalse: [self halt.
>>                                "Caused by mustBeBoolean handling"
>>                                ^ctxt]]
>> neither 'willStore' nor 'willReallySend' nor 'willReturn'
>> checks that method contains no bytecode, but an primitive which does
>> quick return of literal value.
>> I think a #willReturn need to be modified to check against this
>> primitive number.
>> Another way - is to force compiler to not optimize the 'doit' method.
>> Unfortunately squeak's compiler having no option to turn off all
>> optimizations.
>>
>> 3. because of 2. the process continue simulation and returns to a
>> #newProcess: method
>
> ah, forgot to add:
>
> and because debugger waits a method's context to be activated:
>
>        [debugger interruptedContext method == aCompiledMethod]
>                whileFalse: [debugger send].
>
> but its never is, because its having no chance to iterrupt inside that
> method  - '0' .
> That's why its going to 'Processor terminateActive' without any clues
> that something went wrong.
>
>> newProcess
>>        "Answer a Process running the code in the receiver. The process is not
>>        scheduled."
>>        <primitive: 19> "Simulation guard"
>>        ^Process
>>                forContext:
>>                        [self value.
>>                        Processor terminateActive]
>>                priority: Processor activePriority
>>
>> where "Processor terminateActive" effectively kills/suspends the
>> debugger process, because active process is not the simulated process,
>> as this method thinking :)
>>
>> This could be fixed like following:
>>
>> newProcess
>>        "Answer a Process running the code in the receiver. The process is not
>>        scheduled."
>>        <primitive: 19> "Simulation guard"
>>  | process |
>>        ^process := Process
>>                forContext:
>>                        [self value.
>>                        process terminate]
>>                priority: Processor activePriority
>>
>> ---
>> It seems works at first try, not sure about side effects. I'm letting
>> you to explore :)
>> On debug '0' its now spawns another error: subscript out of bounds.
>> But its not hangs anymore.
>>
>>
>>
>>> Cheers,
>>>  - Andreas
>>>
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Andreas.Raab
In reply to this post by Bert Freudenberg
Bert Freudenberg wrote:
>>> I know why :)
>>>
>> Please tell us :)
>
> I told Andreas privately, didn't want to spoil the fun for the others.
> But your analysis is correct.

Indeed. Brilliant bit of analysis. You guys *are* Masters of Squeak (tm)

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Igor Stasenko
2009/6/25 Andreas Raab <[hidden email]>:

> Bert Freudenberg wrote:
>>>>
>>>> I know why :)
>>>>
>>> Please tell us :)
>>
>> I told Andreas privately, didn't want to spoil the fun for the others. But
>> your analysis is correct.
>
> Indeed. Brilliant bit of analysis. You guys *are* Masters of Squeak (tm)
>

Can i have cake, please :))))

> Cheers,
>  - Andreas
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Randal L. Schwartz
>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:

Igor> Can i have cake, please :))))

Pssst.  the cake is a lie!

</meme>

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Bert Freudenberg
In reply to this post by Igor Stasenko

On 25.06.2009, at 20:14, Igor Stasenko wrote:

> 2009/6/25 Andreas Raab <[hidden email]>:
>> Bert Freudenberg wrote:
>>>>>
>>>>> I know why :)
>>>>>
>>>> Please tell us :)
>>>
>>> I told Andreas privately, didn't want to spoil the fun for the  
>>> others. But
>>> your analysis is correct.
>>
>> Indeed. Brilliant bit of analysis. You guys *are* Masters of Squeak  
>> (tm)
>>
>
> Can i have cake, please :))))



Sure - tasting good:

                   _____
            _..--'''@   @'''--.._
          .'   @_/-//-\/>/>'/ @  '.
         (  @  /_<//<'/----------^-)
         |'._  @     //|###########|
         |~  ''--..@|',|}}}}}}}}}}}|
         |  ~   ~   |/ |###########|
         | ~~  ~   ~|./|{{{{{{{{{{{|
          '._ ~ ~ ~ |,/`````````````
       jrei  ''--.~.|/


- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Igor Stasenko
2009/6/25 Bert Freudenberg <[hidden email]>:

>
> On 25.06.2009, at 20:14, Igor Stasenko wrote:
>
>> 2009/6/25 Andreas Raab <[hidden email]>:
>>>
>>> Bert Freudenberg wrote:
>>>>>>
>>>>>> I know why :)
>>>>>>
>>>>> Please tell us :)
>>>>
>>>> I told Andreas privately, didn't want to spoil the fun for the others.
>>>> But
>>>> your analysis is correct.
>>>
>>> Indeed. Brilliant bit of analysis. You guys *are* Masters of Squeak (tm)
>>>
>>
>> Can i have cake, please :))))
>
>
>
> Sure - tasting good:
>
>                  _____
>           _..--'''@   @'''--.._
>         .'   @_/-//-\/>/>'/ @  '.
>        (  @  /_<//<'/----------^-)
>        |'._  @     //|###########|
>        |~  ''--..@|',|}}}}}}}}}}}|
>        |  ~   ~   |/ |###########|
>        | ~~  ~   ~|./|{{{{{{{{{{{|
>         '._ ~ ~ ~ |,/`````````````
>      jrei  ''--.~.|/
>
>
Yeah!!

http://paulhutch.com/wordpress/wp-content/uploads/2007/05/demotivator1-small.jpg


> - Bert -
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Göran Krampe
Impressive guys!

Especially while taking the timestamp of your emails into account :)

regards, Göran


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: [Masters of Squeak] Have fun figuring this out

Ian Trudel-2
In reply to this post by Igor Stasenko
2009/6/25 Igor Stasenko <[hidden email]>:
> Can i have cake, please :))))

Ah! You're definitively Russian. They eat cake for every other
occasion. Way too much sugar for me. =)

Regards,
Ian

--
http://mecenia.blogspot.com/

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Sugar on a Stick

Bert Freudenberg
On 25.06.2009, at 22:12, Ian Trudel wrote:

> 2009/6/25 Igor Stasenko <[hidden email]>:
>> Can i have cake, please :))))
>
> Ah! You're definitively Russian. They eat cake for every other
> occasion. Way too much sugar for me. =)


Speaking of Sugar, have you seen the Sugar Labs press release?

http://news.google.com/news?q=SugarLabs

Some news outlets even mention Etoys ...

- Bert -



12