OLPC

最近のディスクイメージではetoysが動かなくなっていたことを知らされました。これはひどいOLPCの方はスケジュールを変えることをためらわずに、他の人には「今週はバグだしとフィックスだけをする」といっておきながら、中では激しくいらなそうなライブラリとかを消していっていたわけですな。

水星と太陽

西海岸では、水星の太陽面通過はお昼過ぎのイベントでした。Dannyが望遠鏡を持ってきて駐車場でみんなに見せてくれました。望遠鏡の中では、赤い丸の中に黒い点があるだけなんですけどね。でもわくわくします。

ある人が、「南半球に行ったらもっとよく見えるのかな?」と言っていましたが?

C5 2007

http://www.cm.is.ritsumei.ac.jp/c5-07/

参加登録開始!だそうです。あと、Workshop Dayというものがあるそうですが、高田さんが一生懸命アナウンスをしているところを見るとどうやらまだ時間が埋まらないようです。なにかアイディアがある方は是非。

先月の後半に「裏仕事」とかいっていたのは、C5に向けての論文でした。OLPCの最初のデッドラインを目前にしながら別の事をやっていることを公言するのがはばかられたのですが、われわれはちゃんとやるべきことができて、かつ論文も送付するところまではできたので、今明かされる事実、です。通るとよいのだけれど。

Pepsi and Coke (No. 6)

I kind of made it sound like "Pepsi and Coke (No. 5)" was the last one, but that is not necessarily the case^^; I got a simple assignment from Ian.

The assignment (specifically speaking, I said "I want it" first, and then he said "you can make one") is to write the "apply" function. It takes a function and a list (Scheme allows to give more than one list, but it is not essential for now) and call the function with the elements in the list as arguments.

Actually, before I started this assignment, Ian did mention that there are a few VPU instructions missing to implement "apply". Nonetheless, I tried.

I modified compile.st, a source file of Jolt written in Pepsi. For the first-order approximation, I wrote a version that takes spliced arguments (i.e., it is the form of "(apply func arg0 arg1 ...)"). For this one, I've modified the SyntaxTable variable so that it has a line:

	at: #apply	  put: #xApply:;

and wrote a method:

Compiler xApply: aForm
[
   "(apply func args ...)"
    (aForm copyFrom: 1) reverseDo: [:arg | arg compile: self].
    vpu iCalli: aForm size - 2.
   ^ nil
]

As you see, this is a slightly modified version of Compiler>>form:, but it just do one less thing to skip the first "apply" keyword. It worked as expected. This shows that you can modify compile.st. However, what I would like to do is to enable a form:

   (apply func (arg0 arg1 ...))

Here is a vertion with limited functionality:

Compiler xApply: aForm
[
   "(apply func (arg0 arg1 ...)"
    | args func |
    args := (self compile: (aForm at: 2)) value.
    args reverseDo: [:arg | vpu ldPtr: arg].
    (aForm at: 1) compile: self.
    vpu iCalli: args size.
   ^ nil
]

This one only works if it is used at the top-level. You can do something like:

