Writing a primitive test first in Exupery

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

Writing a primitive test first in Exupery

Bryce Kampjes

Here's a quick sketch of what's needed to write a primitive test
first in Exupery. This is aimed at getting Yakov started on his
SummerTalk project but should also be useful to others who wish
to write primitives for Exupery.

Exupery is written test first using two layers of testing. First
story tests are written to cover the functionality, they run compiled
methods and check the compiled method does the right thing. Then
programmer tests are written to cover the actual code. Ideally all
new functionality is covered by both a full set of story tests and
programmer tests.

Primitive code is implemented in IntermediateSimplifier which
converts high level intermediate into low level intermediate.

I normally write the story tests first, often all the ones I can think
of while reading through the interpreters implementation.  Then I
write the programmer tests one by one while implementing the code. I
normally run the story tests to figure out what programmer test is
needed next.

First write a story test:

      ExuperyStoryTests>>testReturnTrue
        self compile: ' ^ true'.
        self should: [self example = true]

This test will cover the case where the method is compiled
directly, another test may be written to handle the inlined
case for completeness.

Now look at IntermediateSimplifierTests>>testAtPrimitive. Use
this as an example to write a test for the "^ true" primitive.
It should be possible to figure out what the primitive number is
by debugging the failing testReturnTrue test.

Browse around IntermediateEmitter to find out what facilities are
there. In this case trueAddress and falseAddress look interesting.
MockIntermediateEmitter is used during testing, it checks that the
simplifier is producing the right intermediate and fails immediately
if there's a problem. The aim is to write a test then write the code
in the debugger produced from the failing test.

Bryce
_______________________________________________
Exupery mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery
Reply | Threaded
Open this post in threaded view
|

Re: Writing a primitive test first in Exupery

iakovz
 > Primitive code is implemented in IntermediateSimplifier which
 > converts high level intermediate into low level intermediate.

Could some information about intermediates be provided?

 > Now look at IntermediateSimplifierTests>>testAtPrimitive. Use
 > this as an example to write a test for the "^ true" primitive.

IntermediateSimplifierTests >>testAtPrimitive
        source := MedMethod
                                createIntermediate:
                                        #((block 1  (primitive 60 Array block2 receiver arg1) ))
                                for: machine.
        mockEmitter expectEmission:
                #((block1
                                (mov arg1 t1) "Index"
                                (mov receiver t2) "receiver"
                                (addressOfIndexedElement t2 t1 block2))
                        (block2)).
        ...


It was discovered that createIntermediate:for: is connected with  
IntermediateCreator>>createBlock and friends... In order  
testTruePrimitive to be written, it's needed to be known how to write  
such arrays
                                #((block 1  (primitive 60 Array block2 receiver arg1) ))

Talking about MockIntermediateEmitter. Is this a pidgin assembler  
stateements
                                (mov arg1 t1) "Index"
                                (mov receiver t2) "receiver"
                                (addressOfIndexedElement t2 t1 block2))
There's MockIntermediateEmitter>>addressOfIndexedElement:at:failTo:  
which probably is connected with
                                (addressOfIndexedElement t2 t1 block2))
..but there's no something similar to mov...

It would be great if some more details will be given regarding how  
typical primitive test code is written

Thanks in advance


Yakov



_______________________________________________
Exupery mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery
Reply | Threaded
Open this post in threaded view
|

Re: Writing a primitive test first in Exupery

Bryce Kampjes
Yakov Zaytsev writes:
 >  > Primitive code is implemented in IntermediateSimplifier which
 >  > converts high level intermediate into low level intermediate.
 >
 > Could some information about intermediates be provided?

Sorry for the delay, I just wrote a fairly detailed reply then
lost it. I'll rewrite it tomorrow night.

The best thing to read to understand the intermediate forms is:

    http://goran.krampe.se/exuperyDesign.pdf

Bryce
_______________________________________________
Exupery mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery
Reply | Threaded
Open this post in threaded view
|

Re: Writing a primitive test first in Exupery

iakovz
Bryce,

It's an excellent documentation piece!

Why you haven't provided me with it from the start ;)

Great I think I'll go rather faster then

PS
Anyway, I'll continue to use mail list as a primary place to discuss
my progress..

Best regards,



On 6/26/07, [hidden email] <[hidden email]> wrote:

> Yakov Zaytsev writes:
>  >  > Primitive code is implemented in IntermediateSimplifier which
>  >  > converts high level intermediate into low level intermediate.
>  >
>  > Could some information about intermediates be provided?
>
> Sorry for the delay, I just wrote a fairly detailed reply then
> lost it. I'll rewrite it tomorrow night.
>
> The best thing to read to understand the intermediate forms is:
>
>     http://goran.krampe.se/exuperyDesign.pdf
>
> Bryce
> _______________________________________________
> Exupery mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery
>
_______________________________________________
Exupery mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery
Reply | Threaded
Open this post in threaded view
|

Re: Writing a primitive test first in Exupery

Bryce Kampjes
In reply to this post by iakovz
Yakov Zaytsev writes:
 >  > Now look at IntermediateSimplifierTests>>testAtPrimitive. Use
 >  > this as an example to write a test for the "^ true" primitive.
 >
 > IntermediateSimplifierTests >>testAtPrimitive
 > source := MedMethod
 > createIntermediate:
 > #((block 1  (primitive 60 Array block2 receiver arg1) ))
 > for: machine.
 > mockEmitter expectEmission:
 > #((block1
 > (mov arg1 t1) "Index"
 > (mov receiver t2) "receiver"
 > (addressOfIndexedElement t2 t1 block2))
 > (block2)).
 > ...

What's literally happening in the test above is a method is created
from the first array literal by IntermediateCreator. A mock is set
up from the second array literal ("#((block1 ..."), the mock then
tests that Intermediate simplifier makes the corresponding calls to
(Mock)IntermediateEmitter.

The #expectEmission: really programs the mock to expect a series of
calls. #addressOfIndexedElement is a call to IntermediateEmitter, not
a piece of intermediate, IntermediateEmitter expands it into several
low level intermediate expressions.

The tests create both an input method using #createIntermediate:for:
and a mock that's responsible for most of the testing. Once both are
created then the IntermediateSimplifier is called. If it calls the
wrong method on IntermediateEmitter an assertion fails bringing up a
debugger. This makes it easy to write code during a failing test
in the debugger because chances are the method to change is in the
back trace.

 >
 > It was discovered that createIntermediate:for: is connected with  
 > IntermediateCreator>>createBlock and friends... In order  
 > testTruePrimitive to be written, it's needed to be known how to write  
 > such arrays
 > #((block 1  (primitive 60 Array block2 receiver arg1) ))
 >
 > Talking about MockIntermediateEmitter. Is this a pidgin assembler  
 > stateements
 > (mov arg1 t1) "Index"
 > (mov receiver t2) "receiver"
 > (addressOfIndexedElement t2 t1 block2))
 > There's MockIntermediateEmitter>>addressOfIndexedElement:at:failTo:  
 > which probably is connected with
 > (addressOfIndexedElement t2 t1 block2))
 > ..but there's no something similar to mov...

Neither the input intermediate nor the output intermediate are
assembly. Both are register transfer languages. The output
intermediate (low level intermediate) is below assembly, it's
translated into assembly by the instruction selector. The instruction
selector matches patterns of low level intermediate to create a single
instruction.

To perform an addition and store the result in a register in low level
intermediate "(mov (add 10 20) resultRegister)" is used.

Bryce
_______________________________________________
Exupery mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/exupery