オペコードなどについて考察する

以下のは雑記・考察ログです。すでに絶滅した過去の仕様、関係のない話題、ファイクレオネに存在しない概念などが数多く含まれています。最新の仕様だけ知りたい人は設定一覧をお読みください。専門用語の一覧は用語集に掲載されています。インタプリタで実装されている追加仕様などについてはインタプリタの追加設定一覧(暫定)を参照ください。Twitterで出た質問はTogetterにまとめてあります(part1, part2, part3)。ソースコードの例としては非再帰フィボナッチ再帰フィボナッチquicksort開平があります。

1. 設定

Google SpreadSheetで作業中OBSOLETE:: 2017/08/29 23:40時点で既に部分的に無効
2017/08/28:
呼び出し規約を確定させる
スタックの掃除をするのは呼び出し側
いじって良いレジスタは4個 (f0 ~ f3)
引数は前からスタックに積む
戻り値は単純型ならレジスタ (f0) でやり取り

2. 実践

さて、呼び出し規約も決まったことだし色々書いていきますかね。とりあえずフィボナッチ書こう。スタックを管理するのは(ダイスロール)f5ですな。まずはCっぽく。

int fib(int a)
{
	register int f0 = a;
	register int f1 = 0; 
	register int f2 = 1;
	register int f3;
	while(f0) {
		f0--;
		f3 = f1 + f2;
		f1 = f2;
		f2 = f3;
	}
	f0 = f1;
	return f0;
}

解説

f0544332211005
f100111122335
f211112233558
f3 1 2 3 5 8

x86風に書いてみる

	MOV f0 [ESP+4]
	MOV f1 0
	MOV f2 1
a:	EQU f0 0
	J_C b ;フラグを見てジャンプ
	ADD f0 -1
	MOV f3 f1
	ADD f3 f2
	MOV f1 f2
	MOV f2 f3
	JMP a
b:	MOV f0 f1
	JMP [ESP]
	ADD ESP 4

リパに翻訳

	krz f0 [f5+4]
	krz f1 0
	krz f2 1
is:	sie f0 0
	J_C ka ; どうしよう
	ata f0 -1
	krz f3 f1
	ata f3 f2
	krz f1 f2
	krz f2 f3
	krz xx is
ka:	krz f0 f1
	krz xx [f5]
	ata f5 4

というか、自明に「xxをいじる = ジャンプ」なので、ジャンプ命令を作ってそれをkrz xx abcdeと書いても良い設定にすればよい。ファイクレオネにはWPのおかげで既にワープ・瞬間移動・縮地法の類がありそうなので、それを流用するのが自然な気がする。

3. 設定part2

2で出てきた設定を(明示・暗黙共に)まとめる。

4. Fafs falira sashimiと打ち合わせ

「フラグを見て代入するかどうか決める」命令をどうすべきか迷ったので、打ち合わせを行った。その結果、比較演算子系統のニーモニックが全部作り直しになった。

4-1. 結果

基本構文:

fi 第一オペランド 第二オペランド 比較表現
malkrz レジスタ 

例:

fi f0 f1 lloler
malkrz f2 f3

この構文は、上記の例に即するなら、Fi f0 es f1 le loler, mal krantairzarth f2'c f3'i. 「f0がf1よりも大きいならば、f3をf2にコピーする」というリパライン語表現にちょうど対応する。

4-2. 念のため補足

もちろん、実際の処理としては、【fi ~ lloler命令は「第一オペランドが第二オペランドよりも大きいならばフラグを立てる」命令であり、malkrz命令が「フラグが立っているときにのみ第一オペランドに第二オペランドの値を代入する」命令である】ということであり、自然なリパライン語として読めるかどうかということは正しいアセンブリ言語になるかどうかとは当然別物である。

その証拠に、リパライン語では上記の文をFi f0 es f1 le loler, krantairzarth f2'c f3'i.というふうにmalという語を抜かして表現しても意味は変わらないが、

fi f0 f1 lloler
krz f2 f3

は当然「f0がf1よりも大きいならばフラグを立てる。さてそれはともかくf3をf2にコピーする」という別の意味の命令群になる。リパラオネ人がこの仕様に苦しむのは、まるで現世でC系統の言語を習い始めた人がif(a = 0)とかif(a == 0||1)とか書いてしまうようなものである。

5. 実践part2

ということで、4.に基づき前述のフィボナッチを修正していこう。

	krz f0 [f5+4]
	krz f1 0
	krz f2 1
is:	fi f0 0 cloler ; ce loler 
	malkrz xx ka 
	ata f0 -1
	krz f3 f1
	ata f3 f2
	krz f1 f2
	krz f2 f3
	krz xx is
ka:	krz f0 f1
	krz xx [f5]
	ata f5 4

よし、これで初めての関数である。やったー。

しかし、clolerがやっぱりちょっと長い気がするなぁ(他が短すぎるだけともいう)

さて、じゃあ再帰フィボナッチも実装しましょうかね。まずはC

int fib2(int a)
{
	register int f0 = a;
	register int f1;
	register int f2;

	if(f0 < 2) {
		goto fin;
	}

	f1 = f0;
	f1--;
	f0 = fib2(f1);
	f2 = f0;
	f1--;
	f0 = fib2(f1);
	f2 += f0;
	f0 = f2;

	fin:
	return f0;
}

まずはx86もどき混じりで翻訳。

fib2:	krz f0 [f5+4]
	fi f0 2 xyloler
	malkrz xx iska
	krz f1 f0
	ata f1 -1
	PUSH f1
	CALL fib2
	POP f1 ;関数呼び出しでf1が破壊されるので修復
	krz f2 f0
	ata f1 -1
	PUSH f2
	PUSH f1
	CALL fib2
	POP
	POP f2
	ata f2 f0
	krz f0 f2
iska:	RET

次に、関数呼び出しとスタック操作について整理しよう。

スタックにiskaをプッシュする

	ata f5 -4	; f5を持ち上げて
	krz [f5] iska	; 積む

スタックをポップしてiskaに代入

	krz iska [f5]	; スタックの値を代入
	ata f5 4	; f5を下げる

return f0;

	krz xx [f5]	; リターンアドレスに飛んで
	ata f5 4	; スタックからリターンアドレスを削除

f0 = func();

	; えっと、
	ata f5 -4	; スタックにリターンアドレスを
	krz [f5] xx	; 積む
	krz xx func	; 関数のアドレスにジャンプ
	; でいいのかな?
	; いいえ。積んだときのxxはkrz xx funcを指しています。よってこれでは無限ループします
	; さてどうしよう。
	; 普通ならここで素直にCALLのニーモニックを作ればいいんだろうが、2003'd ferlesylの作者は全部をxxへの操作としたがる人だ
	; そうだ、2つのkrzを1回で行う命令を作ればいいんだ
	; 名前はqa stevypo krzの略でqskrzとでもすればいいか。
	; krz fi stの後にkrz st irをすることをqskrz fi st irと書けることにすればよい。
	; 実際処理としてよくありそうなやつだし。汎用性あるし採用していいでしょ
	; ということで仕切り直し

f0 = func();

	ata f5 -4	; スタックを準備
	qskrz [f5] xx func	; リターンアドレスを積んで、同一命令で関数のアドレスにジャンプ

CALLの実装書いてて気づいたけど、前にxxを1増やすって書いたの嘘やん。固定長でもないし1byteでもないもん。単純に「次の命令を指すところにxxが移動する」ですな。

さて、ここまでやったところで翻訳。

fib2:	krz f0 [f5+4]
	fi f0 2 xyloler
	malkrz xx iska
	krz f1 f0
	ata f1 -1
	ata f5 -4
	krz [f5] f1
	ata f5 -4
	qskrz [f5] xx fib2
	krz f1 [f5]
	ata f5 4
	krz f2 f0
	ata f1 -1
	ata f5 -4	
	krz [f5] f2
	ata f5 -4	
	krz [f5] f1
	ata f5 -4
	qskrz [f5] xx fib2
	krz f2 [f5+4]
	ata f5 8
	ata f2 f0
	krz f0 f2
iska:	krz xx [f5]
	ata f5 4

6. 課題

まず、5に出てきた新規設定をまとめる。

この2番目と3番目を組み合わせると、なんと関数呼び出しが実行できるのである。

また、slackで出てきた課題について述べる。

待てよ?qskrz fi st irをCでいう「fi = st; st = ir;」ではなく「tmp = st; st = ir; fi = tmp;」であると再定義してやれば、上記のコードに一切の変更を与えずかつfiとirが同一であるときXCHGとして使えるのでは!?これは楽しいぞ。とりあえず命令名を変えなくては。Fafs氏に訊こう。


Fafs「qa'd stevypen snidost「二回移動」でqssでいかがでしょうか」

なるほど。まあ片方が移動で片方がコピーなのだが、fi = irのときはswapだしまあよかろう。

llolerについても反応を得た。「lloとでもすればいいのじゃろうなあ」とのこと。同意。

語順についても反応を得た。リパラオネ人は-'i -'cを好むらしい。となると再設計か?めんどい。とは言え、バート人は-'c -'iを好むそうだ。じゃあ「設計者はバート人だったので無意識のうちにV -'c -'iでデザインしていたが、リパラオネ人に-'i -'cの方が自然だと言われた。とはいえ既存のコードを全部修正するのは面倒だったので『ci指定擬似命令』をアセンブリに組み込んだ」という設定にしよう。

7. 実践part3

とりあえず、仕様がそれなりに変わったので書き直す。

非再帰フィボナッチ

::'c'i
	krz f0 [f5+4]
	krz f1 0
	krz f2 1
is:	fi f0 0 clo
	malkrz xx ka 
	ata f0 -1
	krz f3 f1
	ata f3 f2
	qss f1 f2 f3
	krz xx is
ka:	krz f0 f1
	krz xx [f5]
	ata f5 4

再帰フィボナッチ

::'c'i
fib2:	krz f0 [f5+4]
	fi f0 2 xylo
	malkrz xx iska
	krz f1 f0
	ata f1 -1
	ata f5 -4
	krz [f5] f1
	ata f5 -4
	qss [f5] xx fib2
	krz f1 [f5]
	ata f5 4
	krz f2 f0
	ata f1 -1
	ata f5 -4	
	krz [f5] f2
	ata f5 -4	
	krz [f5] f1
	ata f5 -4
	qss [f5] xx fib2
	krz f2 [f5+4]
	ata f5 8
	ata f2 f0
	krz f0 f2
iska:	krz xx [f5]
	ata f5 4

角かっこ記法・名前空間の衝突などまだ課題は残るが、とりあえずクイックソートでも書くか。まずはC

void quicksort(int* const a, int l, int r)
{
	register int* const f0 = a;
	register int f1 = l; 
	register int f2 = r;
	register int f3;
	if(f1 >= f2) {
		goto fin;
	}
	f3 = f1;
	f3++;
	
panqa:
	if(f3 > r) {
		goto fistir;
	}
	f2 = l;
	f2 = f0[f2];
	if(f0[f3] >= f2) {
		goto iska;
	}
	f1++;
	qss(f0[f3],f0[f1],f0[f3]);
iska: 
	f3++;
	goto panqa;

fistir:
	f2 = l;
	qss(f0[f1],f0[f2],f0[f1]);

	int p = f1;
	quicksort(a,l,p-1);
	quicksort(a,p+1,r);
fin:	
	return;	
}

うわぁ(うわぁ)。とりあえずハンドコンパイルせねば

::'c'i
ycax:
	krz f2 [f5+4] ; r
	krz f1 [f5+8] ; l
	krz f0 [f5+12] ; a
	fi f1 f2 xolo
	malkrz xx lus
	krz f3 f1
	ata f3 1
panqa:
	fi f3 [f5+4] llo
	malkrz xx fistir
	krz f2 [f5+8]
	krz f2 [f0+f2]
	fi f2 [f0+f3] xtlo
	malkrz xx iska
	ata f1 1
	qss [f0+f3] [f0+f1] [f0+f3]
iska:
	ata f3 1
	krz xx panqa
fistir:
	krz f2 [f5+8]
	qss [f0+f1] [f0+f2] [f0+f1]

	ata f5 -4
	krz [f5] f1 ; push p
	ata f5 -4
	krz [f5] [f5+20] ; push a
	ata f5 -4
	krz [f5] [f5+20] ; push l
	ata f5 -4
	krz f1 [f5+12] ; f1 = p
	ata f1 -1
	krz [f5] f1 ; push p-1
	ata f5 -4
	qss [f5] xx ycax
	ata f5 4 ; aはconstなのでスタックに残っているaを信用してよい
	krz f1 [f5+8] ; f1 = p
	ata f1 1
	krz [f5] f1 ; push p+1
	ata f5 -4
	krz [f5] [f5+20] ; push r
	ata f5 -4
	qss [f5] xx ycax
lus:
	krz xx [f5]
	ata f5 4

疲れた。うーん、ataが多いのが気に入らないなぁ

8. 設定

書き忘れてた設定を思い出したので書いておく。nta fistir'c 即値'iはata fistir'c (-即値)'iに翻訳される。上記アセンブリでひたすらataを使っているのはそういう理由である。

また、符号付きと符号なしを明示的に区別しないほうが楽だよなーとも思っているが、問題は大小比較。今までのコードは正数と負数の比較をしていないのでどちらでもいいんだが、両方用意するとか決めるとかしないとなぁ。

あと、notequalを除いて比較命令が出揃ったので掲載しよう。

fi ~ xtlofi * es * xut loler以下ならフラグを立てる
fi ~ xylofi * es * xy loler未満ならフラグを立てる
fi ~ clofi * es * ce loler同等ならフラグを立てる
fi ~ xolofi * es * xo loler以上ならフラグを立てる
fi ~ llofi * es * le loler超過ならフラグを立てる

