HSP: オブジェクトファイルのサイズを小さく

実行ファイルのサイズが小さい方が、一般的に使用メモリも少なく動作も速いです。
# もちろん、そうじゃない場合もある気がしますが。
# でも仮に同じ速度で動いた場合、サイズが小さい方がきっと良いでしょう。
よって、ここではHSPにおいて実行ファイルの元となるオブジェクトファイル(start.ax)のファイルサイズを小さくする方法を書きます。
HSP3.0とHSP2.61で確認しています。新たにHSP3.1で確認しているものがあります。

省略できるパラメータは省略する

HSPでは命令で省略できるパラメータが存在します。
例えばウィンドウ全体を何かの色で塗りつぶしたい場合、boxf命令を使う場合があります。
ウィンドウのサイズが640x480ドットだった場合、

	boxf 0, 0, 640, 480

とするよりも、

	boxf

とする方が start.ax のサイズが16バイト小さくなります。
# HSP 2.61では12バイト小さくなる。

1パラメータ当たり、約2バイト小さくなります。
# じゃあ何故上の例は4パラメータで12バイト小さくなったのかというと、
# HSPでは 0 〜 512 以外の値はこの範囲の値より4バイト増えるようです。


文字列は少なく

プログラム中に書く文字列はなるべく少なくしましょう。
例えばフォントを何回も指定したいとき、

	font "MS ゴシック", 16
	; ...いろいろ処理
	font "MS ゴシック", 32
	; ...いろいろ処理

と書くよりは、

	fontname = "MS ゴシック"
	font fontname, 16
	; ...いろいろ処理
	font fontname, 32
	; ...いろいろ処理

とした方が小さくなります。

ちなみにプリプロセッサ命令で#defineがありますが、これは定数をそのまま置き換えてしまうので最初の例と同じになってしまいます。
サイズを小さくしたい場合は定数より変数を使うようにしましょう。


マイナス値も変数に

使用回数が多くないと効果がありませんが、以下のように同じ値のマイナス値が何度も出てきた場合、変数に入れた方が良いです。
(HSP3.1で確認)

	a = -1
	b = -1
	c = -1
	d = -1
	e = -1
	f = -1
	g = -1
	h = -1

これは以下のように修正しましょう。

	minus = -1
	a = minus
	b = minus
	c = minus
	d = minus
	e = minus
	f = minus
	g = minus
	h = minus

確認したところ、8回以上同じマイナス値が出てきたら、上記のように変数に入れた方が良いです。


マイナス値にしたいときは0で引く

変数に入っている値の極性を反対にしたい場合(例えば a = 5 を a = -5 にしたい場合)は、以下のような方法があると思います。
(HSP3.31で確認)

	a = -a	; (A)
	a = a * (-1) ; (B)
	a = 0 - a ; (C)

上記(A)(B)(C)の中では、(C)が一番小さくなります。


配列よりも変数を

配列を直接使うよりは、変数に代入して使った方がコンパクトになります。

	mes a(0)
	mes a(0)
	mes a(0)

と書くよりも、

	b = a(0)
	mes b
	mes b
	mes b

と書いた方がコンパクトです。

また、多次元配列よりも1次元配列を使った方がコンパクトになります。
例えば、2次元配列で座標を管理したいことがあると思いますが、

	xy(0, 0) = 200
	xy(1, 0) = 100
	xy(0, 1) = 300
	xy(1, 1) = 50
	;; 以下、xy(x, y)を用いて処理

とするよりも、

	xy = 200, 100, 300, 50
	x = 0
	y = x + 1
	;; xy(x) と xy(y)を用いて処理
	x += 2
	y = x + 1
	;; xy(x) と xy(y)を用いて処理

という感じにしたほうがコンパクトになると思います。
工夫してみましょう。


gosubを使う

同じ記述はgosubを使ってサブルーチンにまとめた方が良いです。
上の配列と絡んできますが、例えば、

	col = 191, 255, 191
	p = 0
	color col(p), col(p+1), col(p+2)
	;; いろいろ処理
	color col(p), col(p+1), col(p+2)
	;;

という記述は、(配列変数のせいで)実はcolor命令だけをgosubに移動するだけでもコンパクトになります。

	col = 191, 255, 191
	p = 0
	gosub *setColor
	;; いろいろ処理
	gosub *setColor
	;;

*setColor
	color col(p), col(p+1), col(p+2)
	return

ただ、これだとgosubでジャンプする分、明らかに処理速度が遅くなっていると思います。
(推定です。検証はしていません。最近のパソコンなら全然気にならないと思いますが。)


括弧を少なく - HSP 2.xのみ

HSP 2.xの式は左から順に計算されていきます。(HSP3からは演算子優先となりました)
例えば、(1 + 2) * 3 と書く必要はなく、1 + 2 * 3 でも同じ答え(9)となります。
括弧1組当たり4バイト減らせます。

また、if文で単一の評価式を(C言語のように)

	if (x == 0) {
		; ...何か処理
	}

と括弧で囲む必要はなく、

	if x == 0 {
		; ...何か処理
	}

でO.K.です。

左優先で計算されることを考えると、if文で複数の式を評価したい場合は最初の式の括弧は省略できます。

	if x == 0 | (y == 1) | (z == 2) {
		; ... (x == 0)としなくて良い。
	}


記述を見直す

処理の記述を見直してみましょう。
もっとコンパクトに書ける場合があります。

例えば、

	if (x > 0) & (y > 0) & (z > 0) {
		; ...
	}

のような記述は以下のように書くこともできます。

	if x & y & z {
		; ...
	}

ただし先の例と同じにする場合、x, y, zのそれぞれの値が正であるという前提が必要となります。
また、x, y, zの各ビットのどこかが1で重ならない場合もダメです。
つまり x = 1 (0b0001), y = 2 (0b0010), z = 4 (0b0100) のような値の時、ビット演算で値が0になってしまうので偽となります。
まぁこれはプログラマが注意するということで。(この場合は少なくとも奇数にしていれば大丈夫)

別の例として、

	if x == 10 {
		y = 0
		; ... 何か処理が続く
	} else {
		y = 1
	}

のような記述は、多少効率が落ちる気がしますが (本当に落ちるのかな?)

	y = 1
	if x == 10 {
		y = 0
		; ... 何か処理が続く
	}

と書くとサイズが小さくなります。