04_05_01


いざ書くとなると特に書くこと無いなぁ…

奈良に都って結構不便なんじゃないだろうか。 ちょっと移動するのにも山登ったりしそうだし。

ラーメンの店色々行ってみるんだけど、 どうも、どの店も僕と合わない…と、思ってたんだけど、 これってただ単に僕がラーメン嫌いなだけなんじゃないだろうか。

--

光学式マウスだ。

今使ってんのは光学式マウスなのである。 この光学式マウスっていうのは、 最初のうちはいいんだけど、慣れてくるとその使いにくさがなんとなくわかってくる。

普通のマウスっていうのは、何も悩まなくても、 適当にマウスパッド使ってりゃそれなりにスムーズに動いた。 けど、光学式マウスは違う。光学式マウスはマウスパッドの上だとむしろ 使えないことも結構ある。

まあ、光学式マウスを使うときは、色々材質に気を使わないといけない。 で、光学式に適した物っていうのはだいたいざらざらしてる感じで、 手触りがよくない。もう二度と光学式は買わないようにしようと思う。

--

あーわかんないなぁ…

前のローカル変数の話の続きだ。

{
	a = 40;

	var a;
	...
}

こういう場合の挙動をどうするか、だ。 諸事情により構文解析時に宣言されてない変数を弾くことはできないとしてほしい。 まあ、アレだ。ブロックを値として運んだりして、それを評価したらブロックが実行されるの。 んで、その中で束縛されてない変数を評価した値は そのブロックを評価した環境に影響されるとか。そんな感じで。

前説明した実装だと、宣言した位置に関係無くローカル変数はローカル変数に なってしまう感じだ。だから、最初の 変数a は次に宣言されてる a と同じになってしまうわけだ。 Rubyだと変数の宣言は無くて、変数の頭($,@)で区別してるからなんとでもなってるんだけど、 接頭辞はできれば使いたくないような(Cっぽくなくなる)。

いくつか案があって、宣言する位置はシカトして評価するとか、スピードを捨ててローカル変数も全部 ハッシュにして、宣言するたびに領域作って、領域が無い場合にエラーにするとか、 とりあえずローカル変数として扱って、ローカル変数テーブルに生死を表すビットを付けておいて、 var文を処理する時に生きてるフラグ立てるとか、 Cみたいに先頭じゃないと宣言できないとか、いっそlet文でやるとか。

JavaScriptの場合だと、

function x()
{
  {
    var b = 50;
  }

  print("b="+b);
}

これで、"b=50"らしい。ブロックローカル変数の概念は無いような。 というか、JavaScriptは宣言無くてもいいのか…うーむ、困ったなぁ…どうしようか…

面倒だから全部ハッシュテーブルでやることにする。以上。

static tree
eval_context_block( tree block )
{
  tree ns = nl_namespace_create();

  push_namespace( ns );
  eval_block( block );
  pop_namespace( ns );
}

こんな感じで可能。

--

var x = 80000;

namespace nanika {
	var x = 50;
	nldef func()
	{
		x = 10000;
		nl::std::print("nanika::x=",x,"\n");
	}
}
nanika::func();
nl::std::print( "x=", x, "\n" );

/* 

実行結果

nanika::x=10000
x=80000

 */

とりあえず、GCCのtreeを中間表現に使うインタプリタでこのくらいまで動いた。 あとは、JavaScriptっぽいOOな機能とかクロージャとか。 それとコンパイラの部分。

恐ろしくハッシュをチェーンしまくるし、ブロックに入る度にハッシュテーブル作るし、 それがゴミとして残るし実行速度は遅い。 まあ、仕方無いか。速度はそれほど必要ではないだろうし。 あと、GCが面倒。ちゃんとプロテクトかけないといけない。

04_05_02


ひょっとしたら需要があるかもしれないので昨日の GCCのtreeを中間表現に使うインタプリタっていうのを置いときます。 GCCのRTLに変換される前のtreeを弄るプログラムをインタプリタで動かして コンパイル時のコード生成をやりたいとかそういう話。 ただ、RTLへの変換は全然わからなくなって、一度挫折してるので、今度もできるかどうかは謎。

3.4.0で動作確認。3.3.2とかではコンパイルできないのを確認。 gcc-3.4.0/gcc/内に展開して、./configure --enable-languages=asdf。で、make zxc1 とかで動くのではないかと。あんまり確認してないけど。 まあ、今のところはプログラミングに使えないと思うけど、GCCのtreeをどうやって弄るかの参考くらいには 使えると思います。

--

SDLでIM

明日からまたインターネットに繋がらなくなるので、とりあえず動いたところまで書いておく。

はやくインターネットに繋がるようにしたほうがいいなぁ…


wo:
出してから5時間くらいしかいじってないんだけど、致命的みたいな感じのバグがぼこぼこ出てくる。

こんなんでええんかいなー。
とりあえず、気に食わない部分はリファクタリングと称して、低レベルな部分だろうと変更しまくって、テストなんかしないでそのままって感じなのが原因だろうっていうのはわかるんだけど。

