- 追加された行はこの色です。
- 削除された行はこの色です。
''AngelScript''
LuaとかSquirrelは動的型スクリプト言語。
静的なものがないかと探していたらangelscriptを見つけた。
ちょっといじってみよう。
#contents
* リンク [#sb7bd538]
http://www.angelcode.com/angelscript/
http://angelscript.pbwiki.com/
http://liw.rulez.jp/index.php?%A5%D7%A5%ED%A5%B0%A5%E9%A5%E0%2FAngelScript
* スクリプト実行の順序 [#t99be81c]
+ エンジン作成
+ コールバック登録(エラー,例外時に活躍?)
+ スクリプトファイルをエンジンに登録
+ ビルド(コンパイル) ← さすが静的型。
+ 実行
+ 後片付け
includeは自前で実装しているのね。
* 構文 [#l789f3fc]
** class [#zbe0b959]
- public,protected,privateは無し。
- 継承もなし。
- コンストラクタ,デストラクタは有り。
- operatorは可能?(未確認)
** import [#tf87bcd5]
他のmoduleの''関数''(Typeは不可)を自分のmodule内で使うための機能。
なので,一工夫したほうがいいかも。
その一例。
実装クラス(L_MathVector3)はIObjectを必ず継承する。
外部に公開する関数(F_MathVector3_*)はクラス外に宣言し,引数の先頭に必ずIObjectをとる。
他のモジュールは,公開されたその関数を通してアクセスするか,そのラッパークラス(MathVector3)を使ってアクセスする。
:C++コード|
#code(c,){{
// IObject型を追加。
engine->RegisterInterface("IObject");
}}
:Vector3_Local.as|
こいつは,mathモジュールでのみコンパイルされる。
クラスの内部実装を記述している。
#code(c,){{
// module math - local
class L_MathVector3 : IObject
{
L_MathVector3(){ /* */ }
float mX;
float mY;
float mZ;
float& x()
{
return mX;
}
void normalize()
{
//...
}
};
IObject@ F_MathVector3_Constructor()
{
MathVector3 obj;
return @obj;
}
float& F_MathVector3_x( const IObject@ in obj )
{
return cast<L_Vector3>(obj).mX;
}
void F_MathVector3_normalize( IObject@ obj )
{
cast<L_Vector3>(obj).normalize();
}
}}
:Vector3.as|
こいつは,他のmoduleでコンパイルされる。
クラスの内部実装は書かず,内部実装が書かれている関数を呼ぶだけに留める。
#code(c,){{
// module public
import IObject@ F_MathVector3_Constructor() from "math";
import float& F_MathVector3_x( const IObject& in ) from "math";
import void F_MathVector3_normalize( const IObject& in ) from "math";
class MathVector3
{
MathVector3()
{
mObj = F_MathVector3_Constructor();
}
IObject@ mObj;
float& x()
{
return F_MathVector3_x( mObj );
}
void normalize()
{
F_MathVector3_normalize( mObj );
}
};
}}
* バイトコード [#t4292d88]
生成されるバイトコードの比較。
** 組み込み型vs組み込み型のラッパークラス [#j2458c83]
#code(c,){{
class MyUInt
{
MyUInt( const uint& in aVal )
{
this.mVal = aVal;
}
uint mVal;
};
void cla()
{
MyUInt i(0);
i.mVal += 1;
}
//-----------------------------------------------------------
Temps: 2, 3
0 0 * PUSH 3
- 12,5 -
1 3 * SUSPEND
2 3 * VAR v1
3 4 * SetV4 v2, 0x0 (i:0, f:0)
5 4 * VAR v2
6 5 * GETREF 0
7 5 * GETREF 1
8 5 * ALLOC 0xa8cebf8, 66
- 13,5 -
11 3 * SUSPEND
12 3 * PSF v1
13 4 * CHKREF
14 4 * RDS4
15 4 * ADDSi 16
17 4 * PopRPtr
18 3 * RDR4 v2
19 3 * ADDIi v2, v2, 1
22 3 * WRTV4 v2
- 14,2 -
23 3 * SUSPEND
24 3 * PSF v1
25 4 * FREE 0xa8cebf8
27 3 * 0:
27 0 * RET 0
}}
#code(c,){{
void sca()
{
uint i = 0;
i += 1;
}
//-----------------------------------------------------------
Temps: 2
0 0 * PUSH 2
- 18,5 -
1 2 * SUSPEND
2 2 * SetV4 v1, 0x0 (i:0, f:0)
- 19,5 -
4 2 * SUSPEND
5 2 * ADDIi v1, v1, 1
- 20,2 -
8 2 * SUSPEND
9 2 * 0:
9 0 * RET 0
}}
極力組み込み型を使ったほうが良さげ。
** 普通の関数コールvsメンバ関数コール [#d676c000]
#code(c,){{
class Class
{
void classFunc()
{
}
};
void callClassFunc( Class@ obj )
{
obj.classFunc();
}
//-----------------------------------------------------------
Temps:
- 48,5 -
0 0 * SUSPEND
1 0 * PSF v0
2 1 * CHKREF
3 1 * RDS4
4 1 * CALL 68 (void Class::classFunc())
- 49,2 -
6 0 * SUSPEND
7 0 * 0:
7 0 * PSF v0
8 1 * FREE 0xa8d0230
10 0 * RET 1
}}
#code(c,){{
void func()
{
}
void callFunc()
{
func();
}
//-----------------------------------------------------------
Temps:
- 57,5 -
0 0 * SUSPEND
1 0 * CALL 74 (void func())
- 58,2 -
3 0 * SUSPEND
4 0 * 0:
4 0 * RET 0
}}