Squirrel 2.2 リファレンスマニュアル
- この記事は http://www.squirrel-lang.org/doc/squirrel2.html の和訳です。
- この記事は http://wikiwiki.jp/lua/?Squirrel_Lang%2Ftoc に移行しました。
- ここにある文章は今後メンテナンスされる可能性は低いです。
第1章 はじめに
Squirrelは高レベルimperative-OOなプログラミング言語で、ゲームのようなアプリケーションが要求する、サイズ、メモリ幅、リアルタイム性に適した強力なスクリプティングツールとして設計されている。Squirrelは動的な型、委譲、高階関数、ジェネレータ、末尾再帰、例外操作、自動メモリ管理といった幅広い機能を提供しているにも関わらず、コンパイラと仮想マシン両方で約6000行のC++コードに収まっている。
第2章 言語
この章では、この言語の文法と意味について述べる。
文法構造
識別子
識別子はアルファベット文字もしくは '_' で始まり、任意の数のアルファベット文字か '_' か数("0"から"9")が続いたものである。Squirrelは大文字小文字を区別するため、大文字と小文字を異なる文字として取り扱う。例えば、"foo"と"Foo"と"fOo"は3つの異なる識別子として扱われる。
id := [a-zA-Z_]+[a-zA-Z_0-9]*
キーワード
次の単語はこの言語によって予約された語であり、識別子として用いることはできない。
break | case | catch | class | clone | continue |
default | delegate | delete | else | extends | for |
function | if | in | local | null | resume |
return | switch | this | throw | try | typeof |
while | parent | yield | constructor | vargc | vargv |
instanceof | true | false | static |
これらのキーワードの詳細は後に説明する。
演算子
Squirrelは次の演算子を認識する。
! | != | || | == | && | <= | >= | > |
+ | += | - | -= | / | /= | * | *= |
% | %= | ++ | -- | <- | = | & | ^ |
| | ~ | >> | << | >>> |
他のトークン
他に使用されるトークンは次の通り。
{ | } | [ | ] | . | : | :: | ' | ; | " | @" |
リテラル
Squirrelでは整数、浮動小数点数、文字列リテラルを使用できる。
34 | 整数 |
0xFF00A120 | 整数 |
'a' | 整数 |
1.52 | 浮動小数点数 |
1.e2 | 浮動小数点数 |
1.e-2 | 浮動小数点数 |
"I'm a string" | 文字列 |
@"I'm a verbatim string" | 文字列 |
@" I'm a multiline verbatim string " | 文字列 |
IntegerLiteral := [0-9]+ | '0x' [0-9A-Fa-f]+ | ''' [.]+ '''
FloatLiteral := [0-9]+ '.' [0-9]+
FloatLiteral := [0-9]+ '.' 'e'|'E' '+'|'-' [0-9]+
StringLiteral := '"' [.]* '"'
VerbatimStringLiteral := '@' '"' [.]* '"'
コメント
コメントは、コンパイラは無視するがプログラマには有用なテキストである。コメントは通常、コードの注釈を埋め込むために用いられる。コンパイラはこれらを空白として取り扱う。
スラッシュ、アスタリスク(/*)に始まり、*/が出現するまでの改行を含む全ての文字。この文法はANSI Cと同じである。
/* これは 複数行コメントである。 これらはコンパイラによって無視される。 */
ふたつのスラッシュ(//)。これは直前にバックスラッシュがない改行まで続く。これは一般に「一行コメント」と呼ばれる。
//これは一行コメントである。これはコンパイラによって無視される。
値とデータ型
Squirrelは動的型言語であるため、型を持つ値へと参照している場合でも、変数は型を持たない。Squirrelの基本型は整数、浮動小数点数(float)、文字列、null、テーブル、配列、関数、ジェネレータ、クラス、インスタンス、真偽値、スレッド、ユーザデータである。
整数
32ビット(もしくはそれ以上)の符号付き整数を表現する。
local a = 123 // 10進数 local b = 0x0012 // 16進数 local c = 075 // 8進数 local c = 'w' // 文字コード
浮動小数点数(float)
32ビット(もしくはそれ以上)の浮動小数点数を表現する。
local a = 1.0 local b = 0.234
文字列
文字列は不変な文字列シーケンスであり、文字列を変更するには新しい文字列を作成する必要がある。
Squirrelの文字列はCやC++のように振る舞い、二重引用符 " によって区切られ、エスケープシーケンス(\t, \a, \b, \n, \r, \v, \f, \\, \", \', \0, \xhhhh)を含めることができる。
逐語的文字列(verbatim string)のリテラルは @" で始まり、対応する " で終了する。逐語的文字列のリテラルは改行を越えることができる。そのとき、二重引用符の間のホワイトスペースを含めることができる。
local a = "I'm a wonderful string\n" // は文字列の最後に改行を持つ local x = @"I'm a verbatim string\n" // この \n は 通常の文字列での \\n としてコピーされる
逐語的文字列リテラルの「エスケープシーケンスなし」ルールの唯一の例外は、二重引用符である。逐語的文字列中の二重引用符は2回連続させる必要がある。
local multiline = @" これは複数行の文字列である。 これは全ての改行を ""埋め込む"" ことができる。 "
Null
無効、空、存在しない参照を表現するプリミティブである。null型はただひとつの値を持ち、それはnullと呼ばれる。
local a = null
真偽値型
真偽値型は2つの値だけを持つ。これらのリテラルはtrueとfalseである。真偽値は条件の検証(条件が真か偽かを表現する)に用いられる。
local a = true;
テーブル
テーブルは、キーと値のペア(スロットと呼ばれる)として実装された連想コンテナである。
local t = {} local test = { a = 10 b = function(a) { return a + 1; } }
配列
配列はオブジェクトの単純なシーケンスであり、そのサイズは動的であり、添字は常に0から始まる。
local a = ["私", "は", "配列"] local b = [null] b[0] = a[2];
関数
関数は一般には他のC風の言語とほとんどのプログラミング言語のものと似ている。しかし、若干の違いがある(後述)。
クラス
クラスは、キーと値のペアとして実装された連想コンテナである。クラスはクラス式またはクラス命令文を通して作成される。クラスメンバは、他のクラスオブジェクトのひとつから作成時に継承される。クラス作成後には、クラスのインスタンスが作成されるまで、メンバを追加することができる。
インスタンス
クラスインスタンスはクラスオブジェクトを呼び出すことで作成される。テーブルと同様、インスタンスはキーと値のペアで実装されている。インスタンスのメンバは動的に追加や削除を行うことができないが、その値を変更することはできる。
ジェネレータ
ジェネレータはyield命令によって中断でき、後で再開ができる関数である(ジェネレータの項を参照せよ)。
ユーザデータ
ユーザデータオブジェクトは、ホストアプリケーションによって定義されているがSquirrelの変数中に蓄えられているメモリの塊(やポインタ)である(ユーザデータとユーザポインタの項を参照せよ)。
スレッド
スレッドは協調スレッド(これはコルーチンとして知られる)の実行を表現するオブジェクトである。
弱参照
弱参照は、他の(数値ではない)オブジェクトを差すが、それへの強参照を所有しないオブジェクトである(弱参照の項を参照せよ)。
実行コンテキスト
実行コンテキストは関数スタックフレームと関数環境オブジェクト(this)の和集合である。スタックフレームはスタックの一部であり、その本体で宣言されたローカル変数が蓄えられている。環境オブジェクトは暗黙の引数であり、関数呼び出しで自動的に渡される(関数の節を参照せよ)。実行中に、関数の本体はその実行コンテキストを透過的に参照することができる。これは、単一の識別子はローカル変数または環境オブジェクトのスロットのどちらかから参照することができることを意味する。グローバル変数は特別な書式を求められる(変数の節を参照せよ)。キーワードthisによって、環境オブジェクトに明示的にアクセスすることができる。
変数
Squirrelの変数には2つの型がある。ローカル変数とテーブル(または配列)のスロットである。グローバル変数はテーブルに蓄えられているため、これはテーブルスロットである。
単一の識別子は、ローカル変数または環境オブジェクトのスロットを参照する。
derefexp := id;
_table["foo"] _array[10]
テーブルには . を用いることもできる。
derefexp := exp '.' id
_table.foo
最初に、Squirrelは識別子がローカル変数かどうかをチェックする(なお、関数の引数はローカル変数である)。もしそうでないなら、次にそれが環境オブジェクト(this)のメンバかどうかをチェックする。
例えば、次の例ではローカル変数 a へアクセスして10が出力されるだろう。
function testy(arg) { local a = 10; print(a); return arg; }
次の例では、fooがthis.fooもしくはthis["foo"]として評価される。
function testy(arg) { local a = 10; return arg + foo; }
グローバル変数はルートテーブルと呼ばれるテーブルに蓄えられている。通常、グローバルスコープにおいて、環境オブジェクトはルートテーブルである。しかし、他のスコープからグローバルテーブルへ明示的にアクセスする場合には、スロット名の前に :: を付ける必要がある(例えば::fooのように)。
exp:= '::' id
例えば、次の例ではグローバル変数fooへアクセスしている。
function testy(arg) { local a = 10; return arg + ::foo; }
しかし、Squirrel 2.0以降では、もし変数がローカルにもthisにも見付からないときには、Squirrelはルートテーブルを見に行くようになった。
function test() { foo = 10; }
上の例は次の例と等価である。
function test() { if ("foo" in this) { this.foo = 10; } else { ::foo = 10; } }
命令文
Squirrelのプログラムは単純な命令文のシーケンスである。
stats := stat [';'|'\n'] stats
Squirrelのおける命令文はC系の言語(C, C++, Java, C#など)と同程度であり、代入、関数呼び出し、プログラムフロー操作構造などからなる。加えて、yieldやテーブルと配列のコンストラクタなどのようないくつかの特別な命令文がある(これらの全ての詳細は後述)。命令文は改行もしくは ; によって区切られる(もしくswitch/case文中におけるcase文のキーワードやdefault)。もし、文の次が } なら、改行と ; も不要である。
ブロック
stat := '{' stats '}'
中括弧 { } によって区切られた命令文のシーケンスはブロックと呼ばれる。ブロックはそれ自体が命令文である。
制御命令
Squirrelはif, while, do-while, switch-case, for, foreachといったほとんどの一般的な制御命令を実装している。
trueとfalse
Squirrelは真偽値型を持つが、C++のようにnull、0(整数)、0.0(浮動小数点数)をfalseと見なし、他の値をtrueと見なす。
if/else
stat:= 'if' '(' exp ')' stat ['else' stat]
どちらの命令を実行するのかは式の結果次第である。
if (a > b) a = b; else b = a; //// if (a == 10) { b = a + b; return a; }
while
stat:= 'while' '(' exp ')' stat
条件がfalseとなるまで命令文を実行する。
function testy(n) { local a = 0; while (a < n) a += 1; while(1) { if (a < 0) break; a -= 1; } }
do/while
stat:= 'do' stat 'while' '(' expression ')'
命令文を一回実行し、その後は条件式がfalseとなるまでその命令文の実行を繰り返す。
local a = 0; do { print(a + "\n"); a += 1; } while (a > 100)
switch
stat := 'switch' ''( exp ')' '{'
'case' case_exp ':' stats
['default' ':' stats]
'}'
その本体内のひとつのcase文に制御を渡すことで、複数のコードから選択することを可能にする制御命令である。その制御はexpと一致するcase_expを持つラベルへ遷移する。一致したものがなければ、(もし存在するなら)defaultラベルへと飛ぶ。switch命令は任意の数のcaseを含めることができる。同じ結果となる式を持つcaseが2つあるときは、最初のものが先に考慮される。defaultラベルは必ずひとつで最後になければならない。break命令はswitchブロックを抜けるために用いられる。
ループ命令
for
stat:= 'for' '(' [initexp] ';' [condexp] ';' [incexp] ')' statement
条件がfalseとならない間、命令文を実行する。
for (local a = 0; a < 10; a += 1) print(a + "\n"); // or glob <- null for (glob = 0; glob < 10; glob += 1) { print(glob + "\n"); } // or for (;;){ print(loops forever + "\n"); }
foreach
'foreach' '(' [index_id','] value_id 'in' exp ')' stat
配列、テーブル、クラス、文字列、ジェネレータに含まれる全要素に対して命令文を実行する。もし、expがジェネレータなら、それは(可能な間だけ)繰り返しの度に再開される。その値はresumeの結果となり、添字はこの繰り返しの回数であり、0から開始する。
local a = [10, 23, 33, 41, 589, 56] foreach(idx, val in a) print("index=" + idx + " value=" + val + "\n"); // or foreach(val in a) print("value=" + val + "\n");
break
stat := 'break'
break命令はループ(for, foreach, while, do/while)の実行を終了させる。または、switch命令を抜ける。
continue
stat := 'continue'
continue命令は後に続く命令の実行をスキップして、ループの次の繰り返しへ進ませる。
return
stat:= return [exp]
return命令は現在の関数とジェネレータの実行を終了させる。このとき、式の結果を返すことができる。もし、式が省かれているなら、nullが返される。ジェネレータ内部でreturn命令が使用されているときは、ジェネレータはもはや再開できなくなる。
yield
stat := yield [exp]
(ジェネレータの項を参照せよ).
ローカル変数宣言
initz := id [= exp][',' initz] stat := 'local' initz
ローカル変数はプログラムのどの箇所でも宣言することができる。それは宣言箇所から、それが宣言されたブロックの終りまで存在する。
例外: ローカル宣言はループの最初の式に行うこともできる。
for (local a = 0; a < 10; a += 1) print(a);
関数宣言
funcname := id ['::' id]
stat:= 'function' id ['::' id]+ '(' args ')'[':' '(' args ')'] stat
新しい関数を作成する。
クラス宣言
memberdecl := id '=' exp [';'] | '[' exp ']' '=' exp [';'] | functionstat | 'constructor' functionexp
stat:= 'class' derefexp ['extends' derefexp] '{'
[memberdecl]
'}'
新しいクラスを作成する。
try/catch
stat:= 'try' stat 'catch' '(' id ')' stat
try命令は実行時エラーやthrow命令などによって例外状態が発生するようなコードブロックを囲む。catch節は例外操作コードを提供する。catch節が例外を捕らえたとき、その id には例外が割り付けられている。
throw
stat:= 'throw' exp
例外を投げる。どのような値を投げることもできる。
式
stat := exp
Squirrelのおいて、全ての式は命令文と見なすことができる。このとき、式の結果は捨てられる。
式
代入(=)と新規スロット(<-)
exp := derefexp '=' exp
exp:= derefexp '<-' exp
Squirrelは2種類の代入を実装している。ひとつめは( = による)通常の代入である。
a = 10;
ふたつめは「新規スロット」代入である。
a <- 10;
新規スロット代入は新規スロットをテーブルへ追加することができる(テーブルの項を参照せよ)。もし、スロットがそのテーブルに既に存在しているなら、通常の代入と同じ動作となる。
演算子
?: 演算子
exp := exp_cond '?' exp1 ':' exp2
どちらの条件を評価するのかは式の結果次第である。
算術式
exp:= 'exp' op 'exp'
Squirrelは標準の算術演算子 +, -, *, /, % をサポートしている。これ以外にも、簡略演算子(+=, -=, *=, /=, %=)、インクリメントとデクリメント(++, --)もサポートしている。
a += 2; // は次の式と同じである a = a + 2; x++ // は次の式と同じである x = x + 1
全ての演算子は整数と浮動小数点数に対して正常に機能する。もし、オペランドのひとつが整数でもうひとつが浮動小数点数なら、式の結果は浮動小数点数となる。演算子 + は文字列では特別な振る舞いをする。もし、オペランドのひとつが文字列であるなら、演算子 + はもうひとつのオペランドを文字列に変換しようと試み、その後、両者を結合する。インスタンスとテーブルに対しては、_tostringが呼び出される。
関係式
exp:= 'exp' op 'exp'
Squirrelにおける関係式は ==, <, <=, >, >=, != である。
これらの演算子は、式がfalseならnullを返し、式がtrueならnull以外の値を返す。内部的には、VMはtrueとして整数の 1 を使用しているが、これは将来に変更されるかもしれない。
論理式
exp := exp op exp
exp := '!' exp
Squirrelにおける論理式は &&, ||, ! である。
演算子 && (論理積)は最初の引数がnullならnullを返し、それ以外は2番目の引数を返す。演算子 || (論理和)は最初の引数がnullでないならその値を返し、それ以外は2番目の引数を返す。
演算子 ! は否定対象がnull以外の値ならnullを返し、対象がnullならnull以外の値を返す。
in 演算子
exp:= keyexp 'in' tableexp
テーブルのスロットが存在するかどうかをテストする。もし、keyexpがtableexpに存在するなら、null以外を返す。
local t= { foo = "I'm foo", [123] = "I'm not foo" } if ("foo" in t) dostuff("yep"); if (123 in t) dostuff();
instanceof 演算子
exp:= instanceexp 'instanceof' classexp
クラスインスタンスが特定のクラスのインスタンスであるかどうかをテストする。もし、instanceexpがclassexpのインスタンスであるなら、null以外を返す。
typeof 演算子
exp:= 'typeof' exp
型名を文字列で返す。
local a = {}, b = "squirrel" print(typeof a); // "table"が表示される print(typeof b); // "string"が表示される
コンマ演算子
exp:= exp ',' exp
コンマ演算子は2つの式を左から右に順番に評価する。この演算結果は右の式の結果であり、左の式の結果は無視される。
local j = 0, k = 0; for(local i = 0; i < 10; i++, j++) { k = i + j; } local a, k; a = (k = 1, k + 2); // aは3になる
ビット操作演算子
exp:= 'exp' op 'exp'
exp := '~' exp
Squirrelは標準のC風のビット操作演算子 &, |, ^, ~, <<, >> に加えて、論理シフト演算子 >>> をサポートしている。論理シフト演算子 >>> は通常のシフト演算子 >> のように機能するが、左のオペランドを符号なし整数として扱うため、符号の影響を受けない。これらの演算子は整数値にのみ機能し、他の型を渡したときは例外が発生する。
演算子の優先順位
演算子 | 優先度 |
---|---|
-, ~, !, typeof, ++, -- | 低い |
/, *, % ... | |
+, - | |
<<, >>, >>> | |
<, <=, >, >= | |
==, != | |
& | |
^ | |
| | |
&&, in | |
|| | |
?: | |
+=, =, -= ... | |
,(comma operator) | 高い |
テーブルコンストラクタ
tslots := ( 'id' '=' exp | '[' exp ']' '=' exp ) [',']
exp := '{' [tslots] '}'
新しいテーブルを作成する。
local a = {} // 空テーブルを作成する
テーブルコンストラクタでスロット宣言を含めることもできる。これは次の書式を取る。
id = exp [',']
キーとしてidを、値としてexpを取る新規スロットを作成する。
local a = { slot1 = "I'm the slot value" }
別の書式として次のようなものがある。
'[' exp1 ']' = exp2 [',']
キーとしてexp1を、値としてexp2を取る新規スロットを作成する。
local a= { [1] = "I'm the value" }
この2つの書式を混ぜて使用することができる。
local table = { a = 10, b = "string", [10] = {}, function bau(a, b) { return a + b; } }
スロット宣言の間にあるコンマはオプションである。
委譲
exp:= 'delegate' parentexp : exp
テーブルの親をセットする。parentexpの結果にexpの式の結果の親をセットする(委譲の項を参照せよ)。
クローン
exp:= 'clone' exp
クローンはテーブル、配列、クラスインスタンスの浅いコピーを行う(新しいオブジェクトに全スロットをコピーするが、再帰的には処理しない)。もし、元のテーブルが委譲を持っているなら、(コピーされずに)同じ委譲が委譲として新しいテーブルに代入される(委譲の項を参照せよ)。
クローンが完了した直後に、メタメソッド_clonedが呼び出される(メタメソッドの節を参照せよ)。
クラスインスタンスがクローンされたときは、コンストラクタは呼び出されない(代わりに、_clonedで初期化を行う必要がある)。
配列コンストラクタ
exp := '[' [explist] ']'
新しい配列を作成する。
a <- [] // 空の配列を作成
配列はコンストラクト時に引数付きで初期化することもできる。
a <- [1, "string!", [], {}] // 4要素で配列を作成
テーブル
テーブルは、キーと値のペア(スロットと呼ばれる)として実装された連想コンテナである。値としては任意の型を用いることができ、キーとしてはnull以外の型を用いることができる。テーブルはSquirrelの骨格であり、委譲とその他の多くの機能はこの型を通して実装されている。グローバル変数を蓄えている環境でさえテーブルである(これはルートテーブルとして知られている)。
コンストラクト
テーブルはテーブルコンストラクタを通して作成される(テーブルコンストラクタの項を参照せよ)。
スロットの作成
存在しているテーブルへの新規スロットの追加は「新規スロット」演算子 <- を用いて行われる。この演算子は通常の演算子と同様に機能するが、スロットが存在しないときはそれを作成する。
local a = {}
このとき、次の例は例外が発生する。なぜなら、newslotと呼ばれるスロットがテーブル a には存在していないからである。
a.newslot = 1234
次の例は成功するだろう。
a.newslot <- 1234;
または、
a[1] <- "I'm the value of the new slot";
スロットの削除
exp:= delete derefexp
スロットの削除はキーワードdeleteによって行われる。この式の結果は削除されたスロットの値となる。
a <- { test1 = 1234 deleteme = "now" } delete a.test1 print(delete a.deleteme); // この結果は文字列 "now" となる
配列
配列は値のシーケンスであり、添字として0から(配列のサイズ - 1)までの整数値を取る。配列の要素はその添字を通して得ることができる。
local a = ["I'm a string", 123] print(typeof a[0]) // "string"と表示される print(typeof a[1]) // integer"と表示される
配列とその要素のリサイズ、挿入、削除などは標準関数を通じて行われる(組み込み関数の節を参照せよ)。
関数
関数は整数や文字列と同様にファーストクラスオブジェクトであり、テーブルスロット、ローカル変数、配列に代入可能であり、関数に引数として渡すことができる。関数はSquirrel上もしくは(ANSI C互換の呼び出し規約によって)ネイティブ言語で実装することができる。
関数宣言
関数は関数式を通して宣言される。
local a = function(a, b, c) {return a + b - c;}
シンタックスシュガーを用いて、次のように宣言することもできる。
function ciao(a, b, c) { return a + b - c; }
また、次のコードと等価である。
this.ciao <- function(a, b) { return a + b - c; }
このような宣言をすることも可能である。
T <- {} function T::ciao(a, b, c) { return a + b - c; } // これは次のように書ける T.ciao <- function(a, b, c) { return a + b - c; } // or T <- { function ciao(a, b, c) { return a + b - c; } }
デフォルトパラメータ
Squirrelの関数はデフォルトパラメータを持つことができる。
デフォルトパラメータ付きの関数は次のように宣言される。
function test(a,b,c = 10, d = 20) { .... }
関数testが呼び出されてパラメータcとdが指定されていないなら、VMは自動的にこれらのパラメータにデフォルト値を代入する。デフォルトパラメータは任意のSquirrelの式をとることができ、この式は実行時に評価される。
可変長引数
Squirrelの関数は可変長引数の関数を用いることができる。
可変長引数の関数は3つのドット(...)を引数リストの最後に追加することで宣言される。
関数が呼び出されたとき、全ての余分の引数はvargvと呼ばれる疑似配列を通してアクセスすることができる。
vargvで用いることができる添字は数値(整数もしくは浮動小数点数)のみである。vargvが持つ引数の数は疑似変数vargcに代入されている。vargvは実オブジェクトではないので、代入や引数として渡すことができないことに注意せよ。
function test(a, b, ...) { for(local i = 0; i < vargc; i++) { ::print("varparam " + i + " = " + vargv[i] + "\n"); } } test("goes in a", "goes in b", 0, 1, 2, 3, 4, 5, 6, 7, 8);
関数呼び出し
exp:= derefexp '(' explist ')'
この式はexplis、derefexpの順で評価されて最後に呼び出しが行われる。
Squirrelにおける全ての関数呼び出しは、隠しパラメータとして環境オブジェクトthisが呼び出された関数に渡される。このパラメータthisはオブジェクトであり、関数はそのオブジェクトから参照可能である。
もし次のような書式で関数を呼び出した場合、fooに渡される環境オブジェクトはtableとなる。
table.foo(a)
foo(x, y) // this.foo(x, y)と等価
このとき、環境オブジェクトはthisとなる(呼び出し元の関数と同じ)。
環境の関数への束縛
デフォルトではSquirrelの関数呼び出しでは環境オブジェクトとしてthisを渡す。関数はそのオブジェクトから参照可能である。しかし、組み込みメソッドclosure.bindenv(env_obj)を用いることで、クロージャへの静的な環境の束縛をすることができる。メソッドbindenv()はそれに割り付けられた環境とともに、クロージャの新しいインスタンスを返す。環境オブジェクトが関数に束縛されると、その関数が呼び出されたときには常にそのthisパラメータは前もって束縛していた環境となる。このメカニズムはC#の委譲に類似したコールバック系を実装するために有用である。
注意
クロージャは環境オブジェクトを束縛するために弱参照を保持する。このため、オブジェクトが削除された場合、次回のクロージャへの呼び出しでは環境オブジェクトがnullとなる。
自由変数
自由変数は、その関数スコープ内では見えないが、関数によって参照される変数である。次の例において、関数foo()はxとyとtestyを自由変数として宣言している。
local x = 10, y = 20 testy <- "I'm testy" function foo(a, b):(x, y, testy) { ::print(testy); return a + b + x + y; }
関数作成時に、自由変数の値は凍結され、関数に割り付けられる。それが呼ばれる度に、その値は暗黙のパラメータとして関数に渡される。
末尾再帰
末尾再帰は部分的にプログラムの再帰を繰り返しに変更するための手法である。ある関数の再帰的呼び出しがその関数の最後の実行命令文であったとき(returnの直前)、末尾再帰が適用される。もし適用されたなら、再帰を呼び出し前に、Squirrelインタプリタは呼び出し元のスタックフレームを崩す。これによって、スタックオーバーフローの危険なしに、非常に深い再帰をすることが可能となる。
function loopy(n) { if (n > 0){ ::print("n=" + n + "\n"); return loopy(n - 1); } } loopy(1000);
クラス
SquirrelはJavaやC++などの言語と同様のクラスメカニズムを実装している。しかし、その動的性質により、いくつかの性質が異なる。クラスは整数や文字列と同様にファーストクラスオブジェクトであり、テーブルスロット、ローカル変数、配列に代入可能であり、関数に引数として渡すことができる。
クラス宣言
クラスオブジェクトはキーワードclassを通して作成される。クラスオブジェクトはテーブルの宣言と同じ書式に従う(テーブルの節を参照せよ)。唯一の違いは、セパレータに , だけでなく ; も使用できることである。
例えば、次の通り。
class Foo { // constructor constructor(a) { testy = ["stuff", 1, 2, 3]; } // member function function PrintTesty() { foreach(i, val in testy) { ::print("idx = " + i + " = " + val + " \n"); } } // property testy = null; }
上の例は、次の例のシンタックスシュガーである。
Foo <- class { // constructor constructor(a) { testy = ["stuff", 1, 2, 3]; testy = a; } // member function function PrintTesty() { foreach(i, val in testy) { ::print("idx = " + i + " = " + val + " \n"); } } // property testy = null; }
名前空間を模倣するために、次のように宣言することもできる。
// just 2 regular nested tables FakeNamespace <- { Utils = {} } class FakeNamespace.Utils.SuperClass { constructor() { ::print("FakeNamespace.Utils.SuperClass") } function DoSomething() { ::print("DoSomething()") } } function FakeNamespace::Utils::SuperClass::DoSomethingElse() { ::print("FakeNamespace::Utils::SuperClass::DoSomethingElse()") } local testy = FakeNamespace.Utils.SuperClass(); testy.DoSomething(); testy.DoSomethingElse();
宣言後にも、メソッドとプロパティはテーブルと同様に(演算子 <- と = によって)、追加と変更ができる。
// 新しいプロパティを追加 Foo.stuff <- 10; // 既に存在しているプロパティのデフォルトの値を変更 Foo.testy = "これは文字列"; // 新しいメソッドを追加 function Foo::DoSomething(a,b) { return a + b; }
クラスがインスタンス化された後は、プロパティとメソッドをそのクラスへ新たに追加することはできなくなる。
静的変数
Squirrelのクラスは静的メンバ変数をサポートしている。静的変数は、全てのクラスインスタンス間でその値を共有する。静的変数はその変数宣言の前にキーワードstaticを付けて宣言する。その宣言はクラス本体で行わなければならない。
Note
静的変数は読み込み専用である。
class Foo { constructor() { //..stuff } name = "通常の変数"; // 静的変数 static classname = "クラス名はFoo"; };
クラス属性値
クラスはそのメンバに属性値を関連付けることができる。属性値はメタデータの一種であり、文書文字列やIDEのプロパティやコード生成器などのようなアプリケーションに特化した情報を蓄えるために用いることができる。クラス属性値は、クラス本体のメンバ宣言の前に、シンボル </ />によって区切られて宣言される。
例を次に示す。
class Foo </ test = "これはクラスレベルの属性値" />{ </ test = "なんとなくな属性値" /> // PrintTestyの属性値 function PrintTesty() { foreach(i, val in testy) { ::print("idx = " + i + " = " + val + " \n"); } } </ flippy = 10, second = [1, 2, 3] /> // testyの属性値 testy = null; }
実際には、クラス属性値はテーブルである。Squirrelは可読性の向上させるために、属性値の宣言を中括弧 { } のかわりに </ /> を用いる。
これは、テーブルに適用される全てのルールは、属性値にも適用できることを意味する。
属性値は組み込み関数classobj.getattributes(membername)によって探索することができる(組み込み関数の節を参照せよ)。また、classobj.setattributes(membername,val)によって追加と変更を行うことができる。
次のコードはFooのメンバの属性値を全て出力させる。
foreach(member, val in Foo) { ::print(member + "\n"); local attr; if((attr = Foo.getattributes(member)) != null) { foreach(i, v in attr) { ::print("\t" + i + " = " + (typeof v) + "\n"); } } else { ::print("\t<属性値がない>\n") } }
クラスインスタンス
クラスオブジェクトはいくつかのテーブルの機能を受け継いでいるが、同じクラスの複数のインスタンスを作成できるという違いがある。クラスインスタンスはそれを作成したテーブルと同じ構造を共有するが、独自の値を持つこともできるオブジェクトである。クラスのインスタンス化は関数の記法を用いるので、クラスインスタンスはクラスオブジェクトを呼び出すことで作成される。クラスインスタンスを返す関数のようなクラスを想像すると便利である(?)。
// Fooのインスタンスを新たに作成 local inst = Foo();
クラスインスタンスが作成されたとき、そのメンバはクラス宣言で指定された値で初期化される。
クラスがコンストラクタと呼ばれるメソッドを定義したとき、クラスのインスタンス化時には自動的にそれが呼び出される。コンストラクタメソッドは引数を持つことができる。これは、インスタンス化が要求されたときの引数の数に影響する。通常の関数と同様に、コンストラクタは(パラメータ ... によって)可変長引数を扱うことができる。
class Rect { constructor(w, h) { width = w; height = h; } x = 0; y = 0; width = null; height = null; } // Rectのコンストラクタは2つの引数を持つので、クラスは2引数で「呼び出す」必要がある。 local rc = Rect(100, 100);
インスタンスが作成された後、テーブルに適用されているルールに従って、そのプロパティに代入やフェッチすることができる。メソッドはセットできない。
インスタンスのメンバは削除できない。
インスタンスを作成したクラスオブジェクトは組み込み関数instance.getclass()を通して検索することができる(組み込み関数の節を参照せよ)
演算子instanceofはクラスインスタンスが特定のクラスのインスタンスかどうかをテストする。
local rc = Rect(100, 100); if(rc instanceof ::Rect) { ::print("It's a rect"); } else { ::print("It isn't a rect"); }
継承
Squirrelのクラスは単一継承をサポートしている。これは、クラス定義において、キーワードextendsを式の後に追加することで行う。導出クラスの文法は次のようになる。
class SuperFoo extends Foo { function DoSomething() { ::print("I'm doing something"); } }
導出クラスが宣言されたとき、Squirrelはまず全ての基底クラスのメンバを新しいクラスにコピーし、次に宣言の残りの評価を行う。
導出クラスはその基底クラスから全てのメンバとプロパティを継承している。導出クラスが基底関数をオーバーライドした場合、基底クラスの実装は隠蔽される。基底クラスオブジェクトからそのメソッドへフェッチすることで、基底クラスのオーバーライドされたメソッドへアクセスすることは可能である。
例を次に示す。
class Foo { function DoSomething() { ::print("I'm the base"); } }; class SuperFoo extends Foo { // overridden method function DoSomething() { // calls the base method ::Foo.DoSomething(); ::print("I'm doing something"); } }
コンストラクタに対しても同様のルールが適用される。コンストラクタは正規の関数である(構築時に自動的に呼び出される点が異なるが)。
class Base { constructor() { ::print("Base constructor\n"); } } class Child extends Base { constructor() { ::Base.constructor(); ::print("Child constructor\n"); } } local test = Child();
基底クラスはキーワードparentによって調べることができる。parentは「疑似スロット」であり、スロットparentにセットすることはできない。
local thebaseclass = SuperFoo.parent;
メソッドは特別の保護ポリシーを持たない。そのため、同じオブジェクトのメソッドを呼び出すとき、クラス内の別メソッドを呼ぶような基底クラスのメソッドがあったとしても、導出クラスのオーバーライドしているメソッドが呼ばれるだろう。
class Foo { function DoSomething() { ::print("I'm the base"); } function DoIt() { DoSomething(); } }; class SuperFoo extends Foo { // overridden method function DoSomething() { ::print("I'm the derived"); } function DoIt() { ::Foo.DoIt(); } } // creates a new instance of SuperFoo local inst = SuperFoo(); // prints "I'm the derived" inst.DoIt();
メタメソッド
クラスインスタンスはメタメソッドによって言語の意味的な様相をカスタマイズすることができる(メタメソッドの節を参照せよ)C++プログラマにとって、メタメソッドはおおまかに言うと演算子オーバーロードのように振る舞うものである。クラスが使用できるメタメソッドは_add, _sub, _mul, _div, _unm, _modulo, _set, _get, _typeof, _nexti, _cmp, _call, _delslot, _tostringである。
クラスオブジェクトは、_newmemberと_inheritedという2つのメタメソッドのみが使用できる。
メタメソッド_addを実装したクラスを作成する例を次に示す。
class Vector3 { constructor(...) { if(vargc >= 3) { x = vargv[0]; y = vargv[1]; z = vargv[2]; } } function _add(other) { return ::Vector3(x + other.x, y + other.y, z + other.z); } x = 0; y = 0; z = 0; } local v0 = Vector3(1, 2, 3) local v1 = Vector3(11, 12, 13) local v2 = v0 + v1; ::print(v2.x + "," + v2.y + "," + v2.z + "\n");
2.1以降は、クラスは_inheritedと_newmember2つのメタメソッドを新たにサポートする。_inheritedは_inheritedを実装したクラスを継承したときに呼び出される。_newmemberは(宣言時に)クラスにメンバが追加されたときに呼び出される。
ジェネレータ
yield命令を含む関数は「ジェネレータ関数」と呼ばれる。ジェネレータ関数が呼ばれたとき、それは関数本体を実行するかわりに、中断状態にあるジェネレータを新たに返す。返されたジェネレータは(それが生存している間は)resume命令によって再開することができる。yieldキーワードはジェネレータの実行を中断させる。このとき、ジェネレータを再開させた関数へ、式の結果を返すことができる。明示的なreturn命令と関数本体の末尾による終了で、ジェネレータは死亡する。また、ジェネレータ実行中に取り扱えない例外が発生したときも、ジェネレータは自動的に死亡する。死亡したジェネレータはもはや再開することはできない。
function geny(n) { for (local i = 0; i < n; i += 1) yield i; return null; } local gtor = geny(10); local x; while (x = resume gtor) print(x + "\n");
このプログラムの出力結果は次のようになる。
0 1 2 3 4 5 6 7 8 9
定数と列挙
Squirrelでは定数値を識別子に束縛することができ、これはコンパイル時に評価される。これによって定数と列挙を通して行える。
定数
定数は特定の値を識別子に束縛する。定数はグローバルな値と似ているが、コンパイル時に評価されるため値が変更されることはない。
定数値として整数、浮動小数点数、文字列リテラルを使用することができる。式は用いることができない。次のような構文で使用される。
const foobar = 100; const floatbar = 1.2; const stringbar = "I'm a contant string";
定義された時点から定数は常にグローバルスコープであり、後に続く任意のコードから参照することができる。定数は他の同名のグローバルスロットを隠蔽する (このグローバルスロットは :: を用いて見ることができる)
local x = foobar * 2;
列挙
定数同様、列挙も特定の値を識別子に束縛する。列挙もコンパイル時に評価されるため値が変更されることはない。
ひとつのenumでひとつの列挙が導入される。列挙値として整数、浮動小数点数、文字列リテラルを使用することができる。式は用いることができない。次のような構文で使用される。
enum Stuff { first, // 値0をとる second, // 値1をとる third // 値2をとる }
or
enum Stuff { first = 10 second = "string" third = 1.2 }
列挙値は静的メンバと同様の方法でアクセスされる。メンバ名は列挙名で修飾されなければならない(上記の例ではStuff.second)。列挙は他の同名のグローバルスロットを隠蔽する (このグローバルスロットは :: を用いて見ることができる)
local x = Stuff.first * 2;
実装 (Implementation notes)
列挙と定数はコンパイル時の機能である。整数、浮動小数点数、文字列リテラルだけが定数と列挙で宣言することができる。式は許されない(コンパイル時に評価しなければならないので)。列挙と定数が宣言されたとき、それらはコンパイル時にconsttableに追加されるこのテーブルはVMの共有ステートにおいて蓄えられ、VMとすべてのスレッドで共有される。そのため、roottableと同様実行時に変更することができる。組み込み関数getconsttable()を通してconsttableにアクセスすることができ、組み込み関数setconsttable()を通して変更することができる。
いくつかの例を挙げる。
// 定数の作成 getconsttable()["something"] <- 10" // 列挙の作成 getconsttable()["somethingelse"] <- { a = "10", c = "20", d = "200"}; // 定数の削除 delete getconsttable()["something"] // 列挙の削除 delete getconsttable()["somethingelse"]
このシステムによって、定数と列挙を手続き的に宣言することができるようになり、任意のSquirrelの型(関数、クラスなど)を定数と列挙に代入することができるようになる。しかし、これはコードチャンクのシリアライズを不可能にする。
スレッド
Squirrelは協調スレッド(コルーチンとも呼ばれる)をサポートしている。協調スレッドは実行中に中断でき、呼び出し元に値を返すことができるサブルーチンである。後にこの実行は、中断した場所から再開することができる。
一見すると、Squirrelのスレッドはジェネレータと同じように見えるかもしれない。事実、その挙動は非常に似ている。しかし、ジェネレータは呼び出し元のスタック上で動作し、ローカルなルーチンスタックだけを持つのに対して、スレッドは独自の実行スタックとグローバルテーブルとエラーハンドラを持つ。これによってスレッドはネストされた呼び出しを中断でき、独自のエラーポリシーを持つことができる。
スレッドの使用
スレッドは組み込み関数newthread(func)を通じて作成される。この関数は引数をしてSquirrel関数をひとつ取り、それを新しいスレッドオブジェクトにバインドする(これがスレッドの本体となる)。この関数の戻り値のスレッドオブジェクトの初期状態はidleである。このスレッドは関数 threadobj.call()によって開始することができる。メソッドcallに渡される引数は、そのスレッドの関数へ渡される。
スレッドは関数suspend()を呼び出すことで中断することができる。このとき、スレッドをメソッドwakeup()で起こした(またはメソッド call()で開始させた)関数に戻る(もし suspend()に引数がひとつ渡されたなら、それは呼び出し元への戻り値となる。引数がないなら戻り値はnullとなる)。
中断されたスレッドは関数 threadobj.wakeupを呼び出すことで再開することができる。このとき、以前のsuspendの位置に戻る(もし、wakeup()に引数がひとつ渡されたなら、それは関数suspend()への戻り値となる。引数がないなら、戻り値はnullとなる)。
そのメイン関数が明示的なreturn命令や関数本体の末尾によって終了するか、実行中に取り扱えない例外が発生したときに、スレッドは終了する。
function coroutine_test(a, b) { ::print(a + " " + b + "\n"); local ret = ::suspend("suspend 1"); ::print("the coroutine says " + ret + "\n"); ret = ::suspend("suspend 2"); ::print("the coroutine says " + ret + "\n"); ret = ::suspend("suspend 3"); ::print("the coroutine says " + ret + "\n"); return "I'm done" } local coro = ::newthread(coroutine_test); local susparam = coro.call("test", "coroutine"); // コルーチンの開始 local i = 1; do { ::print("suspend passed (" + susparam + ")\n") susparam = coro.wakeup("ciao " + i); ++i; } while (coro.getstatus() == "suspended") ::print("return passed (" + susparam + ")\n")
このプログラムの結果は次のようになる。
test coroutine suspend passed (suspend 1) the coroutine says ciao 1 suspend passed (suspend 2) the coroutine says ciao 2 suspend passed (suspend 3) the coroutine says ciao 3 return passed (I'm done).
次の興味深い例ではスレッドと末尾再帰を組み合わせている。
function state1() { ::suspend("state1"); return state2(); // 末尾呼び出し } function state2() { ::suspend("state2"); return state3(); // 末尾呼び出し } function state3() { ::suspend("state3"); return state1(); // 末尾呼び出し } local statethread = ::newthread(state1) ::print(statethread.call()+"\n"); for(local i = 0; i < 10000; i++) ::print(statethread.wakeup() + "\n");
弱参照
弱参照によって、オブジェクト自身の生存期間の影響を受けることなく、オブジェクトを参照するオブジェクトを作成することができるようになる。Squirrelにおいて、弱参照オブジェクトはファーストクラスオブジェクトであり、組み込みメソッドobj.weakref()を通して作成される。nullを除く全ての型はメソッドweakref()を実装している。しかし、真偽型、整数型、浮動小数点数型において、そのメソッドは単純にそのオブジェクト自身を返す(これらの型は常に値渡し(passed by value)されるため)。
弱参照オブジェクトがコンテナ(テーブルスロット、配列、クラス、インスタンス)に代入されたときの取り扱いは他のオブジェクトと異なる。弱参照オブジェクトを持つコンテナスロットをフェッチしたとき、それは常に(弱参照オブジェクト自体ではなく)弱参照オブジェクトが差す値を返す。これによって、プログラマはこれらが弱参照かどうかという事実を気にする必要がなくなる。弱参照オブジェクトが差す値が破壊されたとき、弱参照オブジェクトは自動的にnullにセットされる。
local t = {} local a = ["first", "second", "third"] // 弱参照オブジェクトを作成して、それをテーブルのスロットへ代入する t.thearray = a.weakref();
テーブルスロットthearrayは配列への弱参照オブジェクトとなる。次の例は"first"を出力する。テーブル(や他の全てのコンテナ)は常に弱参照オブジェクトが差すオブジェクトを返すからである。
print(t.thearray[0]);
配列を差す強参照はローカル変数aが所有する。よって、次の例によってaに整数が代入されると、配列は破壊される。
a = 123;
弱参照オブジェクトが差すオブジェクトが破壊されたとき、弱参照オブジェクトはnullを差すようになるため、次の例では"null"が出力される。
::print(typeof(t.thearray))
弱参照オブジェクトの明示的な取り扱い
弱参照オブジェクトがローカル変数へ代入された場合は、弱参照オブジェクトとして取り扱われる。
local t = {} local weakobj = t.weakref();
次の例は"weakref"と出力される。
::print(typeof(weakobj))
弱参照オブジェクトが差すオブジェクトは組み込みメソッドweakref.ref()を通して得ることができる。
次の例は"table"と出力される。
::print(typeof(weakobj.ref()))
委譲
Squirrelは暗黙の委譲をサポートしている。全てのテーブルとユーザデータは親テーブル(委譲)を持つことができる。親テーブルは通常のテーブルであり、その子に対する特別な振る舞いを定義することができる。テーブル(もしくはユーザデータ)が、対応するスロットを持たないキーを指定されたとき、インタプリタは自動的にその親へgetまたはsetの処理を委譲する。
Entity <- {} function Entity::DoStuff() { ::print(_name); } local newentity = delegate Entity : { _name = "I'm the new entity" } newentity.DoStuff(); // prints "I'm the new entity"
テーブルの親はキーワードparentを通じて検索される。parentは「擬似スロット」である。スロットparentがセットされていないとき、かわりに委譲命令を使用しなければならない。
local thedelegate = newentity.parent;
メタメソッド
メタメソッドは言語の意味的な様相をカスタマイズすることを可能にするメカニズムである。これらのメソッドは通常の関数で、テーブルparent(委譲)またはクラス宣言に配置されている。メタメソッドを定義するだけで、テーブルとクラスインスタンスの振る舞いの様相を大きく変更することが可能となる。(インスタンスではなく)クラスオブジェクトは、_newmemberと_inheritedという2つのメタメソッドのみをサポートする。
例えば、2つのテーブルに対し通常の == とは違う関係の演算子を用いるとき、VMはテーブルの親がメソッド_cmpを持っているかどうかを調べる。もし持っているならそれを呼び出して、2つのテーブルの関係を決定する。
local comparable = { _cmp = function (other) { if (name < other.name) return -1; if (name > other.name) return 1; return 0; } } local a = delegate comparable : { name = "Alberto" }; local b = delegate comparable : { name = "Wouter" }; if (a > b) print("a>b") else print("b<=a");
クラスに対して、上記のコードは次のようになる。
class Comparable { constructor(n) { name = n; } function _cmp(other) { if (name < other.name) return -1; if (name > other.name) return 1; return 0; } name = null; } local a = Comparable("Alberto"); local b = Comparable("Wouter"); if (a > b) print("a>b") else print("b<=a");
_set
インデックス idx がこのオブジェクトまたは委譲チェーンに存在しないときに呼び出される。
function _set(idx, val) // val を返す
_get
インデックス idx がこのオブジェクトまたは委譲チェーンに存在しないときに呼び出される。
function _get(idx) // フェッチされた値を返す
_newslot
テーブルに新規スロットを追加するときに呼び出される。
function _newslot(key, val) // val を返す
もし、対象となるテーブル上にスロットが既に存在しているなら、"new slot" 演算子を用いたとしてもこのメソッドは呼び出されない。
_delslot
テーブルからスロットを削除するときに呼び出される。
このメソッドが呼び出されるなら、Squirrelはそのスロットの削除を行わない。
function _delslot(key)
_add
演算子 +
function _add(op) // this + op の結果を返す
_sub
(_addのような)演算子 -
_mul
(_addのような)演算子 *
_div
(_addのような)演算子 /
_modulo
(_addのような)演算子 %
_unm
単項演算子 -
function _unm()
_typeof
テーブル、ユーザデータ、クラスインスタンス上の演算子 typeof によって呼び出される。
function _typeof() // 文字列としてthisの型を返す
_cmp
演算子 < > <= >=をエミュレートするために呼び出される。
function _cmp(other)
次のような整数を返す。
>0 | if this > other |
0 | if this == other |
<0 | if this < other |
_call
テーブル、ユーザデータ、クラスインスタンスが呼び出されたときに、呼び出される。
function _call(original_this, params…)
_cloned
テーブル、ユーザデータ、クラスインスタンスが複製(クローン)されたときに、複製先から呼び出される。
function _cloned(original)
_nexti
テーブル、ユーザデータ、クラスインスタンスがforeachループによって反復されたときに、呼び出される。
function _nexti(previdx)
previdxがnullなら、最初の反復であることを意味する。この関数は「次」の値のインデックスを返さなければならない。
_tostring
文字列連結中や表示関数がテーブル、ユーザデータ、クラスインスタンスを表示するときに呼び出される。このメソッドはAPI関数sq_tostring()によっても呼び出される。
function _tostring()
オブジェクトの文字列表現を返さなければならない。
_inherited
クラスオブジェクトを_inheritedを実装しているクラスから継承させるときに呼び出される。
function _inherited(attributes)
戻り値は無視される。
_newmember
クラス本体で宣言される各メンバに対して(宣言時に)呼び出される。
function _newmember(index, value, attributes)
もし、この関数が実装されているなら、メンバはクラスに追加されない。
組み込み関数
Squirrel VMは組み込み補助関数を持つ。
グローバルシンボル
array(size, [fill])
指定サイズの配列を作成して返す。もし、オプション引数fillが指定されていたら、新配列のスロットはこの値で埋められる。もしfillが省略されているなら、nullが代わりに用いられる。
seterrorhandler(func)
実行時エラーハンドラをセットする。
setdebughook(hook_func)
デバッグフックをセットする。
enabledebuginfo(enable)
コンパイル時のデバッグ行情報生成を有効/無効にする。enableがnullでないなら有効、enableがnullなら無効である。
getroottable()
VMのルートテーブルを返す。
assert(exp)
もし、expがnullなら例外を投げる。
print(x)
xを標準出力に表示する。
compilestring(string, [buffername])
Squirrelスクリプトを含んでいる文字列をコンパイルして関数に変換し、それを返す。
local compiledscript = compilestring("::print(\"ciao\")"); // run the script compiledscript();
collectgarbage()
ガーベージコレクタを呼び出し、発見し(て削除し)た循環参照の数を返す
type(obj)
メタメソッド_typeofを呼び出さずに、オブジェクトの「生」の型を返す。
getstackinfos(level)
指定されたコールスタックレベルのスタック情報を返す。次のようなフォーマットのテーブルを返す。
{ func = "DoStuff", // 関数名 src = "test.nut", // ソースファイル名 line = 10, // 行番号 locals = { // ローカル変数のテーブル a = 10, testy = "I'm a string" } }
level = 0は現在の関数、level = 1は呼び出し元、といったようになる。もしそのスタックレベルが存在しないなら、この関数はnullを返す。
newthread(threadfunc)
強調スレッドオブジェクト(コルーチン)を新たに作成し、それを返す。
デフォルト委譲
nullとユーザデータを除いて、全てのSquirrelオブジェクトは、そのオブジェクト自体からの情報の操作と取得のための関数の集合を含んだデフォルト委譲を持つ。
整数
- tofloat()
値を浮動小数点数に変換して、それを返す - tostring()
値を文字列に変換して、それを返す - tointeger()
整数値を返す(ダミー関数) - tochar()
整数によって表現された文字を含む文字列を返す - weakref()
ダミー関数。整数自体を返す
浮動小数点数
- tofloat()
浮動小数点数の値を返す(ダミー関数) - tointeger()
値を整数に変換して、それを返す - tostring()
値を文字列に変換して、それを返す - tochar()
浮動小数点数の整数部によって表現された文字を含む文字列を返す - weakref()
ダミー関数。浮動小数点数自体を返す
真偽値
- tofloat()
trueなら1.0を、falseなら0.0を返す - tointeger()
trueなら1を、falseなら0を返す - tostring()
trueなら"true"を、falseなら"false"を返す - weakref()
ダミー関数。真偽値自体を返す
文字列
- len()
文字列の長さを返す - tointeger()
文字列を整数に変換して、それを返す - tofloat()
文字列を浮動小数点数に変換して、それを返す - tostring()
文字列を返す(ダミー関数) - slice(start, [end])
新規文字列として部分文字列を返す。startからendまで(endは含まれない)をコピーする。もしstartが負なら、添字は (文字列長 + start) として計算される。もしendが負なら、添字は (文字列長 + end) として計算される。もしendが省略されたなら、endは文字列長であるとする - find(substr, [startidx])
startidxの位置から部分文字列substrを検索し、最初に発見した部分文字列の添字を返す。もしstartidxが省略されたなら、検索は文字列の先頭から行われる。もしsubstrが発見できなければ、この関数はnullを返す - tolower()
文字列を小文字(lowercase)にした文字列を返す(元の文字列は変化しない) - toupper()
文字列を大文字(uppercase)にした文字列を返す(元の文字列は変化しない) - weakref()
このオブジェクトへの弱参照を返す
テーブル
- len()
テーブル中のスロットの数を返す - rawget(key)
委譲を用いずにスロットkeyから値を得る - rawset(key, val)
委譲を用いずにスロットkeyに値をセットする。もしスロットが存在しないなら、作成される - rawdelete()
委譲を用いずにスロットkeyを削除し、その値を返す。もしスロットが存在しないなら、nullが返される - rawin(key)
もしスロットkeyが存在するなら、trueを返す。この関数は演算子inと同じ動作をするが、委譲を行わない。 - weakref()
このオブジェクトへの弱参照を返す - tostring()
メタメソッド_tostringを呼び出す。それが失敗したなら"(insatnce : pointer)"を返す - clear()
テーブルから全スロットを削除する。
配列
- len()
配列の長さを返す - append(val)
値valを配列の末尾に追加する - extend(array)
与えられた配列の全要素を追加することで、この配列を拡張する - pop()
配列末尾から値を削除してその値を返す - top()
もっとも大きい添字を持つ配列の値を返す - insert(idx, val)
値valを配列の位置idxに挿入する - remove(idx)
配列の位置idxの値を削除する - resize(size, [fill])
配列をリサイズする。(もし以前のサイズよりも指定サイズが大きい場合)もしオプション引数fillが指定されているなら、新しい配列のスロットをその値で埋める。もし引数fillが省略されているなら、nullが使用される - sort([compare_func])
配列をソートする。カスタム比較関数をオプションとして渡すことができる。この関数プロトタイプは次の通りfunction custom_compare(a, b) { if (a > b) return 1 else if (a < b) return -1 return 0; }
- reverse()
配列要素の位置を反転する - slice(start, [end])
新規配列として部分配列を返す。startからendまで(endは含まれない)をコピーする。もしstartが負なら、添字は (配列長 + start) として計算される。もしendが負なら、添字は (配列長 + end) として計算される。もしendが省略されたなら、endは配列長であるとする - weakref()
このオブジェクトへの弱参照を返す - tostring()
"(array : pointer)"を返す - clear()
配列から全スロットを削除する。
関数
- call(_this, args…)
指定された環境(this)オブジェクトと引数で関数を呼ぶ - pcall(_this, args…)
指定された環境(this)オブジェクトと引数で関数を呼ぶ。失敗時にこの関数はエラーコールバックを呼ばない(pcallは'protected call'の略)。 - acall(array_args)
指定された環境(this)オブジェクトと引数で関数を呼ぶ。この関数は呼び出し先の関数に渡された引数を含む配列を受け入れる。 - pacall(array_args)
指定された環境(this)オブジェクトと引数で関数を呼ぶこの関数は呼び出し先の関数に渡された引数を含む配列を受け入れる。失敗時にこの関数はエラーコールバックを呼ばない(pacallは'protected array call'の略)。 - weakref()
このオブジェクトへの弱参照を返す - tostring()
"(closure : pointer)"を返す - bindenv(env)
この関数(クロージャ)を複製し、環境オブジェクトをオブジェクトenv(テーブル、クラス、インスタンス)で束縛する。新規関数の引数には常にenvがセットされるようになる。作成された関数は、その環境オブジェクトを弱参照として保持するので、その生存期間の制御をすることができないので、注意すること。
クラス
- instance()
クラスの新たなインスタンスを返す。この関数はインスタンスのコンストラクタを呼ばない。コンストラクタは明示的に呼ばれなければならない(例えば、class_inst.constructor(class_inst) ) - getattributes(membername)
指定されたメンバの属性を返す。引数membernameがnullなら、この関数はクラス属性を返す - getattributes(membername, attr)
指定されたメンバの属性をセットし、以前の属性値を返す。引数membernameがnullなら、この関数はクラス属性をセットする - rawin(key)
もしスロットkeyが存在するなら、trueを返す。この関数は演算子inと同じ動作をするが、委譲を行わない。 - weakref()
このオブジェクトへの弱参照を返す - tostring()
"(class : pointer)"を返す
クラスインスタンス
- getclass()
このインスタンスを作成したクラスを返す - rawin(key)
もしスロットkeyが存在するならtrueを返す。この関数は演算子inと同じ動作をするが、委譲を行わない。 - weakref()
このオブジェクトへの弱参照を返す - tostring()
メタメソッド_tostringを呼び出す。それが失敗したなら"(insatnce : pointer)"を返す
ジェネレータ
- getstatus()
ジェネレータの状態を示す文字列("idle", "running", "suspended")を返す - weakref()
このオブジェクトへの弱参照を返す - tostring()
"(generator : pointer)"を返す
スレッド
- call(...)
引数を指定してスレッドを開始する - wakeup([wakeupval])
中断されているスレッドを再開する。スレッドを中断したときの関数(通常suspended())に対する戻り値として用いるためのオプション引数が指定可能である。 - getstatus()
スレッドの状態を示す文字列("idle", "running", "suspended")を返す - weakref()
このオブジェクトへの弱参照を返す - tostring()
"(thread : pointer)"を返す
弱参照
- ref()
弱参照が指しているオブジェクトを返す。もしそのオブジェクトが既に削除されているならnullを返す - weakref()
このオブジェクトへの弱参照を返す - tostring()
"(weakref : pointer)"を返す
第3章 Embedding Squirrel
この章では、ホストアプリケーションへSquirrelを組み込む方法について述べる。この章を理解するためにはC言語の知識が必要である。
拡張言語としての性質により、Squirrelのコンパイラと仮想マシン(VM)はCライブラリとして実装されている。このライブラリにはスクリプトのコンパイル、関数の呼び出し、データの操作、VMの拡張を行うための関数が含まれている。この言語をアプリケーションに組み込むために必要な宣言は、ヘッダファイルの"squirrel.h"のみである。
メモリ管理
Squirrelは参照カウント(RC)をメモリ管理の基本システムとして用い、要求に応じて補助的にマークアンドスイープ・ガベージコレクタ(GC)を呼び出す。
ふたつのコンパイル時オプションがある。
- RCとGCを用いる (デフォルト)
ホストアプリケーションでは関数sq_collectgarbage()を呼ぶことができ、実行時にGCサイクルを行うことができる。 GCはホストアプリケーションから明示的に呼ばれない限り、VMによって実行されない。 - RCのみを用いる (#define NO_GARBAGE_COLLECTOR)
この場合、VMが循環参照を検出することは不可能である。よって、メモリリークを回避するために、プログラマが明示的にこれを解決する必要がある。
2番目のオプションを用いる唯一の利点は、初期設定のGC付きのものと較べて、各オプジェクトを保存するのためのポインタを2つ分(32ビットシステムでは8バイト)節約できることである。これはテーブル、配列、関数、スレッド、ユーザデータ、ジェネレータに影響する(他には影響を与えない)。このオプションは実行速度には影響を与えない。
Unicode
デフォルトではSquirrelの文字列はプレーン8ビットASCII文字となる。しかし、VMにシンボル'_UNICODE'がdefineされているなら、コンパイラとAPIで文字が16ビットとして扱われる。
64ビットアーキテクチャ
SquirrelはC++プリプロセッサ上で'_SQ64'をdefineすることで64ビットアーキテクチャとしてコンパイルすることができる。このフラグはsquirrel.hをincludeするすべてのプロジェクトでdefineされるべきである。
エラーの慣習
ほとんどのAPI関数はSQRESULTの値を返す。SQRESULTは関数が完全に成功したかどうかを示す。マクロSQ_SUCCEEDED()とSQ_FAILED()は関数の結果をテストするのに使用される。
if (SQ_FAILED(sq_getstring(v, -1, &s))) printf("getstring failed");
Squirrelの初期化
ホストアプリケーションが最初にすべきことはVMを作成することである。関数sq_open()によって、ホストアプリケーションは任意の数のVMを作成することができる。
それぞれのVMは、必要でなくなったときに関数sq_close()を用いて解放させる必要がある。
int main(int argc, char** argv) { HSQUIRRELVM v = sq_open(1024); // VMを初期スタックサイズ1024で作成 // ここでSquirrelを用いた処理を行う sq_close(v); }
スタック
Squirrelはスタックを通して、VMの持つ値を変更する。この仕組みはプログラミング言語Luaから継承されている。例えば、Squirrelの関数をC言語から呼ぶためには、関数や引数をスタックにpushし、それから関数を呼ぶ必要がある。また同様に、SquirrelからC言語の関数を呼ぶためには、引数をスタックに積む必要がある。
スタックのインデックス
多くのAPI関数はインデックスによって、スタックの任意の要素を参照することができる。スタックのインデックスは次のような慣習に従う:
- スタックベースは1である
- 負のインデックスはスタックトップからのオフセットを意味する。例えば、-1はスタックトップとなる
- 0は不正なインデックスである
例を次に示す。この表はVMのスタックである。
スタック | 正のインデックス | 負のインデックス |
---|---|---|
"test" | 4 | -1(トップ) |
1 | 3 | -2 |
0.5 | 2 | -3 |
"foo" | 1(ベース) | -4 |
上の例では関数sq_gettopは4を返す。
スタックの操作
Squirrelスタック上のデータのpushと探索のために、API関数がいくつか提供されている。
既に存在している値をスタックのトップに置き直すためには、次の関数を使用する。
void sq_push(HSQUIRRELVM v, SQInteger idx);
任意の数の要素をpopするためには、次の関数を使用する。
void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop);
スタックから要素を削除するには、次の関数を使用する。
void sq_remove(HSQUIRRELVM v, SQInteger idx);
To retrieve the top index (and size) of the current virtual stack you must call sq_gettop
SQInteger sq_gettop(HSQUIRRELVM v);
スタックのサイズを指定した値だけ確保させるには、関数sq_settopを使用する。
void sq_settop(HSQUIRRELVM v, SQInteger newtop);
newtopが以前の値よりも大きいなら、スタックの新しい箇所には値としてnullが与えられる。
次の関数はC言語の値をスタックへpushする。
void sq_pushstring(HSQUIRRELVM v, const SQChar *s, SQInteger len); void sq_pushfloat(HSQUIRRELVM v, SQFloat f); void sq_pushinteger(HSQUIRRELVM v, SQInteger n); void sq_pushuserpointer(HSQUIRRELVM v, SQUserPointer p); void sq_pushbool(HSQUIRRELVM v, SQBool b);
次の関数はスタックへnullをpushする。
void sq_pushnull(HSQUIRRELVM v);
スタックの任意の位置の値の型を知るには、次の関数を使用する。
SQObjectType sq_gettype(HSQUIRRELVM v, SQInteger idx);
この結果は次のうちのどれかになる。
OT_NULL, OT_INTEGER, OT_FLOAT, OT_STRING, OT_TABLE, OT_ARRAY, OT_USERDATA, OT_CLOSURE, OT_NATIVECLOSURE, OT_GENERATOR, OT_USERPOINTER, OT_BOOL, OT_INSTANCE, OT_CLASS, OT_WEAKREF
次の関数はスタック上のSquirrelの値をC言語の値へと変換する。
SQRESULT sq_getstring(HSQUIRRELVM v, SQInteger idx, const SQChar **c); SQRESULT sq_getinteger(HSQUIRRELVM v, SQInteger idx, SQInteger *i); SQRESULT sq_getfloat(HSQUIRRELVM v, SQInteger idx, SQFloat *f); SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p); SQRESULT sq_getuserdata(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p, SQUserPointer *typetag); SQRESULT sq_getbool(HSQUIRRELVM v, SQInteger idx, SQBool *p);
関数sq_cmpはスタックから2つの値をpopし、その2つの値の(ANSI Cのstrcmpのような)関係を返す。
SQInteger sq_cmp(HSQUIRRELVM v);
実行時エラー処理
Squirrelのコード上で(try/catchを用いて)例外が扱われていないとき、実行時エラーが発生して現在のプログラムの実行は中断される。コールバック関数をセットして、ホストプログラムから実行時エラーを横取りすることが可能である。これは、スクリプト作成者に意味のあるエラーを表示させたり、ビジュアルデバッガを実装するために有用である。
次のAPIの呼び出しは、スタックからひとつのSquirrel関数をpopし、それをエラーハンドラとしてセットする。
SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
エラーハンドラは環境オブジェクト(this)ともうひとつのオブジェクト(これは任意のSquirrelの型が可能)の2引数で呼び出される。
スクリプトのコンパイル
関数sq_compileを用いることで、Squirrelスクリプトのコンパイルを行うことができる。
typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer userdata); SQRESULT sq_compile(HSQUIRRELVM v, SQREADFUNC read,SQUserPointer p, const SQChar *sourcename, SQBool raiseerror);
スクリプトをコンパイルするために、ホストアプリケーションが読み込み関数(SQLEXREADFUNC)を実装する必要がある。この関数はスクリプトとともにコンパイラに与えられ、コンパイラが文字を読む必要があるときに毎回呼び出される。これは成功したときには1文字を返し、ソースの終端では0を返す必要がある。
もし、sq_compileが成功したなら、コンパイル済みスクリプトがSquirrelの関数としてスタックにpushされる。
注意: スクリプトを実行するために、sq_compile()によって生成された関数はsq_call()で呼び出す必要がある。
次の例はファイルを読み込む"read"関数である。
SQInteger file_lexfeedASCII(SQUserPointer file) { int ret; char c; if( ( ret = fread(&c, sizeof(c), 1, (FILE *)file ) > 0) ) return c; return 0; } int compile_file(HSQUIRRELVM v, const char* filename) { FILE* f = fopen(filename, "rb"); if (f) { sq_compile(v, file_lexfeedASCII, file, filename, 1); fclose(f); return 1; } return 0; }
コンパイラが文法エラーで失敗したなら、コンパイラはコンパイラエラーハンドラを呼び出そうとする。これは次のように宣言する必要がある。
typedef void (*SQCOMPILERERROR)(HSQUIRRELVM /*v*/, const SQChar* /*desc*/, const SQChar* /*source*/, SQInteger /*line*/, SQInteger /*column*/);
そして、これは次のAPIによってセットすることができる。
void sq_setcompilererrorhandler(HSQUIRRELVM v, SQCOMPILERERROR f);
関数の呼び出し
Squirrel関数を呼び出すためには、その関数をスタックにpushし、続けて引数をpushして、それから関数sq_callを呼び出す必要がある。この関数は引数をpopし、もしsq_callの第3引数がtrueであるなら戻り値をpushする。
sq_pushroottable(v); sq_pushstring(v, "foo", -1); sq_get(v, -2); // ルートテーブルから関数を取得 sq_pushroottable(v); // 'this' (関数の環境オブジェクト) sq_pushinteger(v, 1); sq_pushfloat(v, 2.0); sq_pushstring(v, "three", -1); sq_call(v, 4, SQFalse); sq_pop(v, 2); // ルートテーブルと関数のpop
これは次のSquirrelコードと等価である。
foo(1, 2.0, "three");
もしSquirrelコード実行中に、実行時エラーが発生した(もしくは例外が投げられた)なら、sq_callは失敗する。
C関数の作成
ネイティブC関数は次のプロトタイプを持つ必要がある。
typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
引数は呼び出すVMのハンドルであり、戻り値は次のルールに従う整数である。
値 | 説明 |
---|---|
1 | 関数が戻り値を返すとき |
0 | 関数が戻り値を返さないとき |
SQ_ERROR | 実行時エラーが投げられたとき |
Cの関数ポインタから、新規の呼び出し可能なSquirrel関数を取得するには、sq_newclosure()を呼び出し、Cの関数をそれに渡す必要がある。
その関数が呼ばれたとき、スタックベースはその関数の第1引数で、トップは最後の引数である。値を返すためには、その関数内で値をpushして戻り値を1にする必要がある。
次の例は、引数の型をプリントし、引数の数を返す関数である。
SQInteger print_args(HSQUIRRELVM v) { SQInteger nargs = sq_gettop(v); // 引数の数 for(SQInteger n = 1; n <= nargs; ++n) { printf("arg %d is ", n); switch(sq_gettype(v, n)) { case OT_NULL: printf("null"); break; case OT_INTEGER: printf("integer"); break; case OT_FLOAT: printf("float"); break; case OT_STRING: printf("string"); break; case OT_TABLE: printf("table"); break; case OT_ARRAY: printf("array"); break; case OT_USERDATA: printf("userdata"); break; case OT_CLOSURE: printf("closure(function)"); break; case OT_NATIVECLOSURE: printf("native closure(C function)"); break; case OT_GENERATOR: printf("generator"); break; case OT_USERPOINTER: printf("userpointer"); break; default: return sq_throwerror(v, "invalid param"); // 例外を投げる } } printf("\n"); sq_pushinteger(v, nargs); // 戻り値として引数の数を返すので、それをpush return 1; // 戻り値を返すので1 }
関数を登録する例を次に示す。
SQInteger register_global_func(HSQUIRRELVM v, SQFUNCTION f, const char* fname) { sq_pushroottable(v); sq_pushstring(v, fname, -1); sq_newclosure(v, f, 0, 0); // 新規関数を作成 sq_createslot(v, -3); sq_pop(v, 1); // ルートテーブルをpop }
テーブルと配列の操作
新規テーブルはsq_newtableを呼び出すことで作成される。この関数は新規テーブルをスタックにpushする。
void sq_newtable (HSQUIRRELVM v);
新規スロットを作成するには、次の関数を使用する。
SQRESULT sq_createslot(HSQUIRRELVM v, SQInteger idx);
テーブルの委譲の設定や取得をするには、次の関数を使用する。
SQRESULT sq_setdelegate(HSQUIRRELVM v, SQInteger idx); SQRESULT sq_getdelegate(HSQUIRRELVM v, SQInteger idx);
新規配列はsq_newarrayを使用する。これはスタックに新規配列をpushする。引数サイズが1以上なら、その要素をnullで初期化する。
void sq_newarray (HSQUIRRELVM v, SQInteger size);
配列の最後に値を追加するには、次の関数を使用する。
SQRESULT sq_arrayappend(HSQUIRRELVM v, SQInteger idx);
配列の最後から値を削除するには、次の関数を使用する。
SQRESULT sq_arraypop(HSQUIRRELVM v, SQInteger idx, SQInteger pushval);
配列をリサイズするには、次の関数を使用する。
SQRESULT sq_arrayresize(HSQUIRRELVM v, SQInteger idx, SQInteger newsize);
配列やテーブルのサイズを取得するには、次の関数を使用する。
SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx);
配列やテーブルに値をセットするには、次の関数を使用する。
SQRESULT sq_set(HSQUIRRELVM v, SQInteger idx);
配列やテーブルから値を取得するには、次の関数を使用する。
SQRESULT sq_get(HSQUIRRELVM v, SQInteger idx);
委譲なしで配列やテーブルから値のセットや取得を行うには、次の関数を使用する。
SQRESULT sq_rawget(HSQUIRRELVM v, SQInteger idx); SQRESULT sq_rawset(HSQUIRRELVM v, SQInteger idx);
配列やテーブルの要素を繰り返すには、次の関数を使用する。
SQRESULT sq_next(HSQUIRRELVM v, SQInteger idx);
これは繰り返しを行う例である。
// ここで、テーブルか配列をpush sq_pushnull(v) // null反復子 while(SQ_SUCCEEDED(sq_next(v, -2))) { // この時点で-1が値で、-2がキーとなる sq_pop(v, 2); // 次の反復の前にキーと値をpopする } sq_pop(v, 1); // null反復子をpop
ユーザデータとユーザポインタ
Squirrelはホストアプリケーションで任意のデータチャンクをSquirrelの値として代入することができる。これはユーザデータ型によって可能となる。
SQUserPointer sq_newuserdata (HSQUIRRELVM v, SQUnsignedInteger size);
関数sq_newuserdataが呼び出されたとき、Squirrelは新規ユーザデータを指定されたサイズでメモリに割り当て、そのバッファをポインタとして返し、そのオブジェクトをスタックにpushする。この時点で、アプリケーションはこのメモリチャンクに任意のことを行うことができる。他のすべての組み込み型と同様に、VMは自動的にこのメモリの解放を行う。ユーザデータは関数呼び出しやテーブルスロットへの保存に用いることができる。
デフォルトではSquirrelはユーザデータを直接操作することができない。しかし、委譲を代入して、それをテーブルのように振る舞うにようにすることができる。ユーザデータ削除時に、アプリケーションはユーザデータオブジェクト内のデータに対して何かを行いたいときがある。ユーザデータが削除される前に、VMによって呼び出されるコールバックを設定することは可能である。これはAPIのsq_setreleasehookを呼び出すことでできる。
typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer, SQInteger size); void sq_setreleasehook(HSQUIRRELVM v, SQInteger idx, SQRELEASEHOOK hook);
別の種類のユーザデータとしてユーザポインタがある。この型は通常のユーザデータのようなメモリチャンクではなくただの'void*'である。これには委譲を持たせることはできず、値渡しになる。そのため、ユーザポインタのpushはメモリ割り当てが発生しない。
void sq_pushuserpointer(HSQUIRRELVM v, SQUserPointer p);
レジストリテーブル
レジストリテーブルはVMとVMのすべてのスレッド間で共有できる隠しテーブルである。このテーブルはCのAPIからのみアクセス可能であり、ネイティブCライブラリ実装のための補助構造である。例えば、sqstdlib(Squirrel標準ライブラリ)はこれを設定の保存とオブジェクト委譲の共有のために用いている。レジストリテーブルはAPIのsq_pushregistrytableによってアクセス可能である。
void sq_pushregistrytable(HSQUIRRELVM v);
C言語のAPIからSquirrelの値への強参照の維持
SquirrelはCのAPIから値を参照することができる。関数sq_getstackobject()で、(任意の)Squirrelオブジェクトへのハンドルが取得できる。オブジェクトハンドルは、オブジェクトへの参照の追加や削除によって、その生存期間を操作するために用いることができる。オブジェクトはsq_pushobject()を用いることで、VMスタックに再pushすることができる。
HSQOBJECT obj; sq_resetobject(v, &obj) // ハンドルを初期化 sq_geststackobject(v, -2, &obj); // 位置-2からオブジェクトハンドルを得る sq_addref(v, &obj); // オブジェクトへの参照を追加 … //do stuff sq_pushobject(v, &obj); // スタック上のオブジェクトをpush sq_release(v, &obj); // オブジェクトを解放
デバッグインタフェース
Squirrel VMは非常に単純なデバッグインタフェースを用意しており、これによって完全機能のデバッガを構築することが用意である。sq_setreleasehookによって、VMの1行ごとの実行時や関数の呼び出しや終了時に呼ばれるようなコールバック関数を設定することが可能である。このコールバックは現在の行、ソース、(あるなら)関数名を引数として持つ。
SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);
次のコードはデバッグフックがどのようなものかを示す(明らかにこの関数をC言語で実装することは可能である)。
function debughook(event_type, sourcefile, line, funcname) { local fname = funcname? funcname : "unknown"; local srcfile = sourcefile? sourcefile : "unknown" switch (event_type) { case 'l': // called every line(that contains some code) ::print("LINE line [" + line + "] func [" + fname + "]"); ::print("file [" + srcfile + "]\n"); break; case 'c': // called when a function has been called ::print("LINE line [" + line + "] func [" + fname + "]"); ::print("file [" + srcfile + "]\n"); break; case 'r': // called when a function returns ::print("LINE line [" + line + "] func [" + fname + "]"); ::print("file [" + srcfile + "]\n"); break; } }
引数event_typeは次のいずれかになる。
イベント型 | 説明 |
---|---|
| | 各行の実行時 |
c | 関数の呼び出し時 |
r | 関数の終了時 |
完全機能のデバッガは常にローカル変数と呼び出しスタックを表示することができる。呼び出しスタック情報はsq_getstackinfos()によって検索することができる。
SQInteger sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si);
ローカル変数情報はsq_getlocal()によって検索することができる。
SQInteger sq_getlocal(HSQUIRRELVM v, SQUnsignedInteger level, SQUnsignedInteger nseq);
行ごとのコールバックを受けるには、スクリプトをデバッグ情報付きでコンパイルする必要がある。これはsq_enabledebuginfo()を使うことで可能になる。
void sq_enabledebuginfo(HSQUIRRELVM v, SQInteger debuginfo);
第4章 APIリファレンス
仮想マシン
sq_close
void sq_close(HSQUIRRELVM v);
SquirrelのVMとすべての関連したフレンドVMを解放する。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_getforeignptr
SQUserPointer sq_getforeignptr(HSQUIRRELVM v);
VMインスタンスの外部(foreign)ポインタを返す。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
現在のVMの外部(foreign)ポインタ
sq_getprintfunc
SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);
指定されたVMにおける、現在の表示関数を返す(sq_setprintfuncも参照せよ)。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
SQPRINTFUNCTIONへのポインタ。ただし関数はセットされていないならNULL。
sq_getvmstate
SQInteger sq_getvmstate(HSQUIRRELVM v);
VMの実行状態を返す。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
VMの状態を示す整数値。次の定数が定義されている。
- SQ_VMSTATE_IDLE
- SQ_VMSTATE_RUNNING
p- SQ_VMSTATE_SUSPENDED
sq_move
void sq_move(HSQUIRRELVM dest, HSQUIRRELVM src, SQInteger idx);
移動元VMのスタック上のインデックス位置にあるオブジェクトを、移動先VMのスタックへpushする。
引数:
- HSQUIRRELVM dest
移動先のVM - HSQUIRRELVM src
移動元のVM - SQInteger idx
移動対象値の移動元スタック上でのインデックス
sq_newthread
HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize);
第1引数として渡されたVMのフレンドVMを新たに作成し、それをスレッドオブジェクトとしてスタックにpushする。
引数:
- HSQUIRRELVM friendvm
VM - SQInteger initialstacksize
スロットのスタックサイズ(オブジェクト数)
戻り値:
新規VMへのポインタ
注意:
デフォルトではルートテーブルは第1引数として渡されたVMと共有される。新規VMの生存期間はスタックにpushされた「スレッド」オブジェクトに束縛され、通常のSquirrelオブジェクトと同様に振る舞う。
sq_open
HSQUIRRELVM sq_open(SQInteger initialstacksize);
新たな実行スタックを持つSquirrel VMの新しいインスタンスを作成する。
引数:
- SQInteger initialstacksize
スロットのスタックサイズ(オブジェクト数)
戻り値:
Squirrel VMへのハンドル
注意:
返されたVMはsq_releasevmによって解放しなければならない。
sq_pushconsttable
SQRESULT sq_pushconsttable(HSQUIRRELVM v);
現在のconsttableをスタックにpushする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_pushregistrytable
SQRESULT sq_pushregistrytable(HSQUIRRELVM v);
レジストリテーブルをスタックにpushする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_pushroottable
SQRESULT sq_pushroottable(HSQUIRRELVM v);
現在のルートテーブルをスタックにpushする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_seterrorhandler
void sq_seterrorhandler(HSQUIRRELVM v);
スタックからクロージャまたはネイティブクロージャをpopし、それを実行時エラーハンドラとしてセットする。
引数:
- HSQUIRRELVM v
ターゲットVM
注意:
エラーハンドラはフレンドVMに共有される。
sq_setforeignptr
void sq_setforeignptr(HSQUIRRELVM v, SQUserPointer p);
特定のVMインスタンスの外部(foreign)ポインタをセットする。外部ポインタは、VMに関連付けられた任意のユーザ定義のポインタである(デフォルトでは値ID0)。このポインタはVMによって無視される。
引数:
- HSQUIRRELVM v
ターゲットVM - SQUserPointer p
セットされるべきポインタ
sq_setprintfunc
void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);
VMの表示関数をセットする。この関数は組み込み関数::print()で文字列を出力するのに用いられる。
引数:
- HSQUIRRELVM v
ターゲットVM - SQPRINTFUNCTION printfunc
表示関数へのポインタ。出力を無効するならNULL
注意:
表示関数は次のプロトタイプである: void printfunc(HSQUIRRELVM v, const SQChar *s, ...)
sq_setroottable
void sq_setroottable(HSQUIRRELVM v);
テーブルをスタックからpopしてそれをルートテーブルとしてセットする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_setconsttable
void sq_setconsttable(HSQUIRRELVM v);
スタックからテーブルをpopして、それをconsttableとする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_suspendvm
HRESULT sq_suspendvm(HSQUIRRELVM v);
指定したVMの実行を中断する。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
SQRESULT
C関数はこの戻り値を返さなければならない(例参照)
注意:
C関数の式を返す場合にのみsq_resultは呼び出すことができる。Cの呼び出しやメタメソッドによって既に中断されているときには、この関数は失敗する。
例
SQInteger suspend_vm_example(HSQUIRRELVM v) { return sq_suspendvm(v); }
sq_wakeupvm
HRESULT sq_wakeupvm(HSQUIRRELVM v, SQBool resumedret, SQBool retval, SQBool raiseerror);
前回中断されたVMの実行を再開する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQBool resumedret
trueなら、その関数はスタックから値をひとつpopし、それを(前回VMを中断させた)関数の戻り値として使用する。 - SQBool retval
trueなら、この関数の戻り値をスタックにpushする - SQBool raiseerror
trueなら、呼び出し実行中に実行時エラーが発生した場合は、VMがエラーハンドラを呼び出すようにする
戻り値:
HRESULT
コンパイラ
sq_compile
SQRESULT sq_compile(HSQUIRRELVM v, HSQLEXREADFUNC read, SQUserPointer p, const SQChar * sourcename, SQBool raiseerror);
Squirrelのプログラムをコンパイルする。もしそれが成功したなら、コンパイルされたスクリプトを関数としてスタックにpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - HSQLEXREADFUNC read
コンパイラにプログラムを与えるための読み込み関数へのポインタ - SQUserPointer p
呼び出しごとに、コンパイラによって読み込み関数へ渡されるユーザ定義ポインタ - const SQChar * sourcename
プログラムのシンボル名(実行時エラーをより意味あるものにするためのみに使用される) - SQBool raiseerror
この値がtrueなら、エラー時にコンパイルエラーハンドラが呼び出される
戻り値:
SQRESULT
もしsq_compileが失敗したなら、スタックにはなにもpushされない。
注意
エラー時に、この関数はsq_setcompilererrorhandlerによってセットされた関数を呼び出す。
sq_compilebuffer
SQRESULT sq_compilebuffer(HSQUIRRELVM v, const SQChar* s, SQInteger size, const SQChar * sourcename, SQBool raiseerror);
メモリバッファからSquirrelプログラムをコンパイルする。もしそれが成功したなら、コンパイルされたスクリプトを関数としてスタックにpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - const SQChar* s
コンパイルされるバッファへのポインタ - SQInteger size
引数 s のバッファ文字数 - const SQChar * sourcename
プログラムのシンボル名(実行時エラーをより意味あるものにするためのみに使用される) - SQBool raiseerror
この値がtrueなら、エラー時にコンパイルエラーハンドラが呼び出される
戻り値:
SQRESULT
もしsq_compileが失敗したなら、スタックにはなにもpushされない。
注意
エラー時に、この関数はsq_setcompilererrorhandlerによってセットされた関数を呼び出す。
sq_enabledebuginfo
void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable);
コンパイル時のデバッグ行情報生成の有効/無効を設定する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQBool enable
trueならデバッグ情報生成を有効にする。この値が0なら無効にする。
注意
この関数はすべてのスレッドに影響する
sq_notifyallexceptions
void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable);
ハンドルされた例外のエラーコールバック通知の有効/無効を設定する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQBool enable
trueならハンドルされた例外のエラーコールバック通知が有効になる。
注意
もし例外がハンドルされない(try/catchトラップがコールスタック中に存在しない)なら、デフォルトではVMはエラーコールバックのみを呼び出す。もしnotifyallexceptionsが有効なら、たとえtry/catchブロック中であっても、どのような例外に対してVMはエラーコールバックを呼び出す。この機能はデバッガの実装には有用である。
sq_setcompilererrorhandler
void sq_setcompilererrorhandler(HSQUIRRELVM v, SQCOMPILERERROR f);
コンパイラエラーハンドラ関数をセットする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQCOMPILERERROR f
エラーハンドラ関数へのポインタ
注意
もし引数 f がNULLなら、コンパイルエラーが発生しても関数は呼び出されない。コンパイラエラーハンドラはフレンドVM間で共有される。
スタック操作
sq_cmp
SQInteger sq_cmp(HSQUIRRELVM v);
スタックから2つのオブジェクトをpopして、これらを較べる。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
> 0 | if obj1 > obj2 |
== 0 | if obj1 == obj2 |
< 0 | if obj1 < obj2 |
sq_gettop
SQInteger sq_gettop(HSQUIRRELVM v);
スタックトップのインデックスを返す。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
スタックトップのインデックスを示す整数値
sq_pop
void sq_pop(HSQUIRRELVM v, SQInteger nelementstopop);
スタックからn個の要素をpopする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger nelementstopop
popする要素数
sq_poptop
void sq_poptop(HSQUIRRELVM v);
スタックから1個の要素をpopする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_push
void sq_push(HSQUIRRELVM v, SQInteger idx);
スタックのインデックス位置にある値をpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
pushする値のスタックのインデックス
sq_remove
void sq_remove(HSQUIRRELVM v, SQInteger idx);
スタックの任意の位置にある要素を削除する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
削除する要素のインデックス
sq_reservestack
void sq_reservestack(HSQUIRRELVM v, SQInteger nsize);
スタック領域の残りが少なくとも指定サイズはあることを保証する。もしスタックがそれより小さければ、自動的に大きくする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger nsize
要求スタックサイズ
sq_settop
void sq_settop(HSQUIRRELVM v, SQInteger v);
スタックをリサイズする。もし新しいトップが現在のトップより大きければ、関数はnullをpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger v
新しいトップインデックス
オブジェクトの生成と操作
sq_bindenv
SQRESULT sq_bindenv(HSQUIRRELVM v, SQInteger idx);
スタックからオブジェクト(テーブル、インスタンス、クラスのどれかでなければならない)をpopし、スタック上の指定位置にあるクロージャを複製(クローン)し、popしたオブジェクトをクローンクロージャの環境としてセットする。その新しいクローンクロージャはスタックトップへpushされる。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
ターゲットクロージャのインデックス
戻り値:
SQRESULT
注意:
クローンクロージャは環境オブジェクトを弱参照で保持する。
sq_createinstance
SQRESULT sq_createinstance(HSQUIRRELVM v, SQInteger idx);
スタック上のインデックス位置にあるクラスのインスタンスを作成する。この新しいクラスインスタンスはスタックトップにpushされる。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
ターゲットクラスのインデックス
戻り値:
SQRESULT
注意:
この関数はインスタンスのコンストラクタを呼び出さない。インスタンスを作成して自動的にコンストラクタを呼び出すには、代わりにsq_callを使用しなければならない。
sq_getbool
SQRESULT sq_getbool(HSQUIRRELVM v, SQInteger idx, SQBool * b);
スタック上の指定位置にある真偽値を得る。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQBool * b
値が格納される真偽値へのポインタ
戻り値:
SQRESULT
sq_getclosureinfo
SQRESULT sq_getclosureinfo(HSQUIRRELVM v, SQInteger idx, SQUnsignedInteger * nparams, SQUnsignedInteger * nfreevars);
Squirrelのクロージャから引数の数と自由変数の数を調べる。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
ターゲットクロージャのインデックス - SQUnsignedInteger * nparams
引数の数が格納される非符号化整数へのポインタ - SQUnsignedInteger * nfreevars
自由変数の数が格納される非符号化整数へのポインタ
戻り値:
SQRESULT
sq_getfloat
SQRESULT sq_getfloat(HSQUIRRELVM v, SQInteger idx, SQFloat * f);
スタック上の指定位置にある浮動小数点型の値を得る。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQFloat * f
値が格納される浮動小数点数へのポインタ
戻り値:
SQRESULT
sq_getinstanceup
SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer * up, SQUSerPointer typetag);
クラスインスタンスのユーザポインタをスタックの指定された位置から取得する。もし、引数'typetag'が0ではないなら、この関数はインスタンスのクラスやベースクラスが、指定されたタグでタグ付けられたものかどうかをチェックする。もしそうでないなら、関数は失敗する。'typetag'が0ならタグチェックは行われない。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタックのインデックス - SQUserPointer * up
結果が渡されるユーザポインタへのポインタ - SQUSerPointer typetag
型チェックを行うべき型。これが0なら無視される
戻り値:
SQRESULT
sq_getinteger
SQRESULT sq_getinteger(HSQUIRRELVM v, SQInteger idx, SQInteger * i);
スタックの指定位置にある整数の値を取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQInteger * i
値を格納する整数へのポインタ
戻り値:
SQRESULT
sq_getscratchpad
SQChar * sq_getscratchpad(HSQUIRRELVM v, SQInteger minsize);
少なくともminsizeと同じ大きさを持つメモリバッファへのポインタを返す。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger minsize
スクラッチパッドバッファへの要求サイズ
注意:
バッファは次のsq_getscratchpad呼び出しがあるまで有効である。
sq_getsize
SQObjectType sq_getsize(HSQUIRRELVM v, SQInteger idx);
スタックの指定位置にある値のサイズを取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス
戻り値:
スタック上のインデックス位置の値のサイズ
注意:
この関数は文字列、配列、テーブル、ユーザデータに対してのみ動作する。もしこれらの型でないなら、この関数は-1を返す。
sq_getstring
SQRESULT sq_getstring(HSQUIRRELVM v, SQInteger idx, const SQChar ** c);
スタック上の指定位置にある文字列へのポインタを取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - const SQChar ** c
文字列へのポインタを格納するポインタへのポインタ
戻り値:
SQRESULT
sq_getthread
SQRESULT sq_getthread(HSQUIRRELVM v, SQInteger idx, HSQUIRRELVM* v);
スタック上の指定位置にあるスレッドへのポインタを取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - HSQUIRRELVM* v
スレッドポインタを格納する変数へのポインタ
戻り値:
SQRESULT
sq_gettype
SQObjectType sq_gettype(HSQUIRRELVM v, SQInteger idx);
スタック上の指定位置にある値の型を返す。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス
戻り値:
スタック上の指定位置にある値の型
sq_gettypetag
SQRESULT sq_gettypetag(HSQUIRRELVM v, SQInteger idx, SQUserPointer * typetag);
スタック上の指定位置にあるオブジェクト(ユーザデータもしくはクラス)のタイプタグを取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQUserPointer * typetag
タグを格納する変数へのポインタ
戻り値:
SQRESULT
注意:
この関数はインスタンスに対しても機能する。もし、対象オブジェクトがインスタンスであるなら、ベースクラスのタイプタグがフェッチされる。
sq_getuserdata
SQRESULT sq_getuserdata(HSQUIRRELVM v, SQInteger idx, SQUserPointer * p, SQUserPointer * typetag);
スタック上の指定位置にあるユーザデータの値へのポインタを取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQUserPointer * p
ユーザデータのペイロードを指すユーザポインタへのポインタ - SQUserPointer * typetag
ユーザデータタグを格納するSQUserPointerへのポインタ(sq_settypetagを参照せよ)。この引数はnullにできる
戻り値:
SQRESULT
sq_getuserpointer
SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer * p);
スタック上の指定位置にあるユーザポインタの値を取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQUserPointer * p
値を格納するユーザデータへのポインタ
戻り値:
SQRESULT
sq_newarray
void sq_newarray(HSQUIRRELVM v, SQInteger size);
配列を作成し、それをスタック上にpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger size
作成される配列のサイズ
sq_newclass
SQRESULT sq_newclass(HSQUIRRELVM v, SQBool hasbase);
新しいクラスオブジェクトを作成する。もし引数hasbaseが0でないなら、この関数はスタックからクラスをひとつpopし、新クラスをそのクラスから継承させる。
引数:
- HSQUIRRELVM v
ターゲットVM - SQBool hasbase
もし、引数がtrueなら、この関数はスタックトップにベースクラスがあるとみなす
戻り値:
SQRESULT
sq_newclosure
void sq_newclosure(HSQUIRRELVM v, HSQFUNCTION func, SQInteger nfreevars);
新しいネイティブクロージャを作成し、そのクロージャ用の自由変数としてn個分をスタックからpopする。そして、スタックへネイティブクロージャをpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - HSQFUNCTION func
ネイティブ関数へのポインタ - SQInteger nfreevars
自由変数の数(0も可能)
sq_newtable
void sq_newtable(HSQUIRRELVM v);
新しいテーブルを作成して、それをスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_newuserdata
SQUserPointer sq_newuserdata(HSQUIRRELVM v, SQUnsignedInteger size);
新しいユーザデータを作成し、それをスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQUnsignedInteger size
作成されるユーザデータのサイズ(バイト)
sq_pushbool
void sq_pushbool(HSQUIRRELVM v, SQBool b);
真偽値をスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQBool b
pushされる真偽値(SQTrueまたはSQFalse)
sq_pushfloat
void sq_pushfloat(HSQUIRRELVM v, SQFloat f);
浮動小数点数をスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQFloat f
pushされる浮動小数点数
sq_pushinteger
void sq_pushinteger(HSQUIRRELVM v, SQInteger n);
整数をスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger n
pushされる整数
sq_pushnull
void sq_pushnull(HSQUIRRELVM v);
nullをスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_pushstring
void sq_pushstring(HSQUIRRELVM v, const SQChar * s, SQInteger len);
文字列をスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - const SQChar * s
pushされる文字列へのポインタ - SQInteger len
文字列sの長さ
注意:
もし引数lenが0未満であるなら、VMはstrlen(s)によって文字列長を計算する。
sq_pushuserpointer
void sq_pushuserpointer(HSQUIRRELVM v, SQUserPointer p);
ユーザポインタをスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQUserPointer p
pushされるユーザポインタ
sq_setclassudsize
SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
もし、「ユーザデータのサイズ」が1以上なら、クラスのユーザデータのサイズをセットする。クラスのインスタンスが作成されたとき、インスタンスのあるメモリチャンクの末尾に追加スペースが予約される。このインスタンスのユーザポインタもまた自動的にこのメモリ領域にセットされる。このメソッドはクラスインスタンスに付随するデータを移動するアプリケーションにおいてメモリ割り当てを最小にすることができる。
If a class 'user data size' is greater than 0. When an instance of the class is created additional space will is reserved at the end of the memory chunk where the instance is stored. The userpointer of the instance will also be automatically set to this memory area. This allows to minimize allocations in applications that have to carry data along with the class instance.
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQInteger udsize
ユーザデータの予約バイト数
戻り値:
SQRESULT
sq_setinstanceup
SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer up);
クラスインスタンスのユーザポインタをスタックの指定位置にセットする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQUserPointer up
任意のユーザポインタ
戻り値:
SQRESULT
sq_setnativeclosurename
SQRESULT sq_setnativeclosurename(HSQUIRRELVM v, SQInteger idx, const SQChar * name);
スタック上のidxの位置にあるネイティブクロージャの名前を設定する。ネイティブクロージャの名前は純粋にデバグ用である。コールスタック上にこのクロージャがあるときは、この名前が関数sq_stackinfosを通して検索される。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
ネイティブクロージャのスタック位置 - const SQChar * name
設定する関数名
戻り値:
SQRESULT
sq_setparamscheck
SQRESULT sq_setparamscheck(HSQUIRRELVM v, SQInteger nparamscheck, const SQChar * typemask);
スタックトップにあるネイティブクロージャのための、引数の検証スキームを設定する。関数に受け入れることが可能な引数の数と(オプションとして)その型の検証を行うことができる。sq_setparamscheckによって設定された引数スキーマと関数呼び出しが合致しないときは例外が投げられる。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger nparamscheck
引数の数を検証するかどうかを決定する。隠れ引数であるthisを含む。値 内容 0 引数の数について、検証を行わない 正 指定された値で、引数の数を検証 負 指定された値で、引数の数がそれ以上あるかどうかを検証 SQ_MATCHTYPEMASKSTRING typemaskから自動的に値を決定する(例えば、".sn"なら3) - const SQChar * typemask
関数に渡す引数の型を検証するためのマスク。NULLのときは型検証を行わない。
注意:
typemaskはゼロ終端の文字列からなり、引数の型に次のような文字を使用できる。
文字 | 型 |
---|---|
o | null |
i | integer |
f | float |
n | integer, float |
s | string |
t | table |
a | array |
u | userdata |
c | closure, nativeclosure |
g | generator |
p | userpointer |
v | thread |
x | instance |
y | class |
b | bool |
. | any |
'|'は "or" を意味し、これによって複数の型が受け入れ可能な引数を作成することができる(これには使用数の制限はない)。空白は無視するため、可読性向上のために型の間に空白を挿入することができる。
typemaskによる引数の長さが、nparamscheckで指定された数に満たないとき、残りの引数は型検証されない。
例として、次のような引数を取る関数を考える。
- thisがテーブル
- 第1引数が数値
- 第2引数が数値かuserpointer
このときのスキーマは"tsn|p"(table, string, number or userpointer)と表現される。
例:
SQInteger testy(HSQUIRRELVM v) { SQUserPointer p; const SQChar* s; SQInteger i; // no type checking, if the call comply to the mask //surely the functions will succeed. sq_getuserdata(v, 1, &p, NULL); sq_getstring(v, 2, &s); sq_getinteger(v, 3, &i); // ... do something return 0; } // the reg code // ...stuff sq_newclosure(v, testy, 0); // expects exactly 3 parameters(userdata,string,number) sq_setparamscheck(v, 3, _SC("usn")); // ...stuff
sq_setreleasehook
void sq_setreleasehook(HSQUIRRELVM v, SQInteger idx, SQRELEASEHOOK hook);
スタック上の指定位置にあるユーザデータのリリースフックをセットする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQRELEASEHOOK hook
フック関数ポインタ(下の例を見よ)
注意:
この関数フックは、ユーザデータのメモリが削除される前にVMによって呼び出される。
例:
/* tyedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size); */ SQInteger my_release_hook(SQUserPointer p,SQInteger size) { /* なにかする */ return 1; }
sq_settypetag
SQRESULT sq_settypetag(HSQUIRRELVM v, SQInteger idx, SQUserPointer typetag);
スタック上の指定位置にあるオブジェクト(ユーザデータまたはクラス)のタイプタグをセットする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQUserPointer typetag
任意のSQUserPointer
戻り値:
SQRESULT
sq_tobool
void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool * b);
スタック上の指定位置の値をboolとして取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス - SQBool * b
値を格納するbool値へのポインタ
注意:
もしオブジェクトがbool型でないなら、この関数はSquirrelの規則に従って値をbool値に変換する。例えば1はtrueとし、0はfalseとする。
sq_tostring
void sq_tostring(HSQUIRRELVM v, SQInteger idx);
スタック上の指定位置のオブジェクトを文字列へ変換し、その文字列をスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のインデックス
呼び出し
sq_call
SQRESULT sq_call(HSQUIRRELVM v, SQInteger params, SQBool retval, SQBool raiseerror);
クロージャまたはネイティブクロージャを呼び出す。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger params
関数の引数の数 - SQBool retval
trueなら、この関数の戻り値をスタックにpushする - SQBool raiseerror
trueなら、呼び出し実行中に実行時エラーが発生した場合は、VMがエラーハンドラを呼び出すようにする
戻り値:
SQRESULT
注意:
この関数はすべての引数をpopし、スタック上のこのクロージャを取り除く。もしretvalがtrueであるなら、クロージャの戻り値がpushされる。もし関数実行がsq_suspendvmによって中断されたなら、クロージャと引数はスタックから自動的にpopされない。
sq_getlasterror
SQRESULT sq_getlasterror(HSQUIRRELVM v);
スタックに最後に発生したエラー(ラストエラー)をpushする。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
SQRESULT
注意:
pushされたエラー記述子は、任意の正規なSquirrel型となり得る。
sq_getlocal
const SQChar * sq_getlocal(HSQUIRRELVM v, SQUnsignedInteger level, SQUnsignedInteger nseq);
指定したスタッックフレームと番号で、スタック上のローカル変数の名前を取得し、現在の値をpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQUnsignedInteger level
コールスタックの関数インデックス。0を現在の関数とする。 - SQUnsignedInteger nseq
スタックフレームにおけるローカル変数のインデックス (0はthis)
戻り値:
もし変数が指定されたレベル/番号に存在するならローカル変数の名前を、そうでないならNULLを返す。
sq_reseterror
void sq_reseterror(HSQUIRRELVM v);
VM上のラストエラーをnullにリセットする。
引数:
- HSQUIRRELVM v
ターゲットVM
sq_resume
SQRESULT sq_resume(HSQUIRRELVM v, SQBool retval, SQBool raiseerror);
スタックトップにあるジェネレータを再開する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQBool retval
trueなら、この関数の戻り値をスタックにpushする - SQBool raiseerror
trueなら、呼び出し実行中に実行時エラーが発生した場合は、VMがエラーハンドラを呼び出すようにする
戻り値:
SQRESULT
注意:
retvalが0以外なら、ジェネレータの戻り値はpushされる
sq_throwerror
SQRESULT sq_throwerror(HSQUIRRELVM v, const SQChar * err);
VMのラストエラーをセットし、VM上で例外を起こすためにネイティブクロージャによって返されるべき値を返す。
引数:
- HSQUIRRELVM v
ターゲットVM - const SQChar * err
投げられるべきエラーの記述
戻り値:
VM上で例外を投げるためにネイティブクロージャによって返されるべき値
オブジェクト操作
sq_arrayappend
SQRESULT sq_arrayappend(HSQUIRRELVM v, SQInteger idx);
スタックから値をpopして、それをスタック上の指定位置にある配列の末尾に追加する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象配列のインデックス
戻り値
SQRESULT
注意:
配列に対してのみ動作する。
sq_arraypop
SQRESULT sq_arraypop(HSQUIRRELVM v, SQInteger idx);
スタック上の指定位置にある配列の末尾から値を取り出す。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象配列のインデックス
戻り値
SQRESULT
注意:
配列に対してのみ動作する。
sq_arrayresize
SQRESULT sq_arrayresize(HSQUIRRELVM v, SQInteger idx, SQInteger newsize);
スタック上の指定位置にある配列をリサイズする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象配列のインデックス - SQInteger newsize
配列の要求サイズ
戻り値
SQRESULT
注意:
配列に対してのみ動作する。もし、newsizeが現在のサイズよりも大きいなら、新しい配列のスロットはnullで埋められる。
sq_arrayreverse
SQRESULT sq_arrayreverse(HSQUIRRELVM v, SQInteger idx);
指定された配列を反転する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象配列のインデックス
戻り値
SQRESULT
注意:
配列に対してのみ動作する。
sq_clear
SQRESULT sq_clear(HSQUIRRELVM v, SQInteger idx);
指定位置にあるテーブルや配列のすべての要素を消す。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値
SQRESULT
注意:
テーブルや配列のみで有効
sq_clone
SQRESULT sq_clone(HSQUIRRELVM v, SQInteger idx);
指定位置にあるテーブル、配列、クラスインスタンスを複製(クローン)し、それをスタックにpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値
SQRESULT
sq_createslot
SQRESULT sq_createslot(HSQUIRRELVM v, SQInteger idx);
スタックからキーと値をpopし、スタックの指定位置にあるテーブルやクラスに対してset操作を行う。もしスロットが存在しないなら、作成される。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象テーブルのインデックス
戻り値
SQRESULT
注意:
テーブル委譲によってメタメソッド_newslotが呼び出される。これはテーブルに対してのみ機能する。
[バージョン2.0.5以降、この関数は非推奨となった。代わりにsq_newslot()を使用せよ。]
sq_deleteslot
SQRESULT sq_deleteslot(HSQUIRRELVM v, SQInteger idx, SQBool pushval);
スタックからキーをpopし、スタックの指定位置にあるテーブルからそのスロットを削除する。もし、スロットが存在しないなら、なにも起こらない。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象テーブルのインデックス - SQBool pushval
trueなら、この関数は削除されたスロットの値をpushする。
戻り値
SQRESULT
注意:
テーブル委譲によってメタメソッド_delslotが呼び出される。これはテーブルに対してのみ機能する。
sq_get
SQRESULT sq_get(HSQUIRRELVM v, SQInteger idx);
スタックからキーをpopし、スタックの指定位置にあるオブジェクトに対してget操作を行う。そして、その結果をスタックへpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値
SQRESULT
注意:
この呼び出しは通常の脱参照のように、委譲システムを呼び出す。これはテーブル、配列、ユーザデータに対して動作する。もしこの関数が失敗したら、スタック上にはなにもpushされない。
sq_getattributes
SQRESULT sq_getattributes(HSQUIRRELVM v, SQInteger idx);
クラスメンバの属性値を取得する。この関数はスタックからキーをpopして、スタックの指定位置にあるクラスからキーで指定したクラスメンバの属性値をpushする。もしキーがnullなら、この関数はクラス属性を取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象クラスのインデックス
戻り値
SQRESULT
sq_getclass
SQRESULT sq_getclass(HSQUIRRELVM v, SQInteger idx);
スタックの指定位置にあるクラスインスタンスのクラスをpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象クラスインスタンスのインデックス
戻り値
SQRESULT
sq_getdelegate
SQRESULT sq_getdelegate(HSQUIRRELVM v, SQInteger idx);
スタックの指定位置にあるオブジェクトの現在の委譲をpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値
SQRESULT
sq_getfreevariable
const SQChar * sq_getfreevariable(HSQUIRRELVM v, SQInteger idx, SQInteger nval);
スタックの指定位置にあるクロージャの自由変数の値を取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
(クロージャ)スタック上の対象オブジェクトのインデックス - SQInteger nval
(クロージャに関する)自由変数の0ベースのインデックス
戻り値:
純粋Squirrelクロージャに対する自由変数名。エラーの場合や変数インデックスが範囲外のときはnull
注意:
Cのネイティブクロージャに対しては、この関数は常に失敗する。
sq_getweakrefval
SQRESULT sq_getweakrefval(HSQUIRRELVM v, SQInteger idx);
スタックの指定位置にある弱参照によってポイントされているオブジェクトをpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
対象弱参照のインデックス
戻り値:
SQRESULT
注意:
もしこの関数が失敗したなら、スタックにはなにもpushされない。
sq_instanceof
SQBool sq_instanceof(HSQUIRRELVM v);
オブジェクトが特定クラスのインスタンスであるかどうかを調べる。インスタンスとクラスをスタック上に置く必要がある。
引数:
- HSQUIRRELVM v
ターゲットVM
戻り値:
もしスタックの位置-2のインスタンスが、スタックの位置-1のクラスオブジェクトのインスタンスであるならSQTrue。
注意:
この関数はスタックからオブジェクトをpopしない。
sq_newslot
SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
スタックからキーと値をpopし、スタックの指定位置にあるテーブルやクラスに対してset操作を行う。もしスロットが存在しないなら、作成される。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象テーブルのインデックス - SQBool bstatic
SQTrueなら静的メンバとして作成する。この引数は対象オブジェクトがクラスであるときのみ使用される。
戻り値:
SQRESULT
注意:
テーブル委譲によってメタメソッド_newslotが呼び出される。これはテーブルに対してのみ機能する。
sq_next
SQRESULT sq_next(HSQUIRRELVM v, SQInteger idx);
スタックに配列、テーブル、クラススロットの次のキーと値をpushする。反復を開始するためには、スタックトップにnullがある必要がある。各呼び出しにおいて、この関数はnullを反復子に置き換え、コンテナスロットのキーと値をpushする。各反復で、アプリケーションは前のキーと値をpopしなければならないが、反復子は残さなければならない(つまり、これは次の反復のための参照点として用いられる)。全スロットが反復されたとき、この関数は失敗する(テーブルと配列操作を参照せよ)。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象テーブルのインデックス
戻り値:
SQRESULT
sq_rawdeleteslot
SQRESULT sq_rawdeleteslot(HSQUIRRELVM v, SQInteger idx, SQBool pushval);
メタメソッド_delslotqを用いずに、テーブルからスロットを削除する。スタックからキーをpopし、スタックの指定位置にあるテーブルからそのスロットを削除する。もし、スロットが存在しないなら、なにも起こらない。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象テーブルのインデックス - SQBool pushval
trueなら、この関数は削除されたスロットの値をpushする。
戻り値:
SQRESULT
sq_rawget
SQRESULT sq_rawget(HSQUIRRELVM v, SQInteger idx);
スタックからキーをpopし、スタックの指定位置にあるオブジェクトに対して(メタメソッドや委譲を用いずに)get操作を行う。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値:
SQRESULT
注意:
これはテーブルと配列に対してのみ機能する。
sq_rawset
SQRESULT sq_rawset(HSQUIRRELVM v, SQInteger idx);
スタックからキーと値をpopし、スタックの指定位置にあるオブジェクトに対して(メタメソッドや委譲を用いずに)set操作を行う。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値:
SQRESULT
注意:
これはテーブルと配列に対してのみ機能する。もしこの関数が失敗したら、スタック上にはなにもpushされない。
sq_set
SQRESULT sq_set(HSQUIRRELVM v, SQInteger idx);
スタックからキーと値をpopし、スタックの指定位置にあるオブジェクトに対してset操作を行う。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値:
SQRESULT
注意:
この呼び出しは通常の代入のように委譲システムを呼び出す。これはテーブル、配列、ユーザデータに対して動作する。
sq_setattributes
SQRESULT sq_setattributes(HSQUIRRELVM v, SQInteger idx);
クラスメンバの属性値をセットする。この関数はスタックからキーと値をpopし、スタックの指定位置にあるクラスに対して(キーで指定された)属性をセットする。もし、キーがnullなら、この関数はクラス属性をセットする。もしこの関数が成功したなら、古い属性値はスタックへpushされる。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象クラスのインデックス
戻り値:
SQRESULT
sq_setdelegate
SQRESULT sq_setdelegate(HSQUIRRELVM v, SQInteger idx);
スタックからテーブルをpopし、スタックの指定位置オブジェクトを委譲としてそれにセットする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス
戻り値:
SQRESULT
注意:
オブジェクトから委譲を削除するためには委譲としてnullを用いる必要がある。
sq_setfreevariable
SQRESULT sq_setfreevariable(HSQUIRRELVM v, SQInteger idx, SQInteger nval);
スタックから値をpopし、スタックの指定位置にあるクロージャの自由変数としてそれをセットする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のターゲットオブジェクトのインデックス - SQInteger nval
(クロージャへ関連づける)自由変数の0ベースのインデックス
戻り値:
SQRESULT
sq_weakref
void sq_weakref(HSQUIRRELVM v, SQInteger idx);
スタックの指定位置にあるオブジェクトへの弱参照をpushする。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上のターゲットオブジェクトへのインデックス
戻り値:
SQRESULT
注意:
もしidxの位置にあるオブジェクトが整数、浮動小数点数、真偽値、nullであるなら、弱参照オブジェクトの代わりにそのオブジェクト自体がpushされる。
バイトコード直列化
sq_readclosure
SQRESULT sq_readclosure(HSQUIRRELVM v, SQREADFUNC readf, SQUserPointer up);
クロージャをデシリアライズ(読み込み)し、そのクロージャをスタックトップへpushする。その入力元は読み込みコールバック内でユーザが定義する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQREADFUNC readf
デシリアライズ中にVMによって呼び出される読み込み関数へのポインタ - SQUserPointer up
読み込み関数への呼び出しごとに渡されるポインタ
戻り値:
SQRESULT
sq_writeclosure
SQRESULT sq_writeclosure(HSQUIRRELVM v, SQWRITEFUNC writef, SQUserPointer up);
スタックトップにあるクロージャをシリアライズ(書き込み)する。その出力先は書き込みコールバック内でユーザが定義する。
引き数:
- HSQUIRRELVM v
ターゲットVM - SQWRITEFUNC writef
シリアライズ中にVMによって呼び出される書き込み関数へのポインタ - SQUserPointer up
書き込み関数への呼び出しごとに渡されるポインタ
戻り値:
SQRESULT
注意:
自由変数付きのクロージャはシリアライズすることができない。
生オブジェクト操作
sq_addref
void sq_addref(HSQUIRRELVM v, HSQOBJECT * po);
対象オブジェクトハンドラの参照カウントを1増やす。
引数:
- HSQUIRRELVM v
ターゲットVM - HSQOBJECT * po
オブジェクトハンドラへのポインタ
sq_getobjtypetag
SQRESULT sq_getobjtypetag(HSQOBJECT * o, SQUserPointer * typetag);
生オブジェクト参照(ユーザデータもしくはクラス)のタイプタグを得る。
引数:
- HSQOBJECT * o
オブジェクトハンドラへのポインタ - SQUserPointer * typetag
タグが格納される変数へのポインタ
戻り値:
SQRESULT
注意:
この関数はインスタンスに対しても機能する。もし対象オブジェクトがインスタンスなら、そのベースクラスのタイプタグがフェッチされる。
sq_getstackobj
SQRESULT sq_getstackobj(HSQUIRRELVM v, SQInteger idx, HSQOBJECT * po);
スタックからオブジェクトを得て、それをオブジェクトハンドラに格納する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger idx
スタック上の対象オブジェクトのインデックス - HSQOBJECT * po
オブジェクトハンドラへのポインタ
戻り値:
SQRESULT
sq_objtobool
SQBool sq_objtobool(HSQOBJECT * po);
生オブジェクト参照の真偽値を返す。
引数:
- HSQOBJECT * po
オブジェクトハンドラへのポインタ
注意:
もしオブジェクトがboolでないなら、常にfalseが返される。
sq_objtofloat
SQFloat sq_objtofloat(HSQOBJECT * po);
生オブジェクト参照の浮動小数点数を返す。
引数:
- HSQOBJECT * po
オブジェクトハンドラへのポインタ
注意:
もしオブジェクトが整数ならfloatへ変換される。もしオブジェクトが数値でないなら、常に0が返される。
sq_objtointeger
SQInteger sq_objtointeger(HSQOBJECT * po);
生オブジェクト参照の整数値を返す。
引数:
- HSQOBJECT * po
オブジェクトハンドラへのポインタ
注意:
もしオブジェクトがfloatならそれは整数に変換される。もしオブジェクトが数値でないなら、常に0が返される。
sq_objtostring
const SQChar * sq_objtostring(HSQOBJECT * po);
生オブジェクト参照の文字列を返す。
引数:
- HSQOBJECT * po
オブジェクトハンドラへのポインタ
注意:
もしオブジェクトが文字列を参照しないなら、常にNULLが返される。
sq_pushobject
void sq_pushobject(HSQUIRRELVM v, HSQOBJECT obj);
オブジェクトハンドラによって参照されたオブジェクトをスタックへpushする。
引数:
- HSQUIRRELVM vターゲットVM
- HSQOBJECT objオブジェクトハンドラ
sq_release
SQBool sq_release(HSQUIRRELVM v, HSQOBJECT * po);
オブジェクトハンドラの参照カウントを1減らす。
引数:
- HSQUIRRELVM v
ターゲットVM - HSQOBJECT * po
オブジェクトハンドラへのポインタ
戻り値:
- SQTrue オブジェクトハンドラが全ての参照を失なったとき (sq_addrefで追加されたものも含む)
- SQFalse それ以外
注意:
もし、全ての参照を失なった場合、この関数はオブジェクトハンドラをnullにリセットさせる。
訳注: sq_addrefと対となる関数。
sq_resetobject
void sq_resetobject(HSQUIRRELVM v, HSQOBJECT * po);
オブジェクトハンドラをリセット(初期化)する。
引数:
- HSQUIRRELVM v
ターゲットVM - HSQOBJECT * po
オブジェクトハンドラへのポインタ
注意:
すべてのオブジェクトハンドラはこの関数によって初期化されなければならない。
デバッグインタフェース
sq_setdebughook
void sq_setdebughook(HSQUIRRELVM v);
クロージャをスタックからpopし、それをデバックフックとしてセットする。
引数:
- HSQUIRRELVM v
ターゲットVM
注意:
「行ごとの」コールバックを受け取るためには、行情報付きでスクリプトをコンパイルする必要がある。行情報が取得できない場合、「コールとリターン」コールバックのみが呼び出される。
sq_stackinfos
SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos * si);
コールスタック上の指定されたスタック情報を取得する。
引数:
- HSQUIRRELVM v
ターゲットVM - SQInteger level
呼び出すスタックレベル - SQStackInfos * si
スタック情報を格納する構造体SQStackInfosへのポインタ
戻り値:
SQRESULT
(Last modified: 2010-04-02 15:20:37) [validate]