0.3

0.3
配列実装、関数呼び出しまわりが腐ってたのを修正、あと、なんか色々。投げやりなREADMEとか。
全然テストしてません。自己責任で。


昨日言ってた配列を実装。

field nanika_array: int []

def start() -> void :
	nanika_array[0] = 4
	nanika_array[1] = 255
	yield
	nanika_array[1] = 8
	yield
	nanika_array[0] = 9
	yield

こんなふうにしといて、

#include "loader.h"
#include "vm.h"
#include <stdio.h>

static a24z_value a24z_field[8];

enum {
	FIELD_NANIKA_ARRAY,
};

int
main( )
{
	struct a24z_program *prog;
	struct a24z_vm *vm;
	struct a24z_native_funcs natives;
	a24z_value buf[4];

	natives.func_table = NULL;
	natives.method_table = NULL;
	prog = a24z_load_file( "test.a24zc", &natives, NULL );

	if ( prog == NULL )
		return 1;

	/* ここで nanika_array の配列を指定 */
	POINTER_VALUE(a24z_field[FIELD_NANIKA_ARRAY]) = buf;

	vm = new_a24z_vm( prog, a24z_field );
	a24z_vm_run( vm );
	printf("nanika_array[0]=%d, nanika_array[1]=%d\n",
	       INT_VALUE(buf[0]), INT_VALUE(buf[1]));
	a24z_vm_run( vm );
	printf("nanika_array[0]=%d, nanika_array[1]=%d\n",
	       INT_VALUE(buf[0]), INT_VALUE(buf[1]));
	a24z_vm_run( vm );
	printf("nanika_array[0]=%d, nanika_array[1]=%d\n",
	       INT_VALUE(buf[0]), INT_VALUE(buf[1]));

	a24z_unload_program( prog );


	return 0;
}

こーすれば、

nanika_array[0]=4, nanika_array[1]=255
nanika_array[0]=4, nanika_array[1]=8
nanika_array[0]=9, nanika_array[1]=8

こんな感じに。実行時に配列を作る方法は無いけど、mallocとかを呼べるようにしてやれば一応可能。
Cの関数を呼ぶ方法は、func_tableに関数を入れておいて、プログラムのほうでexternしておけば使える。

field nanika_array: int[]

extern new_array( size:int ) -> int []
extern delete_array( ptr: int [] ) -> void

def start() -> void :
	nanika_array = new_array( 8 )
	nanika_array[0] = 4
	nanika_array[1] = 255
	yield
	delete_array( nanika_array )

こんなふうにしておいて、

#include "loader.h"
#include "vm.h"
#include <stdio.h>
#include <stdlib.h>

enum {
	FIELD_NANIKA_ARRAY,
};

static a24z_value
new_array( a24z_value *sp )
{
	int size = INT_VALUE(sp[0]);
	a24z_value v;
	POINTER_VALUE(v) = malloc( size * sizeof(a24z_value) );

	puts("new");

	return v;
}

static a24z_value
delete_array( a24z_value *sp )
{
	a24z_value *ptr = POINTER_VALUE( sp[0] );
	a24z_value v;
	free( ptr );

	puts("delete");

	return v;
}

static a24z_native_func func_table[] = {
	new_array,
	delete_array,
};

int
main( )
{
	struct a24z_program *prog;
	struct a24z_vm *vm;
	struct a24z_native_funcs natives;

	a24z_value field[8];

	/* ここで呼び出す関数を指定 */
	natives.func_table = func_table;
	natives.method_table = NULL;
	prog = a24z_load_file( "test.a24zc", &natives, field );

	if ( prog == NULL )
		return 1;

	vm = new_a24z_vm( prog, field );
	a24z_vm_run( vm );
	printf("nanika_array[0]=%d, nanika_array[1]=%d\n",
	       INT_VALUE( POINTER_VALUE(field[FIELD_NANIKA_ARRAY])[0] ),
	       INT_VALUE( POINTER_VALUE(field[FIELD_NANIKA_ARRAY])[1] ) );
	a24z_vm_run( vm );
	a24z_unload_program( prog );


	return 0;
}

こんな感じ。関数もfieldと一緒で、上から順番にインデックスが付けられていく。


これで、とりあえず欲しいと思ってた機能はひととおり揃ったはず。
あとは、start以外の関数を呼べるようにするとかだろうか。でも、それは、また、インターフェースどうするかがわかんないんだよな…実装は簡単なんだけど。


で、えーと、面倒になってきたので、最適化の話は明日にでも。