tag:blogger.com,1999:blog-84774459755887537062024-02-20T17:08:52.427-08:00StandardsBlogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer.
<a href="http://github.com/ujihisa">github/ujihisa</a>ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.comBlogger197125tag:blogger.com,1999:blog-8477445975588753706.post-41523341526908651732013-12-11T00:07:00.002-08:002013-12-11T00:08:28.199-08:00moved!moved to wordpress.com<br />
<http: ujihisa.wordpress.com=""><br /></http:>
<http: ujihisa.wordpress.com=""><a href="http://ujihisa.wordpress.com/">http://ujihisa.wordpress.com/</a></http:><br />
<http: ujihisa.wordpress.com="">see you there!
</http:>ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-14893519178965049862013-08-23T18:25:00.001-07:002013-08-23T18:25:29.375-07:00if_lua accelerates Vim scripts<p>Vim has some foreign language interfaces available for Vim script, to allow you to make a Vim plugin with using other programming languages besides Vim script, such as Python, Scheme, or Ruby. This is not only handy that you can attempt to make your code more readable with using ways of writing code that Vim script can't or using libraries exclusive for the language, but also provides faster computation. Vim script runs slower than many of you expect.</p>
<p>Lua is a general purpose programming language which works particularly well about embedding to an existing system written in C. It is very natural that Vim has lua interface as <code>if_lua</code>.</p>
<p><img src="https://a248.e.akamai.net/camo.github.com/1a47eabae549c43ab6a2a85f852793ccd16f60c2/687474703a2f2f7777772e63656c73697573313431342e636f6d2f75706c6f6164732f76696d2d656469746f725f6c6f676f2e706e67" alt="vim" /> <img src="http://www.plop.nl/pics/lua.gif" alt="lua" /></p>
<p>The significant part of <code>if_lua</code> is that it works really fast.</p>
<p>Comparison between Pure Vim script, <code>if_lua</code>, and <code>if_python</code>: <a href="https://github.com/vim-jp/issues/issues/48#issuecomment-15355516">https://github.com/vim-jp/issues/issues/48#issuecomment-15355516</a></p>
<ul>
<li>Vim script: 1.4985sec</li>
<li>Luajit: 0.0013sec (1152 times faster than Vim script)</li>
<li>Python: 0.0272sec (20 times faster than Vim script)</li>
</ul>
<p>Time to start</p>
<ul>
<li><code>if_lua</code> = 0.000297sec</li>
<li><code>if_python</code> = 0.016656sec</li>
<li><code>if_ruby</code> = 0.039039sec</li>
</ul>
<h2 id="now-its-default">Now it's default!</h2>
<div class="figure">
<img src="http://www.chromebook-linux.com/wp-content/uploads/2011/11/gentoolinux1.png" alt="gentoo" /><p class="caption">gentoo</p>
</div>
<p>I submitted a patch to Gentoo Linux 10 month ago, and it was accepted finally in a couple days ago!</p>
<ul>
<li><a href="https://bugs.gentoo.org/show_bug.cgi?id=436744">https://bugs.gentoo.org/show_bug.cgi?id=436744</a> Gentoo's Bugzilla – Bug 436744 vim.eclass - add lua support</li>
</ul>
<p>So if you simply <code>emerge</code> vim or gvim with adding <code>lua</code> and <code>luajit</code> USE flags, the vim will have lua integration!</p>
<h2 id="faq">FAQ</h2>
<ul>
<li>Does speed matter? My Vim already works fast enough.
<ul>
<li>Speed matters. Some auto-completion plugins gave up providing powerful functionality since it took too much time. If it's fast enough that users can't recognize, the authors can implement more functionalities.</li>
</ul></li>
<li>Python is slower than Luajit and Lua, but it's more popular among Vim plugin authors. We should keep using Python.
<ul>
<li>Popularity is just a chicken-or-the-egg problem. If somebody makes a effort to make an egg, that will eventually grows up to a chicken.</li>
</ul></li>
<li>Should I re-implement all the Vim script codes in my Vim plugin? That's too much work...
<ul>
<li>No. Running profiler and writing the bottleneck part in Lua is usually enough. Keep the pure Vim script part for people who don't have <code>if_lua</code> for a while.</li>
</ul></li>
<li>Which plugins are using <code>if_lua</code> for performance? I'd like to refer and learn the technique there.
<ul>
<li><a href="https://github.com/Shougo/neocomplete.vim">neocomplete.vim</a> this requires <code>if_lua</code></li>
<li><a href="https://github.com/Shougo/unite.vim">unite.vim</a> <code>if_lua</code> is optional just for speed</li>
</ul></li>
<li>What <code>if_lua</code> can't do whereas others like <code>if_python</code> can do?
<ul>
<li>Multithreading. This is pros.</li>
<li>Sockets. You may want to ask users to install <a href="https://github.com/Shougo/vimproc.vim">vimproc</a> to use network connections.</li>
<li>Non-blocking IO. Use <code>vimproc</code> instead like above.</li>
<li>In short: <code>if_lua</code> is like faster Vim script; it doesn't add superpower.</li>
</ul></li>
</ul>
<p>Past discussions</p>
<ul>
<li><a href="https://github.com/Shougo/neocomplcache.vim/issues/400">Why not python interface?</a></li>
</ul>
<h2 id="vim-advent-calendar-2012">Vim Advent Calendar 2012</h2>
<p>There is a tech advent calendar ongoing since December 2012 which is all about Vim. This article is for that as its 266th day.</p>
<ul>
<li>Vim Advent Calendar 2012 <a href="http://atnd.org/events/33746">http://atnd.org/events/33746</a></li>
</ul>
<p>I previously posted an article for Vim Advent Calendar 2012 about <code>if_lua</code> and the patch described above on January 17, 2013. The post is <a href="http://vim-users.jp/2013/01/vim-advent-calendar-2012-ujihisa-2/">http://vim-users.jp/2013/01/vim-advent-calendar-2012-ujihisa-2/</a> and is written in Japanese.</p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-82527383899478474532013-01-07T22:02:00.001-08:002013-01-07T22:02:38.785-08:00Day 4 -- JavaScript in a week<p><a href="http://ujihisa.blogspot.com/2013/01/day-3-javascript-in-week.html">previous post</a> <code><-></code> next post</p>
<p>I accidentally started playing <a href="http://en.wikipedia.org/wiki/SimCity_3000">SimCity3000</a> and it ate big amount of my time..</p>
<h2 id="return">return</h2>
<p><a href="https://github.com/ujihisa/jinaw/commit/2dbc9ed0b3240d9081932c5a519a9767a3763ee4"><code class="url">https://github.com/ujihisa/jinaw/commit/2dbc9ed0b3240d9081932c5a519a9767a3763ee4</code></a></p>
<p><code>return</code> is the only one feature to cancel executing the rest of statements, since there's no try/catch exception handling in this subset. Since the <code>run-</code> function to sequentially execute statements isn't something like a loop but an explicit recursion, to implement <code>return</code>, just simply don't recur.</p>
<pre><code>(run '[(var f (function []
[(fcall 'console.log [1])
(return 9)
(fcall 'console.log [2])]))
(fcall 'console.log [(fcall 'f [])])])</code></pre>
<p>This outputs 1 and 9 but not 2.</p>
<h2 id="typeof">typeof</h2>
<p><a href="https://github.com/ujihisa/jinaw/commit/c499b1bc23a11799ffe119d8a974729c6936c4ad"><code class="url">https://github.com/ujihisa/jinaw/commit/c499b1bc23a11799ffe119d8a974729c6936c4ad</code></a></p>
<p>JavaScript has a unary operator <code>typeof</code> to tell the type of a value/variable-name.</p>
<pre><code>> typeof 1
"number"
> var x = 1
> typeof x
"number"
> typeof y
"undefined"</code></pre>
<p>Since <code>typeof</code> isn't a function it has more power than functions; it also accepts undefined variables without throwing <code>ReferenceError</code>.</p>
<pre><code>(run '[(fcall 'console.log [(typeof 1)]);=> "number"
(var x 1)
(fcall 'console.log [(typeof x)]);=> "number"
(fcall 'console.log [(typeof y)]);=> "undefined"
(fcall 'console.log [(typeof (fcall '+ ['x 2]))])]);=> "number"</code></pre>
<h2 id="section">==</h2>
<p><code>==</code> is one of the most difficult aspect of JavaScript. The behavior is too tricky to understand.</p>
<pre><code>> 1 == ['1']
true
> [] == []
false
> [] == ''
true
> 1 == true
true
> 1 == 'true'
false
> '1' == true
true</code></pre>
<p>According to <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Comparison_Operators">specification</a>, the definition of <code>==</code> is</p>
<blockquote>
<p>If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.</p>
</blockquote>
<p>Well, I couldn't clearly understand it. What if one operand is a number and the other is a boolean? What is an operand is a number but the other operand isn't possible to be converted? They aren't written.</p>
<p>I gave up and made <a href="https://github.com/ujihisa/jinaw/commit/b2d5521fc0c40f840dcf84b4e92e5fecfcda5eac">one</a> that works fine for now..</p>
<pre><code>(run '[(fcall 'console.log [(fcall '== [1 1])]);=> true
(fcall 'console.log [(fcall '== [1 2])]);=> false
(fcall 'console.log [(fcall '== ["1" 1])]);=> true
(fcall 'console.log [(fcall '== ["1" 2])]);=> false
(fcall 'console.log [(fcall '== ["1" "1"])]);=> true
(fcall 'console.log [(fcall '== ["1" "2"])]);=> false
(fcall 'console.log [(fcall '== ["aaa" "aab"])])]);=> false</code></pre>
<h2 id="section-1">[]</h2>
<p><a href="https://github.com/ujihisa/jinaw/commit/8878e40f5a21f8a79067aa822d088db12cb87029"><code class="url">https://github.com/ujihisa/jinaw/commit/8878e40f5a21f8a79067aa822d088db12cb87029</code></a></p>
<p><code>[]</code> is a unary operator for objects. Note that "object" is a hash-map or an array in JavaScript terminology. I named it as <code>aref</code> borrowed from Ruby's parser which means array ref, since Clojure doesn't recognize <code>'[]</code> as Symbol but as vector. To distinguish it with user-defined something which name is <code>aref</code>, I named it as <code>-aref</code>.</p>
<pre><code>(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} 0])])]);=> "a"
(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} "1"])])]);=> "b"
(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} 3])])]);=> "undefined"
(run '[(fcall 'console.log [(fcall '-aref [{"0" "a" "1" "b" "2" "c"} "4"])])]); => "undefined"</code></pre>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-26605900197772406072013-01-02T21:45:00.001-08:002013-01-07T22:03:12.020-08:00Day 3 -- JavaScript in a week<p><a href="http://ujihisa.blogspot.com/2013/01/day-2-javascript-in-week.html">previous post</a> <code><-></code> <a href="http://ujihisa.blogspot.com/2013/01/day-4-javascript-in-week.html">next post</a></p>
<p>I made many commits but most of them were improvements for internal structure. Actual new features are <a href="https://github.com/ujihisa/jinaw/commit/64a1c6d6c0acc24bbeff540d8efdde85b8912156">if</a> and <a href="https://github.com/ujihisa/jinaw/commit/724ec640bace45e1366ff0e745bc1beafe04c84c">(strict) equal/notequal</a>.</p>
<h2 id="if">if</h2>
<p>I implemented <code>if</code> as an expression like <code>a ? b : c</code> as below.</p>
<pre><code>(defn evaluate [expr env]
"assumption: env won't change"
(if (list? expr)
(let [[car & cdr] expr]
(case car
if (let [[cond- then- else-] cdr]
(if (js-boolean (evaluate cond- env))
(evaluate then- env)
(evaluate else- env)))
...snip...</code></pre>
<p>Too straightforward to explain. Since <code>cond</code> looked ambiguous to Clojure's one, so I added dash as suffix, and just for naming consistency, I added it to all the names..</p>
<h2 id="equalnot-equal">equal/not equal</h2>
<blockquote>
<p><code>Strict equal (===)</code></p>
<p>Returns true if the operands are strictly equal (see above) with no type conversion.<br /><a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Comparison_Operators"><code class="url">https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Comparison_Operators</code></a></p>
</blockquote>
<p>Luckily I could simply use Clojure's <code>=</code> function.</p>
<pre><code>(defn evaluate [expr env]
"assumption: env won't change"
(if (list? expr)
(let [[car & cdr] expr]
(case car
if (let [[cond- then- else-] cdr]
(if (js-boolean (evaluate cond- env))
(evaluate then- env)
(evaluate else- env)))
function (let [params (first cdr)
body (second cdr)]
{:type :function :params params :body body})
fcall (let [func (evaluate (first cdr) env)
args (map #(evaluate % env) (second cdr))]
(case func
console.log (println (js-string (first args)))
+ (if (every? number? args)
(+ (first args) (second args))
(str (js-string (first args)) (js-string (second args))))
=== (= (first args) (second args))
!== (not= (first args) (second args))
(if (= (:type func) :function)
(let [applied-params (into {} (map (fn [x y] [x y])
(:params func)
args))]
(run- (:body func) (merge env applied-params)))
(prn 'must-not-happen 'missing-function func))))
quote (get env (first cdr) 'missing-local-var)
expr))
expr))</code></pre>
<p>Now you have <code>if</code> and a predicate function, you can make a safe loop with recursive function calls.</p>
<pre><code>var f = function(n) {
(n === 10) ? console.log('end') : f(n + 1);
}
f();</code></pre>
<p>It'll be represented as the below.</p>
<pre><code>(run '[(var f (function [n]
[(fcall 'console.log ['n])
(if (fcall '=== ['n 10])
(fcall 'console.log ["end"])
(fcall 'f [(fcall '+ ['n 1])]))]))
(fcall 'f [0])])</code></pre>
<p>It outputs 0 to 10 and "end"</p>
<h2 id="refactoring-to-make-it-more-declarative">Refactoring to make it more declarative</h2>
<p>You may have noticed that the <code>evaluate</code> function is already long and have guessed that it would get longer and longer as I add more builtin functions. First I made <a href="https://github.com/ujihisa/jinaw/commit/e4ac156e98b57055d2629a9f009849d7efc6ed20">change</a> to separate each built-in functions with updating a global variable <code>*builtins*</code>. That's still not well readable because of the boilerplate code. I made <a href="https://github.com/ujihisa/jinaw/commit/2b1bbee2851f089a3c878ce16e047ef069f85a1e">another change</a> to provide <code>defbuiltin</code> macro. Now you can add a new builtin function with like the following code.</p>
<pre><code>(defbuiltin + [x y]
(if (and (number? x) (number? y))
(+ x y)
(str (js-string x) (js-string y))))</code></pre>
<p>It looks very like Clojure's <code>defn</code>.</p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-51766787563405348572013-01-01T23:46:00.001-08:002013-01-02T21:46:33.153-08:00Day 2 -- JavaScript in a week<p><a href="http://ujihisa.blogspot.com/2012/12/day-1-javascript-in-week_31.html">previous post</a> <code><-></code> <a href="http://ujihisa.blogspot.com/2013/01/day-3-javascript-in-week.html">next post</a></p>
<p>summary:</p>
<ul>
<li><a href="https://github.com/ujihisa/jinaw/commit/f28e7f55559f4919d6718539d413f0e65bd4a9e0">type conversions</a>
<ul>
<li>JavaScript's Boolean(), Number() and String()</li>
<li><code>console.log</code> and <code>+</code> now implicitly convert its arguemnts into String</li>
</ul></li>
<li><a href="https://github.com/ujihisa/jinaw/commit/a50de0f344951e2e36a60131458d8533ea75241a">function literal without closure</a>
<ul>
<li><code>(function(x) { console.log(x); })(2)</code> works</li>
</ul></li>
</ul>
<h2 id="type-conversions-boolean-number-and-string">Type conversions: Boolean(), Number() and String()</h2>
<p><a href="https://github.com/ujihisa/jinaw/commit/f28e7f55559f4919d6718539d413f0e65bd4a9e0"><code class="url">https://github.com/ujihisa/jinaw/commit/f28e7f55559f4919d6718539d413f0e65bd4a9e0</code></a></p>
<pre><code>(defn js-boolean
"https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Boolean"
[value]
(not (get #{0 'null false 'NaN 'undefined} value false)))
(defn js-number
"https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Number"
[value]
(condp instance? value
String (if (empty? value)
0
(let [x (read-string value)]
(if (number? x) x 'NaN)))
Long value
'NaN))
(defn js-string
"https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String"
[value]
(.toString value))</code></pre>
<p>Looks fairly straightforward.</p>
<h2 id="type-conversions-in-operator">Type conversions in + operator</h2>
<p>It works both for numbers and strings.</p>
<ul>
<li><ul>
<li>for numbers <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Arithmetic_Operators"><code class="url">https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Arithmetic_Operators</code></a></li>
</ul></li>
<li><ul>
<li>for strings <a href="https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/String_Operators"><code class="url">https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/String_Operators</code></a></li>
</ul></li>
</ul>
<p>The rule which to choose is really simple. If either one of the operands is not a number, it chooses the string's one and converts both operands to strings.</p>
<blockquote>
<pre><code>> 1 + 2
3
> '1' + 2
"12"
> 1 + '2'
"12"
> '1' + '2'
"12"
> [1] + [2]
"12"
> 1 + [2]
"12"</code></pre>
</blockquote>
<p>so</p>
<pre><code>(defn evaluate [expr env]
"assumption: env won't change"
(if (list? expr)
(let [[car & cdr] expr]
(case car
fcall (let [func (evaluate (first cdr) env)
args (map #(evaluate % env) (second cdr))]
(case func
console.log (println (js-string (first args)))
+ (if (every? number? args)
(+ (first args) (second args))
(str (js-string (first args)) (js-string (second args))))
(prn 'must-not-happen 'missing-function func)))
quote (get env (first cdr))
expr))
expr))</code></pre>
<p>now the runtime outputs "1hello" by <code>console.log(1 + 'hello')</code>.</p>
<h2 id="function-literal-without-closure">function literal without closure</h2>
<p><a href="https://github.com/ujihisa/jinaw/commit/a50de0f344951e2e36a60131458d8533ea75241a"><code class="url">https://github.com/ujihisa/jinaw/commit/a50de0f344951e2e36a60131458d8533ea75241a</code></a></p>
<p>A function object which doesn't have lexical scope is represented simply as a tuple of parameter names and body (a sequence of statements.) Here just for readability in the future I'll use a hash-map which has <code>:type</code>, <code>:params</code>, and <code>:body</code> for function objects.</p>
<pre><code>(defn evaluate [expr env]
"assumption: env won't change"
(if (list? expr)
(let [[car & cdr] expr]
(case car
function (let [params (first cdr)
body (second cdr)]
{:type :function :params params :body body})
fcall (let [func (evaluate (first cdr) env)
args (map #(evaluate % env) (second cdr))]
(case func
console.log (println (js-string (first args)))
+ (if (every? number? args)
(+ (first args) (second args))
(if (= (:type func) :function)
(let [applied-params (into {} (map (fn [x y] [x y])
(:params func)
args))]
(run- (:body func) (merge env applied-params)))
(prn 'must-not-happen 'missing-function func))))
quote (get env (first cdr) 'missing-local-var)
...snip...</code></pre>
<p>It doesn't support <code>return</code> yet.</p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-50351522603095364052012-12-31T19:35:00.001-08:002013-01-01T23:47:28.826-08:00Day 1 -- JavaScript in a week<p><a href="https://github.com/ujihisa/jinaw"><code class="url">https://github.com/ujihisa/jinaw</code></a></p>
<p>I'll make an implementation of a subset of programming language JavaScript within a week.</p>
<p><a href="http://ujihisa.blogspot.com/2013/01/day-2-javascript-in-week.html">next post</a></p>
<h2 id="defining-a-subset-of-javascript">Defining a subset of JavaScript</h2>
<p>The implementation should execute the following JavaScript code.</p>
<pre><code>var acc = 'dummy';
var f = function() {
var acc = [];
return function(x) {
return x ? acc.push(x)&&f(x - 1) : acc;
};
console.log("this won't show up!");
}();
String.prototype.ujihisa = function() {
var x = 10;
return this + f(x);
}
console.log("hello".ujihisa());
console.log(acc == 'dummy');
console.log({'a': 2}.a == 2);</code></pre>
<p>output:</p>
<pre><code>hello10,9,8,7,6,5,4,3,2,1
true
true</code></pre>
<p>That sample JS code covers the following important aspects.</p>
<ul>
<li>statements and expressions</li>
<li>literals (String, Number, Function, Array and Object)</li>
<li>function call, method call, operators, and index/key access of Object</li>
<li>implicit convertion (String + Number)</li>
<li>lexical scope (see <code>acc</code> var)</li>
<li>method addition by prototype</li>
<li><code>return</code> exits from the current function</li>
</ul>
<p>The implementation consists of the following 2 parts.</p>
<ul>
<li>parser (JS code to internal representation in S-expression)</li>
<li>runtime</li>
</ul>
<p>I'll work on runtime first in Clojure, then work on parser in Haskell with parsec.</p>
<h3 id="parsing">parsing</h3>
<p>I don't implement the parser for now but I simply parse the sample code by hand. the first 2 statements will be like the below.</p>
<p>before:</p>
<pre class="js"><code>var acc = 'dummy';
var f = function() {
var acc = [];
return function(x) {
return x ? acc.push(x)&&f(x - 1) : acc;
};
}();</code></pre>
<p>after:</p>
<pre class="sourceCode clojure"><code class="sourceCode clojure">'[(var 'acc <span class="st">"dummy"</span>)
(var 'f
(call
(function []
[[(var 'acc (array))
(return
(function ['x]
[[(return (<span class="kw">if</span> 'x
(<span class="kw">and</span> (mcall 'push 'acc ['x])
(call 'f [(minus 'x <span class="dv">1</span>)]))
'acc))]]))]])
[]))]</code></pre>
<h3 id="day-1-progress">Day 1 progress</h3>
<p><a href="https://github.com/ujihisa/jinaw/commit/6902cd4e9382e2da58fb9d43f8069256e8fe1ded"><code class="url">https://github.com/ujihisa/jinaw/commit/6902cd4e9382e2da58fb9d43f8069256e8fe1ded</code></a></p>
<ul>
<li><p>just finished implementing <code>var</code> and <code>console.log</code></p>
<pre><code>(run '[(var x "hello")
(fcall 'console.log ['x])])</code></pre></li>
<li><p>currently <code>console.log</code> is just a single name of built-in function</p></li>
</ul>
<p><a href="https://github.com/ujihisa/jinaw/commit/30ad8c898a1c806735eaa990656258537b65a34c"><code class="url">https://github.com/ujihisa/jinaw/commit/30ad8c898a1c806735eaa990656258537b65a34c</code></a></p>
<ul>
<li>changed the structure a little bit.. to separate <code>run</code> to handle statements and <code>evaluate</code> to handle an expression</li>
<li><p>now it supports nested function calls</p>
<pre><code>(run '[(var x 1)
(fcall 'console.log [(fcall '+ ['x 2])])])</code></pre></li>
</ul>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-40548794464114510912012-10-21T21:45:00.001-07:002012-10-21T21:45:03.741-07:00I'll be in Japan and Taiwan for a while
<div xmlns='http://www.w3.org/1999/xhtml'>
<ul>
<li>Taiwan: Oct 28</li>
<li>Japan: Oct 28 to Nov 21</li>
<li>Taiwan: Nov 21 to Nov 23</li>
</ul>
<p>I have no particular plans in Taiwan yet besides having awesome 小籠包s there.</p>
<div class='figure'>
<img alt='小籠包 from wikipedia' src='http://upload.wikimedia.org/wikipedia/commons/thumb/d/d2/Xiao_Long_Bao_by_Junhao!.jpg/295px-Xiao_Long_Bao_by_Junhao!.jpg'/><p class='caption'>小籠包 from wikipedia</p>
</div>
<p>Whereas I have plans in Japan -- I'll be organizing 4 conferences/meetups there.</p>
<ul>
<li><a href='http://vim-jp.org/ujihisa.vim-3/'>ujihisa.vim#3</a>: Vim conference</li>
<li>JVM study meetup: about Scala and Clojure</li>
<li><a href='http://cotocoto.jp/event/71098'>Vim study meetup</a></li>
<li><a href='http://ujihisa.github.com/livecoding11/'>LiveCoding#11</a></li>
</ul>
<p>If you are interested in either some of the topics above or me, and have plan to visit Kanto or Kansai area, you should check it out and give a presentation there.</p>
</div>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-69365696792389392822012-10-13T18:59:00.001-07:002012-10-13T22:51:00.263-07:00Mergesort in Haskell, Clojure and Scheme<h2 id="in-haskell">In Haskell</h2>
<p>Mergesort requires O(1) index access so I used Data.Vector instead of List.</p>
<pre><code>import qualified Data.Vector as V
-- length (sort2 x y) == 2
-- sorted (sort2 x y) is true
sort2 :: Ord a => a -> a -> V.Vector a
sort2 x y = if x < y then V.fromList [x, y] else V.fromList [y, x]
-- contract: sorted xs && sorted ys
-- length (merge xs ys) == length xs + length ys
-- sorted (merge xs ys) is true
merge :: Ord a => V.Vector a -> V.Vector a -> V.Vector a
merge xs ys = case (xs V.!? 0, ys V.!? 0) of
(Nothing, _) -> ys
(_, Nothing) -> xs
(Just x, Just y) -> if x < y
then x `V.cons` merge (V.tail xs) ys
else y `V.cons` merge xs (V.tail ys)
-- length (mergeSort xs) == length xs
-- sorted (mergeSort xs) is true
mergeSort' :: Ord a => V.Vector a -> V.Vector a
mergeSort' xs = case V.length xs of
0 -> xs
1 -> xs
2 -> sort2 (V.head xs) (V.last xs)
otherwise -> let (a, b) = split2 xs in
merge (mergeSort' a) (mergeSort' b)
mergeSort :: Ord a => [a] -> [a]
mergeSort = V.toList . mergeSort' . V.fromList
-- contract: length xs > 2
-- (a, b) = split2 xs => length a + length b == length xs
split2 :: Ord a => V.Vector a -> (V.Vector a, V.Vector a)
split2 xs = (V.take (V.length xs `div` 2) xs, V.drop (V.length xs `div` 2) xs)
main = do
print $ mergeSort [3, 1, 4, 1, 5, 9, 2]</code></pre>
<h2 id="in-clojure">In Clojure</h2>
<pre><code>(defn sort2 [x y]
(if (< x y) [x y] [y x]))
(defn merge2 [xs ys]
(cond
(empty? xs) ys
(empty? ys) xs
:else
(let [x (first xs) y (first ys)]
(if (< x y)
(cons x (merge2 (rest xs) ys))
(cons y (merge2 (rest ys) xs))))))
(defn merge-sort [xs]
(cond
(> 2 (count xs)) xs
(= 2 (count xs)) (apply sort2 xs)
:else (let [[a b] (split-at (/ (count xs) 2) xs)]
(merge2 (merge-sort a) (merge-sort b)))))
(prn (merge-sort [3 1 4 1 5 9 2]))</code></pre>
<h2 id="scheme-gauche">Scheme (Gauche)</h2>
<p>With List (slow)</p>
<pre><code>(use srfi-1)
(define (sort2 x y)
(if (< x y) (list x y) (list y x)))
(define (nil? xs)
(eq? xs '()))
(define (merge2 xs ys)
(cond
((nil? xs) ys)
((nil? ys) xs)
((let ((x (car xs))
(y (car ys)))
(if (< x y)
(cons x (merge2 (cdr xs) ys))
(cons y (merge2 xs (cdr ys))))))))
(define (merge-sort xs)
(cond
((> 2 (length xs)) xs)
((= 2 (length xs)) (apply sort2 xs))
((receive (a b) (split-at xs (/ (length xs) 2))
(merge2 (merge-sort a) (merge-sort b))))))
(print (merge-sort '(3 1 4 1 5 9 2 6)))</code></pre>
<p>With Vector (fast)</p>
<pre><code>(use srfi-43)
(define (sort2 x y)
(if (< x y) (vector x y) (vector y x)))
(define (merge2 xs ys)
(cond
((vector-empty? xs) ys)
((vector-empty? ys) xs)
((let ((x (~ xs 0))
(y (~ ys 0)))
(if (< x y)
(vector-append (vector x) (merge2 (vector-copy xs 1 -1) ys))
(vector-append (vector y) (merge2 xs (vector-copy ys 1 -1))))))))
(define (merge-sort xs)
(cond
((> 2 (vector-length xs)) xs)
((= 2 (vector-length xs)) (sort2 (~ xs 0) (~ xs 1)))
((let ((a (vector-copy xs 0 (div (vector-length xs) 2)))
(b (vector-copy xs (div (vector-length xs) 2) -1)))
(merge2 (merge-sort a) (merge-sort b))))))
(print (merge-sort #(3 1 4 1 5 9 2 6)))</code></pre>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-21772353394702324182012-09-18T23:14:00.001-07:002012-09-18T23:14:29.771-07:00Quicksort in Lua<pre><code>function rest(xs)
local ys = {}
for i = 2, #xs do
table.insert(ys, xs[i])
end
return ys
end
function concat(xs, ys)
local zs = {}
for _, v in ipairs(xs) do
table.insert(zs, v)
end
for _, v in ipairs(ys) do
table.insert(zs, v)
end
return zs
end
function qsort(xs)
if (#xs < 2) then
return xs
end
local p, xs = xs[1], rest(xs)
local lesser, greater = {}, {}
for _, x in ipairs(xs) do
if x < p then
table.insert(lesser, x)
else
table.insert(greater, x)
end
end
return concat(qsort(lesser), concat({p}, qsort(greater)))
end
xs = {3, 1, 4, 1, 5, 9}
for _, x in ipairs(qsort(xs)) do
io.write(x .. ' ')
end
print()
-- to check if the original xs isn't destroyed
for _, x in ipairs(xs) do
io.write(x .. ' ')
end
</code></pre>
<p>This works, but the code looks more complicated than it should be.</p>
<p>I rewrote it with using <a href="http://mirven.github.com/underscore.lua/">Underscore.lua</a> and it made the code much easier to read.</p>
<pre><code>_ = require 'underscore'
function concat(xs, ys)
return _(ys):reduce(xs, function(m, x)
return _(m):push(x)
end)
end
function qsort(xs)
if (#xs < 2) then
return xs
end
local p, xs = xs[1], _(xs):rest()
return concat(
_(qsort(_(xs):select(function(x) return x < p end))):push(p),
qsort(_(xs):select(function(x) return x >= p end)))
end
xs = {3, 1, 4, 1, 5, 9}
_(qsort(xs)):each(function(x)
io.write(x .. ' ')
end)
print()
_(xs):each(function(x)
io.write(x .. ' ')
end)
</code></pre>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-36503911125693550822012-09-16T22:08:00.001-07:002012-09-22T11:08:04.320-07:00Eval in Lua<pre><code>assert(loadstring(string.format('return %s', something)))()
</code></pre>
<p>The call of <code>assert</code> is only for debug-friendly.</p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-60100021460972465922012-09-16T19:14:00.001-07:002012-09-16T19:14:07.863-07:00Freeciv on Mac OS X
<div xmlns='http://www.w3.org/1999/xhtml'>
<p>If you haven't play Freeciv, it's a good opportunity to try it. It's a freesoftware which is based on Civilization™. I've been playing Freeciv recently.</p>
<p>It's very easy to install Freeciv on Gentoo Linux: just emerge it. It's not very easy to install it on Mac OS X Snow Leopard.</p>
<p>There are 3 ways to install Freeciv on Mac OS X Snow Leopard. (1) <a href='http://freeciv.wikia.com/wiki/More_distributions'>2.1.9 binary package for Snow Leopard</a>, (2) 2.3.1 with sdl on Homebrew's Homebrew-games, or (3) <a href='https://github.com/jiahao/homebrew'>jinhao's patched version of Homebrew formula</a>. Dont choose (1) or (2).</p>
<p>Freeciv has 2 ways to provide GUI interface; sdl and gtk2. sdl interface is very inconvenient. gtk2 interface is much much better but it needs lots of compiling. Still I recommend gtk2 version for everybody.</p>
<p>Note that don't start Freeciv server on Mac OS X. I don't know why but it consumes all the CPU power. Singleplay in Freeciv simply means it starts server and connects itself. Start a server on a Gentoo machine and connect there to play.</p>
<p>Enjoy!</p>
</div>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-77877539010290478212012-09-09T22:50:00.001-07:002012-09-17T06:53:44.416-07:00English Words Lookup/Completion on Gentoo<p>When I used Mac OS X, I used <code>look</code> command a lot.</p>
<pre><code>$ look standa
standage
standard
standardbred
standardizable
standardization
standardize
standardized
standardizer
standardwise
</code></pre>
<p>A Vim plugin <a href="https://github.com/ujihisa/neco-look">neco-look</a> makes your Vim auto-complete English words, using <code>look</code> command internally.</p>
<div class="figure">
<img src="http://cache.gyazo.com/7e83de0e1244b06382426a5fb7dc854a.png" /><p class="caption"></p>
</div>
<p>I had been looking for how to use the <code>look</code> command on Gentoo Linux. I finally found that how to do that today.. just install the following packages.</p>
<ul>
<li><code>sys-apps/util-linux</code></li>
<li><code>sys-apps/miscfiles</code></li>
</ul>
<p>I used <code>e-file</code> command to find portage packages which depend on <code>look</code> command and its dependency <code>/usr/share/dict/words</code>. Install <code>app-portage/pfl</code> to use <code>e-file</code>.</p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com3tag:blogger.com,1999:blog-8477445975588753706.post-92029844487687150612012-09-07T10:45:00.001-07:002012-09-07T10:46:04.043-07:00DNS Lookup in Scala<pre><code>import javax.naming.directory.{InitialDirContext, Attribute}
import javax.naming.NamingException
import scala.collection.JavaConversions._
object L {
def main(args: Array[String]) {
println('ip, lookupIp(args.head))
}
def lookupIp(host: String): List[String] = {
val attributes = try {
new InitialDirContext getAttributes ("dns:/%s" format host)
} catch {
case _: NamingException => return Nil
}
val list = {
val attributeEnumeration = attributes.getAll
var list = List[Attribute]()
while (attributeEnumeration.hasMore)
list = attributeEnumeration.next :: list
attributeEnumeration.close
list.reverse
}
list map (x => x.getID -> x.get.toString) flatMap {
case ("A", x) => List(x)
case ("CNAME", x) => lookupIp(x)
case (_, x) => Nil
}
}
}
</code></pre>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-24198233448905322182012-09-02T19:17:00.001-07:002012-09-02T19:17:25.891-07:00Minecraft MOD in Clojure
<div xmlns='http://www.w3.org/1999/xhtml'>
<p><a href='http://github.com/ujihisa/cloft'><code class='url'>http://github.com/ujihisa/cloft</code></a></p>
<p>I've been writing Clojure for this Minecraft server MOD. This MOD, cloft, uses Bukkit API and is compatible with Minecraft client version 1.3.1+, including the latest stable version 1.3.2.</p>
<p>This MOD was originally based on <a href='https://github.com/CmdrDats/clj-minecraft'>clj-minecraft</a> made by <a href='http://cmdrdats.wordpress.com/'>Deon Moolman</a>.</p>
<p>I'm also running my own minecraft server with using cloft. If you are interested in playing, feel free to ask me on <a href='http://twitter.com/ujm'>Twitter</a>.</p>
</div>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-58640357162570157882012-07-04T18:52:00.001-07:002012-07-04T18:52:20.608-07:00ZeroMQ Versions and Bindings
<div xmlns='http://www.w3.org/1999/xhtml'>
<p>ZeroMQ has two major versions; 2.x.y and 3.x.y. Even though the latter is still release candidate, people are already using it. The problem is that these two versions don't have compatibility. If one system uses version 3.x.y, whole other systems which talk to the system have to use 3.x.y.</p>
<p>There are some binding libraries for each programming languages. Note that some of them don't support one of the versions. The below is the list as of today.</p>
<ul>
<li><a href='http://www.zeromq.org/bindings:haskell'>Haskell</a>
<ul>
<li>zeromq-haskell: 2.1.x</li>
<li>zeromq-haskell3: 3.1.x</li>
<li>just use cabal to install them</li>
</ul></li>
<li>Clojure
<ul>
<li>(Not directly for Clojure but for JVM languages in general)</li>
<li>jzmq: both 2.x.y and 3.x.y</li>
<li>there are no official clojar/maven/apt/portage packages. one for gentoo is <a href='https://gist.github.com/3045682'>here</a></li>
</ul></li>
<li><a href='http://www.zeromq.org/bindings:scala-binding'>Scala</a>
<ul>
<li>zeromq-scala-binding: 2.1.x
<ul>
<li>(akka-zeromq uses it)</li>
</ul></li>
<li>jzmq: both 2.x.y and 3.x.y
<ul>
<li>(ditto in Clojure)</li>
</ul></li>
</ul></li>
<li><a href='http://www.zeromq.org/bindings:ruby'>Ruby</a>
<ul>
<li>rbzmq: 2.x.y</li>
</ul></li>
<li><a href='http://www.zeromq.org/bindings:python'>Python</a>
<ul>
<li>pyzmq: 2.x.x (experimentally 3.x.x)</li>
</ul></li>
</ul>
<p>Use Haskell, Clojure, Scala or Python to use ZeroMQ even if you use zeromq version 2 just in case at least one system uses version 3. If you need to use Ruby, just use JRuby to use jzmq. It's not very easy to install jzmq, but if you are using Gentoo, it's easy.</p>
</div>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com2tag:blogger.com,1999:blog-8477445975588753706.post-56244457215673343422012-05-09T20:32:00.001-07:002012-05-09T20:32:24.555-07:00Octal or not Octal
<div xmlns='http://www.w3.org/1999/xhtml'>
<p>A number literal with begins with 0 differs between programming languages. For example, a programming language considers 015 as 13, or as 15 just by ignoring the first 0, or even throws an error.</p>
<p>I categorized some programming languages by the view.</p>
<ul>
<li>015 == 13
<ul>
<li>Clojure</li>
<li>Scala</li>
<li>Java</li>
<li>Ruby</li>
<li>C</li>
<li>Vim script</li>
<li>JavaScript</li>
</ul></li>
<li>015 == 15
<ul>
<li>Haskell</li>
<li>Scheme</li>
<li>Emacs Lisp</li>
<li>Lua</li>
<li>Common Lisp</li>
</ul></li>
<li>Exception
<ul>
<li>Python</li>
<li>CoffeeScript</li>
</ul></li>
</ul>
</div>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com2tag:blogger.com,1999:blog-8477445975588753706.post-70400806222307016632012-04-02T21:22:00.001-07:002012-04-02T21:22:31.480-07:00Concurrent PI-Calculator in Clojure
<div xmlns='http://www.w3.org/1999/xhtml'>
<p>Inspired by a tutorial about <a href='http://doc.akka.io/docs/akka/2.0/intro/getting-started-first-scala.html'>akka tutorial in Scala</a> about making a concurrent PI calculator, I made similar on in Clojure without actor model but just with thread and atom.</p>
<pre><code>(ns pi.core
(:import [java.util.concurrent Executors])
(:gen-class))
(def sum (partial reduce +))
(defn f [n]
(/ (if (even? n) 1 -1) (inc (* 2 n))))
(defn solver1 [n]
(double (* 4 (sum (map f (range 0 n))))))
(defn solver2 [n]
(def a (atom 0))
(def tasks
(let [unit (/ n 4)]
(for [m (range 0 4)]
(fn []
(swap! a (partial + (sum (map f (range (* unit m) (* unit (inc m)))))))))))
(let [pool (Executors/newFixedThreadPool (count tasks))]
(doseq [f (.invokeAll pool tasks)]
(.get f))
(.shutdown pool))
(double (* 4 @a)))
(defn -main []
(let [n 2000]
(prn (solver1 n))
(prn (solver2 n))))
</code></pre>
<p>Commenting out the line of solver1/solver2, I got the following results on my 2-core with hyper-threading machine; virtually it's 4 core machine.</p>
<p>solver1</p>
<pre><code>real 3.80
user 4.66
sys 0.09
3.141092653621043
</code></pre>
<p>solver2</p>
<pre><code>real 2.01
user 3.44
sys 0.05
3.141092653621043
</code></pre>
<p>Comparing to the sequential version, the concurrent version was almost 2 times faster.</p>
</div>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-43382363757631091492012-02-05T01:26:00.001-08:002012-02-05T01:41:52.141-08:00IBus-Mozc for Kana Input on US Keyboard Layout<p>There are two major input methods in Japanese language; roma-input and kana-input (*1). Roma-input layouts in popular implementations are same while kana-input layouts are different among implementations for some reason when it's on US Keyboard layout.</p>
<p>I'm a kana typer and a user of US Keyboard Layout. Kana layout of Mac OS X Kotoeri layout and kana layout of ibus-mozc are very different. I had used Kotoeri for a long time, so I decided to change the layout of mozc, but mozc doesn't have an interface to change the layout.</p>
<p>I wrote a patch to make mozc same to Kotoeri's.</p>
<p>kana-layout.patch:</p>
<pre><code>Index: unix/ibus/key_translator.cc
===================================================================
--- unix/ibus/key_translator.cc (revision 94)
+++ unix/ibus/key_translator.cc (working copy)
@@ -254,100 +254,100 @@
// to Right Shift).
{ '\\', "", "" },
}, kana_map_us[] = {
- { '`' , "\xe3\x82\x8d", "\xe3\x82\x8d" }, // "ろ", "ろ"
- { '~' , "\xe3\x82\x8d", "\xe3\x82\x8d" }, // "ろ", "ろ"
- { '1' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
- { '!' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
- { '2' , "\xe3\x81\xb5", "\xe3\x81\xb5" }, // "ふ", "ふ"
+ { '$' , "\xe3\x81\x85", "\xe3\x81\x85" }, // "ぅ", "ぅ"
+ { '(' , "\xe3\x82\x87", "\xe3\x82\x87" }, // "ょ", "ょ"
+ { ',' , "\xe3\x81\xad", "\xe3\x81\xad" }, // "ね", "ね"
+ { '0' , "\xe3\x82\x8f", "\xe3\x82\x8f" }, // "わ", "わ"
+ { '4' , "\xe3\x81\x86", "\xe3\x81\x86" }, // "う", "う"
+ { '8' , "\xe3\x82\x86", "\xe3\x82\x86" }, // "ゆ", "ゆ"
+ { '<' , "\xe3\x80\x81", "\xe3\x80\x81" }, // "、", "、"
{ '@' , "\xe3\x81\xb5", "\xe3\x81\xb5" }, // "ふ", "ふ"
- { '3' , "\xe3\x81\x82", "\xe3\x81\x81" }, // "あ", "ぁ"
- { '#' , "\xe3\x81\x82", "\xe3\x81\x81" }, // "あ", "ぁ"
- { '4' , "\xe3\x81\x86", "\xe3\x81\x85" }, // "う", "ぅ"
- { '$' , "\xe3\x81\x86", "\xe3\x81\x85" }, // "う", "ぅ"
- { '5' , "\xe3\x81\x88", "\xe3\x81\x87" }, // "え", "ぇ"
- { '%' , "\xe3\x81\x88", "\xe3\x81\x87" }, // "え", "ぇ"
- { '6' , "\xe3\x81\x8a", "\xe3\x81\x89" }, // "お", "ぉ"
- { '^' , "\xe3\x81\x8a", "\xe3\x81\x89" }, // "お", "ぉ"
- { '7' , "\xe3\x82\x84", "\xe3\x82\x83" }, // "や", "ゃ"
- { '&' , "\xe3\x82\x84", "\xe3\x82\x83" }, // "や", "ゃ"
- { '8' , "\xe3\x82\x86", "\xe3\x82\x85" }, // "ゆ", "ゅ"
- { '*' , "\xe3\x82\x86", "\xe3\x82\x85" }, // "ゆ", "ゅ"
- { '9' , "\xe3\x82\x88", "\xe3\x82\x87" }, // "よ", "ょ"
- { '(' , "\xe3\x82\x88", "\xe3\x82\x87" }, // "よ", "ょ"
- { '0' , "\xe3\x82\x8f", "\xe3\x82\x92" }, // "わ", "を"
- { ')' , "\xe3\x82\x8f", "\xe3\x82\x92" }, // "わ", "を"
- { '-' , "\xe3\x81\xbb", "\xe3\x83\xbc" }, // "ほ", "ー"
- { '_' , "\xe3\x81\xbb", "\xe3\x83\xbc" }, // "ほ", "ー"
- { '=' , "\xe3\x81\xb8", "\xe3\x81\xb8" }, // "へ", "へ"
- { '+' , "\xe3\x81\xb8", "\xe3\x81\xb8" }, // "へ", "へ"
- { 'q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
- { 'Q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
- { 'w' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
- { 'W' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
- { 'e' , "\xe3\x81\x84", "\xe3\x81\x83" }, // "い", "ぃ"
- { 'E' , "\xe3\x81\x84", "\xe3\x81\x83" }, // "い", "ぃ"
- { 'r' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
- { 'R' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
+ { 'D' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
+ { 'H' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
+ { 'L' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
+ { 'P' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
+ { 'T' , "\xe3\x81\x8b", "\xe3\x81\x8b" }, // "か", "か"
+ { 'X' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
+ { '\\' , "\xe3\x81\xb8", "\xe3\x81\xb8" }, // "へ", "へ"
+ { '`' , "\xef\xbd\x80", "\xef\xbd\x80" }, // "`", "`"
+ { 'd' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
+ { 'h' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
+ { 'l' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
+ { 'p' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
{ 't' , "\xe3\x81\x8b", "\xe3\x81\x8b" }, // "か", "か"
- { 'T' , "\xe3\x81\x8b", "\xe3\x81\x8b" }, // "か", "か"
- { 'y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
- { 'Y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
- { 'u' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
- { 'U' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
- { 'i' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
- { 'I' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
- { 'o' , "\xe3\x82\x89", "\xe3\x82\x89" }, // "ら", "ら"
+ { 'x' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
+ { '|' , "\xe3\x82\x8d", "\xe3\x82\x8d" }, // "ろ", "ろ"
+ { '#' , "\xe3\x81\x81", "\xe3\x81\x81" }, // "ぁ", "ぁ"
+ { '\'' , "\xe3\x81\x91", "\xe3\x81\x91" }, // "け", "け"
+ { '+' , "\xe3\x80\x8c", "\xe3\x80\x8c" }, // "「", "「"
+ { '/' , "\xe3\x82\x81", "\xe3\x82\x81" }, // "め", "め"
+ { '3' , "\xe3\x81\x82", "\xe3\x81\x82" }, // "あ", "あ"
+ { '7' , "\xe3\x82\x84", "\xe3\x82\x84" }, // "や", "や"
+ { ';' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
+ { '?' , "\xe3\x83\xbb", "\xe3\x83\xbb" }, // "・", "・"
+ { 'C' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
+ { 'G' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
+ { 'K' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
{ 'O' , "\xe3\x82\x89", "\xe3\x82\x89" }, // "ら", "ら"
- { 'p' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
- { 'P' , "\xe3\x81\x9b", "\xe3\x81\x9b" }, // "せ", "せ"
+ { 'S' , "\xe3\x81\xa8", "\xe3\x81\xa8" }, // "と", "と"
+ { 'W' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
{ '[' , "\xe3\x82\x9b", "\xe3\x82\x9b" }, // "゛", "゛"
- { '{' , "\xe3\x82\x9b", "\xe3\x82\x9b" }, // "゛", "゛"
- { ']' , "\xe3\x82\x9c", "\xe3\x80\x8c" }, // "゜", "「"
- { '}' , "\xe3\x82\x9c", "\xe3\x80\x8c" }, // "゜", "「"
- { '\\', "\xe3\x82\x80", "\xe3\x80\x8d" }, // "む", "」"
- { '|' , "\xe3\x82\x80", "\xe3\x80\x8d" }, // "む", "」"
- { 'a' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
- { 'A' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
+ { '_' , "\xe3\x81\xbb", "\xe3\x81\xbb" }, // "ほ", "ほ"
+ { 'c' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
+ { 'g' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
+ { 'k' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
+ { 'o' , "\xe3\x82\x89", "\xe3\x82\x89" }, // "ら", "ら"
{ 's' , "\xe3\x81\xa8", "\xe3\x81\xa8" }, // "と", "と"
- { 'S' , "\xe3\x81\xa8", "\xe3\x81\xa8" }, // "と", "と"
- { 'd' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
- { 'D' , "\xe3\x81\x97", "\xe3\x81\x97" }, // "し", "し"
- { 'f' , "\xe3\x81\xaf", "\xe3\x81\xaf" }, // "は", "は"
+ { 'w' , "\xe3\x81\xa6", "\xe3\x81\xa6" }, // "て", "て"
+ { '{' , "\xe3\x80\x8d", "\xe3\x80\x8d" }, // "」", "」"
+ { '"' , "\xe3\x82\x8d", "\xe3\x82\x8d" }, // "ろ", "ろ"
+ { '&' , "\xe3\x82\x83", "\xe3\x82\x83" }, // "ゃ", "ゃ"
+ { '*' , "\xe3\x82\x85", "\xe3\x82\x85" }, // "ゅ", "ゅ"
+ { '.' , "\xe3\x82\x8b", "\xe3\x82\x8b" }, // "る", "る"
+ { '2' , "\xe3\x81\xb5", "\xe3\x81\xb5" }, // "ふ", "ふ"
+ { '6' , "\xe3\x81\x8a", "\xe3\x81\x8a" }, // "お", "お"
+ { ':' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
+ { '>' , "\xe3\x80\x82", "\xe3\x80\x82" }, // "。", "。"
+ { 'B' , "\xe3\x81\x93", "\xe3\x81\x93" }, // "こ", "こ"
{ 'F' , "\xe3\x81\xaf", "\xe3\x81\xaf" }, // "は", "は"
- { 'g' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
- { 'G' , "\xe3\x81\x8d", "\xe3\x81\x8d" }, // "き", "き"
- { 'h' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
- { 'H' , "\xe3\x81\x8f", "\xe3\x81\x8f" }, // "く", "く"
- { 'j' , "\xe3\x81\xbe", "\xe3\x81\xbe" }, // "ま", "ま"
{ 'J' , "\xe3\x81\xbe", "\xe3\x81\xbe" }, // "ま", "ま"
- { 'k' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
- { 'K' , "\xe3\x81\xae", "\xe3\x81\xae" }, // "の", "の"
- { 'l' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
- { 'L' , "\xe3\x82\x8a", "\xe3\x82\x8a" }, // "り", "り"
- { ';' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
- { ':' , "\xe3\x82\x8c", "\xe3\x82\x8c" }, // "れ", "れ"
- { '\'', "\xe3\x81\x91", "\xe3\x81\x91" }, // "け", "け"
- { '\"', "\xe3\x81\x91", "\xe3\x81\x91" }, // "け", "け"
- { 'z' , "\xe3\x81\xa4", "\xe3\x81\xa3" }, // "つ", "っ"
- { 'Z' , "\xe3\x81\xa4", "\xe3\x81\xa3" }, // "つ", "っ"
- { 'x' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
- { 'X' , "\xe3\x81\x95", "\xe3\x81\x95" }, // "さ", "さ"
- { 'c' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
- { 'C' , "\xe3\x81\x9d", "\xe3\x81\x9d" }, // "そ", "そ"
- { 'v' , "\xe3\x81\xb2", "\xe3\x81\xb2" }, // "ひ", "ひ"
+ { 'N' , "\xe3\x81\xbf", "\xe3\x81\xbf" }, // "み", "み"
+ { 'R' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
{ 'V' , "\xe3\x81\xb2", "\xe3\x81\xb2" }, // "ひ", "ひ"
+ { 'Z' , "\xe3\x81\xa3", "\xe3\x81\xa3" }, // "っ", "っ"
+ { '^' , "\xe3\x81\x89", "\xe3\x81\x89" }, // "ぉ", "ぉ"
{ 'b' , "\xe3\x81\x93", "\xe3\x81\x93" }, // "こ", "こ"
- { 'B' , "\xe3\x81\x93", "\xe3\x81\x93" }, // "こ", "こ"
+ { 'f' , "\xe3\x81\xaf", "\xe3\x81\xaf" }, // "は", "は"
+ { 'j' , "\xe3\x81\xbe", "\xe3\x81\xbe" }, // "ま", "ま"
{ 'n' , "\xe3\x81\xbf", "\xe3\x81\xbf" }, // "み", "み"
- { 'N' , "\xe3\x81\xbf", "\xe3\x81\xbf" }, // "み", "み"
+ { 'r' , "\xe3\x81\x99", "\xe3\x81\x99" }, // "す", "す"
+ { 'v' , "\xe3\x81\xb2", "\xe3\x81\xb2" }, // "ひ", "ひ"
+ { 'z' , "\xe3\x81\xa4", "\xe3\x81\xa4" }, // "つ", "つ"
+ { '~' , "\xe3\x80\x9c", "\xe3\x80\x9c" }, // "〜", "〜"
+ { '!' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
+ { '%' , "\xe3\x81\x87", "\xe3\x81\x87" }, // "ぇ", "ぇ"
+ { ')' , "\xe3\x82\x92", "\xe3\x82\x92" }, // "を", "を"
+ { '-' , "\xe3\x81\xbb", "\xe3\x81\xbb" }, // "ほ", "ほ"
+ { '1' , "\xe3\x81\xac", "\xe3\x81\xac" }, // "ぬ", "ぬ"
+ { '5' , "\xe3\x81\x88", "\xe3\x81\x88" }, // "え", "え"
+ { '9' , "\xe3\x82\x88", "\xe3\x82\x88" }, // "よ", "よ"
+ { '=' , "\xe3\x82\x9c", "\xe3\x82\x9c" }, // "゜", "゜"
+ { 'A' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
+ { 'E' , "\xe3\x81\x83", "\xe3\x81\x83" }, // "ぃ", "ぃ"
+ { 'I' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
+ { 'M' , "\xe3\x82\x82", "\xe3\x82\x82" }, // "も", "も"
+ { 'Q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
+ { 'U' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
+ { 'Y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
+ { ']' , "\xe3\x82\x80", "\xe3\x82\x80" }, // "む", "む"
+ { 'a' , "\xe3\x81\xa1", "\xe3\x81\xa1" }, // "ち", "ち"
+ { 'e' , "\xe3\x81\x84", "\xe3\x81\x84" }, // "い", "い"
+ { 'i' , "\xe3\x81\xab", "\xe3\x81\xab" }, // "に", "に"
{ 'm' , "\xe3\x82\x82", "\xe3\x82\x82" }, // "も", "も"
- { 'M' , "\xe3\x82\x82", "\xe3\x82\x82" }, // "も", "も"
- { ',' , "\xe3\x81\xad", "\xe3\x80\x81" }, // "ね", "、"
- { '<' , "\xe3\x81\xad", "\xe3\x80\x81" }, // "ね", "、"
- { '.' , "\xe3\x82\x8b", "\xe3\x80\x82" }, // "る", "。"
- { '>' , "\xe3\x82\x8b", "\xe3\x80\x82" }, // "る", "。"
- { '/' , "\xe3\x82\x81", "\xe3\x83\xbb" }, // "め", "・"
- { '?' , "\xe3\x82\x81", "\xe3\x83\xbb" }, // "め", "・"
+ { 'q' , "\xe3\x81\x9f", "\xe3\x81\x9f" }, // "た", "た"
+ { 'u' , "\xe3\x81\xaa", "\xe3\x81\xaa" }, // "な", "な"
+ { 'y' , "\xe3\x82\x93", "\xe3\x82\x93" }, // "ん", "ん"
+ { '}' , "\xe3\x83\xbc", "\xe3\x83\xbc" }, // "ー", "ー"
};
} // namespace
Index: unix/ibus/mozc_engine.cc
===================================================================
--- unix/ibus/mozc_engine.cc (revision 94)
+++ unix/ibus/mozc_engine.cc (working copy)
@@ -542,8 +542,7 @@
#endif
// TODO(yusukes): use |layout| in IBusEngineDesc if possible.
- const bool layout_is_jp =
- !g_strcmp0(ibus_engine_get_name(engine), "mozc-jp");
+ const bool layout_is_jp = 0;
commands::KeyEvent key;
if (!key_translator_->Translate(
</code></pre>
<p>Here I also made an ebuild for the latest ibus-mozc on gentoo portage. You can just use it if you are a Gentoo user.</p>
<p><a href="http://ujihisa.shiracha.net/static/ibus-mozc-1.3.975.102.tgz"><code class="url">http://ujihisa.shiracha.net/static/ibus-mozc-1.3.975.102.tgz</code></a></p>
<ul>
<li>*1 There are more variety of other input methods like thumb-shift or kyuuri-kai.</li>
</ul>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-1771111207071296982012-02-05T00:17:00.001-08:002012-02-05T00:17:41.073-08:00Realtek RTL8191S WLAN Adapter on Gentoo<p>I bought a wireless network adapter for my Gentoo desktop computer. It's a usb dongle and it says it's Linux-compatible.</p>
<div class="figure">
<img src="http://ecx.images-amazon.com/images/I/31uJCtlzTvL._SL500_AA300_.jpg" alt="RealTek 8191SU" /><p class="caption">RealTek 8191SU</p>
</div>
<p>How to use:</p>
<pre><code>Device Drivers ->
Staging drivers ->
RealTek RTL8712U (RTL8192SU) Wireless LAN NIC driver
</code></pre>
<p>In the menuconfig.</p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-4744950875013244912012-01-22T12:04:00.001-08:002012-01-24T10:25:44.226-08:00AutoKey Rocks<p>Mac OS X has a built-in keyboard shortcut configuration tool in Preferences. You can set both global key bindings and application-specific key bindings.</p>
<p>I had used this to use Cmd key more often than Ctrl key. For example Google Chrome has default key mappings to go to the next tab by <code><ctrl-tab></code> and to the previous tab by <code><shift-ctrl-tab></code>. They break your left pinky easily. I mapped them ad <code><Cmd-j></code> and <code><Cmd-k></code>. That helped the finger.</p>
<p>But there is no such great built-in tool in the Linux world neither in Gnome nor KDE. There is a Keyboard Shortcuts in Preference of Gnome, but it's only for Gnome apps.</p>
<h2 id="autokey">AutoKey</h2>
<p>AutoKey is a similar tool to the Mac OS X built-in keybinding configuration tool. The differences are (1) AutoKey doesn't map a key to a function in the application's menu and (2) AutoKey enables you to run arbitrary scripts.</p>
<p>It's very easy to install on Debian family distributions such as Ubuntu. Gentoo, on the other hand, has an overlay that has autokey-gtk package, but it's broken. You have to get the source code and build it. It also requires you to install some dependencies manually, but it works.</p>
<div class="figure">
<img src="http://cache.gyazo.com/df0a1bcb43c0543b7bea4efcb539ce7a.png" alt="autokey-gtk on gentoo" /><p class="caption">autokey-gtk on gentoo</p>
</div>
<h2 id="added-on-jan-24-2012">(Added on Jan 24 2012)</h2>
<p>There is an issue in autokey that you cannot exclude a window easily. See the end of this discussion to solve it. <a href="http://groups.google.com/group/autokey-users/browse_thread/thread/658ad02cfbde8788"><code class="url">http://groups.google.com/group/autokey-users/browse_thread/thread/658ad02cfbde8788</code></a></p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-69849123270347101002011-12-26T01:14:00.001-08:002011-12-26T01:14:22.612-08:00Compiling a Language to Whitespace<p><a href="http://en.wikipedia.org/wiki/Whitespace_(programming_language)">Whitespace</a> is a widely-known instruction set on a stack-machine virtual machine.</p>
<p>The below is a sample hello world in Whitespace intermediate language. I added some notes that begin with #.</p>
<table width="100%"><tr valign="top">
<td width="50%"><pre wrap="wrap">
Push 0
Push 72
Store
# storing the value 72 to 0th heap
Push 1
Push 101
Store
# storing the value 101 to 1st heap
Push 2
Push 108
Store
Push 3
Push 108
Store
Push 4
Push 111
Store
Push 5
Push 44
Store
Push 6
Push 32
Store
Push 7
Push 119
Store
Push 8
Push 111
Store
Push 9
Push 114
Store
Push 10
Push 108
Store
Push 11
Push 100
Store
Push 12
Push 32
Store
Push 13
Push 111
Store
Push 14
Push 102
Store
Push 15
Push 32
Store
Push 16
Push 115
Store
Push 17
Push 112
Store
Push 18
Push 97
Store
Push 19
Push 99
Store
Push 20
Push 101
Store
Push 21
Push 115
Store
# (cont.d...)
</pre></td>
<td width="50%"><pre wrap="wrap">
Push 22
Push 33
Store
Push 23
Push 0
Store
Push 0
Call "\t \t \t\t \t \t\t\t \t \t \t\t \t \t\t\t \t\t\t \t\t\t "
# Jumping to the ☃ mark with remembering this place to return later
Call "\t \t \t\t \t\t\t \t\t \t \t \t\t \t\t \t\t \t\t\t \t\t\t \t \t \t\t \t\t\t \t\t "
# Jumping to the ☁ mark with remembering this place to return later
End
# Terminating program.
Label " \t \t\t \t \t\t \t \t\t "
Infix Plus
Return
Label "\t \t \t\t \t \t\t\t \t \t \t\t \t \t\t\t \t\t\t \t\t\t "
# ☃
Dup
# Copying the top value of the stack. It's 0 (if you see here for the first time.)
Retrieve
# Getting the 0th value of the heap. It's 72 (if you see here for the first time.)
Dup
If Zero " \t \t\t \t\t\t \t\t \t \t \t\t \t\t\t\t\t \t \t \t \t\t \t \t\t\t \t \t \t\t \t \t\t\t \t\t\t \t\t\t "
OutputChar
Push 1
Infix Plus
Jump "\t \t \t\t \t \t\t\t \t \t \t\t \t \t\t\t \t\t\t \t\t\t "
Label " \t \t\t \t\t\t \t\t \t \t \t\t \t\t\t\t\t \t \t \t \t\t \t \t\t\t \t \t \t\t \t \t\t\t \t\t\t \t\t\t "
Discard
Discard
Return
# Ending the function call and going back to the previous place.
Label " \t \t\t \t \t\t \t \t \t\t \t \t\t\t "
Dup
Dup
ReadChar
Retrieve
Dup
Push 10
Infix Minus
If Zero " \t \t\t \t\t\t \t\t \t \t \t\t \t\t\t\t\t \t \t \t\t \t \t\t \t \t \t\t \t \t\t\t "
Discard
Push 1
Infix Plus
Jump " \t \t\t \t \t\t \t \t \t\t \t \t\t\t "
Label " \t \t\t \t\t\t \t\t \t \t \t\t \t\t\t\t\t \t \t \t\t \t \t\t \t \t \t\t \t \t\t\t "
Discard
Push 1
Infix Plus
Push 0
Store
Return
Label "\t \t \t\t \t\t\t \t\t \t \t \t\t \t\t \t\t \t\t\t \t\t\t \t \t \t\t \t\t\t \t\t "
# ☁
Push 10
Push 13
OutputChar
OutputChar
Return
</pre></td>
</tr></table>
<p>And the result is</p>
<pre><code>Hello, world of spaces!
</code></pre>
<p>You can run it with a little bit fixes of the official whitespace implementation <a href="http://compsoc.dur.ac.uk/whitespace/download.php">wspace 0.3</a> written in Haskell.</p>
<h2 id="a-language">A Language</h2>
<p>I made an experimental small language and it's compiler.</p>
<pre><code>(begin
(def 0 98)
(f 90 7)
(putc (ref 0))
(end)
(defn f (x y)
(putc (g x y)))
(defn g (x y)
(+ x y)))
</code></pre>
<p>Syntax: an expression begins with "(" and a name, arguments for it, and end with ")". If an expression has a value, you have to use the value with enclosing another expression. Otherwise the behavior is undefined. If an expression does not have a value, you must not enclose it as an argument. Otherwise the behavior is undefined.</p>
<ul>
<li>begin
<ul>
<li>combines some expressions that don't have return values</li>
</ul></li>
<li>def {index} {value}
<ul>
<li>assigns the {value} to {index}th slot of heap</li>
</ul></li>
<li>ref {index} -> {value}
<ul>
<li>returns the {value} of {index}th slot of heap</li>
</ul></li>
<li>putc {value}
<ul>
<li>outputs a character which ASCII code is {value}</li>
</ul></li>
<li>end
<ul>
<li>terminates program</li>
</ul></li>
<li>defn {name} ({args}) {body}
<ul>
<li>defines a function</li>
<li>if a program come to defn without using call, the behavior is undefined.</li>
</ul></li>
</ul>
<p>* + {value} {value} -> {value} * obviously</p>
<p>You can "call" a function you made just with ({name} {arg1} {arg2}). You can use arguments of the function just by an identifier like x.</p>
<p>Sample code</p>
<pre><code>(begin
(putc (+ 50 40))
(end))
</code></pre>
<p>That is compiled to</p>
<pre><code>Push 50
Push 40
Infix Plus
OutputChar
End
</code></pre>
<p>and shows 'Z'.</p>
<p>I little bit complicated example</p>
<pre><code>(begin
(def 0 98)
(f 90 7)
(putc (ref 0))
(end)
(defn f (x y)
(putc (g x y)))
(defn g (x y)
(+ x y)))
</code></pre>
<p>compiled to</p>
<pre><code>Push 0
Push 98
Store
Push 90
Push 7
Call "f"
Push 0
Retrieve
OutputChar
End
Label "f"
Push (-1)
Swap
Store
Push (-2)
Swap
Store
Push (-1)
Retrieve
Push (-2)
Retrieve
Call "g"
OutputChar
Return
Label "g"
Push (-3)
Swap
Store
Push (-4)
Swap
Store
Push (-3)
Retrieve
Push (-4)
Retrieve
Infix Plus
Return
</code></pre>
<p>and shows "ab".</p>
<p>You may have noticed that the function argument is in negative number of heaps. If you updates them like by <code>(def -3 100)</code> it may result in breaking something, but since this implementation doesn't support negative literals, it remains safe.</p>
<p>The compiler is below, written in Haskell.</p>
<pre><code>import qualified VM as V
import qualified Text.Parsec as P
import Control.Applicative ((<|>), (<$>))
import qualified Control.Monad.State as S
import qualified Data.Map as M
import Data.Maybe (fromJust)
data Intermediate = Comment String
| Inst V.Instruction
| Paramdef String
| Paramref String
deriving Show
type LispParser = P.ParsecT String () (S.State String)
type ParamMap = M.Map String Integer
main :: IO ()
main = do
code <- readFile "hworld.lisp"
--mapM_ print $ parse code
let runtime = compile (parse code)
mapM_ print runtime
putStrLn "--"
V.vm (V.VM runtime (V.Stack []) (V.Stack []) M.empty 0)
parse :: String -> [Intermediate]
parse str = either (error . show) id $
S.evalState (P.runPT parseExpr () "lisp" str) "toplevel"
parseExpr :: LispParser [Intermediate]
parseExpr = P.try parseInt
<|> parseDefn
<|> parseBuiltin
<|> parseApply
<|> parseVar
parseInt :: LispParser [Intermediate]
parseInt = do
x <- P.many1 P.digit
return [Inst $ V.Push $ read x]
parseAtom :: LispParser String
parseAtom = P.many1 $ P.noneOf " \t\n()"
parseDefn :: LispParser [Intermediate]
parseDefn = do
P.try $ do
ignoringSpaces $ P.char '('
ignoringSpaces $ P.string "defn"
fname <- requireSpaces parseAtom
S.lift $ S.put fname
ignoringSpaces $ P.char '('
names <- ignoringSpaces $ parseAtom `P.sepBy` P.skipMany1 P.space
ignoringSpaces $ P.char ')'
body <- ignoringSpaces parseExpr
ignoringSpaces $ P.char ')'
S.lift $ S.put "toplevel"
return $
Comment "(defn" :
Inst (V.Label fname) :
map (Paramdef . ((fname ++ "/") ++)) names ++
body ++ [Inst V.Return] ++ [Comment ")"]
parseBuiltin :: LispParser [Intermediate]
parseBuiltin = P.try $ do
(fname, xs) <- atomAndArgs
x <- case (fname, length xs) of
("+", 2) -> return [Inst $ V.Infix V.Plus]
("putc", 1) -> return [Inst V.OutputChar]
("def", 2) -> return [Inst V.Store]
("ref", 1) -> return [Inst V.Retrieve]
("end", 0) -> return [Inst V.End]
("begin", _) -> return []
_ -> fail "omg"
return $ Comment ('(' : fname) : concat xs ++ x ++ [Comment ")"]
parseApply :: LispParser [Intermediate]
parseApply = do
(fname, xs) <- atomAndArgs
return $ concat xs ++ [Inst $ V.Call fname]
atomAndArgs :: LispParser (String, [[Intermediate]])
atomAndArgs = do
ignoringSpaces $ P.char '('
fname <- ignoringSpaces parseAtom
xs <- ignoringSpaces $ parseExpr `P.sepBy` P.many1 P.space
P.char ')'
return (fname, xs)
parseVar :: LispParser [Intermediate]
parseVar = do
name <- ignoringSpaces $ P.many1 $ P.noneOf " \t\n()"
fname <- S.lift S.get
return [Paramref $ fname ++ '/' : name]
ignoringSpaces :: LispParser a -> LispParser a
ignoringSpaces f = P.skipMany P.space >> f
requireSpaces :: LispParser a -> LispParser a
requireSpaces f = P.skipMany1 P.space >> f
compile :: [Intermediate] -> [V.Instruction]
compile inters = concat $ S.evalState (mapM compile' inters) M.empty
compile' :: Intermediate -> S.State ParamMap [V.Instruction]
compile' (Comment _) = return []
compile' (Inst x) = return [x]
compile' (Paramdef name) = do
idx <- pred . negate . fromIntegral . M.size <$> S.get
S.modify $ M.insert name idx
return [V.Push idx, V.Swap, V.Store]
compile' (Paramref name) = do
idx <- fromJust . M.lookup name <$> S.get
return [V.Push idx, V.Retrieve]
</code></pre>
<p>This code depends on VM.hs from wspace-0.3 to share the data structure of VM Instruction and to execute the compiled program. If you only want to compile given programs, you don't need VM.hs but just to add the following definition.</p>
<pre><code>data Instruction =
Push Integer
| Dup
| Ref Int
| Slide Int
| Swap
| Discard
| Infix Op
| Store
| Retrieve
| Label Label
| Call Label
| Jump Label
| If Test Label
| Return
| OutputChar
| OutputNum
| ReadChar
| ReadNum
| End
deriving (Show,Eq)
</code></pre>
<p>By the way wspace-0.3 had an issue that it can only handle sequential indices of heap. You can store values in 0th, 1st and 2nd slots of heap, but you cannot store in 100th without completing all indices between 0 to 100. I wrote a patch to allow any index. Feel free to use it.</p>
<pre><code>diff --git VM.hs VM.hs
index c9e96ab..bb74374 100644
--- VM.hs
+++ VM.hs
@@ -1,6 +1,8 @@
module VM where
import IO
+import qualified Data.Map as M
+import Data.Maybe (fromJust)
{- Stack machine for running whitespace programs -}
@@ -35,7 +37,7 @@ type Loc = Integer
type Program = [Instruction]
newtype Stack = Stack [Integer]
-type Heap = [Integer]
+type Heap = M.Map Integer Integer
data VMState = VM {
program :: Program,
@@ -130,13 +132,7 @@ findLabel' m (_:xs) i = findLabel' m xs (i+1)
-- Heap management
retrieve :: Integer -> Heap -> IO Integer
-retrieve x heap = return (heap!!(fromInteger x))
+retrieve x heap = return $ fromJust $ M.lookup x heap
store :: Integer -> Integer -> Heap -> IO Heap
-store x 0 (h:hs) = return (x:hs)
-store x n (h:hs) = do hp <- store x (n-1) hs
- return (h:hp)
-store x 0 [] = return (x:[])
-store x n [] = do hp <- store x (n-1) []
- return (0:hp)
-
+store x n h = return $ M.insert n x h
</code></pre>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-56789225552231481972011-12-22T22:13:00.001-08:002011-12-22T22:22:17.980-08:00Continuous-Passing Conversion in Haskell<p><a href="http://en.wikipedia.org/wiki/Continuation-passing_style"><code class="url">http://en.wikipedia.org/wiki/Continuation-passing_style</code></a></p>
<p>Convert from</p>
<pre><code>(+ (f 0 (g 1)) 2)
</code></pre>
<p>to</p>
<pre><code>(g' (lambda (r0) (f' (lambda (r1) (+ r1 2)) 0 r0)) 1)
</code></pre>
<p>where data structure internally in Haskell is like</p>
<pre><code>data AST = Node [AST] | Leaf Value
data Value = IntVal Int | Plus | Atom String | Lambda [String]
</code></pre>
<h2 id="implementation-and-description">Implementation and description</h2>
<pre><code>import qualified Control.Monad.State as S
data AST = Node [AST] | Leaf Value
instance Show AST where
show (Node xs) = "(" ++ unwords (map show xs) ++ ")"
show (Leaf v) = show v
data Value = IntVal Int | Plus | Atom String | Lambda [String]
instance Show Value where
show (IntVal i) = show i
show Plus = "+"
show (Atom name) = name
show (Lambda names) = "lambda (" ++ unwords names ++ ")"
-- (+ (f 0 (g 1)) 2)
-- (g' (lambda (r0) (f' (lambda (r1) (+ r1 2)) 0 r0)) 1)
program :: AST
program = Node [Leaf Plus,
Node [Leaf (Atom "f"), Leaf (IntVal 0), Node [Leaf (Atom "g"), Leaf (IntVal 1)]],
Leaf (IntVal 2)]
main = do
print program
print $ cps program
cps :: AST -> AST
cps ast =
let (newAst, modifiers) = S.runState (cps' ast) [] in
foldl (flip ($)) newAst modifiers
cps' :: AST -> S.State [AST -> AST] AST
cps' (Node (Leaf (Atom f) : xs)) = do
xs' <- mapM cps' xs
n <- length `fmap` S.get
let name = 'r' : show n
append $ \root -> Node $
(Leaf . Atom $ f ++ "'") :
Node [Leaf (Lambda [name]), root] :
xs'
return $ Leaf (Atom name)
cps' (Node xs) = Node `fmap` mapM cps' xs
cps' c@(Leaf _) = return c
append x = S.modify (x :)
</code></pre>
<p>This converts correctly.</p>
<p>I used State Monad to modify given tree. The function <code>cps</code> starts state and the actual function <code>cps'</code> traverses given AST subtrees recursively.</p>
<pre><code>(+ (f 0 (g 1)) 2)
^^^^^^^^^^^
</code></pre>
<p>When <code>cps'</code> sees this subtree, oh yes the first item of the list is a user-defined function and it's not tail-call, so <code>cps'</code> wants to replace the part with a new variable (say <code>r</code>), and enclose whole tree with new function <code>f'</code> and the arguments.</p>
<pre><code>(f' (lambda (r) ((+ r 2) 0 (g 1))))
^^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^
</code></pre>
<p>It's easy to change subtree but it's not trivial to change outside the subtree. But fortunately we already know that we only have to enclose something around the whole tree, so you can just save a function in state.</p>
<p>After <code>cps'</code> process is done, you apply all functions that the state has accumulatively to enclose trees. That will complete the job.</p>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-69823894240528251292011-12-20T20:56:00.001-08:002011-12-21T00:02:50.547-08:00Unlambda Interpreter in Haskell<blockquote>
<p>Unlambda is a minimal, "nearly pure"[1] functional programming language invented by David Madore. It is based on combinatory logic, a version of the lambda calculus that omits the lambda operator. It relies mainly on two built-in functions (s and k) and an "apply" operator (written `, the backquote character). These alone make it Turing-complete, but there are also some I/O functions to make it possible to interact with the user, some shortcut functions and a function for lazy evaluation. There are no variables in the language.</p>
<p><a href="http://en.wikipedia.org/wiki/Unlambda"><code class="url">http://en.wikipedia.org/wiki/Unlambda</code></a></p>
</blockquote>
<pre><code>import qualified Text.Parsec as P
import Control.Applicative ((*>), (<$>), (<*>))
data AST = Apply AST AST | Val Value
instance Show AST where
show (Apply a b) = "(" ++ show a ++ " " ++ show b ++ ")"
show (Val (Dot c)) = "put-" ++ [c]
show (Val (Builtin c)) = [c]
data Value = Dot Char
| Builtin Char
| PendingK Value
| PendingS1 Value
| PendingS2 Value Value
deriving Show
main = do
let helloworld = "`r```````````.H.e.l.l.o. .w.o.r.l.di"
let fibonacci = "```s``s``sii`ki`k.*``s``s`ks``s`k`s`ks``s``s`ks``s`k`s`kr``s`k`sikk`k``s`ksk"
print $ desugar $ parse helloworld
eval $ desugar $ parse helloworld
--eval $ desugar $ parse fibonacci
parse :: String -> AST
parse = either (error . show) id . P.parse parse' "unlambda"
parse' = P.try (P.char '`' *> (Apply <$> parse' <*> parse'))
P.<|>
P.try (P.char '.' *> (Val . Dot <$> P.anyChar))
P.<|>
P.try (Val . Builtin <$> P.anyChar)
desugar :: AST -> AST
desugar (Apply a b) = Apply (desugar a) (desugar b)
desugar (Val (Builtin 'r')) = Val (Dot '\n')
desugar (Val (Builtin 'i')) = Apply (Apply (Val (Builtin 's')) (Val (Builtin 'k'))) (Val (Builtin 'k')) -- i = ``skk
desugar x = x
eval :: AST -> IO (Value)
eval (Apply a b) = do
a' <- eval a
b' <- eval b
apply a' b'
eval (Val x) = return x
apply :: Value -> Value -> IO Value
apply (Dot c) x = putChar c >> return x
apply (Builtin 'k') x = return $ PendingK x
apply (Builtin 's') x = return $ PendingS1 x
apply (PendingK x) y = return $ x
apply (PendingS1 x) y = return $ PendingS2 x y
apply (PendingS2 x y) z = do
a <- apply x z
b <- apply y z
apply a b
</code></pre>
<ol style="list-style-type: decimal">
<li>parse the given string to abstract syntax tree</li>
<li>desugar the ast; expanding macros like r or i.</li>
<li>interpreter evaluates all nodes!</li>
</ol>
<p>AST</p>
<pre><code>(put-\n (((((((((((put-H put-e) put-l) put-l) put-o) put- ) put-w) put-o) put-r) put-l) put-d) ((s k) k)))
</code></pre>
<p>Result of <code>helloworld</code></p>
<pre><code>Hello world
</code></pre>
<p>Result of <code>fibonacci</code></p>
<pre><code>*
*
**
***
*****
********
*************
*********************
**********************************
*******************************************************
*****************************************************************************************
</code></pre>
<h2 id="added-at-tue-dec-20-235712-pst-2011">(added at Tue Dec 20 23:57:12 PST 2011)</h2>
<p>I also made a stackmachine-based virtual machine and a compiler for it.</p>
<p><a href="https://gist.github.com/1505131"><code class="url">https://gist.github.com/1505131</code></a></p>
<p>This was actually much simpler/easier than I thought. There's a difference between pure interpreter and this virtualmachine, but it's not very big.</p>
<p>For example very short program "hi" that shows "hi" is "``.h.ii" in unlambda. First this parser converts the text to AST.</p>
<pre><code>((put-h put-i) ((s k) k))
</code></pre>
<p>Then the compiler converts the tree to sequence of instructions.</p>
<pre><code>IPush (Dot 'h')
IPush (Dot 'i')
IApply
IPush (Builtin 's')
IPush (Builtin 'k')
IApply
IPush (Builtin 'k')
IApply
IApply
</code></pre>
<p>Then the virtualmachine runtime will run it.</p>
<pre><code>hi
</code></pre>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0tag:blogger.com,1999:blog-8477445975588753706.post-52768571769795938522011-12-18T18:29:00.001-08:002011-12-18T18:29:13.279-08:00Read Raw POST Request Body in Compojure
<div xmlns='http://www.w3.org/1999/xhtml'>
<h2 id='brief-introduction-to-compojure'>Brief introduction to Compojure</h2>
<p>Compojure gives you a shortcut to make a monofunctional web application. For example a Lingr bot is a web application that only need to be responsible with one single endpoint that handles POST request. The below is a web application that only shows "hello" in / endpoint with GET request.</p>
<pre><code>(defroutes hello
(GET "/" [] "hello"))
(run-jetty hello {:port 80})
</code></pre>
<p>Note that it requires you to be the root of the system if you are going to run a web app on port 80.</p>
<p>The main part of the app is just 3 lines of code. That reminds me of code examples for Sinatra, a Ruby web library.</p>
<pre><code>get '/' do
'hello'
end
</code></pre>
<p>Anyways the Compojure example code doesn't work only with the main logic. You are supposed to make a Leiningen project usually to manage the app and its dependent libraries.</p>
<pre><code>$ lein new hello
$ cd hello
</code></pre>
<p>project.clj</p>
<pre><code>(defproject hello "1.0.0-SNAPSHOT"
:main hello.core
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.1"]
[compojure "1.0.0-RC2"]
[ring "1.0.1"]])
</code></pre>
<p>src/hello/core.clj</p>
<pre><code>(ns hello.core
(:use
compojure.core
ring.adapter.jetty))
(defroutes hello
(GET "/" [] "hello"))
(run-jetty hello {:port 80})
</code></pre>
<p>then</p>
<pre><code>$ lein deps
$ lein run
</code></pre>
<p>it should work.</p>
<h2 id='parameters'>Parameters</h2>
<pre><code>(defroutes hello
(GET "/" [] "hello"))
(run-jetty hello {:port 80})
</code></pre>
<p>The 2nd argument of GET, <code>[]</code> in this case, is parameter list for the expression you give in 3rd argument, which mostly for referring GET parameters. That's actually a hashmap that contains <code>:params</code> key which value is also a hashmap of GET parameters. Ditto in POST.</p>
<p>How can we get the raw post parameter?</p>
<pre><code>(POST "/" {params :params} (...))
</code></pre>
<p>In that way you cannot get raw data because it's after the process. You can reconstruct the raw data only when the given parameter is like proper <code>a=1\nb=2</code> form. These days some web apis are required to handle raw POST data, which is mostly in JSON, like a Lingr Bot API.</p>
<p>The answer is in :body of the parameter, but it's not a String but a mysterious HttpParser.Input object, assuming you are using ring as the middleware.</p>
<p><a href='http://jetty.codehaus.org/jetty/jetty-6/apidocs/org/mortbay/jetty/HttpParser.Input.html'><code class='url'>http://jetty.codehaus.org/jetty/jetty-6/apidocs/org/mortbay/jetty/HttpParser.Input.html</code></a></p>
<p>This class looks weird because even though this has <code>read()</code> method the return value type isn't String but int. The other <code>read()</code> looks like you are supposed to pass a mutable data and refer the changed data.</p>
<p>Fortunately we can use <code>slurp</code> Clojure function to hide this complicated behaviour.</p>
<pre><code>(defroutes hello
(POST "/" {body :body} (slurp body)))
</code></pre>
<p>This shows the given raw POST parameter!</p>
</div>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com4tag:blogger.com,1999:blog-8477445975588753706.post-86308963095912995622011-11-15T15:43:00.001-08:002011-11-15T15:46:49.931-08:00Lazy List in C<pre><code>#include <stdio.h>
#include <stdlib.h>
typedef struct list_ {
int x;
struct closure_int_int_list_ *tail;
} *list;
typedef struct closure_int_int_list_ {
list (*call)(int, int);
int x1;
int x2;
} *closure_int_int_list;
closure_int_int_list newclosure(list call(int, int), int x1, int x2)
{
closure_int_int_list c;
c = (closure_int_int_list)malloc(sizeof(*c));
c->call = call;
c->x1 = x1;
c->x2 = x2;
return c;
}
list newlist(int x, closure_int_int_list tail)
{
list xs = (list)malloc(sizeof(struct list_));
xs->x = x;
xs->tail = tail;
return xs;
}
list listtail(list xs)
{
if (xs->tail == NULL) return NULL;
return xs->tail->call(xs->tail->x1, xs->tail->x2);
}
void deletelist(list xs)
{
free(xs->tail);
free(xs);
}
int *takelist(int num, list xs)
{
int *array;
int i;
list p;
array = (int *)malloc(sizeof(int) * num);
p = xs;
for (i = 0; i < num; ++i) {
array[i] = p->x;
p = listtail(p);
}
return array;
}
list fibnext(int a, int b)
{
return newlist(b, newclosure(fibnext, b, a + b));
}
void printarray(int *xs, int size)
{
int i;
for (i = 0; i < size; ++i) {
printf("%d ", xs[i]);
}
}
int main(int argc, char const* argv[])
{
list xs;
int *array;
xs = newlist(1, newclosure(fibnext, 1, 1));
array = takelist(10, xs);
printarray(array, 10);
free(array);
deletelist(xs);
return 0;
}
</code></pre>
<p>result:</p>
<pre><code>1 1 2 3 5 8 13 21 34 55
</code></pre>
ujmhttp://www.blogger.com/profile/08682772434896813808noreply@blogger.com0