そしてこれをspreadsheetサイトの両方に載せて来た。

あ、あとqssとmalkrzを足してこよう。

9. 格組の統一

とりあえず、現状のニーモニック表を貼るとこうなる。

 命令  語源  x86  意味
 krz  krantairzarth  mov  複製
 ata  atakes  add  加算
 nta  ny atakes  sub  減算
 stu  stusni  mul  乗算
 kak  kakites  div  除算
 ada  adal  and  ビット積
 ekc  ekcan  or  ビット和
 nac  nacis  not  ビット反転
 dal  daliual  xnor  ビットxnor
 tod  tesnokon dusnij  shr  右シフト
 rod  restuton dusnij  shl  左シフト
 malkrz  mal krantairzarth  フラグが立っているときのみ複製する
 fi ~ xtlo  fi * es * xut loler  以下ならフラグを立てる
 fi ~ xylo  fi * es * xy loler  未満ならフラグを立てる
 fi ~ clo  fi * es * ce loler  同等ならフラグを立てる
 fi ~ xolo  fi * es * xo loler  以上ならフラグを立てる
 fi ~ llo  fi * es * le loler  超過ならフラグを立てる
 fen  fav es niv e'i  nop
 何もしない
 qss     qa'd stevypen snidost    二重移動 (第1オペランドの値を第2オペランドに代入しつつ第2オペランドの古い値を第3オペランドに代入)

さて、6.の最後で『ci指定擬似命令』なるものを導入した以上、基本的にニーモニックはリパライン語で-'i -'cの形となる動詞に由来すべきである。比較命令はともかく。

ということで、作業が終わった。除算は仕様すら決めていないので後で考えることにして、とりあえず新しくなった表を持ってこよう

 命令  語源  x86  意味
 krz  krantairzarth  mov  複製
 ata  atakeses  add  加算
 nta  ny atakeses  sub  減算
 lat  latvaves  mul  乗算
 (kak)  (kakites)  div  除算
 ada  adales  and  ビット積
 ekc  ekcan  or  ビット和
 nac  nacises  not  ビット反転
 dal  daliuales  xnor  ビットxnor
 dto  dusnij tesnokonj  shr  右シフト
 dro  dusnij restutonj  shl  左シフト
 malkrz  mal krantairzarth  フラグが立っているときのみ複製する
 fi ~ xtlo  fi * es * xut loler  以下ならフラグを立てる
 fi ~ xylo  fi * es * xy loler  未満ならフラグを立てる
 fi ~ clo  fi * es * ce loler  同等ならフラグを立てる
 fi ~ xolo  fi * es * xo loler  以上ならフラグを立てる
 fi ~ llo  fi * es * le loler  超過ならフラグを立てる
 fen  fav es niv e'i  nop
 何もしない
 inj    irzarst ileceonj    二重移動 (第1オペランドの値を第2オペランドに代入しつつ第2オペランドの古い値を第3オペランドに代入)

いぇーい。

10. 整理

10-1. 細かい追加事項

10-2. ソースコード分離

いちいちソースコードを掲載するのも紙面を圧迫しそうなので、ファイルを分離して管理することにした。まずはもともと分離してあったquicksortから。qssをinjに書き換えて、フォントをjietodenにするのも忘れずに。

うーん、やはり角かっこを滅ぼしたいよなぁ

さて、次はフィボナッチを整理するか。とはいえ初期から色々変更点が溜まっているが大丈夫だろうか

10-3. 課題

未解決のを列挙していこう。さらに新規に見つかったやつも。

10-4. マニュアル分離

レジスタ一覧とニーモニック一覧が欲しいと言われたので、作った。

10-5. ソースコード分離part2

ソースコードのフォントを切り替えられる設定にした。あと、とりあえず非再帰フィボナッチ再帰フィボナッチのソースコードを独立ファイルとして公開。

10-6. 課題解決案

nta fistir'c 即値'iはata fistir'c (-即値)'iに翻訳されるという設定を過去に作ったが、負値の書式がまだ決まらんのでアセンブリ言語としてはnta fistir'c 即値'iを許容することとした。ということでソースコードを編集だ。あと、めんどいので現状では負数のリテラルは使用しないことに決めた

11. 進捗

11-1. part1

S.YやFafs falira sashimiと対談して進捗が出た。

旧構文新構文役割
ラベル名:l' ラベル名(後ろから修飾)
nll ラベル名(前から修飾)
ラベル名を定義する
[レジスタ名]レジスタ名@レジスタに入っている番地のメモリを表す。
[レジスタ名 + 定数]レジスタ名 + 定数@レジスタに入っている番地に定数を足した番地のメモリを表す。
[レジスタ名 + レジスタ名]レジスタ名 + レジスタ名@2つのレジスタに入っている数値を足した番地のメモリを表す。

なお、ここで@で転写されている記号はリパライン語では「ioの合字記号」に対応する。Fafs falira sashimiの「理語的には非文的だけど、アセンブリとしてはできるだけ自然言語に近づいてていい感じな気はする」という発言が決定打となり、採用されることとなった。

ラベル名については、リパライン語に既にあるla lexを使うのが「エモい」とのことだったので採用することとした。問題はla lexをどう表現するかで、「llxのほうが統一的」という意見が出たものの、統一性がないほうがかえってラベルを追いやすいということでl'が採用された。

なお、la lexは前の文を指すので、x86とは違ってラベルは文の後ろから指定する。となると関数を表すためにラベルを導入したときにラベル定義が関数定義の2行目に出てきてしまいよろしくない。ということで逆向きを表すny la lexも導入することにした。nl'を提案したものの、「ny la lexの詩語での省略形がny l' l'/nyll/であるからnllのほうが想起されやすい」ということなのでnllに決まった。

とりあえず設定一覧非再帰フィボナッチ再帰フィボナッチquicksortを改定。

11-2. part2

::'c'i'c'iに改定することにした。ということでサンプルと設定集の修正をした。これで一応確定。あと、インデントが要らない気がしてきたので削除。

12. 修正

12-1. バグ修正

関数からreturnするときの処理にバグがあることが発覚した。問題箇所を以下に掲載する。

returnする

	'c'i
	krz xx f5@	; リターンアドレスに飛んで
	ata f5 4	; スタックからリターンアドレスを削除

問題なのは、krz f5@ xxした時点でリターンアドレスに飛んでいるので、その次の行ata f5 4が実行されず、スタックからリターンアドレスを削除できないことである。

ということで、この際呼び出し規約を変更し、「リターンアドレスの分のスタック掃除も呼び出し側の仕事」という仕様にすることにした。

それに従い、非再帰フィボナッチをとりあえず修正した。ついでに手動でウォークスルーを行い、おそらくバグっていないであろうことを確認した。

再帰フィボナッチも修正した。しかし、修正最中に、呼び出し規約の新たな変更案が思いついたのである。

現状を見てみよう。

関数funcを呼び出す

	'c'i
	nta f5 4	; スタックを準備
	inj f5@ xx func	; リターンアドレスを積んで、同一命令で関数のアドレスにジャンプ
	ata f5 4	; スタックからリターンアドレスを削除する

このnta f5 4ata f5 4のペア、無駄では?inj f5-4@ xx funcと書きたい。

ただ、まだマイナスがないので改定するにしてもまた今度である。

さて、quicksortも改定した。ウォークスルーはしていないが、多分合っていると信じたい。

12-2. その他

スタックの伸長方向はアドレスの減少する向きであることを記載した。この仕様、もともと何も考えずにダイスロールで決めた仕様だったけど、よく考えてみると[f5+20]とかのことを考えるとこっちの方が自然だよなぁ

13. 課題

現状の仕様だと、ラベル名と命令名が衝突しても弊害が発生しないが、ラベル名とレジスタ名の衝突は起きうる。将来的に命令が増えても互換性は保たれるが、レジスタが増えるとそうはいかなくなるという課題がありますな。さてどうしよう。

  1. バージョン情報を先頭に指定して、それに応じて読み換える
  2. ラベル名をなんか修飾する(←でも構文もう変えないって宣言したやん)
  3. 初期の段階ではこの問題に気づかないので対処がなされない

よし、3で行くか。

冷静に考えると、ラベル名を「参照」するときはともかく、ラベル名を「定義」するときにはレジスタ名と衝突していればエラー検出はできるので、バージョンが上がってもコンパイルできなくなるだけでこっそり挙動が書き換わることはないはず。じゃあええやん(いいとは言っていない)

まあ、これぐらい欠陥があったほうが「黎明期」っぽくてponaだよね。うんうん。黎明期は任意のものがmalbonaなので。RANDUとかprintfとその%nとか。

ということで、この課題については「修正しない」という方針で。

14. パーサー実装

そろそろインタプリタが欲しくなる今日この頃。Cで書くかHaskellで書くか迷って決められなかったので両方で書いてみる。

とりあえずパーサーは書いた。Haskellでだけだけど。ちゃんと今までに書いた3本も正しく解釈できることがわかった。

15. マイナス問題の解決

ハロー“Hello,World"OSと標準ライブラリのシゴトとしくみを読んだところ、[ESP-4]を実現するためにx86は普通に0xfffffffcを足していた。ということで4294967292を足せばいいでしょう。やったぜ。

ということで呼び出し規約改定しまーす。リターンアドレスはf5-4に積まれる設定にします。

とりあえず非再帰フィボナッチ再帰フィボナッチを修正。さらにquicksortも直した。なんかスタックバグってた気がしたのでウォークスルーした。なお設定に凡ミス(f5は第一引数ではなく最終引数)があったので直した。

16. インタプリタについて

16-1. メモリの仕様

インタプリタは関数を実行するという形式にしたい。じゃあそのリターンアドレスってどうしようか。乱数に聞いたら0xbda574b8という答えを返してきたのでそうしよう。えーと10進数だと…3181737144かなるほど。スタックポインタの位置はどうしよう。これまた乱数でいいか。0x6d7aa0f8、つまり1836753144か。

ということで、インタプリタは、例えば3変数関数なら、以下の条件で関数を実行することになる。

レジスタ

レジスタ名内容
f0なんか
f1なんか
f2なんか
f3なんか
f51836753144

メモリ

番地内容
18367531403181737144
1836753144第三引数
1836753148第二引数
1836753152第一引数
1836753156なんか

文字列へのポインタとかを渡したいし、(ダイスロール、aか)0xa0000000 ~ 0xafffffffのメモリの内容は自由に関数がいじっていいことにしよう。28bitのアドレス空間ってことは256MBか。でかいな。まあいいか。インタプリタだし関数書く側が節度を持ってメモリを使えばいい。

さて、メモリにデータをセットするのはどうやって行おう。あ、そうか、テストしたい関数を呼び出す関数を別に作って、mainではメモリにデータを書き込めばいいのかそれはそうか。

思い出したので書いておくと、2003'd ferlesylでは3181737144@とは書けない。だって即値で書くことなんてあんまないやん。即値でアドレス指定して書き込みたいなら普通にkrz 3181737144 f0 krz 123 f0@と書けば十分だし。

話を戻して、ラップ関数を作るんならmain関数はゼロ引数でいいでしょう。その方が楽だ。ということで改訂。

レジスタ

レジスタ名内容
f0なんか
f1なんか
f2なんか
f3なんか
f51836753144

メモリ

番地内容
1836753132なんか
1836753136なんか
18367531403181737144
1836753144なんか
1836753148なんか
1836753152なんか
1836753156なんか

17. やっぱ直す

4294967292は流石にクソでしょ。revertします。

それに応じてインタプリタのメモリ構成も修正。

レジスタ

レジスタ名内容
f0なんか
f1なんか
f2なんか
f3なんか
f51836753144

メモリ

番地内容
1836753132なんか
1836753136なんか
1836753140なんか
18367531443181737144
1836753148なんか
1836753152なんか
1836753156なんか

はいオーケー。ファイクレオネは救われた。万歳万歳。

18. インタプリタについてpart2

18-1. メモリの仕様part2

とりあえずHaskellでメモリを実装。内部構造はData.Map.Map Word32 Word32で、空メモリと書き込みと読み込みのみを実装。書き込まれていないところから読み込んだ場合、アドレスをシード値とした擬似乱数を返し、さらにそのアクセスを記録する(意図しない値の読み込みはバグなので)。

さて、nxとxxはどうしよう。本来ならopcodeが決まっているのでnxとxxが定義できるはずなのだが、まだ決まっていないのである。

さてさて、そんなことより深刻なバグに気づいた。普通に各アドレスに4byte振ってた。ダメやん。ということで4の倍数のアドレス以外にアクセスした時の処理を考えねば。問題はエンディアンをどうするか。(ダイスロール)ビッグエンディアンで載せよう。

しかし、2003'd ferlesylは基本的に32bitなのに、単一のアドレスの記憶容量はなぜbyte単位なのだろう?まあ、「既存の組み込みOSで使われていたメモリを再利用したかったため」でいいか。CPUはともかくメモリの仕様は変えたくないだろうし。

まあ、わざわざアドレスが振ってあるってことはアドレス単位の書き込みもしたくなるよなぁ。とはいえ必要になった時に考えればいいとは思うが。

とりあえず、Data.Map.Map Word32 Word8に変更する。んで普通は4byte読み出す。

18-2. nxとxx

【再掲】さて、nxとxxはどうしよう。本来ならopcodeが決まっているのでnxとxxが定義できるはずなのだが、まだ決まっていないのである。

えーと、「『次の命令を指すところにxxを移動させる→nxの指す命令を実行する→xxの指す位置にnxを動かす』を繰り返す」という挙動である。しかし今は『次の命令』が分からんのでなぁ、という。

とりあえず、思いついた案。HaskellでData.Map.Map Word32 (Word32, Instruction)Data.Map.Map Label Word32を用意して、第一mapのvalueのfstが『次の命令』、とすればよかろう。

