IRIS/IRIS++ | ゲーム開発プログラミング言語


トップ トップ | 前 | 次


言語仕様





ステートメント

プログラミング言語は 1 つまたはそれ以上のステートメントで構成されています。以下はステートメントの例です。


// レジスタ 0 に 5 を代入
REG $0
ATR 5
// レジスタ 0 の値を画面に表示
ATB $0
PTB

各ステートメントは指示セット、値 (文字列および整数)、オブジェクト、コマンドおよび分離符によって構成されています。文字列は引用符で囲って表されます。改行を入力するには \n を使用します。整数は 32 ビットの 10 進数の値です。指示セットはインタプリタに特定の機能を実行させるように定義されたキーワードです。例えば、ATR は指定されたレジスタに値を代入します。値は、リテラル データまたは値を含むレジスタで表すことができます。詳細についてはレジスタを参照してください。分離符はスペースによって表され、指示セットと値を分離するために使用されます。ステートメントはダブル スラッシュ // で表されたコメントを含むこともできます。コメントはコンパイル時に削除され、IRIS によって解析されません。


// これはコメント
// コメントは解析されない

オブジェクトは先導された下線 (_) で表されます。子オブジェクトまたはコマンドはドット (.) で分離されます。例 : _gameEngine.initialize


レジスタ

レジスタはメモリに読み込まれたコードのバイト位置を保存します。ただし、数値は直接レジスタに保存されます。レジスタはリアル タイムで変動する変数として扱うことができます。文字列および数値 (ただし 32 ビットの整数に制限されます) を保存することができます。IRIS ではレジスタ番号の前にドル記号 ($) で表した 256 個のレジスタ (0 → 255) を使用することができます (例 : $23)。


指示セット

指示セット説明
NOPNo Operation: VM はこの指示セットに対して何もしません
CLRClear Register: 指定されたレジスタの内容をクリアします
ATRAssign To Register: 指定されたレジスタに値 (バイト、文字列またはレジスタ) を代入します
HLTHalt: スクリプトの実行を停止します
PTXPrint Text: テキストを画面に出力します
ATBAssign To Buffer: ATR と似ていますが、値は VM に用意された文字列バッファに保存されます
JMPJump: ラベルにジャンプします
JMSJump To Subroutine: JMP と同じですが、さらにプログラム カウンタ位置が記憶されます
RETReturn: JMS が呼び出された場所にプログラム カウンタを戻します
SUMSum: 値またはレジスタの和を求めます
SBTSubtract: 値またはレジスタを減算します
MLTMultiply: 値またはレジスタの積を求めます
DIVDivide: 値またはレジスタの割り算をします
SKZSkip If Zero: 指定されたレジスタの値が 0 の場合、次の指示セットをスキップします
SKLSkip If Less: 指定されたレジスタの値が指定された値よりも小さい場合、次の指示セットをスキップします
SKGSkip If Greater: 指定されたレジスタの値が指定された値よりも大きい場合、次の指示セットをスキップします
SKESkip If Equal: 指定されたレジスタの値が指定された値と同一の場合、次の指示セットをスキップします
SKNSkip If Not: 指定されたレジスタの値が指定された値と異なる場合、次の指示セットをスキップします
RUNRun: 外部スクリプトを実行します
IMPImport: 外部スクリプトをインポートします (コンパイル時のみ使用されます)
REGRegister: 続く指示セットに対して使用するレジスタを指定します
CLBClear Buffer: 内部バッファに空の文字をセットします
PTBPrint Buffer: 内容を内部バッファに出力します
ENGUse Engine: VM に指定されたエンジンを使用するように伝えます
@...:サブルーチンを定義します : ... はサブルーチンの名前です (例 : @init:)


マクロの使用

IRIS には一部のコードを独自に定義したもので置き換える 2 タイプのコンパイル時変換機能があります。"pre_define.h" ファイルは C 言語の構文に似たマクロの定義を含みます。置き換えはコンパイル前に行われます。"post_define.xml" はバイト コードへのコンパイル時に呼び出される XML 形式の置き換えリストを定義します。



"pre_define.h"


例 :


#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480

マクロ ファイルは定義が見つかるまで上から順に読み込まれます。必要に応じて定義の順番を変更する必要があります。


[エラーのある定義]

// ID_CHARACTER を呼びたいが、ID_CHARACTER はすでに最初の定義に存在する
// つまり、後者は読み込まれない
#define ID_CHARACTER_1 1
#define ID_CHARACTER 0


[順番変更した定義]

// ID_CHARACTER を呼びたい、そして ID_CHARACTER が最初の定義に存在する
// つまり、後者は読み込まれない
#define ID_CHARACTER 0
#define ID_CHARACTER_1 1

"post_define.xml"


例 :


<irisc>
<crypt_key>Uly@Encrypt#6X6O8R3__IRISC:07c05p23L</crypt_key>
<source_code>
<source>//</source><target>%BREAK%//</target>
<source>do {</source><target>%BREAK%%INC_AUTO_NUM%@condition_label_%FILE_PATH%_%AUTO_NUM%:</target>
<source>} until</source><target>%BREAK%REG</target>
<source> loop</source><target>%BREAK%JMP condition_label_%FILE_PATH%_%AUTO_NUM%%DEREF_AUTO_NUM%</target>
    