このへん、「将来的にバグを減らすための布石なんだ」とかって、自己満足に浸れるというか、まあ、正しくは設計段階で見つけるべきものなんだろうけど、あらゆるものを無視して、コード書いてるって感じがして、結構楽しいのである。

こういうのって個人で書いてるプログラムでしか楽しめないからなー。

あんまり関係ないんだけど。

04_05_12


512の日

アレだ。アレ。とうとうHTTPアップローダを使ってしまうわけだ。 会社のネットワークは私用に使ってはいけないんです。本当は。

とりあえず、そこそこ動くSDL-XIMパッチを 上げておく必要があったので、まあ、仕方が無いということで。許してください。

やっぱADSLとか繋げられる環境にしよう…

--

nl::std::print( "hogehoge\n" );

using nl::std;
print("hogehoge2\n");

usingが使える。

namespace A {}

namespace C {
	var nanika = 100;
}

namespace B {
	using C;
	using A;
}

namespace A {
	using B;
}


A::nanika = 100;
nl::std::print( C::nanika ); /* => 100 */

usingがループはしないようにチェックはしてる。 ちょっと汚い方法だけど。あと多分遅い。

namespace A {
	var nanika = 100;
}

A.value = "val\n";

nl::std::print( A.value ); /* => "val" */
nl::std::print( A.nanika ); /* => 100 */

A["nanika"] = 101;
nl::std::print( A.nanika ); /* => 101 */

というか、名前空間はオブジェクトだし、連想配列だ。 このあたり区別しようかと思ったけど、やってること一緒だったので、まあいいか、って感じで。

var obj = nl::std::new_object(); /* 実際は空の名前空間作ってるだけ */

obj.foo = 100; /* => OK. fooは勝手に定義される */
obj::bar = 100; /* => ERROR. barは定義されない */

で、心持ちドットによるアクセスとコロンによるアクセスを区別するようにした。 まあ、この辺は気分の問題だろうか(僕の)。

using nl::std;

namespace Nanika {
	var x = 100;

	nldef func( ) {
		print( int_val, "\n" ); /* this.int_valになる */
		print( x );
	}

}

var obj = new_object();
obj.f = Nanika.func;
obj.int_val = 1024;

obj.f();  /* => 1024 \n 100 */

ローカル変数は全部ハッシュテーブルでなんとかしてるから、こういうのは難しくなかった。

このくらい動いたら十分だと思う。 そろそろコンパイラ部分…ってこれ言うの3回目くらいのような気がする。

あとは例外処理とかだろうか。面倒なんだよなぁ…多分。 とりあえず、エラーしたら exit するのをなんとかしないといけない…そのうち。 あと、アロケートした物のプロテクトをなんとかしないといけない。

nldef do_gc() {
	nl::std::gc();
}

"aaaa" + do_gc();

運悪くGCが動いたら文字列"aaaa"は回収されちゃう。あと、あんまり関係無いけど、 gcc内で使われている、ggc_alloc_stirngは名前に騙されてはいけない。 実際はリークする。

while ( 1 ) {
	ggc_alloc_string( "naninani", -1 );
	ggc_collect();
}

そのうちメモリが無くなって落ちる。いや、識別子とか文字列定数はハッシュテーブルに入ってるとかで、 解放する必要が無いっていうのはなんとなくわかるんだけど、その関数の名前はどうかと思う。

04_05_23


とりあえず、変数を表現するのがVAR_DECLっていうのが わかって嬉しいので、GCCメモでも置いておきます。

あんまり詳しく調べたわけではないし、ゆっくり推敲しながら書いたわけでもないので、 あんまり信用しないほうがいいかと。

間違ってる部分とか、判明した部分とかがあったら適当に修正していく予定。

GCCのソースの中にLANGUAGESっていうファイルがあって、

Right now there is no documentation for the GCC tree -> rtl interfaces
(or more generally the interfaces for adding new languages).

/*
 * 訳(多分):
 * 
 * 今はtreeからrtlへ変換するインターフェース
 * (というか、新しい言語を書くためのインターフェース)
 * について書いたドキュメントはあらへんよ。
 */

とかって書いてあって、まあ、そんな感じらしい。やっぱソース読むしかないのか。


wo:
どこのどいつだ、確かめもしないでtreelangの変数がグローバル変数とか書いたアホは。orz

修正しときます。

04_05_26


defun int nanika( int a )
{
	
}

これが

	.file	"test.asdf"
	.text
	.type	nanika, @function
nanika:
	pushl	%ebp
	movl	%esp, %ebp
	leave
	ret
	.size	nanika, .-nanika
	.section	.note.GNU-stack,"",@progbits
	.ident	"GCC: (GNU) 3.4.0 20040416 (prerelease)"

こうなる。

まあ、型とか引数とかセコい方法でごまかしまくってるんだけど、 それでも、あとはその辺修正していくだけなんじゃないかなぁ…と、思う。 やってみないとわからんけど。

それと、関数の前にdefunキーワードが入るのが非常に嫌なんだけど、 入れないとどうしようもない。そのへんの話はまた後日。

パーサーを汚くすればいけるんだけど…