第一map

kvalue's fstvalue's snd
12341236Krz (L (RPlusNum F5 4)) (Re F0)
12361239Krz (Pure 0) (Re F1)
12391242Krz (Pure 1) (Re F2)
12421244Fi (L (Re F0)) (Pure 0) Clo
12441245MalKrz (Lab "ka") (Re XX)
12451246Nta (Pure 1) (Re F0)
12461247Krz (L (Re F1)) (Re F3)

第二map

kvalue
Lab "is"1242

さて、この2つのmapのペアに何ていう名前をつけようか。tentative loadでいいか。乱数で決めた適当なオペランド長のもとでロードするという。

とりあえず実装した。

18-3. インタプリタ

気がついたらインタプリタが実装し終わっていた。さて実行してみよう。おお、fib 12がちゃんと144を返すではないか。

ん?しかしgarbagesの欄があるのが奇妙だ。初期化されていないメモリを読んだ時にのみこういうことは起きるはずなのだが。アドレスを見る限りf5周りのようだ。

原因究明に成功krzをHaskellのconst関数で実装していたので、メモリから「読んで」それを捨てる、という実装になってしまっていた。なるほど。

19. 諸々

インタプリタでは既に実装してあるので、'i'cを仕様にした。

クイックソート、バグってるつらい。

とりあえずinjによるswapは問題ないことが確認できた

原因判明。直したスタックバグが0xfffffffcのrevertで復活してただけだった。実行してみる。

つらい

原因判明。p[a]はp+a番地じゃなくてp+4a番地だ。とはいえ掛け算とかまだ仕様を固めていないので、とりあえずビットシフトを実装。

しかしやっぱり直らない。もう諦めるか。とりあえずたらい関数でも実装しよう。

動かない。悲しいなぁ

とりあえずファイルから読み込めるように。

再帰フィボナッチとかいじってたら、アルゴリズムが改良できただけでなく、新たなコーディング規約的なものを思いつくことにも成功した。改行不要であることがうまく効いてくる

'c'i    
nta f5 4   krz f5@ 12
nta f5 4   inj f5@ xx fib2   ata f5 8
krz xx f5@

'c'i
nll fib2
krz f0 f5+4@
fi f0 2 xylo   malkrz xx iska
krz f1 f0
nta f1 1

nta f5 4   krz f5@ f1
nta f5 4   inj f5@ xx fib2  ata f5 4

inj f1 f5@ f0  
nta f1 1 

nta f5 4  krz f5@ f1  
nta f5 4  inj f5@ xx fib2  ata f5 8
 
ata f0 f5@  

ata f5 4 
krz xx f5@
l' iska

たらい関数の不可解なバグの原因が判明。nta 4 f5の書き忘れ。しかしそれを直したところでx>yのときには動かないのである。悲しいなぁ。

色々いじくりまわして原因が判明。-1がunsignedだから4294967295になって無限ループ比較の時だけはsignedとunsigned両方作らなきゃいけないのを一回意識したことがあったけどその後忘れてしまっていた。

20. 比較指定子の改良

ということで、比較指定子を改良しなきゃですな。

話した結果、今までの比較指定子はsigned用に使うことにして、unsignedな比較は比較指定子の後ろにnys(ny snakxazで「非負の」の略)をくっつけることにした。あと、fi f1 f2 niv!=を表すのが採用された。ということで書いていきましょう

実装完了。さてたらいだ。動いた!やった!

あと、なぜか知らんがクイックソートが直っていた。なぜだろう。まあいいや。

とりあえずソースコードを整形して…っと、入力例としてはπよりτを使うべきだな。修正しよう。ソースコードを整形し、htmlの方にもそれを反映。

21. 次のステップ

次にすべきこととして、候補は

の3通りぐらいある。迷ったのでアンケートをとったところ、デバッグ環境の整備50%、乗算・除算の実装25%、ドキュメントの整備25%となった。ということで、まずはデバッグ環境と外部関数呼び出しですな

無事ホテルに着いたのでやっていきましょう。

そういえば、除算ってそういえばゼロ割問題もあるやん(あるやん)

22. デバッグ環境と外部関数

22-1. 組み込み関数とアドレスの現状

とりあえず、

をやっていきましょう。さて何から作ろうかな。組み込み関数でも作るか。

現状、「0xbda574b8に飛んだときに明示的にTERMINATEする」という一種の組み込み関数があるわけだ。さて組み込み関数にはどこのアドレスを割り当てようか。とりあえず現状で使っているアドレスの一覧をば

アドレス役割
0x1482e8d4プログラムがロードされる位置
0x6d7aa0f8スタックポインタの初期位置
0xa0000000 - 0xaffffffc自由に関数がいじっていい領域
0xbda574b8ここにreturnすると処理が正常終了する

ふむふむ。じゃあとりあえず0xbdaqqqqqあたりに組み込み関数とかは配置することにしておきましょうかね。まあ単純にラベルとして定義しておいてジャンプしたときにインタプリタが特別に扱えば良い。

22-2. 用語の整理

ステップ実行ともうちょい読みやすいメモリダンプの方が欲しいと言われた。なるほど。

ステップ実行するからにはinteractiveなプログラムにしなきゃいけないが、さてさてinteractiveってどう訳そうか。

聞いたらxarzni'arプログラムというのを提案された。宗教的なカウンセラーだそうだ。めっちゃええやん。現世の情報界隈って宗教的な諸々がほぼ採用されていない(だからこそ「宗教」という語が「vim vs. Emacs」「2-space vs. 4-space indent」とかのことを指せる)ので、対比としても面白いよね

ということで、用語集に追加して、さらに用語集へのリンクをこのページにも貼った。

22-3. コメント

とはいえ現実世界に住まいしものが少しずつ悠里OSに馴染むための過渡期において、コードにコメントが書けるのは相当急務な気もしてきた。むしろ最初は一行一行にコメント残したい。レジスタの値とかではなくそもそも、xoloってなんだっけ?とか言っていちいちドキュメントに戻る手間が省ける。

— ゔぁねろぺ (@Vane11ope) 2017年9月15日

ということで、現世での独自拡張としてセミコロンでのコメントアウト機能を5分で実装した。

22-4. メモリダンプの改良

メモリダンプを改良していきましょう。とりあえず印字用の関数をね

まず、Data.Map.Map Word32 Word8Data.Map.Map Word32 (Maybe Word32)に変換する関数を作成。

そしてそれをShowに繋ぐと、圧倒的に読みやすくなった

22-5. ステップ実行

さて、インタラクティブな…じゃなかった、xarzni'arvenなやつを実装していきましょう。さてコマンドライン引数どうしようか。[]~<>@$&\_が使えるそうだ。

まあいいや。とりあえず-xでええやろ。現世対応のために-Iも許容するか。

22-6. 進捗ダメです

インタラクティブなインタプリタとそうでないインタプリタを分離すべきかどうかという問題

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年9月15日

これで迷っていて2時間ぐらい進捗がない顔をしている https://t.co/Z1jTGiJaAx

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年9月16日

これで迷っていて4時間半ぐらい進捗がない顔をしている https://t.co/bGWFUwnBpP

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年9月16日

進捗ダメです。

22-7. Q&A

Ritchanさん (@aios_ciao)から質問が結構来たのでTogetterにまとめた。ありがたい。後で仕様書書く時に役立てよう。

22-8. 進捗出します

とりあえず-xオプションを追加。

さて、今無限再帰しているのを1個ずつ実行していきたいと。なんかこういうのって不動点コンビネータとかいうの使うと綺麗に書けるんじゃなかったっけ。知らんけど。

書けた。なるほど、不動点コンビネータってこうやって使うのね

さて、型パズルの時間だ。何をどうすればいい?とりあえず、「-xオプションで起動、コマンドでファイルを読み込んでそれをステップ実行」と「-xオプションをつけてファイルパスを指定した状態で起動、それをステップ実行」の2択か。まあロードコマンド作るのがめんどいので後者で。ファイルが提供されていなかったらstderrにメッセージ吐いて終了。

さて、どうすればいいか。ファイルを読んでロードした時点でtoTentativeLoadしているからTentativeLoad型の値を持っている。

モナドの連鎖を理解するのが難しいので、ラッパを剥がすだけの関数unwrapWithを定義。これは(Hardware, TentativeLoad) -> VIO a -> (Either Error Hardware, Logs)という型を持っている。

えーと、execOne (return ())して、Hardwareを回収して、あれLogsを送り込む方法がないぞ。あ、そうか、先頭でtellとかしてやらなきゃいかんのか

んーでもこれ仕様でよくない?ステップ実行なんだから前に書いたログはもう一回書かれない方がいいだろ

さて、次の問題としては、TERMINATEしたのかどうかを判別する方法。現状だとともにreturn ()なんよね

まあBoolを返すようにすればいいか。Trueならステップ実行を継続、Falseなら完全終了。

とりあえずExecute.hs側だけ変えると…あれ、型エラーが起きない。なるほど、もともと()だったやつを握りつぶしているからか。

ということでそれをちゃんと返すようにして、fullExecuteの方もいじる。

あとは諸々をやって、完成。多分。途中でフラグの意味逆にしてバグったけど。

22-9. 組み込み関数

あとは組み込み関数を作ればなんとかなるやろ。何が欲しいかなぁ

こんなもんかなぁ。とりあえずログから実装するか。関数名どうしよう。「出力する」がeinesらしいのでそれでいいか。

さて、アセンブリ言語としては「外部の関数einesの存在」を教えてもらわなきゃいかんよな。Cでいうヘッダファイルを読み込んでプロトタイプ宣言を受け取るみたいな。コンパイラの実装としては標準ライブラリとリンクするみたいな事だと思うけど、インタプリタの場合は単にエミュレート。

さて「外部の関数」ってどう言おう。xokisonが「別の場所で」らしいからそれでいいか。

予約語的なの整理しなきゃだよなぁ、ちょっくらドキュメントいじるか

23. ドキュメントいじり

ちょびっといじった。

24. 外部関数

ラベルに使える文字列を決めていなかったなぁ。ちょうどこの前String型とLabel型を分離したことだし、ちょっと考えておくか。

リパーシェ相当はいいとして、数字、あとアポストロフィ、ハイフンも許容しようかなぁ。アンダーバーも許容するか。

とりあえず、コンストラクタを隠すことでラベルのチェックを徹底するようにした。fullParse "nll 123$$$ fen"を落とすようにした。

リパーシェ相当は…pFftcxkqhRzmnrljwbVvdsgXiyuoeaか。数字は0123456789で、アポストロフィ'とハイフン-とアンダーバー_を許せばええやろ

ということでisAlphaNumを変更します

そしてそれをsettings.htmlの方にも書いた。ついでに+と@の前後のスペースは任意であることも書いた。

25. 開平法とデバッグ

25-1. 開平法

開平法を書こう。ライブラリとして使えそうだし。

ラベルにFとfを両方使ったらバグった。なるほど、toLowerのせいか。直さねば。

そして、同一のラベルが複数あったらエラーにしなきゃいけないのを忘れていたことにも気づいた。

さて、一時しのぎにラベル名をcにしたがまだ動かない。なぜだ。

原因判明。xylonysxyloと書いていた。直したら動いた。

とりあえずHTMLにしてリンクを掲載。

25-2. デバッグ

とりあえずtoLowerを排除した。これで第一の問題は解決。

次に、複数ラベルの検出をせねば。とりあえずモナディックにしよう。

弾いた。これでnll a fen nll a fen nll b fen fen l' bがエラーになる。

26. 会話による進捗

26-1. 「ライブラリ」をどう訳す?

ライブラリをリパライン語でどう呼ぶかについて話し合った。また、パイグ語の方に関しても話し合った。そしてその結果を用語集に書いた

「レシピ本」という提案がFixa.siertija(れもん氏、@_lem0n_)から出たので、「料理の本」ということでjujojel'd akrantierlとした。ただ、長いので当然略されるだろうという話になり、Fafs.faliraが「juakとか音節を取ったり、頭字語としてJAとか、それを文字化してjera」という提案をした。j.vの「juak、パイグ人が好きそう」という発言とFafs.faliraの「リパラオネ人としてはjera」という発言により、「リパライン語ではjeraと呼ばれるが、パイグ語ではjuakと略されており(発音は/juak/または/yak/)、パイグ人エンジニアの多くはこの略称がリパラオネ人にも通じると思い込んでいる」という設定になった。日本語の「CUI」みたいな立ち位置である。

26-2. tkcバイナリの位置付け

いわゆるtkcバイナリについて話し合った。決定したことを以下に書いていく。なお、panqateelで使われるバイナリのことを便宜上j.vバイナリと仮称するが、この呼び方は真理設定ではない。

決定事項歴史設定
tkcバイナリは固定長
j.vバイナリは可変長
黎明期の一般向けの商用コンピュータではメモリの使用量が抑えられる可変長が採用されたが、固定長の方が実行速度が稼ぎやすかった(『nxの次の命令を指すところにxxを移動させる』という処理にメモリアクセスが不要になること、必ず4byte単位になるためアラインメントが楽になることなどが挙げられる)ので、tkcバイナリが後に設計され科学技術計算などのために使われた。
同一のアセンブリ言語が、異なるアセンブラによって翻訳されることでtkcバイナリとj.vバイナリとに分かれるtkcバイナリのシェアはそれほど高くないので、tkcバイナリ用に一から高級言語のコンパイラを作るのも手間であったし、j.vバイナリ用にビルドされたプログラムが利用できないと不便である。よって、アセンブリ言語レベルの互換にすることで、(アーキテクチャ設計の自由度は下がるものの)単純な事前処理でj.vバイナリをtkcバイナリに変換できる(j.vの逆アセンブラ→tkcのアセンブラ、とすればいいし、設計思想が似通っている以上もっと単純に命令の対応表を作るだけで実装できる。まあ前者の方がどちらかがバージョンアップした時に便利だが)という利便性があったので、このような仕様になった。

