<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-475780959494054478</id><updated>2011-10-11T02:26:49.291-07:00</updated><category term='declare'/><category term='ssa'/><category term='tests'/><category term='python-book'/><category term='threads'/><category term='feature'/><category term='ir1'/><category term='inline'/><category term='question'/><category term='howto'/><category term='note'/><title type='text'>Common Lisp Compilers Internals</title><subtitle type='html'>This blog contains chapters from my book 'SBCL Compiler Internals' and some other materials which may be useful for Common Lisp developers.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3076034793574893106</id><published>2011-08-13T13:29:00.000-07:00</published><updated>2011-08-13T13:58:14.357-07:00</updated><title type='text'>[Caps &amp; Mugs] Some of my CL aliens designs</title><content type='html'>Sorry for polluting Planet SBCL with these images (also, it is a good idea to remove my blog from the planet, see the previous post on this), but I designed several simple 'Lisp + aliens' images which I want to put into the public domain. They are not complex or artful, and maybe even agressive (not funny, as the traditional Lisp aliens), but I like them:&lt;br /&gt;&lt;br /&gt;The first:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-4rKCLe1oC3Y/TkbinCQD4xI/AAAAAAAAANw/lXc-F2RQ2IE/s1600/5.tif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 267px;" src="http://4.bp.blogspot.com/-4rKCLe1oC3Y/TkbinCQD4xI/AAAAAAAAANw/lXc-F2RQ2IE/s400/5.tif" border="0" alt=""id="BLOGGER_PHOTO_ID_5640444743575134994" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The second:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-yc8rNPQ9bug/Tkbh274UOSI/AAAAAAAAANg/71-zU3MUNfo/s1600/6.tif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 299px;" src="http://4.bp.blogspot.com/-yc8rNPQ9bug/Tkbh274UOSI/AAAAAAAAANg/71-zU3MUNfo/s400/6.tif" border="0" alt=""id="BLOGGER_PHOTO_ID_5640443917231208738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The third:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-HFTY7eER2Ag/TkbiSC-mYUI/AAAAAAAAANo/CJ8Q9zwdO1k/s1600/7.tif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 299px;" src="http://3.bp.blogspot.com/-HFTY7eER2Ag/TkbiSC-mYUI/AAAAAAAAANo/CJ8Q9zwdO1k/s400/7.tif" border="0" alt=""id="BLOGGER_PHOTO_ID_5640444382993080642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These are in the public domain, so anyone can use them. &lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3076034793574893106?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3076034793574893106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2011/08/caps-mugs-some-of-my-cl-aliens-designs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3076034793574893106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3076034793574893106'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2011/08/caps-mugs-some-of-my-cl-aliens-designs.html' title='[Caps &amp; Mugs] Some of my CL aliens designs'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-4rKCLe1oC3Y/TkbinCQD4xI/AAAAAAAAANw/lXc-F2RQ2IE/s72-c/5.tif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-580962380177559073</id><published>2011-08-11T12:34:00.000-07:00</published><updated>2011-08-12T09:37:30.912-07:00</updated><title type='text'>[Note] Crowdfunding and SBCL</title><content type='html'>I think that you already know about it, but if not, please see &lt;a href="http://www.indiegogo.com/SBCL-Threading-Improvements-1"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;BTW, our 'SBCL Users &amp; Developers' Linkedin group has more than 100 members (105 at the time when I'm writing this post). Thanks to all people who participate.&lt;br /&gt;&lt;br /&gt;And the last update is my personal one: there were some changes in my career, and I cannot say that I am a CL developer at this time. But that's okay - people should try other things, even if they started with the best one :) This blog will be silent during my absence in CL community, I think.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-580962380177559073?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/580962380177559073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2011/08/note-crowdfunding-and-sbcl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/580962380177559073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/580962380177559073'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2011/08/note-crowdfunding-and-sbcl.html' title='[Note] Crowdfunding and SBCL'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-6284592695249837647</id><published>2011-05-02T10:28:00.000-07:00</published><updated>2011-05-02T10:40:41.708-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='threads'/><category scheme='http://www.blogger.com/atom/ns#' term='feature'/><title type='text'>[Feature] MAKE-THREAD with the thread arguments</title><content type='html'>Today seems to be a features day :)&lt;br /&gt;&lt;br /&gt;This feature has the extremely simple implementation (unless I'm missing something here), but it makes the life easier when it comes to the thread function's arguments. So, with this patch you can write the next code:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(defun f (x y) (* x y))&lt;br /&gt;&lt;br /&gt;(sb-thread:make-thread #'f :args '(6 7))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;without messing with the wrapper lambda.&lt;br /&gt;&lt;br /&gt;Maybe this simple thing does not deserve a post, but I am really happy to see it working. The patch is &lt;a href="https://bugs.launchpad.net/sbcl/+bug/727384"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-6284592695249837647?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/6284592695249837647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2011/05/feature-make-thread-with-thread.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/6284592695249837647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/6284592695249837647'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2011/05/feature-make-thread-with-thread.html' title='[Feature] MAKE-THREAD with the thread arguments'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-5084255138426956749</id><published>2011-05-02T06:51:00.000-07:00</published><updated>2011-05-02T10:04:00.546-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='feature'/><category scheme='http://www.blogger.com/atom/ns#' term='tests'/><title type='text'>[Feature] Running tests in parallel</title><content type='html'>This feature may be interesting for the people who often run SBCL tests. It uses several CPU cores to do that quickly. While it is still not finished, there is some early implementation which can be used to measure the performance boost. In case you want to try it yourself, here are the explanations and instructions:&lt;br /&gt;&lt;br /&gt;The idea of the multi-core test launcher is based on the fact that SBCL test files are independent, so they can be loaded and executed in parallel. The classic model with the threads pool and the test files queue fits fine - there is a main, "supervisor" thread, whose job is to spawn additional threads. Every additional thread takes care of one impure test file at a time, and executes it using child SBCL process. The supervisor thread runs all pure tests (most of them are short) and waits for the additional threads to finish.&lt;br /&gt;&lt;br /&gt;On my PC with Phenom X4 920, I use three additional threads and all tests run 3 minutes. Without the parallel launcher, they take 8 minutes to finish. Failures seem to be reported correctly, I have tweaked several tests to check that. However, the failures collection needs synchronization, and I hope to finish with it in the future.&lt;br /&gt;&lt;br /&gt;The performance may be improved even more by splitting all-threads.impure.lisp on several files, but this is a low-priority task. Just make sure that you rename the original threads.impure.lisp before trying this stuff (the file is so long that a separate thread runs it almost 3 minutes, so it should be the first file in the queue, alphabetically). Also, adjust the number of threads as described in Launchpad. The default value are for quad-core systems.&lt;br /&gt;&lt;br /&gt;The issue page and the initial code changes are here:&lt;br /&gt;&lt;br /&gt;&lt;a href="https://bugs.launchpad.net/sbcl/+bug/742777"&gt;https://bugs.launchpad.net/sbcl/+bug/742777&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In case you find any errors/mistakes in the code, please let me know. I am interested to make this feature stable and ready for the upstream.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-5084255138426956749?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/5084255138426956749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2011/05/feature-running-tests-in-parallel.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5084255138426956749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5084255138426956749'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2011/05/feature-running-tests-in-parallel.html' title='[Feature] Running tests in parallel'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-7043931890150609830</id><published>2011-01-11T11:44:00.000-08:00</published><updated>2011-01-11T12:22:33.726-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='howto'/><category scheme='http://www.blogger.com/atom/ns#' term='tests'/><title type='text'>[mini-HOWTO] Writing Regression Tests For SBCL</title><content type='html'>Most of the complex software systems have some kind of regression tests, and SBCL is not an exception. In this short post, I want to answer the next two questions:&lt;br /&gt;&lt;br /&gt;1. Why it is preferable to provide a regression test with the bug report?&lt;br /&gt;2. How to write such a test?&lt;br /&gt;&lt;br /&gt;  Frankly speaking, regression tests are not necessary for bug reports. One may just say “this code is compiled wrongly”, and then attach the code snippet. However, such reports can be hard to understand, especially when we are trying to figure out the desired behavior. In contrary, regression tests always show the desired behavior, so they make the report more informative.&lt;br /&gt;&lt;br /&gt;  Moreover, your report with a regression test always saves the time for SBCL developer who will fix the corresponding bug. A regression test is mandatory for the most of patches, so someone should write it anyway. I do not know about the others, but I prefer the next steps while fixing a bug in SBCL:&lt;br /&gt;&lt;br /&gt;- write a regression test. Make sure that it fails before the fix;&lt;br /&gt;- fix the bug;&lt;br /&gt;- make sure that all regression tests pass.&lt;br /&gt;&lt;br /&gt;  The issue originator knows the problem very well, so he or she can provide the best regression test.&lt;br /&gt;&lt;br /&gt;  So, how to write them? It is surprisingly easy in most cases. First of all, you need to find out the right test file to put your test into. These files are located in &lt;span style="font-style:italic;"&gt;/sbcl/tests&lt;/span&gt; directory. They have the extension “lisp”, and the two important parts before it: the suffix “pure” or “impure”, and the main part which classifies the subject of the tests – in other words, the functionality which is tested. The main part is something like “compiler”, “loop”, “print” etc. The suffix “pure” means that the file contains no tests with global side effects; “impure” files contain tests which define variables, conditions, classes, functions and so on. For example, “loop.pure.lisp” file contains LOOP macro tests without side effects.&lt;br /&gt;&lt;br /&gt;  After you have selected a file, it's a time to write the test itself. The only constant element of all tests is a WITH-TEST wrapper, which binds a human-readable name to your test (it can do other things as well, but I use only :name keyword. See the macro definition in &lt;span style="font-style:italic;"&gt;test-util.lisp&lt;/span&gt; to find out more). The rest of the test body may vary (you can use different assertion clauses, bind handlers for compilation errors or warnings etc.).&lt;br /&gt;&lt;br /&gt;Here is a very simple (and pure) test from &lt;span style="font-style:italic;"&gt;arith.pure.lisp&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TSy1_2oSAAI/AAAAAAAAAMk/eg2H_TclABQ/s1600/T1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 361px; height: 46px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TSy1_2oSAAI/AAAAAAAAAMk/eg2H_TclABQ/s400/T1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5561019748496572418" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  The test passes when ASSERT receives non-NIL value. Obviously, you may use any CL code inside ASSERT. For example:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TSy2RHpin6I/AAAAAAAAAMs/VOOzxQ0VQEQ/s1600/T2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 83px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TSy2RHpin6I/AAAAAAAAAMs/VOOzxQ0VQEQ/s400/T2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5561020045123035042" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  RAISES-ERROR? is an utility macro (defined in &lt;span style="font-style:italic;"&gt;assertoid.lisp&lt;/span&gt;). It is useful when you want to test that a form evaluation signals an error. The optional second argument can be used to specify the condition type, as in the above example.&lt;br /&gt;&lt;br /&gt;  Here is another example – the impure test from &lt;span style="font-style:italic;"&gt;mop.impure.lisp&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TSy3M09vHrI/AAAAAAAAAM0/A6vlG5Pb14g/s1600/T3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 80px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TSy3M09vHrI/AAAAAAAAAM0/A6vlG5Pb14g/s400/T3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5561021070899617458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  The test is impure, because it creates a class definition. Some old tests (like this) miss WITH-TEST, but it is strongly recommended for new ones.&lt;br /&gt;&lt;br /&gt;  It is often required to test that SBCL signals (or does not signals) errors and/or warnings during the particular form compilation. This pure LOOP test can be a good example:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/TSy3oKtTRiI/AAAAAAAAAM8/KNb3Sq3F0JI/s1600/T4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 121px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/TSy3oKtTRiI/AAAAAAAAAM8/KNb3Sq3F0JI/s400/T4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5561021540592731682" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  The test idea is to check the return values of COMPILE. Another way to do something similar is to use HANDLER-CASE (the example from &lt;span style="font-style:italic;"&gt;compiler.pure.lisp&lt;/span&gt;):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TSy4B5XDfFI/AAAAAAAAANE/fsnW7vRIs7I/s1600/T5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 112px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TSy4B5XDfFI/AAAAAAAAANE/fsnW7vRIs7I/s400/T5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5561021982612618322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This test ensures that a compiler note is printed for the non-optimal operation.&lt;br /&gt;&lt;br /&gt;In general, SBCL regression tests are very expressive and powerful -  we can test quite complex functionality in the several lines of code. &lt;br /&gt;&lt;br /&gt;To run the added tests, execute a command (on Linux): &lt;br /&gt;&lt;br /&gt;sh run-tests.sh &lt;span style="font-style:italic;"&gt;filename&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;from &lt;span style="font-style:italic;"&gt;sbcl/tests&lt;/span&gt; directory. Without a file argument, it runs all tests in the regression suite.&lt;br /&gt;&lt;br /&gt;I hope that this short post is helpful for those who have never written any SBCL regression tests. Just try to do it when submitting a new bug report – and you will help SBCL developers a lot.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-7043931890150609830?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/7043931890150609830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2011/01/mini-howto-writing-regression-tests-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/7043931890150609830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/7043931890150609830'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2011/01/mini-howto-writing-regression-tests-for.html' title='[mini-HOWTO] Writing Regression Tests For SBCL'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/TSy1_2oSAAI/AAAAAAAAAMk/eg2H_TclABQ/s72-c/T1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-8886018146701732127</id><published>2010-09-18T10:40:00.000-07:00</published><updated>2010-09-18T10:52:15.531-07:00</updated><title type='text'>SBCL platforms</title><content type='html'>There was a poll in Linkedin about the SBCL platforms, and you can see the final chart below. I cannot say that it shows the real picture, because the number of responses is very small. But anyway, Linux seems to be the reasonable winner here, which is not a big surprise :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/TJT707lpWJI/AAAAAAAAAMQ/0kr5ZbAAb9g/s1600/chart.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 235px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/TJT707lpWJI/AAAAAAAAAMQ/0kr5ZbAAb9g/s400/chart.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5518312330203060370" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-8886018146701732127?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/8886018146701732127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/09/sbcl-platforms.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/8886018146701732127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/8886018146701732127'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/09/sbcl-platforms.html' title='SBCL platforms'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Q48gJ59wg6o/TJT707lpWJI/AAAAAAAAAMQ/0kr5ZbAAb9g/s72-c/chart.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-1088990419421334150</id><published>2010-09-05T11:13:00.000-07:00</published><updated>2010-09-05T13:00:49.828-07:00</updated><title type='text'>SB-GPU: the missing part of SBCL</title><content type='html'>While there is no single point of view regarding the SSA pass in SBCL compiler (see the early talks on #sbcl channel), I know the modern and interesting feature which is missing for sure. This is the ability to mix CPU and GPU code in a single CL application. That is, the ability to write:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(def-gpu-kernel mulmatrix (m1 m2 m3) ...) ;m3 = m2*m1&lt;br /&gt;&lt;br /&gt;(defun my-solver (equation-matrix)&lt;br /&gt;...&lt;br /&gt;(with-gpu-allocated-arrays (a1 a2 a3)&lt;br /&gt;...&lt;br /&gt; (call-gpu-kernel mulmatrix a1 a2 a3 N) ;N only, square stuff&lt;br /&gt;...)&lt;br /&gt;) ;end of the solver&lt;br /&gt;&lt;br /&gt;Let us explain the code a bit. mulmatrix is a GPU kernel, defined using some subset of CL (mostly math functions and array operations). It should be compiled to one of the two GPU-specific assembly-like languages (see below). After that it can be launched transparently by call-gpu-kernel (transparency means that call-gpu-kernel is the ordinary CL macro). &lt;br /&gt;&lt;br /&gt;After the kernel is defined, we should be able to use it from the plain CL (CPU-targeted) code. To achieve this goal, the next steps are required:&lt;br /&gt;&lt;br /&gt;1. Allocate CL data arrays on SBCL side (usually arrays of numbers).&lt;br /&gt;2. Allocate the arrays of same size in GPU memory.&lt;br /&gt;3. Copy the data from CL arrays to GPU arrays.&lt;br /&gt;4. Run the kernels using GPU kernel launcher API (part of ATI Stream / CUDA SDKs) on GPU data arrays.&lt;br /&gt;5. Copy the modified data from GPU arrays to CL data arrays.&lt;br /&gt;6. Use the processed data in your CL application.&lt;br /&gt;&lt;br /&gt;This is only one of the possible approaches, and the inputs are not restricted to be arrays (but GPU parallelism is reasonable to use only for quite large data sets, which are represented by arrays).&lt;br /&gt;&lt;br /&gt;In fact, the very simple variant of the described above things works fine with one proprietary CL application which we have written here in Ukraine. And it is proven to gain over 500x (yes, 500 times faster) execution speed improvement on comparatively simple O(N*N) algorithms benchmarks. With SBCL there will be no 500x (because our proprietary application is deadly slow for some reasons which I will not list here), but I believe that 10-20x for O(N*N) algorithms class is possible.&lt;br /&gt;&lt;br /&gt;The whole architecture for SBCL is here:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TIPo3M3LXUI/AAAAAAAAAMI/xnbrAW5lsy4/s1600/sb-gpu.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 327px; height: 400px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TIPo3M3LXUI/AAAAAAAAAMI/xnbrAW5lsy4/s400/sb-gpu.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5513506403874725186" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;CL subset is translated to the intermediate representation GPU-IR, which has no dependency on the underlying device architecture. Then, we produce the GPU assembly for CUDA devices or ATI Stream devices, depending on the platform where our CL code is loaded and executed. In such a way we have our home-made variant of the portable Lisp-like language for the modern parallel computing. SBCL-side part of the system should live in SB-GPU contrib.&lt;br /&gt;&lt;br /&gt;The bad news are connected with the estimate: at least 6 man-months for GPU-independent part and at least 1-2 man-years for two GPU backends (6-12 months per the backend). I can do this as a PhD thesis (because there will be some scientific part, connected with parallelism and optimisations), but I need to find the appropriate university and a professor who could be interested in this (not necessarily in Ukraine). The thing is that I want to continue my education, so I would like to join the SBCL development activities with that. Is this possible on Earth?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-1088990419421334150?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/1088990419421334150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/09/sb-gpu-missing-part-of-sbcl.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1088990419421334150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1088990419421334150'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/09/sb-gpu-missing-part-of-sbcl.html' title='SB-GPU: the missing part of SBCL'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/TIPo3M3LXUI/AAAAAAAAAMI/xnbrAW5lsy4/s72-c/sb-gpu.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-5265022298191340234</id><published>2010-08-14T09:55:00.000-07:00</published><updated>2010-08-14T11:16:57.052-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ssa'/><title type='text'>[SSA] Two ways to implement it</title><content type='html'>I have evaluated two different approaches to SSAF in SBCL compiler. Both have some advantages and drawbacks, more or less significant from different points of view. So, here they are:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1. Insert the SSA pass after find-initial-dfo call, and modify the legacy IR1 component slightly (insert phi-functions &amp; ensure unique assignments). Come out of SSA before ir1-phases call. &lt;br /&gt;&lt;br /&gt;+ Faster to implement&lt;br /&gt;+ Will probably fix the non-linear LVARs bug&lt;br /&gt;- Does not allow to perform SSA-based optimisations (because it means the IR1 functionality duplication)&lt;br /&gt;- Slows down the compilation process&lt;br /&gt;- Requires a good bidirectional mapping algorithm between SSA form and IR1 representation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2. Remove all IR1 code after make-functional-from-toplevel-lambda (including this function as well), and compile Lisp forms to SSAF. Apply SSA-based optimisations, and finally convert SSAF into VOPs, to use the existing backend. &lt;br /&gt;&lt;br /&gt;+ Count all current IR1 bugs for sure&lt;br /&gt;+ Easier conversion to SSAF (no need to analyse IR1 components)&lt;br /&gt;+ Advanced SSA-based optimization, loops analysis, etc.&lt;br /&gt;+ Probably faster compilation process?&lt;br /&gt;+ More fun and interesting than the first variant&lt;br /&gt;- A really huge project&lt;br /&gt;- New bugs, as usual &lt;br /&gt;- Merging perspectives are unclear (I do not believe that maintainers will throw out almost the whole compiler frontend).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As for now, I would prefer the second approach. I think that it will be a hobby project for me, and it will take a year or two before it can be announced as a beta or so, if at all. From my own development experience I can say that compilers should be designed and implemented by quite large (and preferably not remote) teams, not by a single person. So, this is just my own way to have fun with Common Lisp, and I feel that it is very likely to fail eventually. I do not expect brilliant results here, but I can't stop myself from giving it a try - at least to learn some new and cool things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-5265022298191340234?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/5265022298191340234/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/08/ssa-two-ways-to-implement-it.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5265022298191340234'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5265022298191340234'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/08/ssa-two-ways-to-implement-it.html' title='[SSA] Two ways to implement it'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-949216062649101886</id><published>2010-08-06T08:48:00.000-07:00</published><updated>2010-08-06T10:30:22.977-07:00</updated><title type='text'>[Note] SSA in SBCL (yet another book freeze)</title><content type='html'>Yesterday, we had the quite interesting discussion on #lisp, which was originally about &lt;a href="https://bugs.launchpad.net/sbcl/+bug/309099"&gt;this bug&lt;/a&gt;. Several long-term SBCL developers confirmed that the optimal way to deal with such issues is to implement the SSA pass in the compiler. &lt;br /&gt;&lt;br /&gt;SSA is present in SBCL's TODO list during several years, but there is no implementation yet, and, AFAIK, nobody is working on it now. Since the compilers development is the thing I like the most (and it is my full-time job), I have decided to give it a try. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In this situation, I must call the book activities closed. There are two main reasons for such a decision, and one minor reason:&lt;br /&gt;&lt;br /&gt;1. Free time limit.&lt;br /&gt;2. SSA pass is very likely to change the SBCL's frontend. In such a case the book's material may become obsolete, which means that the book writing efforts are spent in vain.&lt;br /&gt;3. Honestly, it is more fun to develop than to write the books (at least for me). And, there are a lot of good compilers books which could be easily mapped on SBCL. One who really wants to learn it will always find the possibility, like many people did before. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I hope that the readers will understand the situation and agree with me (or even forgive me, in case somebody is hurt by this post). From now on, there will be no new chapters here, so it is reasonable to remove the blog from 'Planet SBCL'. Instead, I will put SSA design and progress reports here occasionally.&lt;br /&gt;&lt;br /&gt;In case I fail to implement SSA, I will leave the SBCL community. Two failures in the same open-source project mean that it was selected wrongly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-949216062649101886?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/949216062649101886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/08/note-ssa-in-sbcl-yet-another-book.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/949216062649101886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/949216062649101886'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/08/note-ssa-in-sbcl-yet-another-book.html' title='[Note] SSA in SBCL (yet another book freeze)'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3059794797572373976</id><published>2010-07-27T09:16:00.000-07:00</published><updated>2010-07-27T09:41:53.590-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 5.1 External References Collection</title><content type='html'>Returned by &lt;span style="font-weight:bold;"&gt;sb-c::find-initial-dfo&lt;/span&gt; components are passed to &lt;span style="font-weight:bold;"&gt;sb-c::compile-component&lt;/span&gt; one by one, in the loop which is located inside &lt;span style="font-weight:bold;"&gt;sb-c::%compile&lt;/span&gt; function (src/compiler/main.lisp). Function &lt;span style="font-weight:bold;"&gt;sb-c::compile-component&lt;/span&gt; runs the individual compilation stages for the component. In case we skip the minor things (like the sanity checks), the first function's action is the analysis and collection of the component's external references. Let us discuss this process, along with the corresponding source file ('src/compiler/xref.lisp'). It starts with &lt;span style="font-weight:bold;"&gt;sb-c::record-component-xrefs&lt;/span&gt; function:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TE8HsvCZFTI/AAAAAAAAALg/wISCYI0WK2E/s1600/F5_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 259px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TE8HsvCZFTI/AAAAAAAAALg/wISCYI0WK2E/s400/F5_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5498622135164802354" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This code is pretty simple. For each &lt;span style="font-weight:bold;"&gt;cblock&lt;/span&gt; in the input component, the local function &lt;span style="font-weight:bold;"&gt;handle-node&lt;/span&gt; records the possible external references for every node in that block. The function uses &lt;span style="font-weight:bold;"&gt;sb-c::record-node-xrefs&lt;/span&gt; to analyse the individual node. The analysis is nothing but &lt;span style="font-weight:bold;"&gt;etypecase&lt;/span&gt; form, which handles every kind of node in a particular way. The complicated part comes with &lt;span style="font-weight:bold;"&gt;sb-c::call-with-block-external-functionals&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TE8I-Sc25sI/AAAAAAAAALo/S2aeJOlXjP8/s1600/F5_4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TE8I-Sc25sI/AAAAAAAAALo/S2aeJOlXjP8/s400/F5_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5498623536240453314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This function actually applies &lt;span style="font-weight:bold;"&gt;handle-node&lt;/span&gt;. It defines &lt;span style="font-weight:bold;"&gt;handle-functional&lt;/span&gt; local function, which filters functionals before passing them to the handler. Also, it handles all functionals whose &lt;span style="font-weight:bold;"&gt;ref&lt;/span&gt; nodes point on the initial functional, in the recursive manner.&lt;br /&gt;&lt;br /&gt;The reference recording happens in &lt;span style="font-weight:bold;"&gt;sb-c::record-xref&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/TE8JteML5-I/AAAAAAAAALw/Z_ugt1ySnjg/s1600/F5_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 370px; height: 118px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/TE8JteML5-I/AAAAAAAAALw/Z_ugt1ySnjg/s400/F5_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5498624346845603810" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To understand the process results better, let us debug it a bit:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TE8KBB7OFnI/AAAAAAAAAL4/RfOhQGNNzEI/s1600/F5_3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 374px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TE8KBB7OFnI/AAAAAAAAAL4/RfOhQGNNzEI/s400/F5_3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5498624682855634546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In this example, the reference kind is :calls. This means that &lt;span style="font-weight:bold;"&gt;f&lt;/span&gt; calls the global function #'+ (or just &lt;span style="font-weight:bold;"&gt;+&lt;/span&gt;,  as you can see on the figure). The context is &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; which corresponds to &lt;span style="font-weight:bold;"&gt;f&lt;/span&gt;, then we see the reference node and &lt;span style="font-weight:bold;"&gt;nil&lt;/span&gt; instead of the source path. At this point we consider the external references collection to be explained enough. The author hopes that the readers also find this process and the related code to be simple.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3059794797572373976?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3059794797572373976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/07/book-chapter-51-external-references.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3059794797572373976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3059794797572373976'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/07/book-chapter-51-external-references.html' title='[Book] Chapter 5.1 External References Collection'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/TE8HsvCZFTI/AAAAAAAAALg/wISCYI0WK2E/s72-c/F5_1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-1051740831451185139</id><published>2010-07-20T10:09:00.000-07:00</published><updated>2010-07-20T10:25:43.634-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='note'/><title type='text'>[Note] My SBCL tree</title><content type='html'>Namely, http://repo.or.cz/w/sbcl/rmarynch.git&lt;br /&gt;&lt;br /&gt;I have some ideas about the current SBCL compiler development. For example, better loops analysis and automatic vectorization are good things to implement. &lt;br /&gt;&lt;br /&gt;However, the constant lack of free time makes these ideas to wait until I will be fired :)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;There was a short discussion on #lisp regarding the current patches review problem (the thing is that they stay in Launchpad for a long time). One of the ideas is to have a branch with all patches applied, and to merge from it into CVS once a month or so. Now I think that I am not the right person to manage such a branch - it is definitely a maintainer's task. So, rmarynch.git will be my personal branch only.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-1051740831451185139?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/1051740831451185139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/07/note-my-sbcl-tree.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1051740831451185139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1051740831451185139'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/07/note-my-sbcl-tree.html' title='[Note] My SBCL tree'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-2145784715013168225</id><published>2010-07-18T06:08:00.000-07:00</published><updated>2010-07-18T06:56:47.326-07:00</updated><title type='text'>[Book] Chapter 4 DFO</title><content type='html'>DFO (depth-first ordering) computation is the next code flow graph processing phase, which comes right after the local calls analysis. The corresponding source file is 'src/compiler/dfo.lisp'. But before starting to talk about the code, let us explain DFO itself, for those readers who are not familiar with this concept.&lt;br /&gt; DFO can be considered to be the result of DFS (depth-first search). The latter, along with BFS (breadth-first search), are two different ways to walk a graph. They both can visit all graph's nodes, as shown on this figure (a graph, DFS and BFS):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/TEL96Z14v7I/AAAAAAAAALI/k-xrcsE3VoU/s1600/F4_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 154px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/TEL96Z14v7I/AAAAAAAAALI/k-xrcsE3VoU/s400/F4_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5495233675156570034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; The main difference between these two methods is that the first one tries to walk the graph by moving between different child levels first, while the second (BFS) visits all children on the same level first, and then moves to the next level. Of course, this explanation is informal – refer to your discrete math book to find out more.&lt;br /&gt; DFS is also useful when we want to classify the graph's edges. A graph may be quite complex, with many edges connecting nodes in a certain way. The next four categories are possible (this classification evolves naturally from DFS algorithm):&lt;br /&gt;&lt;br /&gt;- tree edges;&lt;br /&gt;- forward edges;&lt;br /&gt;- back edges;&lt;br /&gt;- cross edges.&lt;br /&gt;&lt;br /&gt; However, SBCL uses DFS to find out the independent components and their elements only, and it does not classify the connections between them.  Taking this into account, readers should probably consider DFS to be just a tree walk in our case.&lt;br /&gt;&lt;br /&gt; We choose &lt;span style="font-weight:bold;"&gt;sb-c::find-initial-dfo&lt;/span&gt; (called in &lt;span style="font-weight:bold;"&gt;sb-c::%compile&lt;/span&gt;, 'src/compiler/main.lisp') as a starting point for the code discussion. It receives the list which contains the exactly one functional – the one we are compiling. Then, it does the next steps:&lt;br /&gt;&lt;br /&gt;- fetches the component of the functional, and a list of functionals which are in this component;&lt;br /&gt;&lt;br /&gt;- iterates over that list, calling &lt;span style="font-weight:bold;"&gt;sb-c::dfo-scavenge-dependency-graph&lt;/span&gt; for each functional;&lt;br /&gt;&lt;br /&gt;- collects the component which was returned by  &lt;span style="font-weight:bold;"&gt;sb-c::dfo-scavenge-dependency-graph&lt;/span&gt; (this collection does not happen always – the same component is not collected twice);&lt;br /&gt;&lt;br /&gt;- deletes the original component of the input functional, in case the component's kind is :initial;&lt;br /&gt;&lt;br /&gt;- after the components are collected, the last two actions: blocks numbering and components classification (in &lt;span style="font-weight:bold;"&gt;sb-c::separate-toplevelish-components&lt;/span&gt;) complete the function body.&lt;br /&gt;&lt;br /&gt; Let us move to  &lt;span style="font-weight:bold;"&gt;sb-c::dfo-scavenge-dependency-graph&lt;/span&gt;. What is bad about DFO code, is the individual functions size, which is impossible to fit into the book's standard page. So, please find its source (there is also the excellent comment) and then continue with this chapter.&lt;br /&gt;&lt;br /&gt; There are four main branches in this function: the first performs a simple check to find out whether the functional is already in the given component, and returns that component. The second merges the old non-initial component into the given component. Third branch is related to the second, it checks the block's 'flag' slot to find the initial components which are already walked during DFO computation (this slot value is set in &lt;span style="font-weight:bold;"&gt;sb-c::find-initial-dfo-aux&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt; The most interesting and long branch is the fourth one. Here the function builds DFO for the functional and its elements. It should do the next things to accomplish that:&lt;br /&gt;&lt;br /&gt;- move the input &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; structure instance from its old component to the new, as well as &lt;span style="font-weight:bold;"&gt;clambda bind&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; blocks;&lt;br /&gt;&lt;br /&gt;- call &lt;span style="font-weight:bold;"&gt;sb-c::find-initial-dfo-aux&lt;/span&gt; (see below);&lt;br /&gt;&lt;br /&gt;- declare several local functions: 'scavenge-closure-var', 'scavenge-lambda', 'scavenge-entry' and so on. They all use &lt;span style="font-weight:bold;"&gt;sb-c::dfo-scavenge-dependency-graph&lt;/span&gt; directly or indirectly – after the certain simple checks are done;&lt;br /&gt;&lt;br /&gt;- iterate over the dependency list of the input &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; (more precisely, over 'calls-or-closes' sparse set elements) and call one of the inner functions to scavenge every element. Eventually this ends with the recursive call into  &lt;span style="font-weight:bold;"&gt;sb-c::dfo-scavenge-dependency-graph&lt;/span&gt;. This is a key point to understand: Python is merging all pieces of the entire functional representation into the single component recursively. In case you understand this sentence, you understand what is DFO computation in SBCL.&lt;br /&gt;&lt;br /&gt;Function &lt;span style="font-weight:bold;"&gt;sb-c::find-initial-dfo-aux&lt;/span&gt; is shown here:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/TEMB4fUYK6I/AAAAAAAAALQ/iWrATbNUavc/s1600/F4_3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 196px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/TEMB4fUYK6I/AAAAAAAAALQ/iWrATbNUavc/s400/F4_3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5495238040313408418" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As you see, the code is quite simple. The strategy is to join the block's component with the given input component, unless the block's component is initial, the same as the input component, or the block is already processed by this function (its 'flag' slot is set). Actual flag setting occurs in the default branch, which is full of the interesting stuff. First of all, we have a call into &lt;span style="font-weight:bold;"&gt;sb-c::scavenge-home-dependency-graph&lt;/span&gt; here:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TEMCrsCBS5I/AAAAAAAAALY/mQcb6R-eVzY/s1600/F4_4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 151px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TEMCrsCBS5I/AAAAAAAAALY/mQcb6R-eVzY/s400/F4_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5495238919899401106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; This function finds the right component to merge the block's successors into (recall that a block which contains &lt;span style="font-weight:bold;"&gt;bind&lt;/span&gt; node is the first in the functional blocks chain).  In &lt;span style="font-weight:bold;"&gt;sb-c::find-initial-dfo-aux&lt;/span&gt; all these successors are recursively processed, and their common component is derived finally. The tiny function &lt;span style="font-weight:bold;"&gt;sb-c::remove-from-dfo&lt;/span&gt; (it is located in ir1util.lisp, as well as &lt;span style="font-weight:bold;"&gt;sb-c::add-to-dfo&lt;/span&gt;) is used to break the old next/prev relations of the block, and &lt;span style="font-weight:bold;"&gt;sb-c::add-to-dfo&lt;/span&gt; is used to insert the block after the component's head block.&lt;br /&gt;&lt;br /&gt; The actual code which joins two components, &lt;span style="font-weight:bold;"&gt;sb-c::join-components&lt;/span&gt;, is quite simple and long enough to omit it in this book. We believe that readers also find this function to be easy understandable.&lt;br /&gt;&lt;br /&gt; The last function to discuss in this chapter is &lt;span style="font-weight:bold;"&gt;sb-c::separate-toplevelish-components&lt;/span&gt;. It is called as a last form in &lt;span style="font-weight:bold;"&gt;sb-c::find-initial-dfo&lt;/span&gt;. Its job is to classify the toplevel components which were discovered during DFO computation. The function iterates over the list of these components, and creates three lists of them, by category: nontop-components, top-components and hairy-top-components. Classification rules are based on the analysis of the external references and toplevel functionals presence in a component. &lt;br /&gt;&lt;br /&gt; As for now, that is all about DFO computation in SBCL. We will meet it again later, in &lt;span style="font-weight:bold;"&gt;sb-c::dfo-as-needed&lt;/span&gt;, but at this time it is enough to know that DFO in Python provides the certain connections between all elements of the same Lisp form representation in the compiler. These connections allow easy and consistent walking of the entire functional, which is important for many compilation-related algorithms.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-2145784715013168225?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/2145784715013168225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/07/book-chapter-4-dfo.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2145784715013168225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2145784715013168225'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/07/book-chapter-4-dfo.html' title='[Book] Chapter 4 DFO'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Q48gJ59wg6o/TEL96Z14v7I/AAAAAAAAALI/k-xrcsE3VoU/s72-c/F4_1.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-292079894159517219</id><published>2010-07-09T02:39:00.000-07:00</published><updated>2010-07-09T06:13:34.803-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='note'/><title type='text'>[Note] New chapters schedule</title><content type='html'>I have found that it is better to put complete chapters for the review at once, instead of posting several parts of a chapter. The advantages of this approach:&lt;br /&gt;&lt;br /&gt;1) The chapter is solid and more consistent (because I can modify the earlier parts after I have discovered something at the end of a particular topic).&lt;br /&gt;&lt;br /&gt;2) It is easier to track changes, comments etc. when we have the less number of posts.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Since a typical chapter has 3-4 parts, it takes a month to write the complete one. So, I plan to post Chapter 4 by the end of this month. I have the first part ready, but I feel that it may be changed while I move across dfo.lisp.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So, please visit this blog at the end of July. Maybe I will finish the chapter earlier, but the end of the month is the guaranteed deadline:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-292079894159517219?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/292079894159517219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/07/note-new-chapters-schedule.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/292079894159517219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/292079894159517219'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/07/note-new-chapters-schedule.html' title='[Note] New chapters schedule'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-4702590050438560948</id><published>2010-07-02T09:36:00.000-07:00</published><updated>2010-07-02T10:10:14.803-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='inline'/><title type='text'>[Book] Chapter 3.2 Let Conversion</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Let&lt;/span&gt; conversion is the second part of the local calls processing, and its goal is to place (inline) the callee's flow graph elements inside the caller's home &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt;. The explanation of this short sentence is the subject of this chapter.&lt;br /&gt; The actual conversion for a functional (strictly speaking, for &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt;) begins with &lt;span style="font-weight:bold;"&gt;sb-c::maybe-let-convert&lt;/span&gt; call. This function performs all necessary checks to make sure that it is possible to proceed with the conversion. The next things are verified:&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; as a leaf is referenced only once;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; represents an ordinary function or is used in local calls several times (see node.lisp about &lt;span style="font-weight:bold;"&gt;nil&lt;/span&gt; and :assignment functional kinds. Note that :assignment functionals are not converted, due to the narrower constraint which follows this one);&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; has no XEP;&lt;br /&gt;&lt;br /&gt;- the call is :local, and both the destination node and the block this &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; is in are not scheduled for deletion;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;sb-c::ok-initial-convert-p&lt;/span&gt; returns &lt;span style="font-weight:bold;"&gt;t&lt;/span&gt; for this &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt;. This short predicate filters functions which are likely to have more than one leaf reference in the future;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; is not the home lambda of the destination node.&lt;br /&gt;&lt;br /&gt; After the above conditions are satisfied, &lt;span style="font-weight:bold;"&gt;sb-c::let-convert&lt;/span&gt; comes into play. Its job is to arrange the stages of the conversion, as you can see on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4XgFS3G2I/AAAAAAAAAKY/xZbbzSFE3GA/s1600/F3_12.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 136px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4XgFS3G2I/AAAAAAAAAKY/xZbbzSFE3GA/s400/F3_12.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5489350835755752290" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; The first step is the insertion of a fresh &lt;span style="font-weight:bold;"&gt;let&lt;/span&gt; body, which happens in &lt;span style="font-weight:bold;"&gt;sb-c::insert-let-body&lt;/span&gt;. We give the code, as well as the explanation for this process:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4cvtktAdI/AAAAAAAAALA/LD67WLiwMOQ/s1600/F3_13.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 215px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4cvtktAdI/AAAAAAAAALA/LD67WLiwMOQ/s400/F3_13.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5489356601824182738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; First of all, home blocks of &lt;span style="font-weight:bold;"&gt;basic-combination&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;clambda bind&lt;/span&gt; nodes are fetched, along with &lt;span style="font-weight:bold;"&gt;basic-combination's&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;bind's&lt;/span&gt; home components. When unoptimized component of &lt;span style="font-weight:bold;"&gt;basic-combination&lt;/span&gt; is not the same as &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; has, both components are merged by &lt;span style="font-weight:bold;"&gt;sb-c::join-components&lt;/span&gt; ('src/compiler/dfo.lisp'). This means that the entire &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; component's code now shares the same component with the &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; caller. After that, caller's block is split in such a way that the call (&lt;span style="font-weight:bold;"&gt;basic-combination&lt;/span&gt;) node becomes the last node in the original block. Finally, the block of &lt;span style="font-weight:bold;"&gt;bind&lt;/span&gt; node is inserted right after the call node (block), and the block which was the successor of the call block originally ('next-block') is returned. Recall that (node.lisp comments) &lt;span style="font-weight:bold;"&gt;bind&lt;/span&gt; node marks the beginning of the entire &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt;, and includes all computations in that functional to the code flow graph (using control transfers). So, now &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; is literally inside the caller's code. &lt;br /&gt;&lt;br /&gt; The next step is &lt;span style="font-weight:bold;"&gt;sb-c::move-return-stuff&lt;/span&gt; call (Figure 3.14).  There is a decent comment right above the function in the sources, but anyway let us add a few words to it. Ignoring &lt;span style="font-weight:bold;"&gt;sb-c::unconvert-tail-calls&lt;/span&gt; temporarily, the function begins with fetching &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; nodes of both caller and callee &lt;span style="font-weight:bold;"&gt;clambdas&lt;/span&gt;.  In case the caller has this node, and the node is in &lt;span style="font-weight:bold;"&gt;cblocks&lt;/span&gt; which is scheduled for deletion, the node is removed. Then, a trivial check for non-nil callee's &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; node is performed. After that, three scenarios are possible:&lt;br /&gt;&lt;br /&gt;- there are both the caller's &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; node and the code after that node (that is, 'next-block' &lt;span style="font-weight:bold;"&gt;cblock&lt;/span&gt;) present, or at least 'next-block' is non-nil; and callee's &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; nodes' block is not scheduled for deletion (the last requirement stays in the next scenario as well). This situation is handled in &lt;span style="font-weight:bold;"&gt;sb-c::move-return-uses&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;- there is the caller's &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; node, but there is no code after it (that is, we have a tail call case). This is also a subject to &lt;span style="font-weight:bold;"&gt;sb-c::move-return-uses&lt;/span&gt;, but there is the additional preparation before the actual call – the compiler ensures the caller's &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; node to be the last node in its block (see &lt;span style="font-weight:bold;"&gt;sb-c::ensure-block-start&lt;/span&gt; in ir1util.lisp, :inside-block case), and assumes 'next-block' to be the same &lt;span style="font-weight:bold;"&gt;cblock&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;- the default scenario: the call itself is assumed to be tail, and the callee's &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; node is moved to the caller's &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4aNGhfSGI/AAAAAAAAAKg/BI7piWb_2nI/s1600/F3_14.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 324px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4aNGhfSGI/AAAAAAAAAKg/BI7piWb_2nI/s400/F3_14.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5489353808202909794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now it is a time to talk about the skipped function -  &lt;span style="font-weight:bold;"&gt;sb-c::unconvert-tail-calls&lt;/span&gt;. Its code is on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TC4adQOTLRI/AAAAAAAAAKo/-vMnvB0AXZU/s1600/F3_15.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 261px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TC4adQOTLRI/AAAAAAAAAKo/-vMnvB0AXZU/s400/F3_15.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5489354085684686098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; This function iterates over all &lt;span style="font-weight:bold;"&gt;clambdas&lt;/span&gt; which are in use by the callee ('fun'). In case the call is represented by a node in the tail position and the node home &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; is 'fun' itself, the compiler marks the node to be non-tail positioned. Then, the most significant part of the processing occurs for ordinary, cleanup or &lt;span style="font-weight:bold;"&gt;optional-dispatch&lt;/span&gt; kinds of functionals. The block of 'this-call' node is fetched, along with &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; which is the destination of the original (input) call node. Then this block is separated from its first successor, and linked with 'next-block'. As you remember from &lt;span style="font-weight:bold;"&gt;sb-c::insert-let-body&lt;/span&gt; discussion, this 'next-block' contains all the code which was moved into a new block in &lt;span style="font-weight:bold;"&gt;sb-c::node-ends-block&lt;/span&gt; call. Finally, 'this-call' provides the value of the original call node. This connection is done with &lt;span style="font-weight:bold;"&gt;sb-c::add-lvar-use&lt;/span&gt;. See also the sources comments for &lt;span style="font-weight:bold;"&gt;sb-c::unconvert-tail-calls&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Function &lt;span style="font-weight:bold;"&gt;sb-c::move-return-stuff&lt;/span&gt; uses &lt;span style="font-weight:bold;"&gt;sb-c::move-return-uses&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/TC4bVgU4xFI/AAAAAAAAAKw/nPMHDsGz2L4/s1600/F3_16.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 247px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/TC4bVgU4xFI/AAAAAAAAAKw/nPMHDsGz2L4/s400/F3_16.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5489355052079957074" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Things which happen here are comparatively simple. First of all, the function fetches the callee's &lt;span style="font-weight:bold;"&gt;return&lt;/span&gt; node and the block this node is in. Then, the block is disconnected from its component's tail block ('tail block' is the successor of the exit point, so the unlink operation is valid. See the comment in node.lisp about 'tail' slot of &lt;span style="font-weight:bold;"&gt;component&lt;/span&gt; structure) and linked with 'next-block'. Return node itself is removed from the flow graph. Finally, all nodes which use the value from 'result' are modified to use the value from the converted call node ('lvar'). For the process details, see the small function &lt;span style="font-weight:bold;"&gt;sb-c::substitute-lvar-uses&lt;/span&gt; in ir1util.lisp.&lt;br /&gt;&lt;br /&gt; The last function which we should discuss in this chapter is &lt;span style="font-weight:bold;"&gt;sb-c::merge-lets&lt;/span&gt;. It is the final function which is used in &lt;span style="font-weight:bold;"&gt;sb-c::let-convert&lt;/span&gt; body:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4cRR--kMI/AAAAAAAAAK4/FnqMs-LSFe8/s1600/F3_17.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 374px; height: 400px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4cRR--kMI/AAAAAAAAAK4/FnqMs-LSFe8/s400/F3_17.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5489356079022117058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; We deleted comments and added line numbers, to fit the function on a single page and to provide the way to reference a certain code line during the discussion. &lt;br /&gt; This function does multiple things. First of all, it unlinks and removes the callee's &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; from the caller's &lt;span style="font-weight:bold;"&gt;component&lt;/span&gt;, lines 811-815. Then, callee is removed from its own tail-set structure's functions list (see &lt;span style="font-weight:bold;"&gt;sb-c::depart-from-tail-set&lt;/span&gt; for details), line 817. In lines 818-831 we can see the change of &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; 'home' and related slots, which now contain the values from caller's home &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt;. The rest of the code moves external dependencies of &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; to its new “home”. That is, the converted function is not an independent functional anymore.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-4702590050438560948?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/4702590050438560948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/07/book-chapter-32-let-conversion.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/4702590050438560948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/4702590050438560948'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/07/book-chapter-32-let-conversion.html' title='[Book] Chapter 3.2 Let Conversion'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/TC4XgFS3G2I/AAAAAAAAAKY/xZbbzSFE3GA/s72-c/F3_12.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-5613961815810691554</id><published>2010-06-25T10:12:00.000-07:00</published><updated>2010-06-25T10:42:58.350-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='inline'/><title type='text'>[Book] Chapter 3 Local Calls Analysis [part 3]</title><content type='html'>Function &lt;span style="font-weight:bold;"&gt;sb-c::convert-lambda-call&lt;/span&gt; is a thin wrapper over &lt;span style="font-weight:bold;"&gt;sb-c::convert-call&lt;/span&gt;. It just checks the arguments count match, and delegates the conversion to the latter function. The same can be stated about &lt;span style="font-weight:bold;"&gt;sb-c::convert-hairy-call&lt;/span&gt;, except that it uses both &lt;span style="font-weight:bold;"&gt;sb-c::convert-call&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;sb-c::convert-more-call&lt;/span&gt;. The last is useful when dealing with those &lt;span style="font-weight:bold;"&gt;optional-dispatch&lt;/span&gt; instances which handle &lt;span style="font-weight:bold;"&gt;&amp;more&lt;/span&gt; or &lt;span style="font-weight:bold;"&gt;&amp;rest&lt;/span&gt; keywords (maybe 'handle' is not the right word here, they just correspond to Lisp forms which were declared with these keywords in their arguments lists).&lt;br /&gt; Since &lt;span style="font-weight:bold;"&gt;sb-c::convert-call&lt;/span&gt; is used more often, let us discuss it first. The sources are shown here:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TCTlGlY01-I/AAAAAAAAAKA/bksfbaFuPkE/s1600/F3_9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 151px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TCTlGlY01-I/AAAAAAAAAKA/bksfbaFuPkE/s400/F3_9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5486762147322320866" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; It begins with &lt;span style="font-weight:bold;"&gt;sb-c::propagate-to-args&lt;/span&gt; call, which uses &lt;span style="font-weight:bold;"&gt;sb-c::assert-lvar-type&lt;/span&gt; to ensure that the actual arguments types will be correct in runtime. Then the kind of call's combination becomes :local, and its arguments lose their 'externally checkable types' due to &lt;span style="font-weight:bold;"&gt;sb-c::flush-lvar-externally-checkable-type&lt;/span&gt; calls ('src/compiler/ir1opt.lisp'). The last function just sets '%externally-checkable-type' slot of &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; instance to &lt;span style="font-weight:bold;"&gt;nil&lt;/span&gt;. The value of this slot is used in &lt;span style="font-weight:bold;"&gt;sb-c::cast-externally-checkable-p&lt;/span&gt; ('src/compiler/checkgen.lisp'), and we will discuss it later in this book. The reason to have a separate function for this simple operation is not so clear, maybe the authors just wanted to have the possibility to debug this flushing. As one can see from the sources, the flushing occurs only when &lt;span style="font-weight:bold;"&gt;sb-c::call-full-like-p&lt;/span&gt; ('src/compiler/ir1util.lisp') returns &lt;span style="font-weight:bold;"&gt;nil&lt;/span&gt;. The last function involves some IR2 stuff, so we are not sure whether we should talk about it in this chapter.&lt;br /&gt;&lt;br /&gt; The last new thing to cover in &lt;span style="font-weight:bold;"&gt;sb-c::convert-call&lt;/span&gt; is &lt;span style="font-weight:bold;"&gt;sb-c::recognize-dynamic-extent-lvars&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/TCTlwjTdkgI/AAAAAAAAAKI/4vqs5RMscWE/s1600/F3_10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 248px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/TCTlwjTdkgI/AAAAAAAAAKI/4vqs5RMscWE/s400/F3_10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5486762868317458946" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; This function iterates on both the caller's and callee's arguments (more precisely, for &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; these are &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; instances, and for &lt;span style="font-weight:bold;"&gt;basic-combination&lt;/span&gt; there is a list of &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; instances in 'args' slot). In case there is &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; instance which denotes a variable with dynamic extent, but the corresponding &lt;span style="font-weight:bold;"&gt;basic-combination&lt;/span&gt; argument has no &lt;span style="font-weight:bold;"&gt;cleanup&lt;/span&gt; instance assigned to it, the result of &lt;span style="font-weight:bold;"&gt;sb-c::handle-nested-dynamic-extent-lvars&lt;/span&gt; call ('src/compiler/ir1util.lisp') is appended to 'dx-lvars'. That function is a bit long to post here, so its analysis is a task for readers. Final actions in the loop are quite simple (except &lt;span style="font-weight:bold;"&gt;sb-c::node-ends-block&lt;/span&gt; call, see below) – the &lt;span style="font-weight:bold;"&gt;entry&lt;/span&gt;/&lt;span style="font-weight:bold;"&gt;cleanup&lt;/span&gt; pair is created, and 'call' node is protected with &lt;span style="font-weight:bold;"&gt;cleanup&lt;/span&gt;. Also, the same &lt;span style="font-weight:bold;"&gt;cleanup&lt;/span&gt; is put into 'dynamic-extent' slot of every &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; instance which misses it initially (and this is the reason why the corresponding variable is in 'dx-lvars' list).&lt;br /&gt;&lt;br /&gt; Since we have met it, let us discuss &lt;span style="font-weight:bold;"&gt;sb-c::node-ends-block&lt;/span&gt; ('src/compiler/ir1util/lisp):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/TCToDfxLssI/AAAAAAAAAKQ/OlYl3C5Vljs/s1600/F3_11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 391px; height: 400px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/TCToDfxLssI/AAAAAAAAAKQ/OlYl3C5Vljs/s400/F3_11.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5486765392809145026" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; The main purpose of this function is to ensure that the given node is the last node in the block, and to make it to be the last node in case it is not. Here are the main steps it does:&lt;br /&gt;&lt;br /&gt;- fetch the nodes' block, the block's last node and the nodes' next &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;- exit in case the input node is the last node in the block;&lt;br /&gt;&lt;br /&gt;- create a new block, which is headed by the nodes' next &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt;. The last node in this block is the last node of the original nodes' block. So, we may assume the original code block (&lt;span style="font-weight:bold;"&gt;cblock&lt;/span&gt;) to be split on two blocks, with the nodes' next &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; as the boundary between them. The successor of the new block is the successor of the original block, and they (old and original blocks) are in the same component;&lt;br /&gt;&lt;br /&gt;- nodes' next &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; now starts a block, so its kind becomes :block-start. The input node becomes the last node in the original block, and its 'next' slot is now nil;&lt;br /&gt;&lt;br /&gt;- for every successor block of the original block, 'new-block' is added to the predecessors list, and the original block is removed from that list;&lt;br /&gt;&lt;br /&gt;- the original block successors list is cleared, and the block is linked with 'new block' (see ir1util.lisp and &lt;span style="font-weight:bold;"&gt;sb-c::link-blocks&lt;/span&gt;, it just establishes successor/predecessor relations between &lt;span style="font-weight:bold;"&gt;cblocks&lt;/span&gt;). Function &lt;span style="font-weight:bold;"&gt;sb-c::add-to-dfo&lt;/span&gt; finishes this process by adjusting next/prev slots of &lt;span style="font-weight:bold;"&gt;cblocks&lt;/span&gt; (you may find this small function in ir1util.lisp);&lt;br /&gt;&lt;br /&gt;- the original block's component reanalysis is scheduled;&lt;br /&gt;&lt;br /&gt;- all &lt;span style="font-weight:bold;"&gt;ctrans&lt;/span&gt; in the new block are updated, so they “know” where they are now;&lt;br /&gt;&lt;br /&gt;- the original block is marked as “interesting” for constraint propagation phase (we will discuss this phase later in the book).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; There exists the last form to discuss before we return to the second branch of the local analysis (that is, to &lt;span style="font-weight:bold;"&gt;sb-c::maybe-let-convert&lt;/span&gt;). It is &lt;span style="font-weight:bold;"&gt;sb-c::convert-more-call&lt;/span&gt;. But here the author is bound to tell the readers honestly: he has never used '&amp;more' lambda list keyword. Quick scan through SBCL User's Manual also gave no insights about this keyword purpose (it is available only in CMUCL/SBCL, as far as the author knows). So, in the first book draft this conversion description is omitted, and we start with &lt;span style="font-weight:bold;"&gt;let&lt;/span&gt; conversion discussion in Chapter 3.2.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-5613961815810691554?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/5613961815810691554/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-3-local-calls-analysis_25.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5613961815810691554'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5613961815810691554'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-3-local-calls-analysis_25.html' title='[Book] Chapter 3 Local Calls Analysis [part 3]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/TCTlGlY01-I/AAAAAAAAAKA/bksfbaFuPkE/s72-c/F3_9.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-2268289125567698131</id><published>2010-06-19T02:58:00.000-07:00</published><updated>2010-06-19T03:26:18.948-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='inline'/><title type='text'>[Book] Chapter 3 Local Calls Analysis [part 2]</title><content type='html'>Entry points for &lt;span style="font-weight:bold;"&gt;optional-dispatch&lt;/span&gt;, as well as ordinary functions and escape/cleanup functionals, are further processed by one of these functions: &lt;span style="font-weight:bold;"&gt;sb-c::convert-mv-call&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;sb-c::convert-lambda-call&lt;/span&gt; or &lt;span style="font-weight:bold;"&gt;sb-c::convert-hairy-call&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt; The first one, &lt;span style="font-weight:bold;"&gt;sb-c::convert-mv-call&lt;/span&gt;, is shown on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TByVqNYu5oI/AAAAAAAAAJg/jdYWqPYdDLE/s1600/F3_5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 223px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TByVqNYu5oI/AAAAAAAAAJg/jdYWqPYdDLE/s400/F3_5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5484422998610863746" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Starting from the very beginning, there is &lt;span style="font-weight:bold;"&gt;sb-c::looks-like-an-mv-bind&lt;/span&gt; call ('src/compiler/ir1util.lisp'). This function checks that the input functional is the instance of  &lt;span style="font-weight:bold;"&gt;optional-dispatch&lt;/span&gt; structure, and the input arguments conform to the certain set of rules (described in the function's comments). Predicate &lt;span style="font-weight:bold;"&gt;sb-impl::singleton-p&lt;/span&gt; is a tiny form in 'src/code/early-extensions.lisp' file, and it is supposed to check that an input argument is a one-element list. In our context this predicate is used to make sure that there is only one reference to the function object, and only one &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; instance in 'args' slot of the &lt;span style="font-weight:bold;"&gt;mv-combination&lt;/span&gt; instance.  Then, the entry point of &lt;span style="font-weight:bold;"&gt;optional-dispatch&lt;/span&gt;, which corresponds to the maximum number of input arguments, is stored in 'ep' variable. In case there are no references to this entry point as to the leaf, the actual call processing begins. First of all, the kind of the call is set to be :local. After this, the entry point 'ep' is added to the set of &lt;span style="font-weight:bold;"&gt;clambdas&lt;/span&gt; which are called by the home &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; of the combination. The set is stored in 'calls-or-closes' slot of &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; instance, and the insertion is performed by &lt;span style="font-weight:bold;"&gt;sb-c::sset-adjoin&lt;/span&gt; function ('src/compiler/sset.lisp'). As a result, the entry point is known to be locally called by the home &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; of 'call' &lt;span style="font-weight:bold;"&gt;mv-combination&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt; Then, function &lt;span style="font-weight:bold;"&gt;sb-c::merge-tail-set&lt;/span&gt; is used to join the tail sets of the entry point and the call combination. Let us discuss it briefly:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/TByXCeQfRDI/AAAAAAAAAJo/yrp17SFksLE/s1600/F3_6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 150px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/TByXCeQfRDI/AAAAAAAAAJo/yrp17SFksLE/s400/F3_6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5484424514968175666" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; We suppose our readers to be familiar with the tail call definition, nevertheless there is a short description: a tail call inside a function body is a call whose return value is used as the direct return value of the function. In case a function contains a tail call to itself, it is considered to be tail-recursive. In Python, every &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; instance maintains 'tail-set' slot, which holds an instance of &lt;span style="font-weight:bold;"&gt;tail-set&lt;/span&gt; structure (node.lisp). There is  the decent comment about this structure in that file, so please read it. The core tail sets merging algorithm is the next: unless two sets are equal, change all callee's functions tail sets to the caller's tail set instance, and then add all callee's tail set functions to that caller's tail set. In such a way, we end up with the single tail set instance, which represents both caller's and callee's tail sets. Finally, the reanalysis of the caller's return &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; is scheduled.&lt;br /&gt;&lt;br /&gt; After this short review, let us come back to &lt;span style="font-weight:bold;"&gt;sb-c::convert-mv-call&lt;/span&gt;. Here is the only interesting thing left – the call of &lt;span style="font-weight:bold;"&gt;sb-c::assert-lvar-type&lt;/span&gt;. This tiny function is defined in 'src/compiler/ir1opt.lisp' file:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TByYmSgMAiI/AAAAAAAAAJw/HrQvpXlrpH4/s1600/F3_7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 116px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TByYmSgMAiI/AAAAAAAAAJw/HrQvpXlrpH4/s400/F3_7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5484426229799715362" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; It does the additional &lt;span style="font-weight:bold;"&gt;cast&lt;/span&gt; node insertion to make sure that a variable receives the value of the certain type. The original &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; is replaced by the new internal &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; (the replacement is done by &lt;span style="font-weight:bold;"&gt;sb-c::substitute-lvar&lt;/span&gt; function from 'src/compiler/ir1util.lisp'. The substitution idea is to find out the destination node of the old &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt;, and to point this node to receive its value from the new &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt;. The actual 'pointing' depends on the node type, see the function body for more details). Then, &lt;span style="font-weight:bold;"&gt;cast&lt;/span&gt; node is inserted using &lt;span style="font-weight:bold;"&gt;sb-c::insert-cast-before&lt;/span&gt; (also ir1util.lisp). The whole assertion process is illustrated on  Figure 3.8 (the destination node type is assumed to be &lt;span style="font-weight:bold;"&gt;cif&lt;/span&gt;, and the elements names are in accordance with the three above procedures' local variables names):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TByZmJoS8KI/AAAAAAAAAJ4/q_1z1QVCteo/s1600/F3_8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TByZmJoS8KI/AAAAAAAAAJ4/q_1z1QVCteo/s400/F3_8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5484427326929432738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Let us explain this figure a bit. First of all, we use dashed lines to show the old connections, which were present before the variable type assertion. As one can see, the things were simple. The variable just transfers its value to the node. After &lt;span style="font-weight:bold;"&gt;cast&lt;/span&gt; node insertion, the data flow is the next: the variable value goes to that &lt;span style="font-weight:bold;"&gt;cast&lt;/span&gt; node, and then (after the value type is validated during the runtime code execution) it gets transferred to 'internal-lvar', which finally delivers it to 'dest' node. Regarding the control flow, the compiler inserts &lt;span style="font-weight:bold;"&gt;cast&lt;/span&gt; node just before 'dest' node, by redirecting the control flow after &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; which was pointing to 'dest' node initially. In order to pass the control flow from &lt;span style="font-weight:bold;"&gt;cast&lt;/span&gt; node to 'dest' node, the dummy &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; 'internal-ctran' is created and inserted into the code flow graph appropriately.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-2268289125567698131?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/2268289125567698131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-3-local-calls-analysis_19.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2268289125567698131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2268289125567698131'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-3-local-calls-analysis_19.html' title='[Book] Chapter 3 Local Calls Analysis [part 2]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/TByVqNYu5oI/AAAAAAAAAJg/jdYWqPYdDLE/s72-c/F3_5.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-2994889359013378256</id><published>2010-06-12T01:43:00.000-07:00</published><updated>2010-06-12T02:13:49.509-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='inline'/><title type='text'>[Book] Chapter 3 Local Calls Analysis [part 1]</title><content type='html'>In this chapter we are going to discuss the code from 'src/compiler/locall.lisp' file. As the readers know, Chapter 2 was dedicated to &lt;span style="font-weight:bold;"&gt;sb-c::make-functional-from-toplevel-lambda&lt;/span&gt; and to IR1 translation which was started by this function. Then, we meet &lt;span style="font-weight:bold;"&gt;sb-c::locall-analyze-clambdas-until-done&lt;/span&gt; function in the body of &lt;span style="font-weight:bold;"&gt;sb-c::%compile&lt;/span&gt;. This is a point where the next IR1 phase, local calls analysis and inlining, comes into play.&lt;br /&gt;&lt;br /&gt; The analysis itself begins with a call into  &lt;span style="font-weight:bold;"&gt;sb-c::locall-analyze-clambdas-until-done&lt;/span&gt;. This simple function is the first place where we meet the widely-used SBCL's (and other compilers use it too) approach to the optimization – it may be expressed as “do something until you are sure that there is nothing to do”. The function maintains 'did-something' local variable, and the analysis process runs iteratively until the variable value is not &lt;span style="font-weight:bold;"&gt;nil&lt;/span&gt;.  &lt;br /&gt;&lt;br /&gt; Each individual iteration is a call into &lt;span style="font-weight:bold;"&gt;sb-c::locall-analyse-component&lt;/span&gt;. This function can do the following:&lt;br /&gt;&lt;br /&gt;- just return in case there is no appropriate functional for the analysis in the component;&lt;br /&gt;&lt;br /&gt;- delete the functional in case it seems to be not used;&lt;br /&gt;&lt;br /&gt;- push the functional into the component's lambdas list and delegate the analysis to &lt;span style="font-weight:bold;"&gt;sb-c::locall-analyze-fun-1&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;- analyse &lt;span style="font-weight:bold;"&gt;clambdas&lt;/span&gt; using &lt;span style="font-weight:bold;"&gt;sb-c::maybe-let-convert&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt; The first branch of the analysis is shown here:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TBNKlA0KGZI/AAAAAAAAAJA/xOq4rpwDXMY/s1600/F3_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 283px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TBNKlA0KGZI/AAAAAAAAAJA/xOq4rpwDXMY/s400/F3_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5481807171174406546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; This function iterates over the functional reference nodes, and does the next steps during each iteration:&lt;br /&gt;&lt;br /&gt;- fetches 'lvar' slot value from the reference node;&lt;br /&gt;&lt;br /&gt;- fetches a destination node for the &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; instance;&lt;br /&gt;&lt;br /&gt;- checks that the connections between 'ref', 'dest' and 'lvar' are established as shown on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/TBNLEQY_KvI/AAAAAAAAAJI/dFOhf2a7nT4/s1600/F3_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 394px; height: 241px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/TBNLEQY_KvI/AAAAAAAAAJI/dFOhf2a7nT4/s400/F3_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5481807707931355890" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; In case they are, an attempt to convert the call will be made, using &lt;span style="font-weight:bold;"&gt;sb-c::convert-call-if-possible&lt;/span&gt;. How should we understand the figure itself? 'Lvar' receives the value from 'ref' node, and this value is nothing but the function object we are going to call. &lt;br /&gt;&lt;br /&gt; When these relations are different, and the combination kind is not :local, the reference node is passed to &lt;span style="font-weight:bold;"&gt;sb-c::reference-entry-point&lt;/span&gt;. Local calls are noted with &lt;span style="font-weight:bold;"&gt;sb-c::note-local-functional&lt;/span&gt; (the result is their names removal from &lt;span style="font-weight:bold;"&gt;*free-funs*&lt;/span&gt; hash table, when these names exist and they are known to be unresolved before the call).&lt;br /&gt;&lt;br /&gt; Function &lt;span style="font-weight:bold;"&gt;sb-c::reference-entry-point&lt;/span&gt; calls &lt;span style="font-weight:bold;"&gt;sb-c::change-ref-leaf&lt;/span&gt; after a few checks on the input argument. The latter function is worth to be put here for some discussion:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TBNMIu5gcWI/AAAAAAAAAJQ/2JKPCmfSSgQ/s1600/F3_3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 234px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TBNMIu5gcWI/AAAAAAAAAJQ/2JKPCmfSSgQ/s400/F3_3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5481808884351922530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; So, let us see what do we have here. First of all, the reference node is added to the leaf's references list. The surprise comes with the second step, when the reference node is removed from the flow graph using &lt;span style="font-weight:bold;"&gt;sb-c::delete-ref&lt;/span&gt;. This deletion, however, does not mean the instance destruction, as one may think at the first sight. It deals mostly with the related cleanups in the flow graph (the particular steps depend on the reference type. This deletion also may schedule the future flow graph reanalysis, by calling &lt;span style="font-weight:bold;"&gt;sb-c::reoptimize-component&lt;/span&gt;). The next step is the node type derivation, which can be completed directly within &lt;span style="font-weight:bold;"&gt;sb-c::change-ref-leaf&lt;/span&gt;, or by calling &lt;span style="font-weight:bold;"&gt;sb-c::derive-node-type&lt;/span&gt; ('src/compiler/ir1opt.lisp'). Finally, &lt;span style="font-weight:bold;"&gt;sb-c::reoptimize-lvar&lt;/span&gt; prepares the future reanalysis of the stuff which is connected with the reference node target variable.&lt;br /&gt;&lt;br /&gt; Function &lt;span style="font-weight:bold;"&gt;sb-c::convert-call-if-possible&lt;/span&gt; performs a lot of checks to make sure that it is permissible to proceed with the call conversion. The most interesting part of the function is here:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TBNMzjpE06I/AAAAAAAAAJY/-ApA2OHZEGI/s1600/F3_4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 392px; height: 242px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TBNMzjpE06I/AAAAAAAAAJY/-ApA2OHZEGI/s400/F3_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5481809620064588706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; There we can see the strange approach to 'entry-fun' slot contents in 'functional' structure. As the comment there (node.lisp) says, it may contain both external entry point (XEP) for the function, or the function itself. So we spend the additional time in &lt;span style="font-weight:bold;"&gt;let&lt;/span&gt; to find out the original function for sure.&lt;br /&gt;&lt;br /&gt; Function &lt;span style="font-weight:bold;"&gt;sb-c::maybe-expand-local-inline&lt;/span&gt; (locall.lisp) is quite long to show it here, but it is important to understand what it does. The function attempts to handle the calls to the functions whose 'kind' slot contains :inline. It begins with checking the compilation policies, because inlining is reasonable only when users are interested in the code speed more than in the code size. Then it performs IR1 conversion of the functional inline expansion. When the functional cannot be inlined, the tag &lt;span style="font-weight:bold;"&gt;locall-already-let-converted&lt;/span&gt; will be thrown, and the original functional will be returned. In case of success, &lt;span style="font-weight:bold;"&gt;sb-c::change-ref-leaf&lt;/span&gt; is used to finish with the expansion, and the result of the expansion conversion is returned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-2994889359013378256?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/2994889359013378256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-3-local-calls-analysis.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2994889359013378256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2994889359013378256'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-3-local-calls-analysis.html' title='[Book] Chapter 3 Local Calls Analysis [part 1]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/TBNKlA0KGZI/AAAAAAAAAJA/xOq4rpwDXMY/s72-c/F3_1.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-953420933293679269</id><published>2010-06-06T10:17:00.000-07:00</published><updated>2010-06-06T10:38:59.225-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.5 Custom IR1 Translators [part 3]</title><content type='html'>Translation of &lt;span style="font-weight:bold;"&gt;%primitive&lt;/span&gt; form requires some preliminary explanations. First of all, what is &lt;span style="font-weight:bold;"&gt;%primitive&lt;/span&gt;? We haven't meet this construction so far. So, &lt;span style="font-weight:bold;"&gt;%primitive&lt;/span&gt; designates a 'simple enough' operation which is known by IR2 backend and whose name is stored in &lt;span style="font-weight:bold;"&gt;sb-c::*backend-template-names*&lt;/span&gt; hash table  ('src/compiler/backend.lisp') as a key. More precisely, 'simple enough' should be read as Virtual Operation (VOP) here. At this time, when we are talking about IR1 phases, it is enough to know that VOP is an abstraction of an elementary operation in the compiler backend. All Lisp forms are eventually represented using VOPs in Python, and VOPs are then translated to machine codes. The virtual operations itself are defined by &lt;span style="font-weight:bold;"&gt;sb-c::define-vop&lt;/span&gt; macro from 'src/compiler/meta-vmdef.lisp' source file.&lt;br /&gt;&lt;br /&gt; Processing of &lt;span style="font-weight:bold;"&gt;%primitive&lt;/span&gt; in IR1 translator is simple: a VOP template is fetched for the given VOP name, and the input arguments amount is verified to match that template. After a few more checks, &lt;span style="font-weight:bold;"&gt;%primitive&lt;/span&gt; gets translated into &lt;span style="font-weight:bold;"&gt;%%primitive&lt;/span&gt;. The latter is handled during IR2 phases.&lt;br /&gt;&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Flet&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;labels&lt;/span&gt; translators share some common functionality, for example, they both use &lt;span style="font-weight:bold;"&gt;sb-int::parse-body&lt;/span&gt; function to deal with the input definition's body. Let us see &lt;span style="font-weight:bold;"&gt;flet&lt;/span&gt; IR1 converter first: &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAvad0-bKHI/AAAAAAAAAIg/wpP4c-mCvR4/s1600/F2_5_12.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 163px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAvad0-bKHI/AAAAAAAAAIg/wpP4c-mCvR4/s400/F2_5_12.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5479713577597872242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; It may be considered to be pretty simple. Notice the usage of &lt;span style="font-weight:bold;"&gt;sb-c::extract-flet-vars&lt;/span&gt; for the local functions definitions analysis (this function is also used in &lt;span style="font-weight:bold;"&gt;labels&lt;/span&gt; converter), the current lexical environment modification (so the defined functions are lexically visible in the inner code), and &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-fbindings&lt;/span&gt; call, which is used to finish with &lt;span style="font-weight:bold;"&gt;flet&lt;/span&gt; translation. Since the last function is present in &lt;span style="font-weight:bold;"&gt;labels&lt;/span&gt; converter as well, let us look at it closer:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/TAva9PEZW8I/AAAAAAAAAIo/Skrist6WTEE/s1600/F2_5_13.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 231px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/TAva9PEZW8I/AAAAAAAAAIo/Skrist6WTEE/s400/F2_5_13.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5479714117178186690" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; It has two branches, and the more interesting and complicated one is connected with the dynamic extent of the defined functions. The next figure helps to understand the conversion process:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAvbYGkXuRI/AAAAAAAAAIw/qVs73vjb1t4/s1600/F2_5_14.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 352px; height: 400px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAvbYGkXuRI/AAAAAAAAAIw/qVs73vjb1t4/s400/F2_5_14.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5479714578752846098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; As one can see, the figure is a typical pattern of the conversions which involve cleanups (for example, compare it with the figure for &lt;span style="font-weight:bold;"&gt;tagbody&lt;/span&gt;). The full meaning of &lt;span style="font-weight:bold;"&gt;%%allocate-closures&lt;/span&gt; form will be clear for us during IR2 phases discussion (note that there is also &lt;span style="font-weight:bold;"&gt;%%allocate-closures&lt;/span&gt; IR1 converter, but it uses &lt;span style="font-weight:bold;"&gt;%allocate-closures&lt;/span&gt; – with a single percent prefix – to express the conversion semantics). &lt;br /&gt;&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Labels&lt;/span&gt; IR1 converter differs from &lt;span style="font-weight:bold;"&gt;flet&lt;/span&gt; due to 'placeholder functions' usage. They reflect the difference between these two approaches to the definition of local functions – when one uses &lt;span style="font-weight:bold;"&gt;labels&lt;/span&gt;, it is permissible to reference the local function within its own body. So, the conversion of local functions in &lt;span style="font-weight:bold;"&gt;labels&lt;/span&gt; goes in two phases -  during the first one they are processed with 'dummy functionals' present in the lexical environment, and during the second one the references to these dummies are substituted with the references to the real local functionals. Please refer to the converter code to see this smart solution in more details.&lt;br /&gt;&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Setq&lt;/span&gt; IR1 converter delegates the main part of the process to &lt;span style="font-weight:bold;"&gt;sb-c::setq-var&lt;/span&gt; function. Before calling it, the converter performs a lot of checks and verifications regarding the destination and the source. Function  &lt;span style="font-weight:bold;"&gt;sb-c::setq-var&lt;/span&gt; is simple and small – the only specific thing it does is the generation of &lt;span style="font-weight:bold;"&gt;set node&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt; The last IR1 converter which we will discuss in this chapter is the one for &lt;span style="font-weight:bold;"&gt;multiple-value-call&lt;/span&gt;. Its code is given below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAvccW4KkZI/AAAAAAAAAI4/lA-lynuulDQ/s1600/F2_5_15.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 209px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAvccW4KkZI/AAAAAAAAAI4/lA-lynuulDQ/s400/F2_5_15.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5479715751361941906" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; We assume our readers to be quite familiar with typical IR1 converters at this time, so we do not give a figure here. Among the important things, please note 'combination/mv-combination' nodes creation, and function's arguments processing in the loop. Obviously, the call itself (we may consider the function's node to represent the 'actual call') occurs after the evaluation of the arguments, as one can guess from the converter code.&lt;br /&gt;&lt;br /&gt; It is interesting to see that our initial example, &lt;span style="font-weight:bold;"&gt;(defun f (x) (* x 3))&lt;/span&gt;, also uses &lt;span style="font-weight:bold;"&gt;combination&lt;/span&gt; nodes. To check this, just put the breakpoint in &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-combination&lt;/span&gt;. You will see not only the multiplication conversion, but some internal forms (like &lt;span style="font-weight:bold;"&gt;%verify-arg-count&lt;/span&gt;) processing as well. &lt;br /&gt;&lt;br /&gt; We consider Chapter 2 to be finished at this point. Author hopes that the readers have some general view of IR1 translators and the raw Lisp forms processing during IR1 phases now. Some special cases, like &lt;span style="font-weight:bold;"&gt;macrolet&lt;/span&gt; conversion, are not covered in this draft of the book, but the key information about early IR1 phases is present.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-953420933293679269?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/953420933293679269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-25-custom-ir1-translators.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/953420933293679269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/953420933293679269'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/06/book-chapter-25-custom-ir1-translators.html' title='[Book] Chapter 2.5 Custom IR1 Translators [part 3]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/TAvad0-bKHI/AAAAAAAAAIg/wpP4c-mCvR4/s72-c/F2_5_12.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3098275892602722263</id><published>2010-05-30T03:20:00.000-07:00</published><updated>2010-05-30T03:37:44.188-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.5 Custom IR1 Translators [part 2]</title><content type='html'>The special operator &lt;span style="font-weight:bold;"&gt;tagbody&lt;/span&gt; is handled by this translator:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAI8UqyRlLI/AAAAAAAAAHY/VmUtk_U2PaA/s1600/F2_5_7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 377px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAI8UqyRlLI/AAAAAAAAAHY/VmUtk_U2PaA/s400/F2_5_7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5477006422616151218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; The translator uses a supplementary function to analyze the body, &lt;span style="font-weight:bold;"&gt;sb-c::parse-tagbody&lt;/span&gt; (from the same source file). For the IR1 conversion, it performs the next steps:&lt;br /&gt;&lt;br /&gt;- allocates a dummy control transfer, a new entry and a new cleanup node;&lt;br /&gt;- collects a tag and its control transfer for all tags in the body;&lt;br /&gt;- converts all segments using &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-progn-body&lt;/span&gt;, and links 'result' &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; with the last segment's return value. Notice the tricky starts/ctrans collection: 'starts' has the dummy control transfer as the first list element, and 'ctrans' has 'next' control transfer as the last list element. This allows to have the elegant solution with &lt;span style="font-weight:bold;"&gt;mapc&lt;/span&gt; later, when control flow goes through all tags and reaches 'next' &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; eventually.&lt;br /&gt;&lt;br /&gt; The conversion result is shown on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAI91OkkEHI/AAAAAAAAAHg/vrqwL115rN4/s1600/F2_5_8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAI91OkkEHI/AAAAAAAAAHg/vrqwL115rN4/s400/F2_5_8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5477008081489760370" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; The translator uses the value of the last segment as a result, so we show it separately with 'last-tag' control transfer.&lt;br /&gt;&lt;br /&gt; Another IR1 translator which is tightly coupled with the above is the one for &lt;span style="font-weight:bold;"&gt;go&lt;/span&gt; special operator. Its code is here:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAI-OWyzWmI/AAAAAAAAAHo/Kzcr1ZnUEuo/s1600/F2_5_9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 151px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/TAI-OWyzWmI/AAAAAAAAAHo/Kzcr1ZnUEuo/s400/F2_5_9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5477008513193695842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; As one can see, it is pretty simple. The translator searches for the tag to go in the current lexical environment, where the tag has been stored by &lt;span style="font-weight:bold;"&gt;tagbody&lt;/span&gt; converter. Then the code flow will be start → exit → tag-ctran. Notice that 'result' &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; is not touched at all. We do not give the explanatory figure here, due to the trivial nature of the conversion.&lt;br /&gt;&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Let&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;let*&lt;/span&gt; converters delegate most of their work to other functions. They both use &lt;span style="font-weight:bold;"&gt;sb-c::extract-let-vars&lt;/span&gt; to extract the essential information about the declared variables. After that, the familiar to us functions &lt;span style="font-weight:bold;"&gt;parse-body, processing-decls, ir1-convert-lambda-body, ir1-convert-aux-bindings&lt;/span&gt; and some others do the rest of the conversion. The main idea of both these conversions is that they are performed in the modified 'post-binding-lexenv' lexical environment.&lt;br /&gt;&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Catch, throw&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;unwind-protect&lt;/span&gt; share some similar principles of the conversion. They are implemented as wrappers over their body code, and use internal forms &lt;span style="font-weight:bold;"&gt;%within-cleanup, %catch, %throw&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;%unwind-protect&lt;/span&gt; to express the conversion in more low-level terms.&lt;br /&gt;&lt;br /&gt; Let us look at &lt;span style="font-weight:bold;"&gt;%within-cleanup&lt;/span&gt; IR1 converter closer. Here is its code:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAI_HgpVfHI/AAAAAAAAAHw/K08AMhoD5ig/s1600/F2_5_10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 174px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAI_HgpVfHI/AAAAAAAAAHw/K08AMhoD5ig/s400/F2_5_10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5477009495090887794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The things which happen during the conversion are illustrated on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAI_W7XAvqI/AAAAAAAAAH4/VZ3F2pmcjOI/s1600/F2_5_11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 314px; height: 400px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/TAI_W7XAvqI/AAAAAAAAAH4/VZ3F2pmcjOI/s400/F2_5_11.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5477009759959826082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Some manipulations with lexical environments and cleanups are not shown here, you can read about them in the source code comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3098275892602722263?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3098275892602722263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-25-custom-ir1-translators_30.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3098275892602722263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3098275892602722263'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-25-custom-ir1-translators_30.html' title='[Book] Chapter 2.5 Custom IR1 Translators [part 2]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/TAI8UqyRlLI/AAAAAAAAAHY/VmUtk_U2PaA/s72-c/F2_5_7.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-8806846148670404987</id><published>2010-05-23T05:05:00.000-07:00</published><updated>2010-05-23T05:53:02.545-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.5 Custom IR1 Translators [part 1]</title><content type='html'>There are several Lisp operators which require special processing during their translation to IR1. In order to handle them, SBCL developers introduced custom IR1 translators. The advantage of this approach is that we can use &lt;span style="font-weight:bold;"&gt;sb-c::def-ir1-translator&lt;/span&gt; macro to register our own handler, without any static dispatches we have seen earlier in this chapter.&lt;br /&gt;&lt;br /&gt; What does this macro do? From the sources in 'src/compiler/macros.lisp' we can say the following: it defines a function named &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-NNN&lt;/span&gt;, where 'NNN' is the Lisp operator name one wants to convert using the custom translator. This function is registered as :ir1-convert &lt;span style="font-weight:bold;"&gt;info&lt;/span&gt; value for the Lisp operator, so  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-functoid&lt;/span&gt; can fetch it and do the call. 'Info' functionality in SBCL is a wrapper over a hash table and it allows to store some data which corresponds to the key. It may happen that we will discuss 'info' in the appendix A.&lt;br /&gt;&lt;br /&gt; The defined converter works using the same input arguments as his static friends (the start &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt;, the next &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; and the result &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt;). The only difference is that it can have a full lambda list as the first argument. For example, let us look at this translator:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S_kbo1kpCrI/AAAAAAAAAGo/cubE7mNo0Ws/s1600/F2_5_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 398px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S_kbo1kpCrI/AAAAAAAAAGo/cubE7mNo0Ws/s400/F2_5_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5474437210435029682" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Upon a call it will do the next things:&lt;br /&gt;&lt;br /&gt;- allocation of the three control transfers and the three blocks to represent the condition and two execution branches;&lt;br /&gt;&lt;br /&gt;- allocation of the appropriate &lt;span style="font-weight:bold;"&gt;cif&lt;/span&gt; node;&lt;br /&gt;&lt;br /&gt;- conversion and insertion of the condition testing code after the 'start' control transfer;&lt;br /&gt;&lt;br /&gt;- linking together predicate, consequent and alternative &lt;span style="font-weight:bold;"&gt;cblocks&lt;/span&gt; (because in general case execution may go in any of the two branches);&lt;br /&gt;&lt;br /&gt;- conversion and insertion of 'then' forms after 'then-ctran' control transfer;&lt;br /&gt;&lt;br /&gt;- conversion and insertion of 'else' forms after 'else-ctran' control transfer.&lt;br /&gt;&lt;br /&gt;Here is the figure which shows the result of &lt;span style="font-weight:bold;"&gt;if&lt;/span&gt; conversion:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S_kc8F6IX1I/AAAAAAAAAGw/hWCftlZsTik/s1600/F2_5_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 270px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S_kc8F6IX1I/AAAAAAAAAGw/hWCftlZsTik/s400/F2_5_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5474438640749272914" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; This figure requires some additional explanations. First of all, we use green arrows to show the control flow, and orange arrows to show the data flow. Why do we need such abstractions? Just because there are &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt; calls inside the converter body. These calls transform 'test', 'then' and 'else' Lisp expressions to some sequences of the blocks. In general we cannot say how to represent these sequences, so we substitute them with 'control flow' concept, and their results assignments with 'data flow' concept. As usual, we show only the slots which are relevant to the figure context. Some structures, like 'start', are shown without any slots at all.&lt;br /&gt;&lt;br /&gt; To debug this converter, one should enter the next code in REPL:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;(trace :encapsulate nil sb-c::ir1-convert-if :break t)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; Notice that :encapsulate keyword is required due to the dynamic nature of the call. The author received this valuable advice from the anonymous reader of this book draft.&lt;br /&gt;&lt;br /&gt; There are thirty three custom IR1 translators in SBCL (for version 1.0.38). The author cannot cover them all in this book, so let us look only at the 'interesting for him' ones. They are: &lt;span style="font-weight:bold;"&gt;block&lt;/span&gt; (do not confuse it with &lt;span style="font-weight:bold;"&gt;cblock&lt;/span&gt; data structure), &lt;span style="font-weight:bold;"&gt;retrun-from, tagbody, go, let, let*, flet, labels, setq, throw, catch, unwind-protect, multiple-value-call&lt;/span&gt;. We also will cover some internal forms translators, like &lt;span style="font-weight:bold;"&gt;%primitive&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Notice that almost all IR1 translators are defined in 'src/compiler/ir1-translators.lisp'.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Block&lt;/span&gt; translator is shown on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S_kep3KheiI/AAAAAAAAAG4/R1RCTnLJsWI/s1600/F2_5_3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 211px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S_kep3KheiI/AAAAAAAAAG4/R1RCTnLJsWI/s400/F2_5_3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5474440526577105442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The conversion result is illustrated on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/S_kfPgH9wmI/AAAAAAAAAHA/yWQ8rk6prkA/s1600/F2_5_4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 368px; height: 400px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/S_kfPgH9wmI/AAAAAAAAAHA/yWQ8rk6prkA/s400/F2_5_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5474441173227389538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; First of all, we have introduced the new symbol “+” on this figure. It means that the marked slot holds a list of values, and the object which is pointed by the arrow is added to that list.&lt;br /&gt;&lt;br /&gt; About the &lt;span style="font-weight:bold;"&gt;block&lt;/span&gt; conversion in general, we should say that it involves the new &lt;span style="font-weight:bold;"&gt;entry&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;cleanup&lt;/span&gt; nodes creation. The &lt;span style="font-weight:bold;"&gt;entry&lt;/span&gt; allows us to exit the block using &lt;span style="font-weight:bold;"&gt;return-from&lt;/span&gt;, and the &lt;span style="font-weight:bold;"&gt;cleanup&lt;/span&gt; handles the exit-related stuff. The dummy control transfer is needed to connect 'entry' node with the in-block code during IR1 conversion in &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-progn-body&lt;/span&gt;. You probably know that &lt;span style="font-weight:bold;"&gt;defun&lt;/span&gt; macro wraps the function form into the &lt;span style="font-weight:bold;"&gt;block&lt;/span&gt; whose name is the function's name, and we always can use &lt;span style="font-weight:bold;"&gt;return-from&lt;/span&gt; inside the function.&lt;br /&gt;&lt;br /&gt;Since we have touched &lt;span style="font-weight:bold;"&gt;return-from&lt;/span&gt; a bit, let us discuss its IR1 converter as well. Here it is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S_kg8k2g5GI/AAAAAAAAAHI/0CnPnml6q5U/s1600/F2_5_5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 219px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S_kg8k2g5GI/AAAAAAAAAHI/0CnPnml6q5U/s400/F2_5_5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5474443047102112866" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The conversion process is illustrated by this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S_khYzvjutI/AAAAAAAAAHQ/zDm_nafnHeY/s1600/F2_5_6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 334px; height: 400px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S_khYzvjutI/AAAAAAAAAHQ/zDm_nafnHeY/s400/F2_5_6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5474443532135807698" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; We use “?” symbol to show that the block relationships cannot be determined. This is because 'exit-ctran' is not likely to be :unused at this point, and the results of a call into &lt;span style="font-weight:bold;"&gt;sb-c::%use-ctran&lt;/span&gt; are not known (it has several branches).&lt;br /&gt;&lt;br /&gt; Although the idea of &lt;span style="font-weight:bold;"&gt;return-from&lt;/span&gt; conversion is simple, we should explain its connections with &lt;span style="font-weight:bold;"&gt;block&lt;/span&gt; conversion. They can be seen when one analyses the result of &lt;span style="font-weight:bold;"&gt;sb-c::lexenv-find&lt;/span&gt; macro in the &lt;span style="font-weight:bold;"&gt;return-from&lt;/span&gt; converter. This result is the list passed to &lt;span style="font-weight:bold;"&gt;sb-c::make-lexenv&lt;/span&gt; in &lt;span style="font-weight:bold;"&gt;block&lt;/span&gt; converter (after :blocks keyword). This list contains a cons cell with the block name as a symbol, and the value of 'env-entry' variable, defined as a list of 'entry' &lt;span style="font-weight:bold;"&gt;node&lt;/span&gt;, 'next' &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; and 'result' &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt;. These three are extracted and used in the &lt;span style="font-weight:bold;"&gt;return-from&lt;/span&gt; converter. Such approach makes it possible to jump out of the code block, by passing the control outside of the block, and by substituting the block's evaluation result with the one evaluated in &lt;span style="font-weight:bold;"&gt;return-from&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-8806846148670404987?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/8806846148670404987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-25-custom-ir1-translators.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/8806846148670404987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/8806846148670404987'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-25-custom-ir1-translators.html' title='[Book] Chapter 2.5 Custom IR1 Translators [part 1]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/S_kbo1kpCrI/AAAAAAAAAGo/cubE7mNo0Ws/s72-c/F2_5_1.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3320181262173404116</id><published>2010-05-19T10:22:00.000-07:00</published><updated>2010-05-19T10:40:53.188-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='question'/><title type='text'>[Question] Is sb-c::ir1-convert-if redundant?</title><content type='html'>Well, I have found that my last post contains a mistake. In fact, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-functoid&lt;/span&gt; does not call any IR1 converters dynamically. To check this, just trace &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-if&lt;/span&gt; (defined by &lt;span style="font-weight:bold;"&gt;sb-c::def-ir1-translator&lt;/span&gt; macro) when compiling&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(defun f (x) (if (= x 2) (+ x 1) (+ x 2)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and you will see that it is never called.&lt;br /&gt;&lt;br /&gt;I have tried several code snippets, but the result is the same.&lt;br /&gt;&lt;br /&gt;So, I will probably continue Chapter 2 till the very end of the functional creation. &lt;br /&gt;&lt;br /&gt;But can somebody tell me why the code defined by &lt;span style="font-weight:bold;"&gt;sb-c::def-ir1-translator&lt;/span&gt; seems to be not used at all? Should I try some special example to see it invoked?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3320181262173404116?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3320181262173404116/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/question-is-sb-cir1-convert-if.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3320181262173404116'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3320181262173404116'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/question-is-sb-cir1-convert-if.html' title='[Question] Is sb-c::ir1-convert-if redundant?'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-5629772037670794147</id><published>2010-05-16T01:50:00.000-07:00</published><updated>2010-05-16T02:16:01.731-07:00</updated><title type='text'>[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 4]</title><content type='html'>In  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-special-bindings&lt;/span&gt; the translated Lisp form can go in two branches, depending on the presence of special variables in that form. When talking about our simple example, &lt;span style="font-weight:bold;"&gt;(defun f (x) (* x 3))&lt;/span&gt;, it goes directly to &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-aux-bindings&lt;/span&gt;. The second branch adds the cleanup code for these variables. Function  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-special-bindings&lt;/span&gt; is called four times during the example compilation,  since &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt; implicitly uses  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda-body&lt;/span&gt;, and the recursion occurs. Frankly speaking, recursive nature of IR1 translation code makes the compiler frontend smaller, but inconvenient for analysis and explanation – just because we need to track a lot of recursion levels.&lt;br /&gt;&lt;br /&gt; Then, in  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-aux-bindings&lt;/span&gt; our example code initially goes directly to &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-progn-body&lt;/span&gt; ('src/compiler/ir1tran.lisp'). At this point we should stop and look at the process in a more detailed way. &lt;br /&gt;&lt;br /&gt; This function receives 'start' and 'next' &lt;span style="font-weight:bold;"&gt;ctrans&lt;/span&gt;, 'result' &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt; and the body – the list of Lisp forms which should be converted. The last form evaluation value will be connected with 'result', and all Lisp forms IR1 translations will be inserted between 'start' and 'next' control transfers.&lt;br /&gt; When the forms list is empty, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-progn-body&lt;/span&gt; assumes these “non-existing” forms evaluation result to be &lt;span style="font-weight:bold;"&gt;nil&lt;/span&gt;, and calls &lt;span style="font-weight:bold;"&gt;sb-c::reference-constant&lt;/span&gt; to put the constant reference into the code flow graph. &lt;br /&gt;&lt;br /&gt; Usually the forms list contains one or more expressions, and they are processed in a loop. In general case each form passes two stages: the instrumentation for code coverage (more precisely, for the certain debugger commands) in &lt;span style="font-weight:bold;"&gt;sb-c::maybe-instrument-progn-like&lt;/span&gt;, and further conversion in &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt;. Let us postpone the instrumentation discussion, and focus on the conversion.&lt;br /&gt;&lt;br /&gt; All of the processed in the loop forms receive a new &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; instance, and then they are passed to  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt; along with that instance.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S--ztyLI_zI/AAAAAAAAAGQ/zPvjc7JcU-Y/s1600/F2_4_10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 243px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S--ztyLI_zI/AAAAAAAAAGQ/zPvjc7JcU-Y/s400/F2_4_10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5471789671422426930" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; As the comment says, this conversion ignores all but the last expression value. This is why all but the last Lisp forms are passed to  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt; with the third (it corresponds to 'result' &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt;) argument set to &lt;span style="font-weight:bold;"&gt;nil&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt; Variable 'this-start' is needed in order to carry the last control transfer instance between the loop iterations.&lt;br /&gt;&lt;br /&gt; Function &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt; is used not only in the above code, but in many custom IR1 translators (they are the subject of Chapter 3). Here it is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/S--0a4Pq--I/AAAAAAAAAGY/iviMmDtwnN0/s1600/F2_4_11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 286px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/S--0a4Pq--I/AAAAAAAAAGY/iviMmDtwnN0/s400/F2_4_11.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5471790446146157538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Function &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt; is widely used, because it acts like the universal dispatcher – that is, it can convert any valid Lisp expression. The actual job gets delegated to one of the four specialized converters. &lt;br /&gt;&lt;br /&gt; The first, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-var&lt;/span&gt;, deals with variables (including alien) and symbol macros. It is easy to understand, because it is comparatively small. The more interesting case is &lt;span style="font-weight:bold;"&gt;sb-c::reference-leaf&lt;/span&gt;, which consists of two parts: the first finds a leaf instance, and the second inserts a reference to it into the flow graph.&lt;br /&gt;&lt;br /&gt; We will skip the search code, but focus on the actual insertion instead. The appropriate  &lt;span style="font-weight:bold;"&gt;sb-c::reference-leaf&lt;/span&gt; sources fragment is shown on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S--1p2pHKzI/AAAAAAAAAGg/2DqN9IvsX_E/s1600/F2_4_12.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 172px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S--1p2pHKzI/AAAAAAAAAGg/2DqN9IvsX_E/s400/F2_4_12.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5471791802925656882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; First of all, a new &lt;span style="font-weight:bold;"&gt;ref&lt;/span&gt; node instance for the given leaf is created. This node is pushed to 'refs' slot of the leaf, and it is marked to be a “used leaf”. The node is inserted after 'start' control transfer by &lt;span style="font-weight:bold;"&gt;sb-c::link-node-to-previous-ctran&lt;/span&gt;. Then, the special type cast node may be inserted to coerce the result. That's all we should know about a leaf processing at this time.&lt;br /&gt;&lt;br /&gt; It should be said that &lt;span style="font-weight:bold;"&gt;sb-c::reference-constant&lt;/span&gt; works in the same way as the simpler (without the type cast) case of  &lt;span style="font-weight:bold;"&gt;sb-c::reference-leaf&lt;/span&gt;. So we will discuss the last of the four specialized converters, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-functoid&lt;/span&gt;. As one may guess from the name, it accepts everything which looks like a function call and which does not fit in previous cases. This converter can act in two ways: call (dynamically, through &lt;span style="font-weight:bold;"&gt;funcall&lt;/span&gt;) a particular IR1 translator in case it is defined for the Lisp form, or delegate the job to &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-common-functoid&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt; The latter function is a dispatcher as well. It uses &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-global-functoid&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-local-combination&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-srctran&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-combination&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt;. The additional thing to say is that all these eventually use &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert&lt;/span&gt;, so the true recursive mess occurs. At this point we should consider our analysis of IR1 conversion code flow to be finished. The translation process will vary significantly depending on the input form, and it is not very helpful to track our simple example through it.&lt;br /&gt;&lt;br /&gt; As a conclusion for this chapter, we should express the main idea of IR1 conversion: the transformation of Lisp forms into individual nodes in the code flow graph. Notice that nodes are inserted linearly, without any flow analysis. It will take place during the next IR1 phases. &lt;br /&gt; &lt;br /&gt; However, our analysis of IR1 conversion elements is continued in the next chapter, where we will look at custom IR1 translators, which were mentioned in &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-functoid&lt;/span&gt; description. They are quite important and interesting, so we hope that we can cross our simple example boundaries to study them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-5629772037670794147?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/5629772037670794147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1_16.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5629772037670794147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5629772037670794147'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1_16.html' title='[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 4]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/S--ztyLI_zI/AAAAAAAAAGQ/zPvjc7JcU-Y/s72-c/F2_4_10.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-694399179400053401</id><published>2010-05-12T00:07:00.000-07:00</published><updated>2010-05-12T00:11:25.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='note'/><title type='text'>[Announcement] Updates schedule</title><content type='html'>In order to make the reviewing process to be more convenient, I will put new chapters to this blog once per week - on Sunday.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-694399179400053401?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/694399179400053401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/announcement-updates-schedule.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/694399179400053401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/694399179400053401'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/announcement-updates-schedule.html' title='[Announcement] Updates schedule'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3584916385909680250</id><published>2010-05-09T03:37:00.000-07:00</published><updated>2010-05-09T05:26:22.755-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 3]</title><content type='html'>Finally, &lt;span style="font-weight:bold;"&gt;sb-c::process-decls&lt;/span&gt; returns control back to &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt;. The latter determines whether optimization policies allow wrapping the input forms into the debug catch (by default this does not happen), and also specifies the forms' return value type explicitly by wrapping them into special operator '&lt;span style="font-weight:bold;"&gt;the&lt;/span&gt;' – only when it is different from the default (or 'wild') type. &lt;br /&gt;&lt;br /&gt; In  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt; further form conversion can go in two branches. The first is a call into &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-hairy-lambda&lt;/span&gt;. It happens in case the lambda has the arguments list with optional or keywords arguments. The simpler lambdas are handled by &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda-body&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt; Since we are going to follow the easier case, let us say a few words about the complex first. It creates &lt;span style="font-weight:bold;"&gt;optional-dispatch&lt;/span&gt; structure instance to represent the optional arguments, and adds it to 'new-functionals' slot of &lt;span style="font-weight:bold;"&gt;*current-component*&lt;/span&gt;. Actual arguments conversion occurs in &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-hairy-args&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt; So, in &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda-body&lt;/span&gt; our Lisp form is going to be converted into &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; structure. This is a long function, but anyway we will dig into it now, because it makes a lot of important steps towards IR1 representation of the input form.&lt;br /&gt;&lt;br /&gt; First of all, &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda-body&lt;/span&gt; creates four structures instances: &lt;span style="font-weight:bold;"&gt;bind&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;lvar&lt;/span&gt;. The first represents input arguments bindings, the second is the resulting IR1 functional which will be returned, the third represents the control transfer to the 'result' node, and the last is the variable which will hold this lambda expression result after the body evaluation. &lt;br /&gt;&lt;br /&gt; Then 'home' slot of &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; instance is set to itself. It also becomes a home lambda for all input arguments' &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structures. In case the variable is special, the corresponding &lt;span style="font-weight:bold;"&gt;global-var&lt;/span&gt; structure will be added to the &lt;span style="font-weight:bold;"&gt;bind&lt;/span&gt; node lexical environment. Otherwise, the original &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; instance will be used, as you can see on this code fragment:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S-aSF6yRzpI/AAAAAAAAAFg/DRUf4IWCaio/s1600/F2_4_4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 164px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S-aSF6yRzpI/AAAAAAAAAFg/DRUf4IWCaio/s400/F2_4_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5469219427865185938" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; This tiny code snippet is all you need to recollect when your friends ask you how do special variables work in Common Lisp :)&lt;br /&gt; The next part of the function creates the lexical environment which will be effective across the input lambda body, and establishes relationships between it, &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;bind&lt;/span&gt; structures instances:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S-aSfZfzCKI/AAAAAAAAAFo/t3v53nFl6LM/s1600/F2_4_5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 331px; height: 79px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S-aSfZfzCKI/AAAAAAAAAFo/t3v53nFl6LM/s400/F2_4_5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5469219865605900450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;At this point we have the next connections between the main data structures:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S-aS5ykO8EI/AAAAAAAAAFw/Yu10PkvZRtI/s1600/F2_4_6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 218px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S-aS5ykO8EI/AAAAAAAAAFw/Yu10PkvZRtI/s400/F2_4_6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5469220319011991618" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What begins after that is a bit complex. So let us explain this code line by line:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S-aTJOfDg6I/AAAAAAAAAF4/esT-lyL1SwE/s1600/F2_4_7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 113px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S-aTJOfDg6I/AAAAAAAAAF4/esT-lyL1SwE/s400/F2_4_7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5469220584204501922" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; The interesting and widely used function &lt;span style="font-weight:bold;"&gt;sb-c::ctran-starts-block&lt;/span&gt; ('src/compiler/ir1util.lisp') returns a &lt;span style="font-weight:bold;"&gt;cblock&lt;/span&gt; structure instance for the given &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt;. The block is started by that &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt;. Namely, the next steps are performed to create the block:&lt;br /&gt;&lt;br /&gt;- check that 'block' slot of &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; instance is empty;&lt;br /&gt;&lt;br /&gt;- a new &lt;span style="font-weight:bold;"&gt;cblock&lt;/span&gt; instance is created and &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; is stored in it's 'start' slot;&lt;br /&gt;&lt;br /&gt;- next and previous blocks for the new block in the code flow graph are determined as the last current component's block and its predecessor, respectively;&lt;br /&gt;&lt;br /&gt;- references between these three blocks and &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; are set;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; is asserted to be not used, and the new block is returned.&lt;br /&gt;&lt;br /&gt; The graphical representation of the result is shown on this figure (old connections between the last and the last but one blocks in the component are shown using dashed lines):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/S-aWS5aPZzI/AAAAAAAAAGA/1iDP0xFNgqw/s1600/F2_4_8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 254px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/S-aWS5aPZzI/AAAAAAAAAGA/1iDP0xFNgqw/s400/F2_4_8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5469224048880740146" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; As one can see, the new block is inserted before the last block in the component, and prev/next slots for all three blocks are updated accordingly.&lt;br /&gt;&lt;br /&gt; In case &lt;span style="font-weight:bold;"&gt;ctran&lt;/span&gt; already starts some block, &lt;span style="font-weight:bold;"&gt;sb-c::ctran-starts-block&lt;/span&gt; simply returns that block.&lt;br /&gt;&lt;br /&gt; But let us go back to the code snippet from  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda-body&lt;/span&gt;. The next thing it does is &lt;span style="font-weight:bold;"&gt;cretrun&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;tail-set&lt;/span&gt; instances creation (both from nodes.lisp file). These two are linked with &lt;span style="font-weight:bold;"&gt;clambda&lt;/span&gt; structure instance appropriate slots. Then the destination of 'return-lvar' variable is set to 'return' node. After that, a tiny function &lt;span style="font-weight:bold;"&gt;sb-c::link-node-to-previous-ctran&lt;/span&gt; from 'src/compiler/ir1tran.lisp' is called to connect the return node with 'result-ctran' control transfer. Finally, 'return' node becomes the last node in our new code block, and this code block is linked with the current component's tail block by &lt;span style="font-weight:bold;"&gt;sb-c::link-blocks&lt;/span&gt; ('src/compiler/ir1util.lisp').&lt;br /&gt;&lt;br /&gt; The final part of &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda-body&lt;/span&gt; which we should analyse is the next:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S-aXJi0OVuI/AAAAAAAAAGI/rnfZ9p4lL8U/s1600/F2_4_9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 168px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S-aXJi0OVuI/AAAAAAAAAGI/rnfZ9p4lL8U/s400/F2_4_9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5469224987708511970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; First of all, the macro &lt;span style="font-weight:bold;"&gt;sb-c::with-component-last-block&lt;/span&gt; ('src/compiler/macros.lisp') wraps all those expressions and executes them inside &lt;span style="font-weight:bold;"&gt;unwind-protect&lt;/span&gt;, to guarantee that the component state will be consistent upon exiting it. This macro also sets the component's last block to the given one temporarily, as you may guess from both its code and its name:)&lt;br /&gt;&lt;br /&gt; What happens inside is quite familiar. Two new &lt;span style="font-weight:bold;"&gt;ctrans&lt;/span&gt; are created, and linked with 'bind' node. A new thing is &lt;span style="font-weight:bold;"&gt;sb-c::use-ctran&lt;/span&gt; from 'src/compiler/ir1tran.lisp'. It is easy and left as an exercise for readers. Function &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-special-bindings&lt;/span&gt; continues the conversion process, and we will look into it below. The last two lines make 'bind' block to be the first block in the component's code flow graph, and push the resulting functional into a list from 'new-functionals' slot of the component.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3584916385909680250?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3584916385909680250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1_09.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3584916385909680250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3584916385909680250'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1_09.html' title='[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 3]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/S-aSF6yRzpI/AAAAAAAAAFg/DRUf4IWCaio/s72-c/F2_4_4.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-5397381075682793176</id><published>2010-05-05T12:33:00.000-07:00</published><updated>2010-06-16T23:30:33.937-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='declare'/><title type='text'>[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 2]</title><content type='html'>We will select type declarations, as the most important in this book context. They are handled by &lt;span style="font-weight:bold;"&gt;sb-c::process-type-decl&lt;/span&gt; function from 'src/compiler/ir1tran.lisp'. &lt;br /&gt;&lt;br /&gt; Assume that we are compiling a form like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(defun h(x) (declare (fixnum x)) (* x 3))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; Then  &lt;span style="font-weight:bold;"&gt;sb-c::process-type-decl&lt;/span&gt; will receive the next arguments:&lt;br /&gt;&lt;br /&gt;- the type declaration form: (fixnum x);&lt;br /&gt;- the instance of &lt;span style="font-weight:bold;"&gt;lexenv&lt;/span&gt; structure;&lt;br /&gt;- the one-element list with &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structure, which corresponds to 'x' variable;&lt;br /&gt;- the declaration context processing keyword, :compile.&lt;br /&gt;&lt;br /&gt; Here we should stop and explain what is &lt;span style="font-weight:bold;"&gt;lexenv&lt;/span&gt; structure. We didn't touch it in chapter 2.3, because it is not defined in 'src/compiler/node.lisp' – we should open 'src/compiler/lexenv.lisp' instead. This structure contains all information about a lexical environment in which a Lisp form is being converted into IR1. By default this argument contains a value of &lt;span style="font-weight:bold;"&gt;*lexenv*&lt;/span&gt; global variable, which was bound in &lt;span style="font-weight:bold;"&gt;sb-c::make-functional-from-toplevel-lambda&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt; So,  &lt;span style="font-weight:bold;"&gt;sb-c::process-type-decl&lt;/span&gt; begins with obtaining a type structure for the given type specifier. Then it iterates over the declared variables names list, calling &lt;span style="font-weight:bold;"&gt;sb-impl::program-assert-symbol-home-package-unlocked&lt;/span&gt; on each name. You probably know that SBCL has COMMON-LISP package locked by default, and all modifications attempts for symbols in that package are checked using that function. This is why the crazy code like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(defun ff() (declare (fixnum *standard-output*)) ())&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;will signal the error:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Compile-time error:&lt;br /&gt;  Lock on package COMMON-LISP violated when declaring the type of *STANDARD-OUTPUT*.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; When modifications are allowed, a variable name is matched with the appropriate &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structure using &lt;span style="font-weight:bold;"&gt;sb-c::find-in-bindings&lt;/span&gt; function first. In our case this gives the result, because we have declared 'x' as a lambda argument. The alternative ways to find something which is connected with a variable name are &lt;span style="font-weight:bold;"&gt;sb-c::lexenv-find&lt;/span&gt; macro ('src/compiler/macros.lisp') and &lt;span style="font-weight:bold;"&gt;sb-c::find-free-var&lt;/span&gt; function. As one can guess, after the failed lookup in the lambda arguments list, Python tries to find a variable in the lexical environment, and, as the last resort, the global scope is checked.&lt;br /&gt;&lt;br /&gt; We have said 'something', because the last two kinds of search are not obligated to return &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structure. It may be also a foreign (alien) variable, as well as a symbol-macro. &lt;br /&gt;&lt;br /&gt; Anyway, in our example we got a valid &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structure, and its further processing is connected with the detection of the suitable type. We cannot always use the proposed type, because a variable may be already typed. So Python derives the final type using &lt;span style="font-weight:bold;"&gt;sb-kernel::type-approx-intersection2&lt;/span&gt; ('src/code/late-type.lisp').&lt;br /&gt;&lt;br /&gt; Finally, 'type' slot of &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structure for our 'x' argument will contain fixnum type, which is printed as # &amp;lt;SB-KERNEL:NUMERIC-TYPE FIXNUM&amp;gt; by Lisp printer. That's all about type declarations handling for lambda arguments. For variables from the lexical environment, or unbound variables, the processing of the type declarations involves the lexical environment update instead of setting the variable type in &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structure.&lt;br /&gt;&lt;br /&gt; To finish with declarations, we should say a few words about other kinds of them. Special declarations are handled by &lt;span style="font-weight:bold;"&gt;sb-c::process-special-decl&lt;/span&gt;. Its job is to ensure that a variable is not ignored or declared locally special, as well as that a variable is not a symbol-macro. Finally, 'specvar' slot of &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; structure will be set to an instance of the appropriate &lt;span style="font-weight:bold;"&gt;global-var&lt;/span&gt; structure, returned by &lt;span style="font-weight:bold;"&gt;sb-c::specvar-for-binding&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt; Functional types declarations are processed in &lt;span style="font-weight:bold;"&gt;sb-c::process-ftype-decl&lt;/span&gt;. The things here go similarly to the types processing, what is even stated in the function comment, so we leave this case analysis as an exercise for readers, as well as the below cases:)&lt;br /&gt;&lt;br /&gt; Handling of 'inline/notinline/maybe-inline' happens in &lt;span style="font-weight:bold;"&gt;sb-c::process-inline-decl&lt;/span&gt;. These declarations affect 'inlinep' slot of the current IR1 functional, or a member of its lexical environment – depending on the local/global nature of the declaration.&lt;br /&gt;&lt;br /&gt; Then, 'ignore/ignorable' case goes to &lt;span style="font-weight:bold;"&gt;sb-c::process-ignore-decl&lt;/span&gt;. We do not stop here at all, that is easy.&lt;br /&gt;&lt;br /&gt; Declarations about optimization policies are handled by &lt;span style="font-weight:bold;"&gt;sb-c::process-optimize-decl&lt;/span&gt;. This function's return value is used to update '%policy' slot in the current &lt;span style="font-weight:bold;"&gt;lexenv&lt;/span&gt; structure (strictly speaking, a new instance is created, but it includes the old lexical environment as a source of default values).&lt;br /&gt;&lt;br /&gt; Declarations 'muffle-conditions/unmuffle-conditions' also affect the lexical environment. They allow to suppress or to enable compiler's diagnostic messages.&lt;br /&gt;&lt;br /&gt;'Values' declaration affects 'result-type' variable, which was discussed above. That is, this declaration specifies a return type of the lambda.  &lt;br /&gt;&lt;br /&gt; Declarations 'disable-package-locks/enable-package-locks' are connected with changes in 'disabled-package-locks' slot of the current lexical environment's structure instance.&lt;br /&gt; &lt;br /&gt; Declarations about dynamic extent belong to a special topics list. We will return to them in the appropriate chapter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-5397381075682793176?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/5397381075682793176/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1_05.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5397381075682793176'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/5397381075682793176'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1_05.html' title='[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 2]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-9139851322756704601</id><published>2010-05-03T12:18:00.000-07:00</published><updated>2011-01-20T10:28:38.193-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 1]</title><content type='html'>Now, when we are a bit familiar with IR1 data structures, let us go ahead and see the actual transform mechanism which converts a Lisp form into IR1 functional. It begins with a call to &lt;span style="font-weight:bold;"&gt;sb-c::make-functional-from-toplevel-lamdba&lt;/span&gt; in 'src/compiler/main.lisp'. This function binds &lt;span style="font-weight:bold;"&gt;*current-component*&lt;/span&gt; variable to a new empty component, modifies the component kind to be :initial, and calls &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambdalike&lt;/span&gt; to obtain the functional entry function. The functional structure as a whole is returned by &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt; later. That functional is considered to be :external, and both the functional entry and the functional itself are assumed to have external references. The result of these actions is the initial (unoptimized) IR1 functional.&lt;br /&gt;&lt;br /&gt; After this high-level overview let us dig into the process deeper. First of all, what is the empty component? In 'src/compiler/ir1util.lisp' you can find &lt;span style="font-weight:bold;"&gt;sb-c::make-empty-component&lt;/span&gt; function. It does the following:&lt;br /&gt;&lt;br /&gt;- creates two empty blocks called 'head' and 'tail';&lt;br /&gt;&lt;br /&gt;- creates a new component whose entry and exit points are the above blocks, 'head' is the entry block and 'tail' is the exit block;&lt;br /&gt;&lt;br /&gt;- sets up references between the component and blocks;&lt;br /&gt;&lt;br /&gt;- sets up references between blocks.&lt;br /&gt;&lt;br /&gt;The resulting empty component is shown on the figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98j0k39urI/AAAAAAAAAE4/LXdS9SZxSmU/s1600/F2_4_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 387px; height: 400px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98j0k39urI/AAAAAAAAAE4/LXdS9SZxSmU/s400/F2_4_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467127858809649842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; On the figure arrows begin at the structure which owns a slot, and point at the slot value. Slot names are separated by horizontal lines. 'Res', 'Tail' and 'Head' are variables names from  &lt;span style="font-weight:bold;"&gt;sb-c::make-empty-component&lt;/span&gt; function. Structures names are just below them. We show only the slots which are relevant in a figure context, and we will use this approach to illustrations through the whole book.&lt;br /&gt;&lt;br /&gt; As one can see, the empty component consists of three structures and may be considered to be simple. Control flow inside this component goes from 'head' block to 'tail' block. Since they are not associated with any nodes, nothing is going to happen in the component scope during its future execution. &lt;br /&gt;&lt;br /&gt; Function  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambdalike&lt;/span&gt; performs different steps to convert the input expression, depending on a kind of the input lambda. We are mostly interested in discussing the &lt;span style="font-weight:bold;"&gt;named-lambda&lt;/span&gt; case, because all functions compilations go through this branch. When talking about the example from previous chapters, there will be two calls of this function. The first handles the toplevel lambda:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98lBH6Tt2I/AAAAAAAAAFA/VhYfEvD1GPY/s1600/T1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 121px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98lBH6Tt2I/AAAAAAAAAFA/VhYfEvD1GPY/s400/T1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467129173884778338" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;and the second handles the named lambda:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98lcNACcmI/AAAAAAAAAFI/WJA5CGxwahc/s1600/T2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 249px; height: 79px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98lcNACcmI/AAAAAAAAAFI/WJA5CGxwahc/s400/T2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467129639107457634" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Pure &lt;span style="font-weight:bold;"&gt;lambda&lt;/span&gt; case goes directly to &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt;. With &lt;span style="font-weight:bold;"&gt;named-lambda&lt;/span&gt; things get a bit complicated:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/S98mLEwZCcI/AAAAAAAAAFQ/jlXKPvAkMo0/s1600/F2_4_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 226px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/S98mLEwZCcI/AAAAAAAAAFQ/jlXKPvAkMo0/s400/F2_4_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467130444348197314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; First of all, the presence of a lambda name is checked, and the lambda expression is obtained. In case the name is valid, IR1 functional for the lambda will be received from &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt;. Lambdas with missing or invalid names are converted in the  alternative condition branch.&lt;br /&gt;&lt;br /&gt; Before the call into  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt;, another call to &lt;span style="font-weight:bold;"&gt;sb-c::get-defined-fun&lt;/span&gt; occurs. This function is located in the same file, 'src/compiler/ir1tran-lambda.lisp'. Its job is to check whether there is an entry for the given name in &lt;span style="font-weight:bold;"&gt;*free-funs*&lt;/span&gt; hash, and to create &lt;span style="font-weight:bold;"&gt;defined-fun&lt;/span&gt; structure instance for the named lambda being compiled. This instance will hold IR1 functional from  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt; in 'functionals' slot. There may be several functionals corresponding to the single defined function, and this slot holds them in a list. &lt;br /&gt;&lt;br /&gt; The most interesting part of the Lisp forms transformation into IR1 begins in  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt;. This function starts with verifying an input lambda expression structure and decomposes it on three parts: forms, declarations (decls) and documentation (doc). Also, all lambda form arguments declarations are converted into IR1 representation by passing them to &lt;span style="font-weight:bold;"&gt;sb-c::make-lambda-vars&lt;/span&gt;. We will analyze this process now, since the results are used in the subsequent calls.&lt;br /&gt;&lt;br /&gt; So,  &lt;span style="font-weight:bold;"&gt;sb-c::make-lambda-vars&lt;/span&gt; begins with the classification of the input variables declarations, by delegating this task to &lt;span style="font-weight:bold;"&gt;sb-c::parse-lambda-list&lt;/span&gt; function from 'src/compiler/parse-lambda-list.lisp'. The latter file is a small one (210 lines in SBCL 1.0.38), and the principles of the parsing are pretty straightforward – &lt;span style="font-weight:bold;"&gt;sb-c::parse-lambda-list-like-thing&lt;/span&gt; acts like a tiny finite state machine (FSM), by iterating over the supplied lambda arguments list and checking their order (more precisely, keywords order) to be right, along with collecting required information about them. Finally, multiple values (twelve! But this is not a limit – I have seen a function returning twenty three values in one Lisp project) are returned to  &lt;span style="font-weight:bold;"&gt;sb-c::make-lambda-vars&lt;/span&gt;. The latter handles all kinds of the lambda vars, with one common step – a call into &lt;span style="font-weight:bold;"&gt;sb-c::varify-lambda-args&lt;/span&gt; to obtain a new &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; IR1 structure. Then, depending on the kind of an lambda argument (&amp;rest, &amp;optional etc.), 'info' slot of this structure will contain the appropriate &lt;span style="font-weight:bold;"&gt;arg-info&lt;/span&gt; structure instance. Upon exiting from  &lt;span style="font-weight:bold;"&gt;sb-c::make-lambda-vars&lt;/span&gt; we do not have arguments declarations – we have a list whose elements are coupled IR1 structures &lt;span style="font-weight:bold;"&gt;lambda-var&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;arg-info&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98oaWZjrcI/AAAAAAAAAFY/_hkNmf5eApY/s1600/F2_4_3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 118px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98oaWZjrcI/AAAAAAAAAFY/_hkNmf5eApY/s400/F2_4_3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467132905805557186" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; After this short overview of the lambda parameters conversion, let us return to  &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambda&lt;/span&gt;. The next step it performs is connected with declarations analysis – namely, with the second part of the input lambda decomposition. This job goes to &lt;span style="font-weight:bold;"&gt;sb-c::process-decls&lt;/span&gt; ('src/compiler/ir1tran.lisp'). &lt;br /&gt;&lt;br /&gt; Declarations are the source of type-related information for a Lisp form (not only about types, but compiler is mostly interested in explicit types knowledge – it makes code optimizations easier).  In order to handle function return type declarations, &lt;span style="font-weight:bold;"&gt;sb-c::process-decls&lt;/span&gt; maintains 'result-type' local variable, and updates it upon every declaration analysis by calling &lt;span style="font-weight:bold;"&gt;sb-kernel::values-type-intersection&lt;/span&gt; to narrow the result type. Individual declarations are processed in &lt;span style="font-weight:bold;"&gt;sb-c::process-1-decl&lt;/span&gt;. This function dispatches all declarations to more specific handlers, like &lt;span style="font-weight:bold;"&gt;sb-c::process-inline-decl&lt;/span&gt;. Looking into this code is a fast way to learn about all types of declarations in Common Lisp:)&lt;br /&gt;&lt;br /&gt; Let us follow the processing of a single declaration till the very end, just to see how they are handled. We also will benefit from the fact that there are common steps in the declarations analysis.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-9139851322756704601?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/9139851322756704601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/9139851322756704601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/9139851322756704601'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-24-from-lisp-forms-to-ir1.html' title='[Book] Chapter 2.4 From Lisp Forms to IR1 Functionals [part 1]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/S98j0k39urI/AAAAAAAAAE4/LXdS9SZxSmU/s72-c/F2_4_1.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-2729861733154908610</id><published>2010-05-03T11:21:00.000-07:00</published><updated>2010-05-03T12:11:56.492-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.3 Primary IR1 Data Structures</title><content type='html'>Every code flow representation in a compiler frontend is some kind of a hierarchy, and IR1 is not an exception. This kind of relationships appears due to the same structure of an input construction, for example, a function in general case contains expressions, and expressions usually have operands – and when we build the simplest model, we may create a data structure called 'function', with a slot named 'expressions' and so on. In SBCL we see a bit complicated variant of this approach, because the industrial CL compiler should use a lot of supplementary data in order to perform code optimizations in the excellent way it does these days.&lt;br /&gt;&lt;br /&gt; During this chapter we will discuss 'src/compiler/node.lisp' file,  where almost all Python internal data structures are defined. We recommend you to read it carefully  before going forward – otherwise it may be hard to understand this chapter and the entire IR1 phase as well. There are many useful comments.&lt;br /&gt;&lt;br /&gt; For a single structure, we copy its sources without included comments to this chapter. Comments about the slots are present in the original file, and we will not repeat them. Our current goal is to learn about structures relationships and purposes, not about the individual slots.&lt;br /&gt; The first one we should look at is 'functional' structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98VMspNDMI/AAAAAAAAAC4/V7mIH6u9FWc/s1600/F2_8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 247px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98VMspNDMI/AAAAAAAAAC4/V7mIH6u9FWc/s400/F2_8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467111780537666754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You probably have noticed that this structure includes another one – 'leaf', here it is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98VsUirmXI/AAAAAAAAADA/QP94RgA96q0/s1600/F2_9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 187px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98VsUirmXI/AAAAAAAAADA/QP94RgA96q0/s400/F2_9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467112323823671666" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Just to stop that chain of includes, we should explain what is 'sset-element' structure. This one allows a structure which includes it to be an element of a sparse set (defined in 'src/compiler/sset.lisp'). More info on this is not required in this chapter, so let us return to the two above structures.&lt;br /&gt;&lt;br /&gt; 'Functional' is a basic element of a Lisp form representation in IR1 as a whole, because it is extended by other data structures which add more information about toplevel forms (and finally 'clambda' structure incorporates all info about a Lisp form).&lt;br /&gt;&lt;br /&gt; 'Leafs' are code flow graph elements which are not connected with the actual code flow (they have no output paths, and can be only referenced by non-leaf elements. Namely, there is a special 'ref' structure for this purpose). However, in SBCL this concept is not so straightforward, because data structures like 'optional-dispatch' may extend 'leaf' and contain code flow graph elements (through references) at the same time. This situation probably can be explained when we take into account that a code unit may be a 'leaf' in the first code flow graph (for example, as a call to the function), and to be the actual second code flow graph itself (which represents that called function definition).  &lt;br /&gt;&lt;br /&gt; 'Component' seems to be the most important data structure in Python. Many compilation stages are operating on components, not functionals. This structure is shown below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98Wz2qwSnI/AAAAAAAAADI/3Tf3iuYEAsQ/s1600/F2_10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 273px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98Wz2qwSnI/AAAAAAAAADI/3Tf3iuYEAsQ/s400/F2_10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467113552755051122" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Components have code blocks as their entry and exit points (you may consider these to be a component boundaries in a code flow graph). A code block ('cblock') data structure is shown below:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98XSeyGQRI/AAAAAAAAADQ/Gt_06tYZt4I/s1600/F2_11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 332px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98XSeyGQRI/AAAAAAAAADQ/Gt_06tYZt4I/s400/F2_11.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467114078919344402" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Code blocks consist of individual nodes (what we have called 'expressions' in the introduction to this chapter, however, this is not a complete analogy), which are defined by 'node' structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98Xx04V89I/AAAAAAAAADY/ZJA3xmdLIeI/s1600/F2_12.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 139px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98Xx04V89I/AAAAAAAAADY/ZJA3xmdLIeI/s400/F2_12.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467114617427063762" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Nodes which produce a value are represented by 'valued-node' structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98YIEjy3GI/AAAAAAAAADg/9nN8ww1ZyrU/s1600/F2_3_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 303px; height: 89px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98YIEjy3GI/AAAAAAAAADg/9nN8ww1ZyrU/s400/F2_3_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467114999592967266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Nodes which reference leafs are instances of 'ref' structure. Notice that it is derived from 'valued-node' as well:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98YbcT7X9I/AAAAAAAAADo/HQ41HWfab5o/s1600/F2_3_5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 116px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98YbcT7X9I/AAAAAAAAADo/HQ41HWfab5o/s400/F2_3_5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467115332386381778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Combinations (function calls) are represented by special nodes – 'basic-combination', 'combination', 'mv-combination'. The last two do not add any new slots, so we will only show the parent structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98YsZtLmkI/AAAAAAAAADw/hfNGttKvF54/s1600/F2_3_6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 393px; height: 131px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98YsZtLmkI/AAAAAAAAADw/hfNGttKvF54/s400/F2_3_6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467115623744772674" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Type check operations in IR1 involve 'cast' nodes:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98a2a2JgLI/AAAAAAAAAEY/2zNWYnn4gV4/s1600/F2_3_8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 336px; height: 86px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98a2a2JgLI/AAAAAAAAAEY/2zNWYnn4gV4/s400/F2_3_8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467117994872766642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Control transfers inside a code block (between nodes) are represented using 'ctran' structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98ZkyCHHFI/AAAAAAAAAD4/c8FbOo7-yug/s1600/F2_13.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 87px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98ZkyCHHFI/AAAAAAAAAD4/c8FbOo7-yug/s400/F2_13.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467116592347683922" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Data transfers between nodes use 'lvar' structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98Z1yjoeCI/AAAAAAAAAEA/vsYqolVNn9E/s1600/F2_14.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 390px; height: 143px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98Z1yjoeCI/AAAAAAAAAEA/vsYqolVNn9E/s400/F2_14.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467116884546058274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Lambdas with optional arguments involve 'optional-dispatch' structure to handle them in IR1:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98aOGha92I/AAAAAAAAAEI/ngwNVRUxQ8c/s1600/F2_3_3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 372px; height: 129px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S98aOGha92I/AAAAAAAAAEI/ngwNVRUxQ8c/s400/F2_3_3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467117302222354274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Arguments itself are represented by 'lambda-var' structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98afMFveiI/AAAAAAAAAEQ/9epz7zFZ3mI/s1600/F2_3_4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 132px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98afMFveiI/AAAAAAAAAEQ/9epz7zFZ3mI/s400/F2_3_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467117595774646818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Finally, there is a 'clambda' structure, the thing which corresponds to the entire Lisp form in IR1:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98bHQ96TGI/AAAAAAAAAEg/5zpzWOJXEi4/s1600/F2_3_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 263px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98bHQ96TGI/AAAAAAAAAEg/5zpzWOJXEi4/s400/F2_3_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467118284278746210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Return values of a lambda are handled using 'creturn' structure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98bZvi-PpI/AAAAAAAAAEo/rCSZWMM8tUE/s1600/F2_3_7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 330px; height: 118px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S98bZvi-PpI/AAAAAAAAAEo/rCSZWMM8tUE/s400/F2_3_7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467118601724903058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Structures which are related to non-local exits, and some IR1 structures which extend the primary structures by adding a few slots are out of this chapter scope. We will talk about them in the appropriate chapters, where they are likely to be met.&lt;br /&gt; Finally, this figure may help you to grasp the nodes/blocks/components relationships in a code flow graph. Flow direction is shown using arrows:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98b91VQVCI/AAAAAAAAAEw/APT_qCWYO3w/s1600/Fflow.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 331px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S98b91VQVCI/AAAAAAAAAEw/APT_qCWYO3w/s400/Fflow.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5467119221753271330" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-2729861733154908610?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/2729861733154908610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-23-primary-ir1-data.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2729861733154908610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/2729861733154908610'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/05/book-chapter-23-primary-ir1-data.html' title='[Book] Chapter 2.3 Primary IR1 Data Structures'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_Q48gJ59wg6o/S98VMspNDMI/AAAAAAAAAC4/V7mIH6u9FWc/s72-c/F2_8.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-9095176062755024134</id><published>2010-04-27T13:23:00.000-07:00</published><updated>2010-04-27T13:48:25.553-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='note'/><title type='text'>[Announcement] SBCL Users &amp; Developers Group in Linkedin</title><content type='html'>I am not sure whether it is a really good idea, as well as that I am a right person to do that when there are many mature SBCL developers around (who are probably better candidates to own such a group), but anyway I have created 'SBCL Users &amp; Developers' group in Linkedin. Its goals are:&lt;br /&gt;&lt;br /&gt;- to see how many people use SBCL&lt;br /&gt;- to gather some statistics about OS families/CPU architectures where SBCL is popular&lt;br /&gt;- to discuss CS domains where Lisp and especially SBCL are useful these days&lt;br /&gt;- other questions which are connected with gathering some SBCL-related statistics.&lt;br /&gt;&lt;br /&gt;This group is open for everyone. Feel free to join it:)&lt;br /&gt;&lt;br /&gt;Also, please note that this group is not a place to report bugs, to ask about SBCL internals or some particulars etc. Please use mailing lists to do that, as you have been doing up to the present.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-9095176062755024134?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/9095176062755024134/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/announcement-sbcl-users-developers.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/9095176062755024134'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/9095176062755024134'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/announcement-sbcl-users-developers.html' title='[Announcement] SBCL Users &amp; Developers Group in Linkedin'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3263904283634126475</id><published>2010-04-26T12:32:00.000-07:00</published><updated>2010-04-26T12:51:48.052-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='note'/><title type='text'>[Announcement] Some delay of Chapter 2.3</title><content type='html'>In order to write Chapter 2.3 "IR1 Data Structures" and make it to be interesting for readers, I need to learn more about these structures usage during IR1 phase. So there will be a delay in a week or two before I start posting that chapter's parts. Thank you for reading the previous ones, your notes were helpful and I have corrected some mistakes in the book using them :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3263904283634126475?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3263904283634126475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/announcement-some-delay-of-chapter-23.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3263904283634126475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3263904283634126475'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/announcement-some-delay-of-chapter-23.html' title='[Announcement] Some delay of Chapter 2.3'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-1022802993866714870</id><published>2010-04-23T13:05:00.000-07:00</published><updated>2010-04-23T13:23:58.813-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.2 Why IR1?</title><content type='html'>In the next chapter we will explore IR1 data structures and relationships between them. It is necessary to have a clear vision of these, because Lisp forms transformations into IR1 are hard to understand without the appropriate knowledge about the target representation. But one may ask about the reason to have IR1 in Python, and we should explain this first.&lt;br /&gt;&lt;br /&gt; Let us start from the general questions. Why do we need IR1 at all? What is the problem with applying code optimization techniques and algorithms directly to Lisp forms? And what are the advantages of IR1 over the raw Lisp code?&lt;br /&gt;&lt;br /&gt; To answer these questions, we should recall that Common Lisp has simple syntax, but complex semantics. It means that its Abstract Syntax Tree (AST) contains a rich set of nodes which require a different kind of processing in the compiler. In case we want to apply code analysis algorithms directly to Lisp forms, we will need to carry a lot of rules to handle every individual node type, as well as these nodes combinations. So, passing the original Lisp code through a complete compiler frontend, with every stage being knowledgeable about the full Common Lisp semantics sounds to be a bad idea.&lt;br /&gt;&lt;br /&gt; What is the alternative? We definitely need to have some semantics reductions per node in order to keep our code transformations rules amount moderate. And the best way to simplify code transformations is connected with making the code representation less diverse. It means that we should select some set of primitives which is enough to satisfy the next goals:&lt;br /&gt;&lt;br /&gt;- primitives itself should be as simple as possible;&lt;br /&gt;&lt;br /&gt;- different primitives count should be as small as possible;&lt;br /&gt;&lt;br /&gt;- we can represent the initial language (source code) in terms of these primitives and  connections between them without any semantics loss.&lt;br /&gt;&lt;br /&gt; So far, so good. But how to select this minimal set of primitives and, what is the hardest thing, how to prove that the selected set satisfies the last, third principle? Primitives selection evolves naturally from the input language we are going to represent. For example, we definitely need something like 'code block', 'unconditional branch', 'conditional branch', 'variable', 'scope' etc. for almost any programming language representation. They may have another names, they may be implicit (represented by relationships, not data structures), but anyway they are fundamental elements.&lt;br /&gt;&lt;br /&gt; To prove that the selected primitives set is exactly enough for the language representation means to prove that there is a valid, semantics-preserving representation for any code one may write with that language. Since there is infinite number of ways to combine a language operands into what we call 'a program', there is no way to strictly prove that in general case (or I have missed something here? In case you know such practical verification methods, please correct my words). So, in real-life compilers this primitives set is a bit redundant. Just to match the input language for sure, without trying to reach the theoretically minimal primitives set (here I probably should say something about Turing machine, which is guaranteed to be a valid representation for any computational process, but I think that we should stay closer to daily practices than to the general theory). You probably know that there are a lot of bugs in Python (at least in version 1.0.37). Some of them are connected with IR1 inconsistencies. So, you may be sure that SBCL is a real-life compiler, with good but not ideal internal code representation selected :)&lt;br /&gt;&lt;br /&gt; After selecting the primitives set, we should think about relationships between them. One may guess that graphs are the most natural representation of a code flow. They are, due to their definition: code flow graph = primitives (nodes) + relationships (edges). Plus, graphs mining algorithms are established and well-known. So there is no need to reinvent the wheel, we may just apply a lot of proven techniques. &lt;br /&gt;&lt;br /&gt; To finish with the theoretical diving, let us say about drawbacks of the simpler representations. We live in the dialectical world, and every win brings some fail as well. In our case the fail is connected with the length of the equivalent IR1 representation – it is much longer than the Lisp code from which it was generated. Semantics is the same, but due to the simpler representation, it takes more elements involved. The obvious analogy is that decimal 256 has the same value (semantics) as binary 10000000, but due to the only two elements – 1 and 0 – used in the latter representation, it takes longer to reflect the same semantics. I am sure that your CS professor has already told you something similar, so I am sorry for such a falling into ABC of the information theory.&lt;br /&gt;&lt;br /&gt; After this short introduction, let us see the primitives and relationships which were selected to be a core of IR1 by its architects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-1022802993866714870?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/1022802993866714870/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-22-why-ir1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1022802993866714870'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1022802993866714870'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-22-why-ir1.html' title='[Book] Chapter 2.2 Why IR1?'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3639166844860154467</id><published>2010-04-21T11:28:00.000-07:00</published><updated>2011-03-30T10:37:52.537-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.1 What Happens With Lisp Forms Before IR1 Stage [part 3]</title><content type='html'>After the macroexpansion the input expression in  &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt; is classified by &lt;span style="font-weight:bold;"&gt;typecase&lt;/span&gt; macro. In our case the classification matches &lt;span style="font-weight:bold;"&gt;list&lt;/span&gt; clause, and the inner code of that clause performs further dispatch based on a first element of the list. This dispatch is interesting in all clauses, so let us analyze all of them.&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;function&lt;/span&gt; case matches, for example, the next input in REPL:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;(function (lambda (x) (+ x 1)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; This returns an instance of a built-in class &lt;span style="font-weight:bold;"&gt;FUNCTION&lt;/span&gt; which corresponds to the given function (as you can see from the example, the function may be  anonymous). The case code checks that you have passed exactly one argument, and it is a valid function name. In case it is, the operation is delegated to &lt;span style="font-weight:bold;"&gt;sb-impl::%coerce-name-to-fun&lt;/span&gt; (which is a simple getter for a function definition, see 'src/code/fdefinition.lisp' on this), in case it is not, for example when it is a lambda, the job gets done by &lt;span style="font-weight:bold;"&gt;sb-impl::%simple-eval&lt;/span&gt; (src/code/eval.lisp);&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;quote&lt;/span&gt; case checks that you have passed exactly one argument, and simply returns it (How simple is &lt;span style="font-weight:bold;"&gt;quote&lt;/span&gt; implementation in SBCL! Without any magic I was hoping to see...);&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;setq&lt;/span&gt; case first of all checks whether you have passed even amount of arguments or odd. When all is right with that, values are assigned to their destinations in a loop, using calls to &lt;span style="font-weight:bold;"&gt;set&lt;/span&gt; and recursive calls to  &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt; in order to evaluate the values which should be assigned;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;progn&lt;/span&gt; case passes control directly to &lt;span style="font-weight:bold;"&gt;sb-impl::simple-eval-progn-body&lt;/span&gt;, in the same source file. Note that it is our case (remember the f(x) macroexpansion?), so we are going to look into it below;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;eval-when&lt;/span&gt; at this point is respected only in case it includes :execute situation. Then the enclosing form is evaluated by  &lt;span style="font-weight:bold;"&gt;sb-impl::simple-eval-progn-body&lt;/span&gt;. Otherwise nil is returned;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;locally&lt;/span&gt; handles the special operator with the same name, by calling &lt;span style="font-weight:bold;"&gt;sb-impl::simple-eval-locally&lt;/span&gt;. In case you wonder about what that operator does, here is the citation from CLHS: “Sequentially evaluates a body of forms in a lexical environment where the given declarations have effect.” So &lt;span style="font-weight:bold;"&gt;sb-impl::simple-eval-locally&lt;/span&gt; does just like that – it mutates &lt;span style="font-weight:bold;"&gt;*lexenv*&lt;/span&gt; variable to match the given lexical environment value, handles given declarations using &lt;span style="font-weight:bold;"&gt;sb-c::process-decls&lt;/span&gt; and then calls &lt;span style="font-weight:bold;"&gt;sb-impl::simple-eval-progn-body&lt;/span&gt; with the lexical environment set to what was returned by &lt;span style="font-weight:bold;"&gt;sb-c::process-decls&lt;/span&gt; (I have no idea how to say this in a simpler way);&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;macrolet&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;symbol-macrolet&lt;/span&gt; require to much digging into Python in order to explain their handling. Let us skip them now, and return to this question when we will have more IR1 level knowledge;&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;if&lt;/span&gt; as a toplevel form is evaluated in place; the code for &lt;span style="font-weight:bold;"&gt;let&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;let*&lt;/span&gt; is also simple. All other list-like structures go to &lt;span style="font-weight:bold;"&gt;sb-impl::%simple-eval&lt;/span&gt; or &lt;span style="font-weight:bold;"&gt;sb-impl::eval-in-lexenv&lt;/span&gt;. These four cases are shown on the figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S89JQPxsVKI/AAAAAAAAACY/dzZJ2uOJmys/s1600/F2_5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 263px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S89JQPxsVKI/AAAAAAAAACY/dzZJ2uOJmys/s400/F2_5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5462665416485393570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note that &lt;span style="font-weight:bold;"&gt;sb-impl::eval-in-lexenv&lt;/span&gt; is a pure wrapper over &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt; when the Lisp evaluator mode is :compile (default, it may be set to :interpret by assigning that keyword to &lt;span style="font-weight:bold;"&gt;sb-ext::*evaluator-mode*&lt;/span&gt; variable):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_Q48gJ59wg6o/S89J6OBDpdI/AAAAAAAAACg/NLZb_TbXOgM/s1600/F2_6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 376px; height: 100px;" src="http://1.bp.blogspot.com/_Q48gJ59wg6o/S89J6OBDpdI/AAAAAAAAACg/NLZb_TbXOgM/s400/F2_6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5462666137567471058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As it was mentioned above, our function macroexpansion matches &lt;span style="font-weight:bold;"&gt;progn&lt;/span&gt; case first, and gets processed by  &lt;span style="font-weight:bold;"&gt;sb-impl::simple-eval-progn-body&lt;/span&gt;. The essential part of this routine is the next:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S89KZGJMBXI/AAAAAAAAACo/e5I3YktSLHw/s1600/F2_7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 83px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S89KZGJMBXI/AAAAAAAAACo/e5I3YktSLHw/s400/F2_7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5462666668030035314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One thing you should remember when looking at this code is that &lt;span style="font-weight:bold;"&gt;do*&lt;/span&gt; evaluates variables bindings sequentially, and &lt;span style="font-weight:bold;"&gt;rest&lt;/span&gt; does the same job as &lt;span style="font-weight:bold;"&gt;cdr&lt;/span&gt;. The idea of this processing is trivial: evaluate all &lt;span style="font-weight:bold;"&gt;progn&lt;/span&gt; subforms using  &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt; and return the result from the last one. &lt;br /&gt; So you have just seen how recursive nature of Lisp greatly simplifies the Lisp evaluator. In our case there will be many calls into &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt;. We can name at least some of them: the first deals with &lt;span style="font-weight:bold;"&gt;defun&lt;/span&gt; macroexpansion and matches &lt;span style="font-weight:bold;"&gt;progn&lt;/span&gt;, the second two handle &lt;span style="font-weight:bold;"&gt;eval-when&lt;/span&gt; forms, then time comes to handle &lt;span style="font-weight:bold;"&gt;sb-impl::%defun&lt;/span&gt; and its arguments... The main thing is not to track them all, but to understand the recursive flow of Lisp evaluation and to imagine its approximate call tree for a given form. &lt;br /&gt; Finally, the recursion ends up with the call to &lt;span style="font-weight:bold;"&gt;sb-impl::%simple-eval&lt;/span&gt; (src/code/eval.lisp), in our case the debugger shows it as&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S89LlTe71FI/AAAAAAAAACw/mpe6uUdW4BY/s1600/T3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 259px; height: 134px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S89LlTe71FI/AAAAAAAAACw/mpe6uUdW4BY/s400/T3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5462667977280967762" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; This function encloses the input expression into a lambda and passes it to &lt;span style="font-weight:bold;"&gt;sb-c::compile-in-lexenv&lt;/span&gt; (src/compiler/target-main.lisp). At this point we can state that Lisp forms arrived to Python compiler. After a few minor checks they pass to &lt;span style="font-weight:bold;"&gt;sb-c::actually-compile&lt;/span&gt; in the same source file. It binds a lot of compilation-related global variables (I am not sure that it is reasonable to explain all here, so let us introduce them in the actual usage order), and invokes &lt;span style="font-weight:bold;"&gt;sb-c::%compile&lt;/span&gt; function from  'src/compiler/main.lisp' file, passing the expression to compile along with several other arguments to it. &lt;br /&gt; We are very close to the beginning of IR1 stage now, but before moving further, we should talk a bit about this representation elements and structure. This topic is covered in the next chapter. Take a rest before reading it, and let the Lisp evaluator concept to find its place in your mind :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3639166844860154467?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3639166844860154467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-21-what-happens-with-lisp_21.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3639166844860154467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3639166844860154467'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-21-what-happens-with-lisp_21.html' title='[Book] Chapter 2.1 What Happens With Lisp Forms Before IR1 Stage [part 3]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Q48gJ59wg6o/S89JQPxsVKI/AAAAAAAAACY/dzZJ2uOJmys/s72-c/F2_5.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-1466739958397293953</id><published>2010-04-19T11:49:00.000-07:00</published><updated>2010-04-19T13:09:34.627-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.1 What Happens With Lisp Forms Before IR1 Stage [part 2]</title><content type='html'>Function  &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt; classifies the input form and handles it accordingly to the form's kind. First of all the input expression is passed through &lt;span style="font-weight:bold;"&gt;macroexpand&lt;/span&gt;, to get rid of any toplevel macros involved in the form. To figure out what is the result in case of our example function, enter this form in REPL (do not forget to remove the breakpoint which was set earlier – use &lt;span style="font-weight:bold;"&gt;untrace&lt;/span&gt; to do that):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(macroexpand '(defun f(x) (* x 3)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You will get the next result:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8ysIfdA3tI/AAAAAAAAABg/jvbR1DOEVd4/s1600/T1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 123px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8ysIfdA3tI/AAAAAAAAABg/jvbR1DOEVd4/s400/T1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5461929709975690962" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; Looks a bit complicated? Well, let us see what we have here. You probably know that &lt;span style="font-weight:bold;"&gt;eval-when&lt;/span&gt; is used to control the evaluation of the enclosed form depending on a set of situations - :compile-toplevel, :load-toplevel or :execute. There is a section in CLHS on this called 'Processing of Top Level Forms', and it is worth to look into it before moving forward with this chapter. In our case a call to  &lt;span style="font-weight:bold;"&gt;sb-c::%compiler-defun&lt;/span&gt; will happen during the form compilation time, and a call to &lt;span style="font-weight:bold;"&gt;sb-impl::%defun&lt;/span&gt; will be during the form loading time. These two forms are considered to be toplevel forms, since they are inside of the toplevel &lt;span style="font-weight:bold;"&gt;progn&lt;/span&gt;, so &lt;span style="font-weight:bold;"&gt;eval-when&lt;/span&gt; handles them accordingly.&lt;br /&gt; Function  &lt;span style="font-weight:bold;"&gt;sb-c::%compiler-defun&lt;/span&gt; from 'src/compiler/ir1tran-lambda.lisp' file registers the first argument (in our case the symbol 'F) to be a known function by calling  &lt;span style="font-weight:bold;"&gt;sb-c::become-defined-fun-name&lt;/span&gt; on that argument. It also performs two minor actions depending on the second and third arguments values, but we can move along without digging a much into it. Just remember that  &lt;span style="font-weight:bold;"&gt;sb-c::%compiler-defun&lt;/span&gt; notifies Python at the compilation time about our attempts to compile a function definition with the certain name.&lt;br /&gt; The next interesting thing in the macroexpansion is &lt;span style="font-weight:bold;"&gt;sb-impl::%defun&lt;/span&gt;. It does almost the same that &lt;span style="font-weight:bold;"&gt;sb-c::%compiler-defun&lt;/span&gt;, and even uses the latter to perform the necessary tasks (by setting third argument – compile-toplevel – to nil, notice that in the first (compile-time) call it was t). Namely, it registers the function name to be known:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/S8yny-rZGYI/AAAAAAAAABQ/J1CWdFl4KYY/s1600/F2_3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 199px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/S8yny-rZGYI/AAAAAAAAABQ/J1CWdFl4KYY/s400/F2_3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5461924942353865090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; Also it deletes all warnings connected with the earlier references to the undefined function which is being defined now. See &lt;span style="font-weight:bold;"&gt;sb-c::note-name-defined&lt;/span&gt; on this. Obviously, &lt;span style="font-weight:bold;"&gt;%defun&lt;/span&gt; is available only in target SBCL, due to #-sb-xc-host placed before its definition.&lt;br /&gt; The last but one tricky thing is &lt;span style="font-weight:bold;"&gt;sb-int::named-lambda&lt;/span&gt;. It serves as a marker of a named form during IR1 phase, for example, it is taken into account by &lt;span style="font-weight:bold;"&gt;sb-c::ir1-convert-lambdalike&lt;/span&gt;. &lt;br /&gt; Finally, what is a call to &lt;span style="font-weight:bold;"&gt;sb-c::source-location&lt;/span&gt; which is present at the end of the macroexpansion? There is an example of a compiler macro usage. It is defined in 'src/code/source-location.lisp', and it's job is to instantiate &lt;span style="font-weight:bold;"&gt;sb-c::definition-source-location&lt;/span&gt; structure during the compile-time expansion. In such a way Python records origins of the compiled definitions, namely in 'namestring' field of that structure instance. To learn more about compiler macros, refer to CLHS, as usual:)&lt;br /&gt; You may wonder how our simple definition became such a monster? It is due to &lt;span style="font-weight:bold;"&gt;defun&lt;/span&gt; being a macro. That macro is a bit long to post it here completely, so we will show only the part which contributed the most:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Q48gJ59wg6o/S8yo0uaRczI/AAAAAAAAABY/QymDkCO1sQo/s1600/F2_4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 165px;" src="http://2.bp.blogspot.com/_Q48gJ59wg6o/S8yo0uaRczI/AAAAAAAAABY/QymDkCO1sQo/s400/F2_4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5461926071858459442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; As you see, all above newcomers are present in that macro body.&lt;br /&gt; Okay, let us return to  &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt; and see what happens there with the macroexpansion result. But I almost hear the reader's question: “What will be the result of a &lt;span style="font-weight:bold;"&gt;defmacro&lt;/span&gt; form macroexpansion?” To get the answer, enter &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(macroexpand '(defmacro f(x) `(+ ,x 1)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and observe even bigger monster:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8ysTVvMo2I/AAAAAAAAABo/z-sgEBCNPC4/s1600/T2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 227px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8ysTVvMo2I/AAAAAAAAABo/z-sgEBCNPC4/s400/T2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5461929896346166114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Do not ask me to interpret that:) Let us stick to functions at this time, when we are young  and the sun is shining so brightly in Ukraine (I hope that the weather in your country is also nice these days...)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-1466739958397293953?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/1466739958397293953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-21-what-happens-with-lisp_19.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1466739958397293953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1466739958397293953'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-21-what-happens-with-lisp_19.html' title='[Book] Chapter 2.1 What Happens With Lisp Forms Before IR1 Stage [part 2]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/S8ysIfdA3tI/AAAAAAAAABg/jvbR1DOEVd4/s72-c/T1.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-1912138301564401569</id><published>2010-04-18T05:46:00.000-07:00</published><updated>2011-03-30T10:36:47.471-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><category scheme='http://www.blogger.com/atom/ns#' term='ir1'/><title type='text'>[Book] Chapter 2.1 What Happens With Lisp Forms Before IR1 Stage [part 1]</title><content type='html'>In this chapter we are going to gain some practical experience with SBCL Compiler. In case you have not downloaded the sources yet, it is a good time to do that. Go to &lt;a href="http://www.sbcl.org/platform-table.html"&gt;SBCL download page&lt;/a&gt; and get the latest sources there. We also hope that you know what is SLIME and have some experience with it. Obviously, you can use any other editor/IDE you have been using for Lisp development by this time. After downloading the sources, build and install SBCL as described in the 'INSTALL' document from the archive root folder. Eventually you should get version 1.0.37 (current at this time, when I am writing this chapter) up and running.&lt;br /&gt; So, what will be discussed in this chapter? The thing is that Lisp forms do not come to IR1 converters directly from Lisp reader. They are processed by several functions before IR1, and we are interested in understanding their role in compilation process. &lt;br /&gt; The easiest way to see what is going on is to place a breakpoint on &lt;span style="font-weight:bold;"&gt;sb-c::make-functional-from-toplevel-lambda&lt;/span&gt; function, which starts IR1 conversion process. In such a simple way we will discover all chain of major Lisp forms processors. So, let us do that by entering this code in REPL (enter this in SBCL launched directly from console, and do not use SLIME, because in the latter case you will reach the breakpoint immediately due to internal SLIME calls into SBCL, which involve compilations):&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;(trace sb-c::make-functional-from-toplevel-lambda :break t)&lt;br /&gt;&lt;/span&gt;&lt;br /&gt; Then we may enter some function definition in REPL, for example:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(defun f(x) (* x 3))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; After this the debugger will be invoked. In the debugger prompt type 'backtrace' and hit enter. You will see all the calls chain, from &lt;span style="font-weight:bold;"&gt;toplevel-init&lt;/span&gt; to &lt;span style="font-weight:bold;"&gt;%compile&lt;/span&gt;. Since we have just met a function whose name starts with '%', let us explain this naming convention. It means that the function is strictly internal and should be used only by the same function without leading '%' in the name. Maybe this rule has exceptions, but it seems to exist.&lt;br /&gt; In the backtrace we will start with the &lt;span style="font-weight:bold;"&gt;sb-imp::repl-fun&lt;/span&gt;, because SBCL initialization process is not very interesting for compilers developers:). This function is not a part of Python (Python package is 'sb-c'), and it is defined in 'src/code/toplevel.lisp' file:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8sCam2o0jI/AAAAAAAAABA/aaODT7EuEL8/s1600/F2_1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 173px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8sCam2o0jI/AAAAAAAAABA/aaODT7EuEL8/s320/F2_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5461461629246427698" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; This function enters infinite REPL cycle, and on every iteration does three important things: prints REPL prompt string “* “ to &lt;span style="font-weight:bold;"&gt;*standard-output*&lt;/span&gt; stream by making funcall into &lt;span style="font-weight:bold;"&gt;sb-impl::repl-prompt-fun&lt;/span&gt; through &lt;span style="font-weight:bold;"&gt;*repl-prompt-fun*&lt;/span&gt; variable; calls the Lisp reader (through a thin wrapper over &lt;span style="font-weight:bold;"&gt;read&lt;/span&gt;, whose function is bound to &lt;span style="font-weight:bold;"&gt;*repl-read-form-fun*&lt;/span&gt; variable), and passes the obtained Lisp form to &lt;span style="font-weight:bold;"&gt;sb-impl::interactive-eval&lt;/span&gt;. Two things to notice are also the argument 'noprint', which allows to suppress printing REPL prompt and evaluation results, and debugging macro &lt;span style="font-weight:bold;"&gt;/show0&lt;/span&gt;, used widely in SBCL for internal code tracing (this macro prints its argument to console). By default this macro does nothing – to enable its functionality, go to 'src/base-target-features.lisp-expr' file, uncomment ':sb-show' feature and rebuild SBCL. However, it produces a lot of info, so do think six times or more before doing that. We will not enable &lt;span style="font-weight:bold;"&gt;/show0&lt;/span&gt; in this book.&lt;br /&gt; Well, we have just seen who calls the Lisp reader in REPL. Lets move along to the next function in our backtrace – &lt;span style="font-weight:bold;"&gt;sb-impl::interactive-eval&lt;/span&gt;.  In the debugger you can see that it receives the entered form as it is:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;(INTERACTIVE-EVAL (DEFUN F (X) (* X 3)))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; This function calls into &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt;, and the only useful things it does itself are updates of many variables with interesting names - &lt;span style="font-weight:bold;"&gt;+++&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;++&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;***&lt;/span&gt; and so on. Luckily, these variables are defined and well-documented just above the function definition. They are connected with saving old evaluation and reading results before computing new ones:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8sHYAWu-9I/AAAAAAAAABI/w8mixXRYKhE/s1600/F2_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 134px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8sHYAWu-9I/AAAAAAAAABI/w8mixXRYKhE/s400/F2_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5461467082110467026" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; With the call to &lt;span style="font-weight:bold;"&gt;sb-int::simple-eval-in-lexenv&lt;/span&gt; the serious game begins. This function is quite large, so we will not give its full source code here. Find it in the file 'src/code/eval.lisp' and then follow the rest of this chapter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-1912138301564401569?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/1912138301564401569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-21-what-happens-with-lisp.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1912138301564401569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1912138301564401569'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-21-what-happens-with-lisp.html' title='[Book] Chapter 2.1 What Happens With Lisp Forms Before IR1 Stage [part 1]'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/S8sCam2o0jI/AAAAAAAAABA/aaODT7EuEL8/s72-c/F2_1.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-1223221049743260087</id><published>2010-04-16T13:49:00.000-07:00</published><updated>2010-04-16T14:19:42.279-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><title type='text'>[Book] Chapter 1.2 General Python Anatomy</title><content type='html'>In this chapter we are going to compose the high-level code flow diagram for Python. But before starting this amazing activity, let us say a few words about compilers in general. It might be useful for people who have too little compilers engineering experience to know the basics from the field. We are not going to be academic, so do not refer to the below as to the scientific definitions.&lt;br /&gt;&lt;br /&gt; On the simplest abstraction level a compiler is a computer program which converts a 'source code' into a code which is considered to be a 'target code'. These two kinds of codes obey some set of rules, given by their languages. In general case a source code is represented using a high-level language, and a target code is expressed in terms of a low-level language. Python compiles from the high-level language Common Lisp into a machine code (low-level assembly language) which is specific for a target CPU architecture (x86, x86-64, SPARC etc.).&lt;br /&gt;&lt;br /&gt; There are many different compilers in the world, but most of them do a common set of steps (sometimes called 'phases') in order to do their job. First of all they parse the source code to make sure that it is syntactically valid and follows the source language syntax rules. In Python this phase is absent – the syntax of the input forms is checked by the Lisp reader. &lt;br /&gt;&lt;br /&gt; The next phase is connected with the source code semantics checks and code optimizations. This step usually requires a special intermediate representation of the input sources, in Python there are two such representations: higher-level IR1 and closer to target code – IR2 (based on Virtual OPerations, VOPs for a virtual machine). IR abbreviation stands for the Intermediate Representation, for sure:). Such representations are better suitable for the code optimization and control flow analysis algorithms, since they often use directed graphs as the underlying data structure.&lt;br /&gt; After all the optimizations and checks are done, time comes to generate the target code. As we have already mentioned above, Python emits assembly instructions for the certain CPU architecture during this phase. &lt;br /&gt; We are going to cover all compilation phases in the next chapters. Let us summarize the above info on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_Q48gJ59wg6o/S8jQS2cZQZI/AAAAAAAAAA4/Ca9J0oCjYZs/s1600/F1_2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 160px; height: 320px;" src="http://3.bp.blogspot.com/_Q48gJ59wg6o/S8jQS2cZQZI/AAAAAAAAAA4/Ca9J0oCjYZs/s320/F1_2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5460843570457559442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; Obviously, the above figure is a high-level abstraction, which hides a lot of particular code transformations inside Python. We decided to avoid making things complicated in advance:) It will be a good time to see them in more detail later.&lt;br /&gt; To finish with the Python overview, we should say a few words about its source tree structure. In case we call the SBCL sources root directory 'src', most of Python code is in 'src/compiler' subfolder. Things which depend on CPU architecture are further separated to subfolders like 'src/compiler/sparc', 'src/compiler/x86' and so on. Some machine-independent Python source code (mostly related to IR2 phases and code dumping) is in 'src/compiler/generic' subfolder.&lt;br /&gt; We will not talk about individual source files now. It will be better to cover them later in the appropriate chapters along with their functionality and role in Python.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-1223221049743260087?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/1223221049743260087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-12-general-python-anatomy.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1223221049743260087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/1223221049743260087'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-12-general-python-anatomy.html' title='[Book] Chapter 1.2 General Python Anatomy'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_Q48gJ59wg6o/S8jQS2cZQZI/AAAAAAAAAA4/Ca9J0oCjYZs/s72-c/F1_2.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-4004950953140104312</id><published>2010-04-16T11:46:00.000-07:00</published><updated>2011-03-30T10:35:11.670-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python-book'/><title type='text'>[Book] Chapter 1.1 What Is Python, And What It Is Not</title><content type='html'>This chapter contains the very basic things which should be clarified before we start the actual Python code analysis. In case you are an experienced SBCL developer, you should probably skip this and move along to the Chapter 2 where we examine the first stage of the compiler. But if you have just started with SBCL development, it might be worth reading the current chapter.&lt;br /&gt;&lt;br /&gt; First of all we should figure out the relationships between Python and other parts of SBCL system. A Common Lisp implementation by SBCL is not only a compiler, but several coupled subsystems, as shown on this figure:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8izTpGz_RI/AAAAAAAAAAw/sZIRK5hs5Qk/s1600/F1_1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 265px; height: 265px;" src="http://4.bp.blogspot.com/_Q48gJ59wg6o/S8izTpGz_RI/AAAAAAAAAAw/sZIRK5hs5Qk/s320/F1_1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5460811698220039442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt; This decomposition is done by functionality, physically there are two main separate components: the runtime application and the Lisp image. The latter includes Common Lisp Object System (CLOS, the implementation is know as Portable Common Loops (PCL)) and Python compiler code as well. But we are more interested in functional differences, so we have selected the SBCL subsystems as shown on that figure.&lt;br /&gt;&lt;br /&gt; Before concentrating on Python, let us say few words about each subsystem. We will not try to give the full definitions, it will be enough for us to know the main responsibility of the each part of SBCL system:&lt;br /&gt;&lt;br /&gt; - Runtime application is intended to handle memory allocation, garbage collection, OS interrupts, OS-dependent multithreading stuff and OS-dependent I/O. It loads the Lisp image upon SBCL startup and serves the necessary OS requests.&lt;br /&gt;&lt;br /&gt; - Lisp Image (Core) contains all the compiled code of Common Lisp implementation. All standard CL functions and some SBCL-specific extensions  are saved in this image. This core also contains runtime Lisp data which allows to restore the saved SBCL system state after the core file is loaded.&lt;br /&gt;&lt;br /&gt; - CLOS code is also a part of Lisp image. We separated it because it has a somewhat specific purpose – it is intended to extend Common Lisp with powerful object-oriented  programming (metaprogramming!) possibilities. CLOS implementation in SBCL and the runtime application are out of this book scope. &lt;br /&gt;  &lt;br /&gt; - Python may be considered to be a heart of SBCL system. It compiles Lisp forms, as you see them in REPL or Lisp source files, into a machine code suitable for actual execution on a particular CPU architecture. A compiler code is also present in Lisp image, that compiler code is generated by a cross-compiler during SBCL build. There is an excellent article about this on SBCL Internals Wiki, and we recommend you to look there in case you are interested in SBCL build process. At this point you should understand that all code in the Lisp image file was produced by Python.&lt;br /&gt;&lt;br /&gt; So, the main thing to remember after you have read the paragraph is that SBCL system and SBCL compiler (Python) are not the same thing. Do not confuse them. We are also sure that you will never confuse SBCL compiler and the famous and popular Python programming language :) Sorry for falling into such obvious cautions, but it will be sad in case such misunderstanding happens.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-4004950953140104312?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/4004950953140104312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-11-what-is-python-and-what.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/4004950953140104312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/4004950953140104312'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/book-chapter-11-what-is-python-and-what.html' title='[Book] Chapter 1.1 What Is Python, And What It Is Not'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Q48gJ59wg6o/S8izTpGz_RI/AAAAAAAAAAw/sZIRK5hs5Qk/s72-c/F1_1.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-475780959494054478.post-3679360222614166767</id><published>2010-04-16T11:13:00.001-07:00</published><updated>2010-04-16T13:03:19.378-07:00</updated><title type='text'>Intro. Why this blog was launched</title><content type='html'>As you may guess from the blog title, it is dedicated to Common Lisp compilers. During my attempts to fix several bugs in SBCL I understood that it would be good to have some SBCL Compiler (Python) internals manual first. It happened that there are only three or fours papers about the subject at this time, and they are not very detailed. Since I have some experience with other compilers internals, I thought that it would be good to try writing such a manual myself. &lt;br /&gt;&lt;br /&gt; Maybe it sounds crazy:), especially because I cannot say that I am a Lisp guru. Yes, I have been using Common Lisp on my daily job for almost three years, and yes, I participate in the development of industrial-level compilers on that job. Is that enough to think that it is a time to write my own book? Probably not... But anyway I have started this manual, because I need it at least for my own SBCL hacking goals. In case somebody else finds it to be useful, I will be happy. &lt;br /&gt;&lt;br /&gt;This blog will hold chapters from the book. In case you find some grammar/logical/fundamental mistakes in these chapters, I will appreciate notes and comments about them. &lt;br /&gt;&lt;br /&gt;Also I will probably post other Lisp-related things here, in case I consider them to be interesting.&lt;br /&gt;&lt;br /&gt;The last thing to mention: I am not a native English speaker, so I apologise for any grammar mistakes you may see in my posts:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/475780959494054478-3679360222614166767?l=insidelisp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://insidelisp.blogspot.com/feeds/3679360222614166767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://insidelisp.blogspot.com/2010/04/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3679360222614166767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/475780959494054478/posts/default/3679360222614166767'/><link rel='alternate' type='text/html' href='http://insidelisp.blogspot.com/2010/04/blog-post.html' title='Intro. Why this blog was launched'/><author><name>Roman Marynchak</name><uri>http://www.blogger.com/profile/01326168723195411291</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
