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 |
> 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 |
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 |
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 |
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 |
Free forum by Nabble | Edit this page |