27. 外部関数とかライブラリとか

やっていきたいですね。眠いので、とりあえず何をやらなきゃいかんかだけまとめて寝ましょう

寝ます

28. ログ追加とファイル整理

『こうすると現世っぽくなってしまうからあえて逆にしよう』というような考えは、かえって現世を意識してしまっていることになるので、悠里創作においては好まれません」という話は大事だと思うので、ログを追加した。

あと、過去にまとめていたログもconversations/の下に移した。

ついでに画像をimg/の下に移した。

29. 外部関数とかライブラリとか(実践編)

やっていきましょう。とりあえずインタプリタのドキュメントを書かねば

29-1. レジスタと同名のラベルの禁止

その前に、nll xx fenが意味解析を通り抜けてしまう細かいバグに気づいたので直していきましょう。

直した。

29-2. ドキュメント

仕様が変わる前に、インタプリタの現仕様のドキュメントを書いた。インタプリタの追加設定一覧(暫定)に置いてある。

29-3. 呼び出し規約の整理と拡張

現状の呼び出し規約、ちょっと自由度高いし、もうちょい束縛したものも考えてみたい。その方が効率上がるかもだし。

まずf0, f1, f2, f3を破壊するかどうか。「破壊していい」がデフォルトだけど、関数によっては破壊しないでくれる方が呼び出し側にとって助かるということもあったりするかも。他には、逆に破壊するにはするけどf1 ~ f3を戻り値としても利用できるような規約があってもいいかも。要するに、「関数のバージョンが上がってもf1は一定値を返し続ける保証」ということ。

あとスタックに積んだ引数に関しても、「破壊しない」「自由に破壊してよい」「有効な値を返す」の3通りがありうる。例えば、lakormeruは関数から返ってきたときにはf0に平方根の整数部分を格納しており、引数のあったところに「元の引数と戻り値の2乗との差」を格納している。これは実装がそうなっているというのもあるが、共に活用できうる情報であるので、「有効な値を返す」保証というのを付与するのも良さそうである。

えーと、「自由に破壊してよい」が最も広い概念で、「破壊しない」と「有効な値を返す」がそれの2つの異なる特殊化だから、無修飾なら無保証、「破壊しない」と「有効な値を返す」についてはなんらかの修飾子を指定という感じでいいか。その修飾子をどこに書くかという問題は残るが。

まあ、理想的にはCのヘッダ的なことをやったりしたいよね。機械に読める関数のドキュメント作って、それを元にどうこうといった感じで。「静的解析して規約が満たされていないときに文句言う」とかはアセンブラの領分を超えている気がするけど、インタプリタとしてはそういう機能があってもいいかも。

とりあえず、表現方法を考えるか。「自由に破壊してよい」が00、「破壊しない」が01、「有効な値を返す」が10、「そもそも存在しない」が11という風に2bitで表せばf0 - f3のを8bitで表せて、引数の情報も表せる。

今までに作った関数でやってみるなら、

関数名f0f1f2f3第一引数第二引数第三引数第四引数
fib11000000001111111
fib21000010101111111
ycax0000000001010111
lakormeru1000000010111111

という感じ。32bit使うなら引数12個までいけるやん!12個引数取る関数もそうそうないだろうし(←フラグ)これで大丈夫でしょ

どちらかと言うとあれか。マクロ的なものとして「00なレジスタの値をスタックに退避して、呼び出した後に復帰させる」みたいな構文が作れるみたいな感じか。あとは、内容が保証されていないレジスタにアクセスしたらwarning出すとか。

さて、2進で表す方法はともかく、アセンブリ言語側でそういうことを表現する方法も作らなきゃな。

話変わるが、todoに書き忘れたけど「これは外部から見える関数です」ということを宣言するアレも必要。

まあこれで「別の呼び出し規約を作る」案件は解決した気がする

ん?いや待てよ、f0 ~ f3を関数が読むかどうかもビットで指定しなきゃいかんかも?引数は読まれることが大前提だからいいとして。まあいいか、レジスタも引数みたいなもんだ、「勝手に読まれることがあるかも」って扱いでいいのでは?(雑)

んーでも普通読まないこと前提だからなぁ。ハードウェアを操作するとかの特別な命令とかの場合だけ引数をレジスタで渡したい感はあるし、1bit増やすか。引数2つ削るだけでイケる。読むなら1、さもなくば0

ということで改訂版

関数名f0f1f2f3第一引数第二引数第三引数第四引数
fib101000000000001111111
fib201000000100101111111
ycax00000000000001010111
lakormeru01000000000010111111

なんか無駄が多い(レジスタに11は不要、とか)気がしないでもないが、まあいいか。自由度は高い方がええやろ(ホントにー?)

ここらで「呼び出し規約の整理と拡張」を一旦閉めようかな

30. 組み込み関数の実装

30-1. アドレスと役割

はい。そろそろ本当に実践していきます。

とりあえずデバッグ出力する外部関数から作っていきましょうね。とりあえずアドレス決めましょう

特殊判定されるリターンアドレスは0xbda574b8なので、とりあえず(Math.randomによるダイスロール)0xba5fb6b0 = 3126834864にでもするか。名前は…後で考えよう。

さて、何を実行させよう?とりあえずデバッグ出力だよな、でも何を出力させよう?うーん。

いや、デバッグ出力じゃなくて普通に出力する用の関数を考えればいいのか。そうすればOSができた後でアプリケーションとして使うこともできるし。

30-2. 「関数呼び出し」って何て言う?

「関数呼び出し」のリパライン語訳について話し合った。fenxe「(食事を)運ぶ もって行く」で表現されることとなった。用語集に追記した。

30-3. 実装しような

実装していきます。printf数が出力されればそれでいい)が欲しいとのことなのでやっていきます。

とりあえず関数をどう実装していくかという話ですな。まあインタプリタに組み込んでしまうのが無難ではありそう。さてやっていくか

うーむ、ハードコードでレジスタをちゃんと正しく操作できる自信がないなぁ…

と思ったらnop関数は楽に実装できた。そして普通にデバッグ出力できた。やったぜ。(テストするときにcallでなくjumpして一瞬詰まった、というのがアレだが)

とりあえず、仕様に書いて更新するか

30-4. 説明追加

デバッグ出力がどういうことをするのかの説明が不足していて誤解を与えたので、それの説明をし、それに関して会話ログを足した。

31. 別名追加

未実装のnac f5@って結局dal 0 f5@で実現できるよね。はい、別名として実装します

32. xokisonとリンカもどきと外部ライブラリ

32-0. 方針

数値で関数を呼ぶのはどう考えても移植性がないので、ちゃんと名前を割り振らなきゃですな。さて標準ライブラリ(?)ってどこに置こう。あと、もちろんライブラリをユーザー側で作れるようにしなきゃね。さて、今のインタプリタってファイルの先頭から実行していって、どこにもmainみたいな印がないけどどうしよう。じゃあ逆転の発想で、ライブラリは全部ライブラリだと明記するか。ライブラリは必ず関数をexportしてるはずだし、逆にmainは関数をexportする必要がない。じゃあexport宣言があるのがライブラリで、そうでなければライブラリでないってことにするか。理想的ではないかもしれないが、まあアリな方針でしょ。さて、関数のexportってどうやって行おう。

32-1. 構文

さて、どういう構文にしようか。kinunsares(公開する)にしたいが、ちょっと長い気もするなぁ

そういえば、【対応する機械語が存在するわけではない、アセンブラ側に伝えるためだけの構文】(過去に書いた文章見ると「擬似命令」って書いてあるな)って現状'i'c'c'iしかないけど…と思ったらl'nllも一応あるな。うーん

とりあえず、何らかの形でkinunsaresを省略したものを構文にしたいが、リパラオネ人の略語の感覚が掴めないのが悩ましい

32-2. 話は変わるが

Togetterが増えた。ついでに、先週(9/23あたり)にまとめたpart2へのリンクも貼っておこう

このページの先頭とかにも貼っておくか。

32-3. kinunsares改めkue

とりあえず、複数ファイルを扱う機構だけでも作ってしまおうかなぁ。先にコードを組んでおいて、後でkinunsares相当を入れればいいだけだし。

と思ったら「kinunsares、形態素ごとに略しそうkueかな」と言われたので確定。

32-4. kueの実装

とりあえず、'c'i'i'cかぐらいしか記録していなかったパーサーの内部状態をいじって、kueの情報も載せることにしよう

kueの情報もパーサーから返せるようにしたので、今度はmain.hsを調整しよう

概形はできたが、問題はリンクだな。というかxokison実装し忘れてるやん

実装した。さてリンカについて考えよう。

32-5. リンカ

現状はInstructionの中にラベルがそのまま仕込んであって、実行時にラベルを見てラベルテーブルから検索してそこに飛ぶという処理にしている。つまりExecuteの方も調整する必要がある。

Executeを見てみるとgetValueFromRという関数内でラベルの解決をしている。これをリンカに任せたい。んー、M.lookupを抽象化すれば十分かもなぁ

とりあえずLinker.hsみたいなものが不可欠か。

単一のファイルのみを扱えるリンカ(リンクできるとは言っていない)を実装。

32-6. 抽象化

とりあえずTentativeLoadを用いているところを全て抽象化できたので、あとはリンカを正しく実装するだけ。

33. 諸々

リンカについて考えたりしている間にあった諸々をまとめておく

33-1. バイナリ案

9月26日(UTC+09:00)に炭酸ソーダさん(@na2co3_ftw)がバイナリ案を考えてくださった。

2003fのバイナリ案を勝手に。 https://t.co/BQb025YKwj こういうことするならちゃんとFAFssに入った方がいいのかな

— 炭酸ソーダ (@na2co3_ftw) 2017年9月26日

33-2. Web版インタプリタ

9月30日(UTC+09:00)に炭酸ソーダさん(@na2co3_ftw)がWeb版インタプリタを作ってくださった。

2003fををGUIでステップ実行できるやつ作った https://t.co/xcxKRxG13N

— 炭酸ソーダ (@na2co3_ftw) 2017年9月30日

33-3. Togetterと用語

Togetterが増えた。副産物として、『関数として用いない、純粋な「ラベル」をリパでどう言うか』『fiでセットしてmalkrzで読むフラグの具体的な名前』という2つの案件が発生した。後者はfio'd famianで良さそう。

33-4. 334

な阪関無

34. リンカの実装

やっていきましょう。

34-1. エラー

TentativeLoadの関数をEither String TentativeLoadじゃなくてEither LoadError TentativeLoadにしようかと思ったが、唯一存在するエラーが"duplicating label(s): " ++ intercalate ", " (map unLabel labels)なので、これはLinkErrorでいいでしょう。

34-2. ロード

ロード地点を順次変えていけばいいわけだが、さてそうなるとサイズ制限をかけなきゃだよな。どれぐらいにしようか。

2005年に64KB制限で苦しんでいる人を見つけた。j.vバイナリは1命令が約4byteだから、64KBとなると16384命令か。「どうやっても64KB以下にならない」と苦しむ後世のエンジニアの顔が見えてたのしいので採用。

プログラム全体のサイズならともかく、単一ファイルの、しかもデバッグ用のインタプリタでの制約ならこれぐらいで十分と判断されてもおかしくないでしょ。後世が困りそうだけど。

そういえば、万進のリパラインでキロバイトとかってどう言うんだろうね。

とりあえず、64KBということは65536byteだから、アドレスに65536 = 0x00010000を足していって次々にロード、という感じか。

その前に、mainが重複したらエラーを吐くようにせねば。重複検出を備えたtoListはよく使うのでリファクタリングしよう。

main重複でエラー、mainがなくてもエラー、そしてとりあえずロードを実装した。64KBを超えても警告は出ない

さて、モナドを解決しよう。まずStringをLinkErrorにするところから。

問題はmapMがData.Map.Mapにおそらくないだろうことだ

あるやん。traverseWithKeyというらしい。さすが。

34-3. リンク

さて、ありがたいライブラリ関数のおかげてロードまでは終わった。コードを整理して、次はリンクだ

とはいえ、リンクはどう解決したものか。まあ案はあって、飛ぶときにはnxの位置を見ればどのファイルに由来するラベルかが分かるので、実行時に名前解決すればいい。

とりあえず、命名規則を統一したいので関数を改名、定義の順番も入れ換えた

待てよ、ロードしたプログラム自体はリンクしないと。Data.Mapをくっつければいいかな。

さてさて、よく考えると、0x00010000刻みでロードしている以上、逆引きとかの手間を考えるとロード位置は0xqqqq0000であるべきだよな。変えよう。

34-4. 仕様変更

仕様変更といってもインタプリタ側のみの変更。初期ロード位置を0x1482e8d4 = 344123604から0x14830000 = 344129536に変更。

34-5. エラー

やっぱり64KB超えたら警告出すべきだよな(それはそう)。検出機構組みましょう。

組んだ。

34-6. リンクpart2

現在のNXの情報をもらうようにする。あと、とりあえずProgram'の型を書く。

readNXは実装完了。currentNXに対応するところのページを開いて、アドレスをlookupするだけの簡単なお仕事。

resolveLabel'はもうちょいめんどい。さて、どういうことをしなきゃいかんか考えてみよう

  1. まず、同一ページにラベルがあるかどうか確認する。あれば終了。
  2. なければ、xokを確認する。xokに無いものは読んではいけないので、xokにないならエラー。
  3. xokにあったら、他のファイルがkueしているやつの一覧を…あらかじめ作っておかなきゃな。
  4. 一覧を読んで、ないならエラー、あるなら該当するページに飛んでラベルを入手。

