Introduction
In the process of reviewing LUA and Python, I singled out for myself that LUA is fast enough, but with a slightly unusual syntax. Python, on the other hand, has a very simple syntax and a lot of useful libraries, but, unfortunately, it turned out to be rather slow, and it is rather difficult to bind to C ++. And here at work I was told to use AngelScript, they say, it is convenient for a bunch, faster than LUA and has a C-like syntax. As soon as I began to study it, I realized that this is the very scripting language of my dream.
Preview
Here is what you can read about this language on Wikipedia:
AngelScript is an engine in which an application can register functions, properties and types that can be used in scripts. Scripts are compiled into modules. The number of modules used varies according to needs. An application can also use different interfaces for each module using configuration groups. This is especially useful when the application works with several types of scripts, for example, GUI, AI, etc.
')
The “Hello, world” program in the simplest case looks like this:
void main() { print("Hello world\n"); }
Yes, the syntax of the language pleases from the very beginning. The language supports both functional programming methods and OOP. From the very beginning, it impresses with its simplicity of registering functions, variables, types.
For example, registering a global variable:
g_Engine->RegisterGlobalProperty("int SomeVal",&SomeVal);
where SomeVal is a variable of type int.
Register global function:
g_Engine->RegisterGlobalFunction("void Print(string val)", asFUNCTION(Print), asCALL_CDECL); void Print(string val) { cout<<val.data(); }
Yes, for AngelScript it is not necessary to write binding functions, which is a huge plus in comparison with other languages. To register your types you have to write a couple of functions. A factory for creating instances and a reference counter, for the Type-reference type, and constructor and destructor calls, for an object of the Type-Value type.
For example, we have a class float3, which we would like to register.
To do this, we register the object as a Type-reference and indicate to it a factory, a reference counter, a method and a function for displaying data on the screen, and this is how it looks.
g_Engine->RegisterObjectType("float3",0,asOBJ_REF); g_Engine->RegisterObjectMethod("float3"," void Normalize()",asMETHOD(float3, Normalize),asCALL_THISCALL); g_Engine->RegisterObjectBehaviour("float3",asBEHAVE_FACTORY,"float3@ new_float3()",asFUNCTION(Float3FactoryE),asCALL_CDECL); g_Engine->RegisterObjectBehaviour("float3",asBEHAVE_ADDREF,"void AddRef()",asMETHOD(float3,AddRef),asCALL_THISCALL); g_Engine->RegisterObjectBehaviour("float3",asBEHAVE_RELEASE,"void Release()",asMETHOD(float3,Release),asCALL_THISCALL); g_Engine->RegisterGlobalFunction("void Print(float3@ val)",asFUNCTION(PrintF3),asCALL_CDECL);
Of course, we will not stop on this, since we need access to the xyz values, so we must also register them, which we do by writing.
g_Engine->RegisterObjectProperty("float3","float x",offsetof(float3,x)); g_Engine->RegisterObjectProperty("float3","float y",offsetof(float3,y)); g_Engine->RegisterObjectProperty("float3","float z",offsetof(float3,z));
Everything is very simple and clear. Now you can write in the script
float3@ ObjPos; ObjPos.x=1; ObjPos.y=2; ObjPos.z=3; ObjPos.Normalize(); Print( ObjPos );
After executing this script, we will see on the screen the value of the normalized vector.
Features
I was very pleased with the possibility of operator overloading in AngelScript. In C ++, there is an operator keyword and an operator symbol for this. AngelScript uses certain functions for this.
¦ - opNeg
¦ ~ opCom
¦ ++ opPreInc
¦ - opPreDec
¦ ++ opPostInc
¦ - opPostDec
¦ == opEquals
¦! = OpEquals
¦ <opCmp
¦ <= opCmp
¦> opCmp
¦> = opCmp
¦ = opAssign
¦ + = opAddAssign
¦ - = opSubAssign
¦ * = opMulAssign
¦ / = opDivAssign
¦ & = opAndAssign
¦ | = opOrAssign
¦ ^ = opXorAssign
¦% = opModAssign
¦ << = opShlAssign
¦ >> = opShrAssign
¦ >>> = opUShrAssign
¦ + opAdd opAdd_r
¦ - opSub opSub_r
¦ * opMul opMul_r
¦ / opDiv opDiv_r
¦% opMod opMod_r
¦ & opAnd opAnd_r
¦ | opOr opOr_r
¦ ^ opXor opXor_r
¦ << opShl opShl_r
¦ >> opShr opShr_r
¦ >>> opUShr opUShr_r
¦ [] opIndex
Suppose we want to make it possible for our vector to support the addition of another vector to itself, for this we slightly modify our class.
class float3:public RefC { public: float x; float y; float z; float3(){x=y=z=0;} void Normalize() { float Len=sqrt(x*x+y*y+z*z); Len=Len?Len:1; x/=Len; y/=Len; z/=Len; } float3* operator+=(float3* _rval) { x+=_rval->x; y+=_rval->y; z+=_rval->z; this->AddRef(); return this; } };
Only the registered new method remains.
g_Engine->RegisterObjectMethod("float3", "float3@ opAddAssign(float3@ _rval)", asMETHOD(float3, operator+=), asCALL_THISCALL);
And now you can safely write like this:
float3@ ObjPos; ObjPos.x=1; ObjPos.y=2; ObjPos.z=3; float3@ ObjOffset; ObjOffset .x=3; ObjOffset .y=1; ObjOffset .z=5; ObjPos+=ObjOffset ; Print( ObjPos );
and we will see on the screen x = 4, y = 3, z = 8.
AngelScript supports properties. It looks like this:
class MyObj { type get_ValueName(); type set_ValueName(type Val); } MyObj a; type tmp=a.ValueName;
Also properties are supported for the index operator:
class MyObj { float get_opIndex(int idx) ; void set_opIndex(int idx, float value); } MyObj a; float val=a[1];
useful links
Developer site
www.angelcode.comSVN WIP repository
angelscript.svn.sourceforge.net/svnroot/angelscript/trunkRussian manual
13d-labs.com/angelscript_manual/main.htmlManual in English
www.angelcode.com/angelscript/sdk/docs/manual/index.htmlJIT Compiler
github.com/BlindMindStudios/AngelScript-JIT-Compiler