.(define f (lambda (x y z) (+ x y z)))
.(apply f '(5 1 3))

but not much more. The #compile: method for Compiler is meant to be used only for a top-level expression. #compile: has some special vpu messages like #iEnter, #ret, and compile:debug:. In the middle of the message, it has a line that reads: "expr compile: self". From this line, the other methods of the Compiler, such as xLet:, xForm:, and etc. recursively call each other to generate a vpu instruction sequence. This version trys to separate the compilation in two stages by colling it explicitly, but it is incorrect for non-top-level cases. Note that "args size" in this code is called at the code generation time, but it doesn't necessarily reflect the runtime value. To see what it means, you can try something like (in conjunction with the declaration of "apply1"):

Compiler xApply1: aForm
[
    | args func |
    args := Association new.
    (aForm at: 1) compile: self.        "push the first argument to the stack"
    vpu ldPtr: args _valuePointer.      "push the address of 'value' to the stack"
    vpu wrw.               		"store the first argument into 'value'"
    vpu drop.              		"remove the first argument and,"
    vpu ldPtr: args.       		"push args to return it"
    StdOut print: 'compiling';
           print: args; cr.    		"print out the args at code-generation time"
    ^ nil
]

With this definition, when you evaluate "(apply1 '10)" what you see is something like;

.(apply1 '10)
'compiling'(nil -> nil)
(nil -> 10) => 9584804

At the code generation time, the sequence of messages to vpu describes "what it would do at runtime". However, because this "(apply1 '10) is at the top-lvel, the code is immediately executed. At run time, the native code generated via vpu fills the 'value' inst var of the Association and returns it. (Obviously, this code assumes that the objects don't move after it is created). When you evaluate:

.(define f (lambda (x) (apply1 x)))
'compiling'(nil -> nil)
 => 10211728
.[(f '5) print]
(nil -> 5) => 9584804
.[(f '3) print]
(nil -> 3) => 9584804

you see that the code-generation is done just once, and the result from different invocation of "apply1" returns the same object (at the address 9584804 in this particular session). However, different invocations with different arguments fill the 'value' inst var differently. (I hope it somewhat makes clear the distinction of code-generation time and run time.)

What the definition of "apply" really should like like is:

(syntax apply
   (lambda (node comp)
     `(let ((_f ,[node second])
	    (args ,[node third])
	    (size [args size]))
	(apply1 _f args size))))

and, in compile.st:

Compiler xApply1: aForm
[
   "(apply1 func args size)"
    | args func |
    (aForm at: 2) compile: self.   "arg ..."
    vpu stTmp: 1.                  "arg to tmp1"
    (aForm at: 3) compile: self.   "size arg ..."
    vpu stTmp: 3.                  "size to tmp3"
    vpu ldInt: 1                   "1 size arg ..."
    vpu perform: #sub.             "(size-1) arg ..."
    vpu stTmp: 2.                  "(size-1) to tmp2"
    ldInt: 4.                      "4 (size-1) arg ..."
    vpu perform: #mul.             "((size-1)*4) arg ..."
    vpu perform: #add.             "(args + (size-1)*4) ..."
    vpu stTmp: 1.                  "(args + (size-1)*4) to tmp1".
    vpu drop.                      "..."
    vpu ldTmp: 2.                  "(size-i) ..."
    define: 0.
    vpu ldInt: 0.                  "0 (size-i) ..."
    vpu perform: #le.              "(<= size 0) ..."
    vpu bt: 1.                     "..."
    vpu ldTmp: 1.                  "&args[i] ..." 
    vpu rdw.                       "args[(size - i)*4] ..."
    vpu ldTmp: 2.                  "(size - i) args[(size - i)*4] ..."
    vpu ldInt: 1                   "1 (size - i) args[(size - i)*4] ..."
    vpu perform: #sub.             "(size-i) arg ..."
    vpu stTmp: 2.                  "(size-i) to tmp2"
    br: 0.
    vpu define: 1.
    (aForm at: 1) compile: self.
    vpu iCalli: args size.

   ^ nil
]
(There may be a lot of bugs.  This is more like a rough sketch.)  The problem is that the last line of xApply1: has "args size", and this cannot be determined until runtime.  In other words, vpu currently only supports function calls with argument counts known at code generation time.  In short, this version doesn't work, and until we have a different "call" instruction, it wouldn't work.

嶋正利さん

Mountain ViewにあるComputer History Museumの人に頼まれたのですが、Computer History Museumでは
http://www.computerhistory.org/events/index.php?id=1162597290
にあるようにIntel 4004 35周年記念イベントを行おうとしています。彼らも嶋先生にぜひとも参加してもらいたいということで連絡を取ろうとしてきたそうなのですが、まだ連絡が取れずじまいだそうです。

もしこの日記をお読みの方で、嶋先生に近しい方がいらっしゃいましたら、「Computer History Museumが先生を招待したいそうなので、"Karen Tucker"(メールアドレスは彼女のラストネーム at computerhistory.org)まで連絡をとってほしいとのことである」とお伝えいただけないでしょうか。

イベントがもう来週に差し迫ってしまっているのでなかなか難しいとは思いますがよろしくお願いします。