そういえば、内部定義とxokが被ったときにエラー出さなきゃだな。

あと、kueしているラベルが不存在ならそれもエラー。

複数のファイルが同一の名前をkueしていたらエラー。

xokしているラベルをkueするのは?まあいいでしょう。関数を横流しするファイル。

さて、ということで、一覧も作ってリンクエラーもちゃんと出してあげなきゃいけないことがわかりました

34-7. エラーpart2

内部定義とxokが被ったときにエラーを出すように。

kueしているラベルが不存在の時もエラーを出すようにした。

待てよ、よく考えたら現状だと横流しすると重複定義エラーが出るな?めんどいので横流しは実装しないでおこう

コードもシンプルになった。

さて、複数のファイルにまたがってkue警察をせねば。sanitizeKueという名前にしようかな

重複検出付きfromListのおかげでかなり楽に実装できた。

34-8. リンクpart3

さて、実装を終わらせていきましょう

終わりました。多分。

fibを分割してみたけど実行できたので、問題なさそう。

さて、説明書いて寝るか。

説明書いた。

35. メッセージ改善

35-1. メモリ出力

境界違反した時のgarbageだと、具体的にどのアドレスにアクセスしてしまったのかが分からないので、それを表示するように。

また、数値は右揃えの方がいいので、右揃えにした。

35-2. 理語でエラーメッセージ

理語でエラーメッセージを出すための準備をせねばなぁ。

とはいえ、どう実現したものか。実行時に切り替えるものである以上、IOの近くで使いたいわけで。

まあ、全部のエラーメッセージをどこかに登録して、IOのところでShowではなく別の処理を使うようにする、とかだろうな

エラーメッセージ以外のメッセージについても対処したいよね

ということで、とりあえずラッパを被せた。

36. 掛け算と割り算

いい加減やっていきましょう。

という案件があるのだ

36-1. 算術右シフト

算術右シフトが必要。実装は一瞬だが命名をせねば

nysがny snakxazで「非負の」の略なので、snaをくっつければいいか?「負の」ってのは微妙な気がするが https://t.co/Nq7t7tUCsN

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月6日

