{"id":264,"date":"2007-01-05T14:03:04","date_gmt":"2007-01-05T14:03:04","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2007\/01\/05\/pathological-macros-for-brainfk\/"},"modified":"2007-01-05T14:03:04","modified_gmt":"2007-01-05T14:03:04","slug":"pathological-macros-for-brainfk","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2007\/01\/05\/pathological-macros-for-brainfk\/","title":{"rendered":"Pathological Macros for BrainF**k"},"content":{"rendered":"<p>Today, I have something really fun and twisted for you. It&#8217;s my favorite variation on<br \/>\n<a href=\"http:\/\/scientopia.org\/blogs\/goodmath\/2006\/07\/gmbm-friday-pathological-programming-languages\">BrainF**k<\/a>, called <a href=\"http:\/\/www.pimpworks.org\/brainfuck\/utils\/eso_bfm\/\">&#8220;BFM&#8221;<\/a>, which is short for &#8220;BrainFunct-Macro&#8221;. It&#8217;s a doubly-Turing-equivalent language &#8211; it&#8217;s got two complete and distinct Turing equivalent computing systems in it: it&#8217;s<br \/>\ngot regular BF on the bottom&#8230; But before BF gets going to run the program,<br \/>\nthe program is pre-processed by a complete lambda-calculus macro expander. <\/p>\n<p><!--more--><\/p>\n<p> Basically, you start with a BF interpreter, and you observe, quite logically, that there&#8217;s a<br \/>\nton of repetition in a typical BF program &#8211; stuff that <em>could<\/em> be nicely extracted. An<br \/>\nobvious example is: suppose you want to add a + b, where they&#8217;re stored in neighboring cells, and<br \/>\nstore the result where a was. In BF, that&#8217;s <code>[-&lt;+&gt;]&lt;<\/code>. <\/p>\n<p> So, you add a way of defining that as a macro:<\/p>\n<pre>\n&amp;add=[-&lt;+&gt;]&lt;;\n<\/pre>\n<p> Next, you notice that gosh, there&#8217;s a lot of similar macros, which you could make the<br \/>\nsame if you could only parameterize them. For instance, what if you wanted to add &#8220;a&#8221; and &#8220;b&#8221;, but<br \/>\nthey were actually three cells apart? The program would be: &#8220;<code>[-&lt;&lt;&lt;+&gt;&gt;&gt;]&lt;&lt;&lt;<\/code>&#8220;. That&#8217;s almost the same as the original adder. But wouldn&#8217;t it be easier to be able to write<br \/>\nrepetitions like that in a smarter way? Like, say, &#8220;3(x)&#8221; to be the equivalent of &#8220;x x x&#8221;? So<br \/>\nthen, as a macro, that program would be:<\/p>\n<pre>\n&amp;addThreeApart=[-3(&lt;)+3(&gt;)]3(&lt;);\n<\/pre>\n<p> And the, you might notice that &#8220;add&#8221; and &#8220;addThreeApart&#8221; are pretty much the same thing &#8211; the only difference is really a parameter, for how many times to repeat the &#8220;&lt;&#8221; and &#8220;&gt;&#8221;s. So you<br \/>\nadd parameters.<\/p>\n<pre>\n&amp;addApart(n)=[-n(&lt;)+n(&gt;)]n(&lt;);\n&amp;add=addApart(1);\n&amp;addThreeApart=addApart(3);\n<\/pre>\n<p> Now, you notice that the &#8220;n&#8221;s are really macros themselves, and what you&#8217;re doing is allowing<br \/>\nyou to write macros that take macros as parameters. So just forget about worrying about it, and just<br \/>\nlet macros be parameters to other macros. And bingo &#8211; you&#8217;ve just created a macro system<br \/>\nwhich is pretty much lambda calculus.<\/p>\n<p> So, you&#8217;ve got a lambda calculus macro system. Well, in Scheme, which is also based on lambda<br \/>\ncalculus, they make code a lot easier to read by allowing you to write <em>local<\/em> function<br \/>\ndefinitions. So why not local macros?<\/p>\n<pre>\n&amp;addNApart(n) =\n&amp;left=n(&lt;);\n&amp;right=n(&gt;)\n[- left + right ] left;\n<\/pre>\n<p> Of course, we&#8217;d also like to be able to use more than one parameter, so that we don&#8217;t need<br \/>\nto curry everything out, right? No problem. Just separate the parameters by &#8220;|&#8221;. We&#8217;ll use this<br \/>\nto built something really crazy; let&#8217;s treat the BF tape as if it were a stack, and write<br \/>\nsome stack-oriented code so that we can build a multiply operator.<\/p>\n<pre>\n&amp;zero=[-];\n&amp;lefttwo = &lt;&lt;;\n&amp;righttwo = &gt;&gt;;\n#copy the nth value on the stack to the top of the stack.\n&amp;rotn(n)=\n&amp;leftn=n(&lt;);\n&amp;rightn=n(&gt;);\n# Push two zeros onto the stack\n2(&gt; zero) 2(&lt;)\n# copy nth value down the stack to the two new stack cells.\nleftn [ - rightn &gt;+&gt;+ lefttwo leftn] rightn\n# copy the second new value back to the nth cell down\nrighttwo\n[- leftwo leftn + righttwo rightn ]\n# move the stack pointer to the first copy of the value.\n&gt;;\n&amp;pushzero = &gt; zero;\n&amp;mult=\npushzero\nlefttwo\n[- righttwo rotn(1) add lefttwo]\nrighttwo\n[- lefttwo + righttwo ]\nlefttwo\n&gt;\n<\/pre>\n<p> Gosh, BF starts to look downright <em>legible<\/em>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today, I have something really fun and twisted for you. It&#8217;s my favorite variation on BrainF**k, called &#8220;BFM&#8221;, which is short for &#8220;BrainFunct-Macro&#8221;. It&#8217;s a doubly-Turing-equivalent language &#8211; it&#8217;s got two complete and distinct Turing equivalent computing systems in it: it&#8217;s got regular BF on the bottom&#8230; But before BF gets going to run the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[92],"tags":[],"class_list":["post-264","post","type-post","status-publish","format-standard","hentry","category-pathological-programming"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-4g","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/264","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/comments?post=264"}],"version-history":[{"count":0,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/264\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=264"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}