<source>}</source><target>%BREAK%@condition_label_%FILE_PATH%_%AUTO_NUM%:%DEREF_AUTO_NUM%</target>    
<source>function </source><target>%INC_AUTO_NUM%JMP condition_label_%FILE_PATH%_%AUTO_NUM%%BREAK%@</target>
<source>() {</source><target>:</target>
    
<source>if(</source><target>%BREAK%%INC_AUTO_NUM%REG </target>
<source>) {</source><target>%BREAK%JMP condition_label_%FILE_PATH%_%AUTO_NUM%</target>

<source>;</source><target>%EMPTY%%BREAK%</target>
<source>(</source><target>%SPACE%</target>
<source>)</source><target>%EMPTY%</target>
<source>print</source><target>PTX</target>
<source>++</source><target> SUM 1</target>
<source>--</source><target> SBT 1</target>
<source>+=</source><target>SUM</target>
<source>+</source><target>SUM</target>
<source>-=</source><target>SBT</target>
<source>-</source><target>SBT</target>
<source>==</source><target>SKE</target>
<source>/=</source><target>DIV</target>
<source>/</source><target>DIV</target>
<source>*=</source><target>MLT</target>
<source>*</source><target>MLT</target>
<source>></source><target>SKL</target>
<source><</source><target>SKG</target>
<source>!=</source><target>SKN</target>
<source>=</source><target>ATR</target>
<source>let </source><target>REG </target>
<source>return</source><target>RET</target>
<source>exec </source><target>RUN </target>
<source>goto </source><target>JMP </target>
<source>call </source><target>JMS </target>
<source>exit</source><target>HLT</target>
<source>$_rga</source><target>$8</target>
<source>$_rgb</source><target>$9</target>
<source>$_rgc</source><target>$10</target>
<source>$_rgd</source><target>$11</target>
<source>$_rge</source><target>$12</target>
<source>$_rgf</source><target>$13</target>
<source>$_once</source><target>$14</target>
<source>$_ret</source><target>$15</target>
<source>$_OPTREG</source><target>$16</target>
</source_code>
  
<engine>
<object>
<source>xml</source><target>0x00</target>
<source>screen</source><target>0x01</target>
<source>width</source><target>0x02</target>
<source>height</source><target>0x03</target>
<source>path</source><target>0x04</target>
<source>state</source><target>0x05</target>
<source>identifier</source><target>0x06</target>
<source>sprite</source><target>0x07</target>
<source>media</source><target>0x08</target>
<source>cursor</source><target>0x09</target>
<source>sound</source><target>0x0A</target>
<source>music</source><target>0x0B</target>
... その他
</object>
<command>
<source>initialize</source><target>0x00</target>
<source>get</source><target>0x01</target>
<source>set</source><target>0x02</target>
<source>open</source><target>0x03</target>
<source>read</source><target>0x04</target>
<source>write</source><target>0x05</target>
<source>load</source><target>0x06</target>
<source>unload</source><target>0x07</target>
<source>create</source><target>0x08</target>
<source>use</source><target>0x09</target>
<source>refresh</source><target>0x0A</target>
<source>clear</source><target>0x0B</target>
<source>begin</source><target>0x0C</target>
<source>end</source><target>0x0D</target>
... その他
</command>
</engine>
</irisc>
  

[irisc::crypt_key]

コンパイルされたバイナリ コードを暗号化するキーを定義します。コードはバイト コードをこの暗号キーで XOR したものになります。


[irisc::source_code::source]、[irisc::source_code::target]

source で定義された文字列は、コンパイル時に target に置き換えられます。置き換えの挙動を制御するために、特別なコンパイラ変数を使用することができます。


変数説明
%BREAK%改行を入力します
%INC_AUTO_NUM%コンパイラ内部のオート番号をインクリメントします
%AUTO_NUM%現在のオート番号を入力します
%DEREF_AUTO_NUM%内部のオート番号への参照を削除します
%FILE_PATH%現在のファイル パスを入力します
%EMPTY%空の文字を入力します (何も表示されません)
%SPACE%空白を一つだけ入力します


[irisc::engine::object::source], [irisc::engine::object::target]

source で定義された文字列は、コンパイル時に target に置き換えられます。


[irisc::engine::command::source], [irisc::engine::command::target]

source で定義された文字列は、コンパイル時に target に置き換えられます。


IRIS++

IRIS の基本指示セットだけを使用した大きいアプリケーションのプログラミングは複雑になるかもしれません。前項で説明したマクロ機能を使用すれば、解読性の向上とコーディングにかかる時間が短縮できます。IRIS++ はマクロ置き換えテクニックを使用して、さらに包括的なプログラム構文で IRIS をカプセル化します。例えば、以下のコードを参照してください。


let $0 = 23 + 5;

"let ""REG "=+;ATRSUM%EMPTY%%BREAK% として post_define.xml に定義しました。コンパイルされると、以下と同様になります。


REG $0
ATR 23
SUM 5

以下は、事前に定義された IRIS++ のキーワードおよびステートメントです。IRIS++ はメイン実行スクリプト内だけに使用可能で、import ステートメントによってインポートされた外部スクリプトには使用できないことに注意してください。


言語仕様

IRIS++ は現代の構造化プログラミング言語に似ています。言語が IRIS をベースにしているため、できることに沢山の制約があります。以下はそれらの機能および制約をまとめたものです。


  • ステートメントはセミコロンで終わる (;)
  • IRIS 指示セットと IRIS++ 言語を混ぜることができる
  • 一時的なレジスタは次のように定義されている : $_rga, $_rgb, $_rgc ...$_rgf を $8, $9, $10 ... $13
  • グローバル レジスタは次のように定義されている : $0, $1, $2 ...$7 を $0, $1, $2 ... $7
  • $_once レジスタは初期化関数が実行されるべきかどうかを判断するために使用される
  • $_ret レジスタは関数の呼び出しによって返ってきた結果を保持する
  • $_OPTREG レジスタはコンパイラがコード最適化のためだけに使用するので、このレジスタをプログラム中で使用してはならない
  • オープン括弧 ({) は必ず function ステートメントと同じ行になくてはならない

算術オペレータ

次の算術オペレータを使用することができます : +、-、*、/ (足し算、引き算、掛け算、割り算)。


論理オペレータ

次の論理・比較オペレータを使用することができます : ==、!=、<、> (一致、不一致、少ない、大きい)。


代入オペレータ

次の代入オペレータを使用することができます : =、+=、-=、*=、/=、++、-- (代入、足し算、引き算、掛け算、割り算、インクリメント、デクリメント)。


let キーワード

指定されたレジスタを操作することを宣言します

// レジスタ A に 23 を代入
let $_rga = 23;
// レジスタ A をインクリメント
let $_rga++;

function キーワード

関数を定義します。関数名は必ず 2 つの丸括弧と空白の後に { シンボルで終わる必要があります。

function initialize() {
// 関数を呼び出す
call main();
}

function main() {
// 処理後に関数の呼び出し元に戻る
return;
}

call キーワード

関数を呼び出します。return キーワードを使用して呼び出し元に戻ります。

call main();

goto キーワード

関数にジャンプして呼び出し元には戻りません。

goto main();

exec キーワード

外部 IRIS スクリプトを実行します。外部スクリプトはコンパイルされている必要があります。

exec "test.bin";

exit キーワード

プログラムの実行を停止します。

exit;

mem キーワード

mem({メモリ アドレス} [{代入オペレータ} {代入値}]);

仮想マシンによって割り当てられた内部メモリを管理します。memory キーワードは IRIS の機能として定義されているわけではなく、UlyGL ゲーム ライブラリのコマンドを使用してメモリの操作をすることに注意してください。このキーワードを使用するには、仮想マシンが内部メモリ アクセスをサポートしている必要があります。

// メモリ 0 = 10
// _memory::seek(0); _memory::set(10); と同等
mem(0 [= 10]);

// メモリ 0 = 12 (既存の値に 2 を足す)
mem(0 [+ 2]);

// メモリ 1 = 8
let $_rgb = 10;
mem(1 [= 23 + 57 / $_rgb]);

// _memory::seek(1); と同等
mem(1);

// _memory::seek(0); let $_rga = _memory::get(); と同等
mem(0 let $_rga = _memory::get());

param キーワード

param[{値 0}, {値 1},, {値 2},,, {値 3}]@{関数名};

パラメータを使用した関数呼び出しのショート カットです。パラメータは 6 つまでの増加するコンマ数によって分けられます。それぞれのパラメータは一時的なレジスタ $_rga から $_rgf に割り当てられます。

// テキストを表示
function show_text() {
// パラメータを指定して print_text 関数を呼び出す
param[ID_FONT_NORMAL, 0,, 0,,, "Hello, World!"]@print_text;
return;
}

function print_text() {
_screen::_text::use($_rga);
_screen::_text::_x::set($_rgb);
_screen::_text::_y::set($_rgc);
_screen::_text::set($_rgd);
_screen::_text::show(0);
return;
}

if ステートメント

if([条件]) { }

条件によってプログラム フローを切り替えます。

// レジスタ A に 23 を代入
let $_rga = 23;
// レジスタ A が 23 の場合、戻る
if($_rga == 23) {
return;
}

// [ヒント]: レジスタに値を代入と同時にロジカル オペレータを使用
if($_rga = _screen::_frame::get() == 30) {
// フレーム カウント == 30 の場合 ...
}

do~until~loop ステートメント

do { } until [条件] loop;

条件ループ機能を提供します。

let $_rga = 0;
// レジスタ A の値が 3 になるまで 3 回ループする
do {
// インクリメント
let $_rga++;
} until $_rga == 3 loop;