snakxazasyk「負が可能な」とするか?(理語として大丈夫だろうか @sashimiwiki

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月6日

ということで、とりあえず暫定的にsnakxazasyk「負が可能な」という訳語を当てる。

んで算術右シフトはdtosnaでよかろう。

実装した。

36-2. 掛け算の仕様

まずは掛け算から。とりあえず、どれくらい選択肢があるかというところから考えていこうか。

そうすればダイスロールできるし。

長い時間迷いすぎている時はダイスロールを使うべしというのが鉄則なわけで。

  1. 「32bitのみ」 or 「64bitのみ」 or 「32bitと64bitで命令が2つある」
  2. 64bit演算の上位ビットを格納する場所は「固定」or「オペランドで指定」
  3. 64bit演算の下位ビットを格納する場所は「固定」or「被乗数の位置」
  4. 被乗数の位置は「固定」or「オペランドで指定」
  5. 乗数の位置は「固定」or「オペランドで指定」

1.については、32bitのみだと浮動小数点数をソフトウェア的に実現したいときに不便なのでなぁ、という感じ。

5.については、乗数が定数だったりするわけで、オペランド指定一択でしょう。さて2.と3.と4.ですな

上位位置:固定上位位置:可変
下位位置:固定、被乗数位置:固定x86のmul
下位位置:固定、被乗数位置:可変
下位位置:可変、被乗数位置:固定
下位位置=被乗数位置:可変今の枠組みに上手く当てはまりそう
下位位置:可変、被乗数位置:可変

x86の仕様を調べてきた。なるほど、imulが複数オペランドで実行された場合は上位32bitは捨てられるのか。

思いついた案:上位位置と下位位置に同じ位置を指定した場合、上位位置の情報が消える

もうこれでいいか。このアセンブリ言語、とりあえず命令の種類を節約するのが大好きだし。

36-3. 掛け算の構文

さて構文考えよう。

えーっとataの比喩を取るなら、'i'cの時はlat 乗数 被乗数=下位'c'iの時はlat 被乗数=下位 乗数

上位ビットどうしよう。

  1. 固定で第三オペランド
  2. 下位ビットの左
  3. 下位ビットの右

ダイスロール!1,4; 2,5; 3,6で割り振ろう。

回したら3。じゃあ下位ビットの右で。

36-4. 掛け算の実装

実装しましょう。

まず構文解析。

そして実装。

37. 「計算する白色」

いわゆるtkcバイナリの名称が決まった。

日本語「計算する白色」
アルテナ語ubeefazi plon
リパライン語lex litarle flan

あと、「計算する白色」(略称: ubpl)が開発された経緯についてもまとめた

「計算する白色」が開発された経緯: 2003fは、命令数は少なく(この点でのみ一見RISC的)、その分の表現力を直交性に回す(直交性に加え、単一の命令で複数の処理を行う、可変長命令であるなどの点を考慮すると、思想としてはCISCの方が近い)という設計思想だった。一方、その直交性の高さは高速化にとっては不便な代物であったので、科学技術などの高速計算には向かなかった。 故に、科学技術計算用の、高速に実行できるアーキテクチャの需要があった。とはいえ、2003fのコード資産が多かったため、それを最大限活用すべく、「2003f用のアセンブリ言語からアセンブルできるバイナリ」として設計されたのが「計算する白色」である。

ちなみに、直交性が高いというのは、Wikipediaの記事にあるように、諸々の組み合わせの制限が少ない(というか殆ど無い)ことを意味する。

38. 入門書

入門書書くか

38-1. 2003lk

そういえば、ubplが出てきたことによって、アーキテクチャとしての2003fとそこで用いられるアセンブリ言語とを区別しなきゃいけなくなるわけだけど、9月23日あたりに言っていた「アセンブリ言語の名前、2003lkとかにしようかなぁ」という案を採用しよう。言った本人j.vは忘れてたけどtkcは覚えてたし。

ということで「用語集」に足してきた。あと、入門書では今後なるべく2003lkの名称を用いるようにする。

38-2. ようこそ

ようこそ的なことを書く。あと、執筆年は(ダイスロール)phil.2005年2月ということにしておこう。

38-3. 非真理設定

真理設定とそれ以外を分離して扱う方針を明記。

38-4. そういえば

炭酸ソーダさんのバイナリ案(33-1.を参照)ではf7を潰して111をxxに当ててるんよね。基本的にこの方針に賛成なので、f7を設定から取り除いておこう。

今まで先延ばしにしておいた理由は、「xxをf4に当てて、f6とf7を単一の64bitレジスタにするのはどうか?」という考えがあったけど、掛け算の仕様も決まったし、あと「ハードウェア側で大事な情報とっておくのには余剰レジスタが2つぐらいあったほうがいいよね」という思いもあるので、f7を削除。

38-5. 掛け算

64bit掛け算だとny snakxazとsnakxazasykで挙動変わりますな(なぜ気づかなかった)

入門書から掛け算に関する記述を消して、と

とはいえ、この64bit掛け算って浮動小数点数とかをサポートするための実装だしなぁ、snakxazasykは実装しなくていいんじゃないかな

やっぱ実装します

実装しました

38-6. 用語

lkurftlesse'd lineparineなのに2003f'd lkurftlessなの不統一じゃない?とか思ってlkurftlessという語を避けてたが、『lkurferlは「話す内容」なわけなんだけど、言語を指すってイメージがあまりない。』とのことなので(辞書に「lkurferl:言語」と載ってたが、改修するらしい)、こちらもlkurftlessに置き換える。

あと節はlexnらしい。

39. 用語と歴史

39-1. 用語と歴史の議論の過去ログ

数日前にあった重要な議論を、遅ればせながら掲載する。

バイトを意味するmejという語は、理語辞書にある通りユーゴック語由来である。しかし、2003fが開発された時代はユエスレオネはハタ王国に出会ったばっかりで国力的にも差がある時代で、2003年前にユーゲ人との言語的接触はほぼないことになってるので、mejというのはそれ以降に入ってきて定着した語ということになる。

ということで、現世の10月5日(日本時間)あたりに『ビット・バイトについては「ビット・バイトとかはリパにもあったけど、現世の「ワード」のようにだんだん廃れていってユーゴックが定着した」という設定』となった。

後にユーゴック語が定着するようになるきっかけとしては、ユーゴック語圏との接触時までにハタ王国は産業革命レベルの発達状況だったはずであることから、追いつけ追い越せ的な日本(の明治時代)的な計算機研究の発達があったのではないか?という話になった。

以上のことから、2003f関連で用いられる用語はユーゴック語由来の表現を基本的に含むべきでないこと基本的に32bit操作しかない以上、2003fの時代には全部ビットとワードでやっていて、バイトはなかったのかもしれないことなどの方向性が定まった。

10月9日に、『ビットのことを「スイッチ」(lysol)と呼んでいた入門書に揃えて、ワードのことはスイッチの複数形(lysolass)と2003f時代は呼んでいた』といった感じにすることとした。物理的な「スイッチ」と抽象的な「ビット」と単位としての「ワード」が紛らわしいこと、また後世は32bit固定ではないことなどがきっかけとなって、後にユーゴック由来のバイト(mej)という単位が定着することとなったと考えれば自然である。

39-2. 有語分離

さて、39-1.で出てきた「2003f関連で用いられる用語はユーゴック語由来の表現を基本的に含むべきでない」という原則を元に用語集を見直してみたところ、いくつかユーゴック語由来の表現が発見された。このページでは2003fの話しかしていないのでそろそろみなさん忘れてきている頃かもしれないが、悠里OSプロジェクト自体は2003f以降の歴史も掲載する場所であるため、ユーゴック語由来の表現は削除するのでなく別表に分離した。ちなみに、xarzni'arの語源に有語が含まれていたのが驚きである。

ついでに、未掲載だったいくつかの用語も掲載することにした。ついでにそれに関する歴史設定も追記。

  1. ladirvirel「アセンブリ言語」:もともと-dirがチェックに引っかかったので載せないでいたのだが、実は-virelも翻訳借用による接尾辞であることが発覚、akrunftaxmavirleの摘発に繋がった。理語は「本来の言語」という意味であるが、「本来の言語」という考え方自体が、後世にできた高級言語と対比した呼び方であり、2003f当時にはなかった概念である。故に、この語は自明に後世にできた語であり、有語を含んでいて全くおかしくない。2003lkという名前から分かるように、2003f当時は「アセンブリ言語」という分類の枠組みはなく、具体的なアーキテクチャ名を指して「◯◯の言語」と呼んでいた。
  2. mej「バイト」:前述の議論のきっかけとなった語である。辞書に『ユーゴック語のmei「バイト」の借用である』と書いてある以上、2003f以降に借用された単語である。理語にはもともと「ワード」を表すlysolassという語があったが、アーキテクチャによってビット数が変わりうることと、物理的な「スイッチ」と抽象的な「ビット」と単位としての「ワード」が紛らわしいことから、lysolassは後に使用頻度が減り、語形が短く一意的なmejが定着することとなった。
  3. lysolass「ワード」:2003fの頃にmejの代わりに用いられていた単語。データ量の単位で、具体的に何ビットを指すかは状況によって異なるが、2003fでは専ら32ビットを指す。理語は「スイッチ」の意味の語lysolの複数形。一意的でないこと、「スイッチ」そのものと紛らわしいことなどから、後に多くの場合においてユーゴック語由来のmejに取って代わられるようになった。

39-3. xarzni'ar

xarzについて話をしたxarzという語は早い段階で借用され、xarzni'arという語と共に早い段階から理語に定着したので、xarzni'arvenは例外的に2003fの時代に用いられうる単語であるということとなった。

39-4. 用語集のミラー

用語集がGoogle Pagesだけにしかないというのも(gitと同期できない点とかが)不便なので、こちらでミラーサイトを作ることにした。

xarzni'arに関する記述を用語集に足した。

39-5. パイグ語

メモリ 筆付 kua2 kun2
レジスタ 激付 gak1 kun2
プログラムカウンタ 軸付 la1 kun2
EIPレジスタ 下付 ut2 kun2

— S.Y@S.Y (@S_Y15) 2017年10月11日

イエロースクリーン 如止 em muo1
アスペクト比 広別 zie1 bau2
右辺値 目端 ta1 tau2
左辺値 筆端 ak2 tau2

— S.Y@S.Y (@S_Y15) 2017年10月11日

関数 律 iak1
ライブラリ 律集 iak2 dat2
CPU 裁軸 xiu1 la1

— S.Y@S.Y (@S_Y15) 2017年10月11日
iak2 dat2はiak1 dat2の誤り

ということで、

メモリ筆付kua2 kun2
レジスタ激付gak1 kun2
プログラムカウンタ軸付la1 kun2
EIPレジスタ下付ut2 kun2
イエロースクリーン如止em muo1
アスペクト比広別zie1 bau2
右辺値目端ta1 tau2
左辺値筆端ak2 tau2
関数iak1
ライブラリ律集iak1 dat2
CPU裁軸xiu1 la1

となった。偶然にもライブラリにjuak感があるので、さらに混乱が捗りそうである。(会話ログはこちらからどうぞ)

用語集にも追記した。

39-6. ユーゴック語とカラムディア

2017/10/17 01:30あたり:

ユーゴック方面の情報史も考えなきゃだよなぁ。理語への語彙流入のきっかけとかも確定していないし(「リーナス・トーバルズ相当とかドナルド・クヌース相当がカラムディアから出た」ぐらいしか案を思いついていない)

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月16日

に対して、kpht氏から「実は私もそれくらいのもんしか考えられなくなっていてな。ハタ王国は100年に満たない間に大国に急成長したチート国家なので、社会主義政党やカリアホ=スカルムレイが成功させてもおかしくないのではと。」という返事(鍵アカ)が来た。まあ、複合的な要因があったにせよ、その中の一つとしてそんな感じのがあったんだろうということにした。アメ車が日本車に負けたりしたわけだし、そんなこともあるやろ。

2017/10/18 17:49

用語集ユーゴック語訳追加できた」とのことなので、ミラーサイトにコピー。


さて、ということはユーゴック語も勉強しなきゃだよな。もちろん、「有語からの借用は非真理設定である」とでもしてしまえば私の言語学習の手間は削減されるわけだが、それではつまらないもんな。チート国家ハタ王国がグングンリードしていって、リパラオネ人ITエンジニアがユーゴック語を学習しなきゃいかん方が面白い。

fafs「そもそも悠里世界の知能職は理語と有語ができないといかん風潮」

j.v「ならなおさらこの設定で好ましいな」

39-7. ネットワーク

インターネットが使われ始める時期を決定するのfēicháng重要だ」という話に。「2003f自体の仕様は無事固まりつつあるし、歴史方面に本腰入れていかないとな(今までもそこそこやってはいたが)」となった。

39-8. rer

理字rerには、巻き舌のrと長音のrという2種類の役割がある。デュテュスンリパーシェではこの二つを区別するというのが従来の定説だった[要出典]が、それについて議論が行われた。

結果、「2003fの時代には派閥が3種類ほど存在した」という設定となった。(faistaderという用語自体はすでに造語されていた)

  1. faista'd rer, faistader(「枝のr」):「発音に応じて巻き舌のrと長音のrを明確に書き分けるべし」という流派。
  2. etollenel(「伝統的やり方」):「昔は同一の文字だったし、直前の文字で発音の区別ができる以上書き分ける必要などない」という流派。
  3. xelkene'd rer(「xelkenのr」):「長母音をVrとして後世に明確化させたときのみ無声r表記にすべきで、それ以外はRで書くべき」という、最も保守的な流派。

外国人教育は合理的なfaistaderで行われ、またFAFssにいたリパラオネ人もfaistader派だったため、2003fのシステムはfaistaderで作られた。ただ、学校教育はetollenelで行われていて、行政文章はxelkene'd rerで書かれており、結局統一はなされなかった。外国人教育はfaistaderで行われ続けたので、理語で書かれた小説では『2種類のrを明確に書き分けることで、話しているのが外国人であることを強調する』という表現技法が生まれた。

40. 言語と歴史

39-9.にしようと思ったが、あまりに長いので分割。

40-1. 燐帝字母の順序

まず、2017年10月12日~10月13日にかけての議論があった。

「文字コードの制定のために燐字が辞書にどう載ってるかを考えなきゃ」ということで、「字を選出しなきゃ、並べようがない」となり、悠里広報が前に出した115字が基本となりそうだという話になった。「パイグ語の何割ぐらいがこの115字で占められるんだろうか」ということで、中国語に適した改良版のZipfの法則について調べるなどした。

燐字頻度分布のモデルはだいたい立ったが、やはり具体的な話はえすわいに聞いてみないとだな

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月13日

10月15日の議論で燐字字書が点画配列となることが決まった。

また、「パイグ語がどれくらいの字数を要しそうかとかいう感覚がよう分かっとらん」という話をしたところ、「『燐帝字母』に議論の対象を限るならば、他のラネーメ語族や一部のリパラオネ語族も昔は燐帝字母を使っていたので、パイグ語基準はあまり良くない」という話となった。そこで、

のどちらが採用されそうか、という話となった時に、「文字コード整備が必要になるものが作れるようになるのはユエスレオネ時代ちょっと前だろうし、その時点で作っても燐帝字母が入らなさそうと考えると、2003fが初めてなんだろうなと考えた」という話となり、2003fの段階で一気に整理されたということとなった。

j.vはこれを「2003fの時にイェスカの元で一気に整理された」と解釈していたが、これは歴史設定に合わないことが後に判明する。

40-2. 燐帝字母の立ち位置

39-8.に収録したrerの議論から派生した話題として起きた、有字のjとxに関する扱い(未収録)から、10月21日に議論が派生した。fafs falira sashimi曰く、

PMCFとの接触はすくなくともデュイン戦争後でユーゲ人との接触のほうが早いゾ。ユエスレオネ上の大多数は旧リパラオネ連邦人が占めていたから大多数はリパライン語を話す人々でいせにほのフェリーサみたいなのは少数だゾ、だから燐字もまず初期文字コードに含まれる理由が説明できない。
2000年代のユエスレオネ人で日常的に燐字を使っている奴はまず居ないので不要不急で何故追加したのかは謎。燐字も有字も特別扱いはない。

とのこと。

珍しく数多くの人が活発に参加する議論となり、以下のような真理設定が生まれた。

41. 用語回収

41-1. 料理派生

過去(26.1)に掲載したライブラリ議論で出てきた「ライブラリ関連の用語(リンカ)とか、ライブラリに対する動詞が自然に料理っぽくなりそうな気がして凄い面白くなりそう」の後で考案された用語について検討していなかったので、検討して掲載する。

出てきていた案がこちら。

リパライン語直訳意味
hynaumares毒を盛る;毒が混入するエンバグする
afnaryl除去する道具;解毒剤;消毒デバッガー(ソフトウェア)」
afnaryler消毒する人デバッガー(人)
arsnus嘔吐;吐くことコアダンプ
arsnuses嘔吐するコアダンプを吐く
zalizales飾る;装飾するpush
ycax整理するpop
artenerfe knloan無銭飲食する異常な値を出力する《要検討》
tvarlon knloan盗み食いするデバッグ出力用の関数
皿を洗う初期化する
汚れた皿未初期化の変数
変数
お箸とかフォークポインタ

「食い逃げ、なんか違うのでは」「食い逃げはどちらかと言うとセキュリティ違反系統では」ぐらいの発言だけをして、それら以外については「採用」とも「不採用」ともせずに放置していたが、

そういえば、「対話型ソフトウェアの」と「シャーツニアーの」でxarzni'arvenが被ってた(計算機科学 vs リパラオネ宗敎斈)

— Fafs (@sashimiwiki) 2017年10月22日

確かに。宗教学者が公共交通機関で計算機科学者の会話聞いたら混乱しそう

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月22日

https://t.co/WKozT12kkj

お試しに小噺を

— Fafs (@sashimiwiki) 2017年10月22日

よきかな(ここら辺の用語、採用してないな。採用して飯食いに行くか)

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月22日

採用?

— Fafs (@sashimiwiki) 2017年10月22日

エンバグ・デバッグ・コアダンプは正式採用するつもり。「汚れた皿」は俗語判定かなぁ(現世の「ゴミが入ってる」ぐらいの頻度では使いそうだけど、企業が脆弱性プレスリリースするときには使わない感じ)

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月22日

なるほどなるほど。

— Fafs (@sashimiwiki) 2017年10月22日

「hynaumares」ってリパライン語として意図性の強い単語?(偶発的な食中毒事件とかに使える?)

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年10月22日

意図性は意義に含まれてないので偶発的なのにも使えるよ。

— Fafs (@sashimiwiki) 2017年10月22日

ということでhynaumares, afnaryl(-er), arsnus(-es)に関しては正式採用。

ycaxについては、既にソートで使っているので避けたいなぁ、という感情

さて、とりあえず用語集に載せますか。と、その前に借用の確認。

はい、arsnus < ars nusnevoだけどarsがユーゴック由来。

41-2. そういえば

-axmがユーゴックからの借用でした。そういうのは辞書に書いておいていただけるとありがたいなぁ。「引っかかるのはakrunftaxm(-es)だな。まあ2003f時代はアセンブリ言語で書いてたわけですし」となった。

41-3. ladirという語

理語ladirは理語laに有語由来の接尾辞-dirがついたものと考えられていたが、ladirの初出は実はユーゲ人との接触より早かったということが確認された。というのも、ユエスレオネ主義の革命歌「国際共産主義活動よ、連合せよ(理:Ispienermedarneust shrlo da enomionas!)」に登場するのである。議論の結果、「古理lrad(神)が関係しているのではなかろうか」という話になった。

ということで、用語集を改定。

42. ラテン字転写の罠

42-1. rer

リパーシェで表示して気づいたけど、たらい関数taraiだと/taːaj/だな。ta'Raiにしないとtarajにならない。

待てよ。

よく考えたらkrzってfaistaderの対象になるな。krzもkRzも許容することにするか #悠里アセンブリ

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年11月3日

krz, malkrz, droの3つか

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年11月3日

ということで、こいつらをfaistader表記にも対応させた。

42-2. ついでに

あ、ついでに、jietoden liparxeだと(lとoだけじゃなく)iとkもめっさ見分けづらいことにも気づいた。

43. 言語と歴史again

ユエスレオネの教科書について話していたところ、「ユエスレオネは民族言語教育にうるさ」く、「多言語教育・多言語行政がわりと取り柄なところがある」とのことで、「多言語の強制的保護はイェスカの思想が強い」とのことなので、「2003f当初から悠里OSに多言語対応入れるモチベが出るのでは?」という説が出た。ただ、「悠里OSの多言語対応はデュインが落ち着いてからが現実的」であるらしく、そういうことなら実際の着手はイェスカ死後なのだろう、となった。「思想的な下地は既にあったが、まともに動き出すのはイェスカ死後にカネが絡みはじめてから」ぐらいの感じで良さそうである。

実際、思想・理想としての多言語の強制的保護が下地にあったとしても、用語やらなんやらを整備するにはカネも時間もかかるわけだし、現実的に始動し出すのは「市場拡大として行われる」ようになってからと考えた方が自然な気がする。

44. 整理

39.5に載っている「CPU 裁軸 xiu1 la1」は古い綴りで、今ではxy1 la1と書く。なお、なぜか用語集に収録されていなかったので載せておく。

45. 選手

45-1. 選手

・2003f以前の歴史(未創作)を引き継ぐであろう理字と理記号
・未だに全貌が掴めない燐字
・「『ハングル大移動』相当はファイクレオネでも起きるのか?」パイグ文字
・「jaxどうしようか、ロシア語っぽくなるのかなぁ」有字
などなど、一癖も二癖もある選手たちが勢揃い!

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年11月15日

・「左から掛かる母音字があるぞい」バート文字

— .sozysozbot.@hsjoihs (@sosoBOTpi) 2017年11月15日

選手多くね?(それでこそ悠里OSプロジェクトというアスリート大会なんだろうが)

— வாய்மையே வெல்லும் (@sashimiwiki) 2017年11月15日

多言語対応、翻訳はおろか、文字表示すらイェスカの生前には完成しなさそう

— .sozysozbot.@hsjoihs@jekto.vatimeliju (@sosoBOTpi) 2017年11月15日

大変そう(小並感)

45-2. 燐字、そしてリパーシェ

パイグ語・古パイグ・燐字などについて考察する」でも書いたが、kpht氏が16x16の燐字フォントを作ってくれた。

とはいえ、文字順を創作しないとなのよなぁ。

あと、S.Yが16x8のリパーシェフォントを作ってくれた。

さて、こうなると全角半角案件が発生してしまうなぁ、どうしたものか

45-3. 理記号

とりあえず、理記号だけでも整理してしまおう。なお、作業はGoogle Spreadsheetで行った。

以下、発掘された案件である。

45-3-1. ハイフンマイナス

現時点で-(0x2D)に当てられている理記号はハイフンである。マイナスは|(0x7C)に当てる案を以前j.vが出しており、もうそれでええやろみたいなノリになった。

45-3-2. 小数点

小数点って何を使うんだろうね。例文とかは文終端記号(ピリオド)を使ってるけど、ファイクレオネでも果たしてそうなのだろうか?

ちなみに、ユーゴックではピリオドで確定であるとのこと。

45-3-3. 引用符

"~"と:~:と<~>と《〜》が使えるらしい。プログラミング言語に絡みそう。

45-4. 選手一覧

2017年11月25日〜11月28日にかけて選手一覧を募ったところ、現状では以下のような感じで良さそうとなった。

優先度高:

文字名理語での名称主な使用言語文字体系文字数下限
リパーシェ(含úý)liparsheリパライン語アルファベット32
有数字(悠里統合数字)dieniepリパライン語、ユーゴック語記号10
理記号akraptリパライン語記号22
燐字linzklarアイル語、パイグ語表語/表意文字298
パイグ文字perger'd lyjotパイグ語結合音節文字(要はハングル)22
有字yrnali'aユーゴック語アルファベット52
有記号yrnali'a'd akraptユーゴック語記号2

優先度中:

文字名理語での名称主な使用言語文字体系文字数下限
バート文字phertarsen lyjotバート語アルファベット/アブギダ39
ヴェフィス文字desveleヴェフィス語アルファベット
スキュリオーティエ文字skyli'orti'e'd lyjot古理語、古ユナ語、現代理語詩語結合音節文字(要はハングル)

優先度低:

文字名理語での名称主な使用言語文字体系文字数下限
藍牌文字arperdzen表語/表意文字
アイラニーヤ文字ai'ranirja'd lyjotファルトクノア・アイル語アブギダ25
タウニラウィッリー文字tauni'rawillir'd lyjotタウニラウィッリー語アブギダ25
ダルヴシア文字darkhvci'aen lyjotダルヴシア語アルファベット
シュペライル文字(アイル文字)xpelai'r (ai'ren lyjot)音節文字
フラッドシャー文字fladxar'd lyjotフレッドシャー語アルファベット25
ラッタッダ文字jufixarla'd lyjotユフィシャール語アブギダ30
ビェシェン文字mildenesija'd lyjotミルドネジア語アルファベット/アブジャド
旧有字ユーゴック語結合音節文字(要はハングル)

