1.言語仕様


1−1.仕様概要


1−2.コンパイル手順

コンパイルは以下のステージで処理されます。

===============
(以下をリンクされた全コード分繰り返す)
[ファイル読み込み]
↓
[プリプロセッサ解釈]
↓
[字句解析]
↓
[デバッグ情報埋め込み]
↓
[構文解析]
↓
[中間コード生成]
↓
[グローバル変数生成](必要に応じて)
↓
[プログラムカウンタ設定](必要に応じて)
===============
「プリプロセッサ解釈」でリンクされるなど、解釈途中でファイルが追加された場合も、全てのコードがコンパイルされるまで動作を繰り返します。 実際は上記のように順番に処理されるのではなく、字句解析以降は構文解析器が字句解析しながら逐次中間コードを生成していきます。


1−3.実行手順

メモリ上にあるコンパイル済みの中間コードを以下の手順で実行します。中間コードはマシン語に直接変換されるわけではなく、インタプリタ方式の仮想マシンにより解釈及び実行されます。

===============
[プログラムカウンタの中間コードを取り込み]
↓
[プログラムカウンタを加算]
↓
[命令解釈]
↓
[オペランド取り込み]
↓
[演算]
↓
[結果の適用]
===============


1−4.システムコールとシステム割り込み

システムコールは字句解析時点でシステムコールとして認識されます。見た目は似ていますが関数とは異なる実装であり、「システムコール型」という変数はありません。そのため、関数型変数にシステムコールを代入することは出来ません。

SphereScript仮想マシンに対して直接命令を発行する『システム割り込み』が存在します。システム割り込みの構文は以下の通りです。パラメータの数はシステム割り込みによって変わります。

===============
__system_interrupt__("システム割り込み名称");
__system_interrupt__(パラメータ1, "システム割り込み名称");
__system_interrupt__(パラメータ1, パラメータ2, "システム割り込み名称");
===============
システム割り込みは以下のものがあります。
===============
システム割り込み名称:wait
パラメータ1    :(int)フレーム
説明        :スクリプト動作を中断し、エンジンに制御を返します。「フレーム」だけ処理を進めると、本割り込みの次の処理からスクリプトは再開されます。

システム割り込み名称:create_thread
パラメータ1    :(string | function)ラベル名もしくは関数
パラメータ2    :(valiable)引数
説明        :スレッドを新たに生成し、実行可能状態にします。スレッドは「ラベル名もしくは関数」で定義されるラベルもしくは関数より実行されます。
           関数の場合「引数」に指定した値がその関数に第1引数として代入されています。
           作成されたスレッドが実行されるタイミングは「1−5.スレッド」を参照してください。

システム割り込み名称:get_thread_id
説明        :スレッド識別子を取得します。

システム割り込み名称:exit_thread
パラメータ1    :(int)スレッド識別子
説明        :「スレッド識別子」に該当するスレッドを終了します。自分自身のスレッドを終了させることも可能です。
           「スレッド識別子」に負の値を設定した場合は、システムコール実行元を含めて全てのスレッドを終了します。

システム割り込み名称:pause_thread
パラメータ1    :(int)スレッド識別子
パラメータ2    :(int)フラグ
説明        :上位のシステムが定義する「ポーズ」状態に対して、「スレッド識別子」に該当するスレッドを停止させなくします。
           「フラグ」がTRUEならば非停止、FALSEならば停止します。スレッドの初期値はFALSEです。

システム割り込み名称:exist_value
パラメータ1    :(string)変数名
説明        :「変数名」で定義される変数の実態が存在する場合はTRUEを取得できます。存在しない場合はFALSEを取得できます。
===============
システム割り込みは通常は直接呼ばれることは無く、ライブラリにより隠蔽されています。仕様については「4.基本関数リファレンス」を参照してください。実装についてはSDKの「SpeSystem/Script/stdlib.spt」を参照してください。


1−5.スレッド

1−5−1.生成方法

スレッドを生成する方法は以下の3つです。

  1. 関数名「main」の関数を定義する
  2. 例)function main() {...}
  3. 関数の定義にautorun属性を付与する
  4. 例)function autorun myfunc() {...}
  5. スクリプト動作中ぬcreate_threadシステム割り込みを使用する
  6. 例)create_thread(myfunc, 0);
main関数はautorun属性が自動的に付与されます。自動的もしくは明示的にautorun属性が付与された関数はコンパイル時にスレッド1つが自動的に用意され、実行可能状態になります。 一つの関数からはスレッドは一つしか作成されません。複数のスレッドを用意したい場合は、create_threadを使用してください。

create_threadシステム割り込み(を内包したcreate_thread関数)を使用する場合は、その場で実行可能なスレッドが一つ作成されます。複数回create_threadを呼ぶことで、一つの関数から複数のスレッドを作り、並列動作させることが出来ます。

1−5−2.スコープ

スレッドごとにスタックは別々に保持しています。異なるスレッドのローカル変数にはアクセスできず、また自身のスレッドのローカル変数は他のスレッドから保護されています。 グローバル変数はスレッド間で共有です。

1−5−3.実行順序

スレッドは作成された順番に実行されます。この事項順序が途中で変わることはありません。

===============
上位システムが処理を行う
↓
最初に作成されたスレッドが処理を行う
↓
2番目に作成されたスレッドが処理を行う
↓
3番目に作成されたスレッドが処理を行う
↓
4番目に...
↓
最初に戻る
===============
SphereScriptは明示的なタスクスイッチを行う擬似マルチタスクであり、勝手に優先順位が変わったり、スレッドごとにCPU持ち時間が変わったり、(マルチコアにより)複数のスレッドが物理的に同時実行されるようなことはありません。 スクリプト内部においてスレッドを新規に作成した場合、上位システムに処理を戻すよりも前に必ずそのスレッドの1回目の処理が行われます。


最初のページへ戻る