a24z紹介
0.2 バグ潰しとか、追加とか色々。
a24z言語はLuaみたいな感じだけど、Luaよりもっと機能を限定したみたいな言語です。っていってもあんまりわからんな。ランタイムのサイズでいうと、5KBを切るぐらいの。
と、思ってたんだけど、Luaとはちょっと違うような。実はLuaってあんまり知らない。
- 組み込み言語
組み込み言語と呼ばれながらも、なんか汎用言語みたいな微妙さがあるLuaとは違う。豊富なグローバル変数でC++オブジェクトとの値のやりとりもそれなりに簡単に。
- できるだけ効率にこだわる
勝手にメモリアロケートされるとかが嫌なので、スタック足りない時以外はメモリアロケートなんか起きない…多分。
変数参照はいつだってインデックスで。ハッシュテーブルはもちろん、リストやら、配列の線型探索すら必要無い。
ここらへん、機械語の1/10ぐらいの速度は出るのではないか、と思う。計測してないけど。予想としてはJITじゃないJavaぐらいの速度が。
そんな感じ。まあ、別にLuaでいいじゃん、と言えば、それまでなんだけど、あんな連想配列やら、ちゃんとしたクロージャなんかいらねーんだよ!!とか思わない?
簡単に説明。
compilerディレクトリでmakeする。すると、compilerの中にa24zcができる。これがコンパイラ。
field x: int field y: float def start() -> void : y = 0.4 x = 4 yield x = 8 y = y * 2.0 yield x = 4 y = y * 2.0 yield
こーいうプログラムを書くとする、んで、test.a24zとでもして、コンパイル
$ a24zc test.a24z test.a24zc
これでコンパイル終わり。test.a24zcがバイトコードの入ったファイル。
んで、
#include "loader.h" #include "vm.h" #include <stdio.h> static a24z_value a24z_field[8]; enum { FIELD_X, FIELD_Y, }; int main( ) { struct a24z_program *prog; struct a24z_vm *vm; struct a24z_native_funcs natives; natives.func_table = NULL; natives.method_table = NULL; prog = a24z_load_file( "test.a24zc", &natives, NULL ); if ( prog == NULL ) return 1; vm = new_a24z_vm( prog, a24z_field ); a24z_vm_run( vm ); printf("x=%d, y=%f\n", INT_VALUE(a24z_field[FIELD_X]), FLOAT_VALUE(a24z_field[FIELD_Y])); a24z_vm_run( vm ); printf("x=%d, y=%f\n", INT_VALUE(a24z_field[FIELD_X]), FLOAT_VALUE(a24z_field[FIELD_Y])); a24z_vm_run( vm ); printf("x=%d, y=%f\n", INT_VALUE(a24z_field[FIELD_X]), FLOAT_VALUE(a24z_field[FIELD_Y])); a24z_unload_program( prog ); return 0; }
こんなプログラムを書いて、liba24zvm.aとリンク。で、実行すると、
x=4, y=0.400000 x=8, y=0.800000 x=4, y=1.600000
こんな感じ。
field x: int field y: float
まず、これが、field変数の宣言。上から順番にインデックスが付いていく。xが0番目、yが1番目。で、field変数はグローバル変数として使える。
def start() -> void : y = 0.4 x = 4
見たまんま。y が 0.4 で x が 4。んで、yieldが中断。a24z_vm_runから帰ってくる。これの繰り返し。基本はこれだけ、というか、このくらいしか機能が無いんだが。
想定する使い方としては、オブジェクトごとにVM割り当てて、あとは適当にfield書き換える、みたいな感じで。よーするに、C++オブジェクトのメソッドの一部だけをスクリプトで書く、みたいなことがやりたかったんですよ。
あとは、読み、書きごとに関数を呼び出すattr変数とか、VMごとではなく、a24z_programごとに共有されるshare変数とか。これについてはまた機会があったら。
関数呼び出しはnatives.func_tableやらnatives.method_tableをぐにょぐにょすれば。