パイグ文字については、全パターン作ると5940パターンある上に、他にアブギダ・結合音節文字が結構ある中でパイグ文字だけ特殊扱いするのもアレだし、ソフトウェア側で何とか対応するのが無難だとは思う。ということで、文字コードには部品だけ入れて合成はソフトウェアだな。大変そうだが。

といっても、全部の部品をバラバラに入れると、それぞれの文字体系で書いた実ファイルのサイズが大きくなるよなぁという。タカンとかの場合は全組み合わせ入れても余裕だしなぁ。

…タカン文字入れ忘れてる。書いとかねば。

46. エントリーポイント

久々にアセンブリ方面の話を。といっても、半月前の収録漏れを掲載するというだけの話だが。(現在が2017年12月6日、当時が2017年11月17日)

ログはこちら。 エントリーポイントを明示するラベルはなく、ファイルの途中から始めたいときにはkrz _fasal xxとでも書いて_fasalから処理を始めたのだろう。なお、fasalはそのまま「始まる地点 先頭」という意味のリパライン語である。

但し、時代が後の方になってくると、先頭から始まっているコードであってもkrz _fasal xxnll _fasalをとりあえず書いておく、ということが起きたりしそうだ(独立した関数になっていた方が色々扱いやすいもんな、順番入れ換えられるし)。で、そうなってくるとわざわざ毎回krz _fasal xxを書くのが面倒になる。よって、_fasalというラベル名を環境側で特別視し、何もしなくても先頭に勝手にkrz _fasal xxが入るようになる。そうすると、最終的には_fasalが事実上のエントリーポイントとして見なされることになり、「実は勝手にkrz _fasal xxが挿入されている」というのは雑学みたいな扱いになる。

よさそう。

47. オペコードなどについて考察する

47-1. 現状

そろそろオペコードやっていきましょうか。

「データへのアクセスは32bit固定長なのになんで命令は8bit単位なのか」などという突っ込みどころが存在するが、まあ気にせずやっていきましょう。

とりあえず、前に炭酸ソーダさんが作ってくださったを見てみよう。

8ビットを基本とした可変長セット
回路設計が簡単になるように考慮
'i'c順を基にする

命令の構成
00oooooo 命令 o:OPCODE
rrrmmmmm 1つめのオペランド。MODEがimmの場合REGは無視される。r:REG m:MODE
(imm/disp)
rrrmmmmm 2つめのオペランド
(imm/disp)
(rrrmmmmm 3つめのオペランド)
(imm/disp)

OPCODE
0xxxxx: オペランド2つの命令
000000: ata +
000001: nta -
000010: ada &
000011: ekc |
000100: dto >>>
000101: dro <<
000110: dtosna >>
000111: dal ~^
001000: krz =
001001: malkrz
01cccc: fi
10xxxx: オペランド3つの命令
100000: inj
101000: lat
101001: latsna

COND
0000 llonys >
0001 xtlonys <=
0010 xolonys >=
0011 xylonys <
0110 clo ==
0111 niv !=
1000 llo >
1001 xtlo <=
1010 xolo >=
1011 xylo <
比較は 右の値 + (-左の値) で行う。順番が逆なのはntaに合わせるため
上記ビットをscznに割り当てる
Z: 加算の結果が0かどうか
C: 加算で最上位ビットで繰り上がりが起きて捨てられたか
判定は、((z AND Z) OR NOT(c OR C)) XOR n で決定する
sが1の場合は比較処理の前に両方の値の最上位ビットを反転さそる

REG
000: f0
001: f1
010: f2
011: f3
101: f5
111: xx

MODE
00000: reg
00100: imm8
00101: imm16
00110: imm32
10000: reg@
10100: reg+disp8@
10101: reg+disp16@
10110: reg+disp32@
11rrr: reg+reg@ r:2つめのreg
immかdispを含むとき、その値を表す8/16/32ビットの値が後続する。
imm8/16は符号無し、disp8/16符号あり(C0ならFFFFFFC0として扱う)


例
'c'i
nll fib1
krz f0 f5+ 4@
krz f1 0
krz f2 1
fi f0 0 clo l' is malkrz xx ka
nta f0 1
krz f3 f1
ata f3 f2
inj f1 f2 f3
krz xx is
krz f0 f1 l' ka
krz xx f5@

1482E8D4: 08 B4 04 00
1482E8D8: 08 04 00 20
1482E8DC: 08 04 01 40
1482E8E0: 16 00 04 00
1482E8E4: 09 06 14 82 E8 FC E0
1482E8EB: 01 04 01 00
1482E8EF: 08 20 60
1482E8F2: 00 40 60
1482E8F5: 20 60 40 20
1482E8F5: 08 06 14 82 E8 E0 E0
1482E8FC: 08 20 00
1482E8FF: 08 B0 E0

とのこと。

よさそう(よさそう)

とりあえずアセンブラでも考えてみるか?Haskellに触れるのは大分久しぶりだな。

インタプリタの方をxarzniarと改名し、ladirvirelyl.hsというファイルを新たに作成。

共通化できそうな処理はCommonIO.hsとして分離し、とりあえず形式だけ合わせたダミーを作成。

さて、まともなコンパイラとリンカを作らねばなぁ。nヶ月前に書いたコードだからどういう構成になってるのかも読み返さねばだし。

47-2. コードリーディング

コードを読み返さないことには何も始まらないので、とりあえずコードを読んでいきましょう。ついでに、1ヶ月以上滞納しているアドカレを書きましょう。

48. そろそろやっていこうな

1月末にインタプリタ部分以外書いてからアドカレを放置したり、そもそもアドカレ以外も全放置している体たらくである。あれ以来やったコミットといえば誤字修正ぐらいしかないだろ。

48-1. 「完全に沈黙してる」

悠里OSプロジェクト完全に沈黙してるし、何で詰まってるんだろう。

— Fafs F. Sashimi@いせにほ書籍化 (@sashimiwiki) 2018年4月25日

私がバートとかパイグ将棋とかにハマってOS側の進捗出してないのが主な原因です https://t.co/djlY0daPCA

— .sozysozbot.@hsjoihs@jekto.vatimeliju (@sosoBOTpi) 2018年4月25日

一応今Rustとかやってるので一応

— .sozysozbot.@hsjoihs@jekto.vatimeliju (@sosoBOTpi) 2018年4月25日

詰まってるというより、やってない

— .sozysozbot.@hsjoihs@jekto.vatimeliju (@sosoBOTpi) 2018年4月25日

とはいえ、完全に0というわけではなくて、

みなさんオレオレOSやろうな

— 千種夜羽△ (@sksat_tty) 2018年4月14日

やりたい(やりたいと言っているうちはやらないの法則)(とはいえRustをやり始めたので進捗) https://t.co/o7jvBQfOoq

— hsjoihs@数情物化語 (@hsjoihs) 2018年4月14日

↓RustでOS書けばいいのでは??? https://t.co/kvLwdUy9CD

— 千種夜羽△ (@sksat_tty) 2018年4月14日

Rust→LLVM→x86とか

Rust→LLVM→2003lk
を並列でできたりしたら最高に楽しそうだなぁ、みたいなことは思っています(2003lk用のなんちゃらエンドを自作する苦行が待っているが)

— hsjoihs@数情物化語 (@hsjoihs) 2018年4月14日

あー,なるほど

— 千種夜羽△ (@sksat_tty) 2018年4月14日

2003lk、仕様と「「インタプリタ」」(アセンブリなのにアセンブルせずに直接実行)だけ作って放置してたら、「AtCoder Beginners Selectionを2003lkで実装した」とかいう人が出てきている状況でとても面白いですhttps://t.co/xg9gXkvZyE

— hsjoihs@数情物化語 (@hsjoihs) 2018年4月14日

おおお

— 千種夜羽△ (@sksat_tty) 2018年4月14日

↓ガチプロの図https://t.co/E4g5sEUhx3

— hsjoihs@数情物化語 (@hsjoihs) 2018年4月14日

プロハラやめろください

— 炭酸ソーダ (@na2co3_ftw) 2018年4月14日

これは期待ですねえ

— 千種夜羽△ (@sksat_tty) 2018年4月14日

と、私がRustをやったりしていた。

48-2. 他の人々

私が沈黙していたn日間、他の人々が色々進捗を出してくださった。ここに書くとページが埋まるので、Togetterにした。本当に皆さんありがとうございます。

48-3. 意気込み

いせにほ書籍化も発表されたし、

「異世界転生したけど日本語が通じなかった」が書籍化します!
タイトルはちょっと変わって画像のになります。表紙を彩るイラストレーターさんは藤ちょこ(@.fuzichoco)さんです!改稿後はシャリヤ視点マシマシになって、書いてる私も楽しかったです!詳細については近況ノートで随時お伝えします! pic.twitter.com/r5btgvrXDI

— Fafs F. Sashimi@いせにほ書籍化 (@sashimiwiki) 2018年5月9日

Rust 1.26もstable releaseされたし、

Announcing Rust 1.26 https://t.co/TPgOdCJ9vL by @rustlang

— Rust LibHunt (@RustLibHunt) 2018年5月10日

そろそろちゃんとやっていきたいところですね。

49. そろそろやっていこうなpart2

「いせにほ書籍化も発表されたし」じゃないよ、もう献本まで行われているという

やっていきましょう。はい。

49-1. hikaliumプロとかとのオフ会

6月30日にjekto.vatimelijuがhikaliumプロ(vatimeliju anlekqaviju lafimertafis)とオフ会をして、悠里OSとかの話もした。

今日はリアルではすじょい氏( @hsjoihs )に会ってきたのだが、うん、はすじょい氏だなという速度で色々話をして盛り上がってとてもよかった(しかし氏は栄養を取るべきである...)。

— hikalium (@hikalium) 2018年6月30日

そういえば、昨日@hikalium 氏とかとオフ会して悠里OSの話とかもしたりしたんよね(なかなか楽しかった)

— .sozysozbot.@hsjoihs@jekto.vatimeliju (@sosoBOTpi) 2018年7月1日

49-2. 文字コード

7月2日、FAFss slackにて。テキストはこちら

49-3. インタプリタの実行方法

インタプリタで何ができるのかソースを読んだところ、なんかステップ実行機能も実装されているらしい。すごい。そんなのすっかり忘れてたので、他人のためにも未来の自分のためにも、テスト方法を書いた。stack使うようになったから実行方法も変わっているという話もある。

49-4. README.mdの執筆

未完のまま放置していたREADME.mdだが、残すはインタプリタ部分だけなので、執筆していっている。

49-5. ラベルの名前解決

README.mdを書いていて、「未定義のラベルを踏んだら実行時エラー」となっていることに気づき、(あれ?こういうのはリンカが検出してくれるんじゃないの?)と思ったりしたが、程なく

のではないかということに気づいた。

さて、そのこととは全く関係なく、サンプルにあるtarai2を何気なくインタプリタで実行したところ、RuntimeError: Undefined label `tarai`と言われ、図らずも上記の仮説が正しいということの確証が得られるなどした。もちろんtarai2も直した。

49-6. 先に機械語やろうぜ

コンパイラを作る件だけど、なんか先に機械語インタプリタ(普通それを仮想マシンと言うのでは)を実装したほうがよいのではという気がした。

というのも、現状こういう話があるからである。(2018年7月5日、FAFss slackにて。)

50. 仕様の不備だったり記載漏れだったり

50-1. 仕様変更:アラインメント制約の追加

詳しくはログを参照していただきたいが、仕様書に書かれていた「アクセスした番地が4の倍数でなくともエラーは出ない。」という記述を撤回し、「西暦2018年8月26日仕様変更:32bitを操作する命令に関して、番地に4の倍数以外を指定したときの動作は未定義(何が起きても構わない)」とする。

また、並行して、前々から作る気であった「8bit/16bitのロード(符号拡張)・ストア命令」を実装することがこれで確定した。なお、unsignedの拡張はビットマスクでできるので、符号拡張だけあれば十分である。

50-2. 「シフト幅は63まで合法」を明記

2017年12月15日の段階で決まっていた「シフト幅は63まで合法」をなんとどこにも記載していなかったため、明記した。

50-3. injの詳細な挙動を明記

inj a b cというのは、「aをbに移動すると同時にbをcに移動する命令」としているが、これではinj a b bの効果が定まらない。Haskell版(とそれをかなり忠実に移植したWebIDE版)の挙動に合わせ、inj a b cの挙動を

  1. bの値を一時保管する
  2. aの値をbに入れる
  3. 一時保管した値をcに入れる

という操作をこの順に行う行為と同等であるべし、と定義することとした。

早見表 (a, b, cはそれぞれ異なる場所を指すとする):
inj a b c : cには旧bが、bには旧aが入る。aは変更されない。
inj a b a : aとbの値が交換される。
inj a a c : cには旧aが入る。aは変更されない。
inj a b b : どの値も変更されない。
inj a a a : どの値も変更されない。

50-4. injの挙動をさらに詳細に

inj なんか f0 f0@としたときに、f0@は旧f0の間接参照だろうか?新f0(=なんか)の間接参照だろうか?

これはさすがに未定義とすることにした。

なお、lat f0 f1@ f1latsna f0 f1@ f1にも同様の穴が発見されたので、未定義にする。

51. malata、そして2003lkは何であるか

2003lk、相対分岐とか相対コールのために、malata (if flag { dst += src }) とかkrzata ( a = b; b += c ) とか欲しいですね。 今ある命令でも頑張れば似たことはできるけど

— 炭酸ソーダ (@na2co3_ftw) 2018年8月4日





メタ的に言うともともと機械語の仕様を定めずに作った言語であるということもあって、2003lkは特定の機械語のビット表現に依存する処理を書かずにプログラムできるような仕様になっている。

故に、現状では相対分岐とか相対コールのためのmalataを入れるつもりはない。(ただし、実際の機械語にする段階でアセンブラがmalata相当の命令に翻訳するという実装は大いにアリである。)

「2003lk、機械語と1対1に対応しないのであればアセンブリ言語ではなく低級言語では」というのは実際半分ほどはそうである。とはいえ、「名前解決をアセンブラに手伝ってもらう代物をもアセンブリ言語と呼ぶのだし、これぐらいの仕事をアセンブラがやるのは許容範囲では」「そもそもx86-64のアセンブリ言語上のmovって35種類の命令を指すのだし、アセンブリ言語上の特定のイディオムを見抜いてそれ用の機械語に翻訳するのはアセンブラとして普通に許されるのでは」とも思うし、アセンブリ言語と言っていいと思う。

52.

52-1. フラグを取り出すイディオム

53. 8bit/16bitのロードとストア

50-1.のログで述べたように、「8bit/16bit は ロード(符号拡張)・ストア命令」だけをサポートする。











ということで、kRz8i, kRz16i, kRz8c, kRz16cの4命令が追加されることとなった。足さねば。

Haskell側でも実装し、仕様も明記した。

54. スタックポインタのアライン

na2co3「『関数が呼ばれた時点で、f5が4で割り切れないといけない。』というのは呼出規約?」

j.v「たしかに。明記しとこ」

55. 巨大な即値

na2co3「WebIDEに即値として巨大な数を入れると、dobuleを経由するため有効桁数で丸められた後、32bitに丸められるが、Haskell版では正確に32bitに丸められるという差を観測した」

j.v「あーなるほど」

na2co3「どうなんでしょう。未定義動作なのかなあ」

j.v「うーむたしかに(うーむ)。2003lkは一貫してオーバーフローの挙動を定義していますし、禁止する積極的理由はたしかにないんですよね」

na2co3「じゃあ対応するかあ」

j.v「こっちも明記しておきます」

56. 入門書

ずっと前から「2003'd ferlesylでプログラミングを学ぶっていう資料欲しいよね。えすわい本人もやってみたいって言ってるし、書いてみるか」と書いていたのを、やっと実行に移している。

とりあえず、現状DPのコードは書けているので、それの解説を書かねば。

入門書はこちら

57. エラーメッセージの理語化

Haskell interpreterについて、「エラーメッセージの理語化:ラッパは被せたので、訳すとかしていかねば」とか言われていた。訳してもらったので足していきたい。

その過程で「kueの動作が良く分からない」と言われた。opcodeの32-0.に書いたように、複数のファイルが渡された場合、kueが無いファイルがmainみたいな扱いになって先頭から実行されるんよね。つまり、kueが無いファイルはただ1つ存在する必要がある。

あ、このことsettingsに書いてないじゃん。書いた。

さて、翻訳もいちいち確認しておくか。念の為。

57-1. リンクエラー

nixo melsrolfenoとなっている。 nix【失敗する】-o【名詞化】; mels【〜に関する】-r-【合成語】olfen【通信の;連絡の;接続する〜;】-o【名詞化】か。

dirjasanasch 無効な 不正の
kakitercenust 構文解析
melsrolfeno (コンパイル過程の意味で)リンクする
delriunerfe 予期せぬ
sliejses 重複する、重なる
piesteten/xanalen (変数や関数などの)グローバルな/ローカルな
kakitercenustusykinerfe 構文解析できない#lipayuna

— Fafs F. Sashimi@いせにほ好評発売中 (@sashimiwiki) 2018年9月15日

なるほど、足したのか。

57-2. 構文エラー

nixo kakitercenustか。kakitercen【割り込む;仕切る;区分けする】-ust【動作】………んー………

「文法エラー」と解してmels krancia nixoとかのほうが義が分かりやすいのでは。

まあ「kakitercenust 構文解析」という定型句として定義するならアリか。

57-3. 実行時エラー

nixo ingglimj。手元の辞書に載っていないので最新版をダウンロード。

「ingglim【副詞】道中で 途中で 道すがらで」よさそう。

「実行時エラー」をNixo ingglimjって訳すのエモくて我ながら好き

— Fafs F. Sashimi@いせにほ好評発売中 (@sashimiwiki) 2018年9月15日

57-4. size limit of a single file was exceeded

panqa'd chertifen xerfo es sach'arrefoien fai jurkenel'd snojostan。えーと。

主語「一つのchertif【(コンピューターの)ファイル】の大きさ」、es 以降の 「sach'arrefoi【オーバーラン】-en【形容詞化】」が補語。あとは「fai【〜の決まりに沿って】;jurkenel【限界】-'d【〜の】;snoj【規定する】-o【名詞化】-stan【定性】」。よさそう。

57-5. "duplicate local label(s): "

"xanalen firsykaloa'st sliejseso: "。xanalenは直訳は「公国の」だが、上記にある通り「ローカルの」らしい。

firsykaloa、「【名詞】ドメイン エイリアス シンボル ラベル;【名詞】サブルーチン 関数;【名詞】間接アドレス参照 間接参照 逆参照」とあるのが闇なんよなぁ。「[文化]理理:firsykaloa参照。」とあるので読んでみるか。

【ftl.a】e es kakitercen kranteerle'c fua kanteto elx edixa Akrantergal.
【ftl.a】e es kanteterl etanerl ol tasniau'it fal liuj.
→e es kanteto polto fai jyvied faovel.

えーとkakitercen kranteerle'c fua N【〜のために本に割って入る】、elx edixa akrantirgal【読み終わった箇所】、kantet【表す】-o【名詞化】。「読み終わった箇所を示すために本に割って入るもの。」はい栞ですね。

kanteterl【表す物】; etan【前置詞:別の名では】-erl【〜する物】; ol【もしくは】; tasniau【関数】-'it【を(従属節)】fal liuj【コンピューターで】

「コンピュータにおいて、別名または関数を表すもの。」んー

最後。kanteto polto fai jyvied faovel。「細かい【代わり-道具】に従って場所を表すもの。」うーむわからぬ。

57-6. "multiple files lack `kue`"

"chertifess mol niv mels `kue`" (心配)、とある。まあ「2個以上の〜」とするのが最適ではあろうが、まあよかろう。

57-7. "all files have `kue`"

"als chertif laxn `kue`"、laxn【内包する】、よさそう。

57-8. "conflict: different files export the same label(s) "

「"sliejseso: cuturlo eustira'd chertifess feat daliu'd firsykaloa "(心配、コロンは"es", "is"で読む場合もあるということ、初学者とかに書かないとなあ。)」とある。 ふむ。

sliejs, -es, -o「重なること」

cuturl, -o「出すこと」

eustira'd「複数の」

chertifess「ファイル」

fea, -t 「(直前)が(直後)を」

daliu'd 「同一の」

firsykaloa 「ラベル」

cuturlって「〜という物を出す」と「〜という場所を出る」の両方があるのか。

まあとりあえず、「複数のファイルが同一のラベルを出すこと」という。よさそう。

57-9. "conflict: cannot import label(s) ~ that is already defined in the file"

"sliejseso: elx mouteo niv cene firsykaloa ~. la lex veles snojo xelvinj fal chertifestan."

えーと「重なること:〜のラベルをロードできない。それは既に(この)ファイルで定義されている。」。良い。

57-10. "cannot export label(s) ~ that is not defined in the file"

"cene niv cuturl firsykaloa ~. la lex niv veles snojo fal chertifestan."。

「〜のラベルを出せない。それはこのファイルで定義されていない。」よさそう。

58. 術語整理

58-1. 擬似命令

xlaiso'd xalergerlとなった。ちなみに「擬似乱数」ならciurlen xalergerlで、「擬似乱数命令」ならciurlen xalergerl'i xlaiso(「乱数っぽいものを発注すること」)。

xaleは動詞ではないので名詞を-enや-'dで取るが、xlaisは自動詞「〜を命令する」の他に他動詞「〜を発注する」があるので対格で受ける。

58-2. firsykaloa

「『ラベル・関数』と『間接アドレス参照 間接参照 逆参照』の義があるのは如何なものか。『間接参照』はyst firsykaloaとでもしたらどうか」と提案したところ、採用された。

58-3. キャッシュ

wounsa「ポケット』となった。

59. アンダーバー

na2co3「_という字、向こうにあるのです? https://docs.google.com/spreadsheets/d/1-pOTZO5zQvBZzwVZqrRjkNkEbJB9lLuD-LNPrCQyAXE/edit#gid=1605663880 これに載ってないので」

j.v「載せ忘れてるなぁ(たしかあったはず)」




ということで暗黙のうちに存在を確定させていたのだった。ということで明記する。

60. fasalについて

46.にこんなことを書いた。

ログはこちら。 エントリーポイントを明示するラベルはなく、ファイルの途中から始めたいときにはkrz _fasal xxとでも書いて_fasalから処理を始めたのだろう。なお、fasalはそのまま「始まる地点 先頭」という意味のリパライン語である。

但し、時代が後の方になってくると、先頭から始まっているコードであってもkrz _fasal xxnll _fasalをとりあえず書いておく、ということが起きたりしそうだ(独立した関数になっていた方が色々扱いやすいもんな、順番入れ換えられるし)。で、そうなってくるとわざわざ毎回krz _fasal xxを書くのが面倒になる。よって、_fasalというラベル名を環境側で特別視し、何もしなくても先頭に勝手にkrz _fasal xxが入るようになる。そうすると、最終的には_fasalが事実上のエントリーポイントとして見なされることになり、「実は勝手にkrz _fasal xxが挿入されている」というのは雑学みたいな扱いになる。

よさそう。

これに対してtkc氏が「そういえば, _fasal でいいんですかね. _ としていいんですかね?(現世感あるけどこれは設定的に問題無いのかと思った) (これ分からんのでtinkaは_fasalからfasalに変更しようと思っている.)」と述べた。

私の感想『_fasalfasal も現状はまだただの名前ですからねぇ。「後世では、処理系に特殊扱いされるので _fasal fasal 'fasal どれでもいい」「どうせ一つのファイルに2種類混在させるやついないやろ」』『「_fasal というラベルがあれば、エントリーポイントを持つファイルの冒頭に勝手に krz _fasal xx が挿入される」というだけの機能なので、「処理系が_fasal fasal 'fasal は特殊扱いして、勝手に冒頭にラベルを入れる」でええやろ、という』

そもそもあくまでボイラープレートを回避するためのものにすぎないのでねぇ。

61. test命令

61-1. 確実に導入します

2018年9月9日あたりに、test命令(bitANDした結果が0なら/0でないならフラグを立てる)を足す提案をj.vがした。炭酸ソーダさんから「命令の数を減らす傾向にあるのにそういう無くても困らない命令入るのかな」という疑問も呈示されたが、例えば正負反転は2命令でできるのに対し(ちなみに6502にも無い)、「test は、最大で krz ada fi の3つを1命令にできるので」と炭酸ソーダさん。そのとおりである。

「あれだけ命令削ってる6502にありますし」「6502の場合andでもフラグ設定するので、bit無くてもそんな困らなさそうじゃん」「しかも即値使えないじゃん。なんだこの命令」とのことであった。andでフラグを設定する保証がない2003lkではもっと役立ってくれることでしょう。

61-2. 名前

さて名前で揉めるんですよ。

その後。テキストログはこちら

結果、まだ決まってない。

62. 定数確保

62-1. 定数作らないとね

という感じで議論され、

というような形になりそうだということとなった。

テキストで再掲すると、

もうちょい仕様っぽくすると(注:以下はまだ厳密にはdraft)(でもまあこうなるっしょ)

lifemperda配置命令lifem

なお、以上の制約の帰結として、アセンブラは命令とlifemperdaを混ぜて配置してもよいし、lifemperdaを全部一箇所に固めて置いてもいい。

既存のメモリアクセス構文

構文役割
レジスタ名@レジスタに入っている番地のメモリを表す。
レジスタ名 + 定数@レジスタに入っている番地に定数を足した番地のメモリを表す。
レジスタ名 + レジスタ名@2つのレジスタに入っている数値を足した番地のメモリを表す。

ラベルを用いたメモリアクセス構文

以下に用いるアクセス方法は、lifem命令についたラベルを用いてそのラベルの属するlifem塊の範囲内にアクセスする場合のみ動作が保証される。

ラベル@ラベルの表す番地のメモリを表す。
ラベル + 定数@ラベルの表す番地に定数を足した番地のメモリを表す。
ラベル + レジスタ@ラベルの表す番地にレジスタに入っている値を足した番地のメモリを表す。
ラベル + 定数 + レジスタ@
ラベル + レジスタ + 定数@
ラベルの表す番地にレジスタに入っている値と定数を足した番地のメモリを表す。

62-2. 文字列の形式


xxx. To do

xxx-1. 割り算

ゼロ割りどうしよう。商を不定値、余りを入力にするとか?あと、負の数がらみをどうするか

xxx-4. 呼び出し規約

アセンブリ言語側で32bit呼び出し規約を表現する方法を作りたいよね → アセンブリ上ならあくまでコメントぐらいにしかならないが。アセンブラがそれを検証してどうこうとかやってくれるなら有意義だとは思うが。

xxx-5. malloc、というかシステムコールみたいな。

malloc欲しい。というより、環境依存であることを明記できるシステムコールとかを書ける仕組み欲しいよね。

xxx-7. マクロ

マクロ欲しい。

xxx-9. 造語

造語(確認)依頼
・値
・即値
・間接参照
・ディスプレイスメント(変位量)
・オフセット
・符号拡張
・ゼロ拡張
・データ幅
・16bit値の通称
・MSB,LSB(BはBitおよびByte)
・エンディアン
・リトルエンディアン
・ビッグエンディアン
・アドレス空間
・リニアな
・実効アドレス

— Ritchan(りっちゃん) (@aios_ciao) 2018年1月26日

20180128造語が行われた。