void RegisterObjectTypeGCBehaviours(asCScriptEngine *engine) { // Register the gc behaviours for the object types int r; engine->objectTypeBehaviours.engine = engine; engine->objectTypeBehaviours.flags = asOBJ_REF | asOBJ_GC; engine->objectTypeBehaviours.name = "_builtin_objecttype_"; #ifndef AS_MAX_PORTABILITY r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCObjectType,AddRef), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCObjectType,Release), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCObjectType,GetRefCount), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCObjectType,SetGCFlag), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCObjectType,GetGCFlag), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCObjectType,EnumReferences), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCObjectType,ReleaseAllHandles), asCALL_THISCALL); asASSERT( r >= 0 ); #else r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ObjectType_AddRef_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ObjectType_Release_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ObjectType_GetRefCount_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ObjectType_SetGCFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ObjectType_GetGCFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ObjectType_EnumReferences_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->objectTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ObjectType_ReleaseAllHandles_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); #endif }
bool Test() { bool fail = Test2(); int r; asIScriptEngine *engine; CBufferedOutStream bout; COutStream out; // Two forms of casts: value cast and ref cast // A value cast actually constructs a new object // A ref cast will only reinterpret a handle, without actually constructing any object // Should be possible to tell AngelScript if it may use the behaviour implicitly or not // Since care must be taken with implicit casts, it is not allowed by default, // i.e. asBEHAVE_VALUE_CAST and asBEHAVE_VALUE_CAST_IMPLICIT or // asBEHAVE_REF_CAST and asBEHAVE_REF_CAST_IMPLICIT //---------------------------------------------------------------------------- // VALUE_CAST // TODO: (Test) Cast from primitive to object is an object constructor/factory // TODO: (Test) Cast from object to object can be either object behaviour or object constructor/factory, // depending on which object registers the cast // TODO: (Implement) It shall be possible to register cast operators as explicit casts. The constructor/factory // is by default an explicit cast, but shall be possible to register as implicit cast. // TODO: (Implement) Type constructors should be made explicit cast only, or perhaps not permit casts at all // TODO: (Test) When compiling operators with non-primitives, the compiler should first look for // compatible registered operator behaviours. If not found, the compiler should see if // there is any cast behaviour that allow conversion of the type to a primitive type. // Test 1 // A class can be implicitly cast to a primitive, if registered the VALUE_CAST behaviour engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->RegisterGlobalFunction("void assert( bool )", asFUNCTION(Assert), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectType("type", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Type_construct0), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Type_construct1), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("type", asBEHAVE_IMPLICIT_VALUE_CAST, "int f()", asFUNCTION(Type_castInt), asCALL_GENERIC); assert( r >= 0 ); asIScriptContext *ctx = 0; r = engine->ExecuteString(0, "type t(5); \n" "int a = t; \n" // conversion to primitive in assignment "assert( a == 5 ); \n" "assert( a + t == 10 ); \n" // conversion to primitive with math operation "a -= t; \n" // conversion to primitive with math operation "assert( a == 0 ); \n" "assert( t == int(5) ); \n" // conversion to primitive with comparison "type b(t); \n" // conversion to primitive with parameter "assert( 32 == (1 << t) ); \n" // conversion to primitive with bitwise operation "assert( (int(5) & t) == 5 ); \n" // conversion to primitive with bitwise operation , &ctx); if( r != 0 ) { if( r == 3 ) PrintException(ctx); fail = true; } if( ctx ) ctx->Release(); // Test 2 // A class won't be converted to primitive if there is no obvious target type // ex: t << 1 - It is not known what type t should be converted to // ex: t + t - It is not known what type t should be converted to // ex: t < t - It is not known what type t should be converted to bout.buffer = ""; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); r = engine->ExecuteString(0, "type t(5); t << 1; "); if( r >= 0 ) fail = true; if( bout.buffer != "ExecuteString (1, 14) : Error : Illegal operation on 'type&'\n" ) { printf(bout.buffer.c_str()); fail = true; } bout.buffer = ""; r = engine->ExecuteString(0, "type t(5); t + t; "); if( r >= 0 ) fail = true; if( bout.buffer != "ExecuteString (1, 14) : Error : No matching operator that takes the types 'type&' and 'type&' found\n" ) { printf(bout.buffer.c_str()); fail = true; } bout.buffer = ""; r = engine->ExecuteString(0, "type t(5); t < t; "); if( r >= 0 ) fail = true; if( bout.buffer != "ExecuteString (1, 14) : Error : No matching operator that takes the types 'type&' and 'type&' found\n" ) { printf(bout.buffer.c_str()); fail = true; } // Test3 // If an object has a cast to more than one matching primitive type, the cast to the // closest matching type will be used, i.e. Obj has cast to int and to float. A type of // int8 is requested, so the cast to int is used engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->ExecuteString(0, "type t(2); assert( (1.0 / t) == (1.0 / 2.0) );"); if( r != asEXECUTION_FINISHED ) fail = true; engine->Release(); // Test4 // It shall not be possible to register a cast behaviour from an object to a boolean type engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->RegisterObjectType("type", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("type", asBEHAVE_IMPLICIT_VALUE_CAST, "bool f()", asFUNCTION(Type_castInt), asCALL_GENERIC); if( r != asNOT_SUPPORTED ) { fail = true; } engine->Release(); // Test5 // Exclicit value cast // TODO: This should work for MAX_PORTABILITY as well if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->RegisterGlobalFunction("void assert( bool )", asFUNCTION(Assert), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectType("type", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Type_construct0), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("type", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Type_construct1), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("type", asBEHAVE_VALUE_CAST, "int f()", asFUNCTION(Type_castInt), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterGlobalBehaviour(asBEHAVE_EQUAL, "bool f(const type &in, const type &in)", asFUNCTION(Type_equal), asCALL_CDECL); assert( r >= 0 ); r = engine->RegisterObjectProperty("type", "int v", 0); // explicit cast to int is allowed r = engine->ExecuteString(0, "type t; t.v = 5; int a = int(t); assert(a == 5);"); if( r < 0 ) fail = true; // as cast to int is allowed, AngelScript also allows cast to float (using cast to int then implicit cast to int) r = engine->ExecuteString(0, "type t; t.v = 5; float a = float(t); assert(a == 5.0f);"); if( r < 0 ) fail = true; // implicit cast to int is not allowed bout.buffer = ""; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); r = engine->ExecuteString(0, "type t; int a = t;"); if( r >= 0 ) fail = true; if( bout.buffer != "ExecuteString (1, 17) : Error : Can't implicitly convert from 'type&' to 'int'.\n" ) { printf(bout.buffer.c_str()); fail = true; } /* // Having an implicit constructor with an int param makes it possible to compare the type with int engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->ExecuteString(0, "type t(5); assert( t == 5 );"); if( r < 0 ) fail = true; */ engine->Release(); } //----------------------------------------------------------------- // REFERENCE_CAST // TODO: This should work for MAX_PORTABILITY as well if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { // It must be possible to cast an object handle to another object handle, without // losing the reference to the original object. This is what will allow applications // to register inheritance for registered types. This should be a special // behaviour, i.e. REF_CAST. // How to provide a cast from a base class to a derived class? // The base class may not know about the derived class, so it must // be the derived class that registers the behaviour. // How to provide interface functionalities to registered types? I.e. a class implements // various interfaces, and a handle to one of the interfaces may be converted to a handle // of another interface that is implemented by the class. // TODO: Can't register casts from primitive to primitive engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); // Class A is the base class engine->RegisterObjectType("A", 0, asOBJ_REF); engine->RegisterObjectBehaviour("A", asBEHAVE_FACTORY, "A@f()", asFUNCTION(A::factory), asCALL_CDECL); engine->RegisterObjectBehaviour("A", asBEHAVE_RELEASE, "void f()", asMETHOD(A, release), asCALL_THISCALL); engine->RegisterObjectBehaviour("A", asBEHAVE_ADDREF, "void f()", asMETHOD(A, addref), asCALL_THISCALL); engine->RegisterObjectBehaviour("A", asBEHAVE_ASSIGNMENT, "A& f(const A &in)", asMETHOD(A, assign), asCALL_THISCALL); engine->RegisterObjectMethod("A", "int test()", asMETHOD(A, test), asCALL_THISCALL); // Class B inherits from class A engine->RegisterObjectType("B", 0, asOBJ_REF); engine->RegisterObjectBehaviour("B", asBEHAVE_FACTORY, "B@f()", asFUNCTION(B::factory), asCALL_CDECL); engine->RegisterObjectBehaviour("B", asBEHAVE_RELEASE, "void f()", asMETHOD(B, release), asCALL_THISCALL); engine->RegisterObjectBehaviour("B", asBEHAVE_ADDREF, "void f()", asMETHOD(B, addref), asCALL_THISCALL); engine->RegisterObjectMethod("B", "int test()", asMETHOD(B, test), asCALL_THISCALL); // Test the classes to make sure they work r = engine->ExecuteString(0, "A a; assert(a.test() == 1); B b; assert(b.test() == 2);"); if( r != asEXECUTION_FINISHED ) fail = true; // It should be possible to register a REF_CAST to allow implicit cast // Test IMPLICIT_REF_CAST from subclass to baseclass r = engine->RegisterGlobalBehaviour(asBEHAVE_IMPLICIT_REF_CAST, "A@ f(B@)", asFUNCTION(B::castToA), asCALL_CDECL); assert( r >= 0 ); r = engine->ExecuteString(0, "B b; A@ a = b; assert(a.test() == 2);"); if( r != asEXECUTION_FINISHED ) fail = true; // Test explicit cast with registered IMPLICIT_REF_CAST r = engine->ExecuteString(0, "B b; A@ a = cast<A>(b); assert(a.test() == 2);"); if( r != asEXECUTION_FINISHED ) fail = true; // It should be possible to assign a value of type B // to and variable of type A due to the implicit ref cast r = engine->ExecuteString(0, "A a; B b; a = b;"); if( r != asEXECUTION_FINISHED ) fail = true; // Test REF_CAST from baseclass to subclass r = engine->RegisterGlobalBehaviour(asBEHAVE_REF_CAST, "B@ f(A@)", asFUNCTION(B::AcastToB), asCALL_CDECL); assert( r >= 0 ); r = engine->ExecuteString(0, "B b; A@ a = cast<A>(b); B@ _b = cast<B>(a); assert(_b.test() == 2);"); if( r != asEXECUTION_FINISHED ) fail = true; // Test REF_CAST from baseclass to subclass, where the cast is invalid r = engine->ExecuteString(0, "A a; B@ b = cast<B>(a); assert(@b == null);"); if( r != asEXECUTION_FINISHED ) fail = true; // TODO: This requires implicit value cast // Test passing a value of B to a function expecting its base class // the compiler will automatically create a copy /* const char *script = "void func(A a) {assert(a.test() == 1);}\n"; r = mod->AddScriptSection(0, "script", script, strlen(script)); r = mod->Build(0); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "B b; func(b)"); if( r < 0 ) fail = true; */ // TODO: A handle to A can not be implicitly cast to a handle to B since it was registered as explicit REF_CAST // TODO: It shouldn't be possible to cast away constness engine->Release(); } // Success return fail; }
bool Test() { bool fail = Test2(); int r; COutStream out; asIScriptContext *ctx; // Test to make sure opIndex properly catches null pointer access // http://www.gamedev.net/topic/676729-crash-instead-of-null-pointer-exception-on-opindex/ { asIScriptEngine *engine = asCreateScriptEngine(); RegisterScriptArray(engine, true); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); ctx = engine->CreateContext(); r = ExecuteString(engine, "array<array<int>@> a = {null}; a[0][0] = 1;", 0, ctx); if (r != asEXECUTION_EXCEPTION) TEST_FAILED; else if( GetExceptionInfo(ctx) != "func: void ExecuteString()\n" "modl: \n" "sect: ExecuteString\n" "line: 1\n" "desc: Null pointer access\n" ) { PRINTF("%s", GetExceptionInfo(ctx).c_str()); TEST_FAILED; } ctx->Release(); engine->ShutDownAndRelease(); } // Test GetTypeDeclaration with arrays // http://www.gamedev.net/topic/663428-simplest-way-to-get-variable-type/ { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptArray(engine, true); int typeId = engine->GetTypeIdByDecl("array<array<int>@>"); if( typeId < 0 ) TEST_FAILED; std::string typeDecl = engine->GetTypeDeclaration(typeId, true); if( typeDecl != "int[]@[]" ) { PRINTF("%s\n", typeDecl.c_str()); TEST_FAILED; } engine->SetDefaultNamespace("foo"); engine->RegisterEnum("MyEnum"); engine->SetDefaultNamespace(""); typeId = engine->GetTypeIdByDecl("array<foo::MyEnum>"); if( typeId < 0 ) TEST_FAILED; typeDecl = engine->GetTypeDeclaration(typeId, true); if( typeDecl != "foo::MyEnum[]" ) { PRINTF("%s\n", typeDecl.c_str()); TEST_FAILED; } engine->ShutDownAndRelease(); } asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); RegisterScriptString_Generic(engine); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; PRINTF("%s: Failed to compile the script\n", TESTNAME); } ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArray()", mod, ctx); if( r != asEXECUTION_FINISHED ) { if( r == asEXECUTION_EXCEPTION ) PRINTF("%s", GetExceptionInfo(ctx).c_str()); PRINTF("%s: Failed to execute script\n", TESTNAME); TEST_FAILED; } if( ctx ) ctx->Release(); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; PRINTF("%s: Failed to compile the script\n", TESTNAME); } r = ExecuteString(engine, "TestArrayException()", mod); if( r != asEXECUTION_EXCEPTION ) { PRINTF("%s: No exception\n", TESTNAME); TEST_FAILED; } mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; PRINTF("%s: Failed to compile the script\n", TESTNAME); } ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArrayMulti()", mod, ctx); if( r != asEXECUTION_FINISHED ) { PRINTF("%s: Failure\n", TESTNAME); TEST_FAILED; } if( r == asEXECUTION_EXCEPTION ) { PRINTF("%s", GetExceptionInfo(ctx).c_str()); } if( ctx ) ctx->Release(); ctx = 0; mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; PRINTF("%s: Failed to compile the script\n", TESTNAME); } ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArrayChar()", mod, ctx); if( r != asEXECUTION_FINISHED ) { PRINTF("%s: Failure\n", TESTNAME); TEST_FAILED; } if( r == asEXECUTION_EXCEPTION ) { PRINTF("%s", GetExceptionInfo(ctx).c_str()); } if( ctx ) ctx->Release(); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script5, strlen(script5), 0); r = mod->Build(); if( r < 0 ) TEST_FAILED; ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArrayInitList()", mod, ctx); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( r == asEXECUTION_EXCEPTION ) PRINTF("%s", GetExceptionInfo(ctx).c_str()); if( ctx ) ctx->Release(); CBufferedOutStream bout; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script6, strlen(script6), 0); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "TestArray (1, 1) : Info : Compiling void Test()\n" "TestArray (4, 16) : Error : Initialization lists cannot be used with 'int'\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Array object must call default constructor of the script classes engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "Test()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Test bool[] on Mac OS X with PPC CPU // Submitted by Edward Rudd const char *script8 = "bool[] f(10); \n" "for (int i=0; i<10; i++) { \n" " f[i] = false; \n" "} \n" "Assert(f[0] == false); \n" "Assert(f[1] == false); \n" "f[0] = true; \n" "Assert(f[0] == true); \n" "Assert(f[1] == false); \n"; r = ExecuteString(engine, script8); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Make sure it is possible to do multiple assignments with the array type r = ExecuteString(engine, "int[] a, b, c; a = b = c;"); if( r < 0 ) TEST_FAILED; engine->Release(); // Test circular reference between types { // Create the script engine asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptArray(engine, true); // Compile asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", "class Hoge" "{" " Hoge(){}" " Hoge(HogeManager&){}" "};" "class HogeManager" "{" " Hoge[] hoges;" "};" , 0); mod->Build(); // Release engine engine->Release(); } // Test multidimensional array initialization { // Create the script engine asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); RegisterScriptArray(engine, true); r = ExecuteString(engine, "int[][] a(2, int[](2)); assert(a[1].length() == 2);\n"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Release engine engine->Release(); } // Test array of void { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); CBufferedOutStream bout; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, false); r = ExecuteString(engine, "array<void> a;"); if( r != -1 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 7) : Error : Attempting to instantiate invalid template type 'array<void>'\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Success return fail; }
bool Test() { bool fail = false; if( !fail ) fail = Test2(); int r; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); COutStream out; CBufferedOutStream bout; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptString_Generic(engine); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); // Register an interface from the application r = engine->RegisterInterface("appintf"); assert( r >= 0 ); r = engine->RegisterInterfaceMethod("appintf", "void test()"); assert( r >= 0 ); // Test working example asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "test()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Test calling the interface method from the application asIObjectType *type = engine->GetModule(0)->GetObjectTypeByName("myclass"); asIScriptObject *obj = (asIScriptObject*)engine->CreateScriptObject(type); int intfTypeId = engine->GetModule(0)->GetTypeIdByDecl("myintf"); type = engine->GetObjectTypeById(intfTypeId); asIScriptFunction *func = type->GetMethodByDecl("void test()"); asIScriptContext *ctx = engine->CreateContext(); r = ctx->Prepare(func); if( r < 0 ) TEST_FAILED; ctx->SetObject(obj); ctx->Execute(); if( r != asEXECUTION_FINISHED ) TEST_FAILED; intfTypeId = engine->GetTypeIdByDecl("appintf"); type = engine->GetObjectTypeById(intfTypeId); func = type->GetMethodByDecl("void test()"); r = ctx->Prepare(func); if( r < 0 ) TEST_FAILED; ctx->SetObject(obj); ctx->Execute(); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( ctx ) ctx->Release(); if( obj ) obj->Release(); // Test class that don't implement all functions of the interface. // Test instanciating an interface. Shouldn't work. // Test that classes don't implement the same interface twice // Try copying an interface variable to another. Shouldn't work. // Test implicit conversion from class to interface that is not being implemented. Should give compiler error // Test implicit conversion from interface to class. Should give compiler error. engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "TestInterface (5, 7) : Error : Missing implementation of 'void intf::test()'\n" "TestInterface (9, 1) : Info : Compiling void test(intf&inout)\n" "TestInterface (11, 9) : Error : Interface 'intf' cannot be instantiated\n" "TestInterface (13, 6) : Error : No appropriate opAssign method found in 'intf' for value assignment\n" "TestInterface (15, 16) : Error : Can't implicitly convert from 'myclass&' to 'nointf@&'.\n" "TestInterface (16, 16) : Error : Can't implicitly convert from 'intf@&' to 'myclass@&'.\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); // Test cast for both temporary handle and non-temporary handle { const char *script = "interface ScriptLogic {} \n" "class PlayerLogic : ScriptLogic {} \n" "ScriptLogic @getScriptObject() { return PlayerLogic(); } \n"; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterStdString(engine); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script); r = mod->Build(); if( r < 0 ) TEST_FAILED; // Non-temporary handle r = ExecuteString(engine, "ScriptLogic @c = getScriptObject(); cast<PlayerLogic>(c);", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Temporary handle r = ExecuteString(engine, "cast<PlayerLogic>(getScriptObject());", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // It should be possible to inherit the implementation of an interface method { const char *script = "interface I { void method(); } \n" "class B { void method() {} } \n" "class D : B, I {} \n" "D d; \n"; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script); r = mod->Build(); if( r < 0 ) TEST_FAILED; engine->Release(); } // Allow script declared interfaces to inherit from other interfaces { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); const char *script = "interface A { void a(); } \n" "interface B : A { void b(); } \n" "class C : B {} \n"; // Must implement both a() and b() bout.buffer = ""; mod->AddScriptSection(TESTNAME, script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "TestInterface (3, 7) : Error : Missing implementation of 'void B::b()'\n" "TestInterface (3, 7) : Error : Missing implementation of 'void A::a()'\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Don't allow shared interface to implement non-shared interface script = "interface A {} \n" "shared interface B : A {} \n"; bout.buffer = ""; mod->AddScriptSection(TESTNAME, script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "TestInterface (2, 22) : Error : Shared type cannot implement non-shared interface 'A'\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Implicit casts to an inherited interface should work script = "interface A {} \n" "interface B : A {} \n" "void func() \n" "{ \n" " A@ a; B@ b; \n" " @a = b; \n" "} \n"; bout.buffer = ""; mod->AddScriptSection(TESTNAME, script); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Don't allow circular inheritance script = "interface A : C {} \n" "interface B : A {} \n" "interface C : B {} \n"; bout.buffer = ""; mod->AddScriptSection(TESTNAME, script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "TestInterface (3, 15) : Error : Can't implement itself, or another interface that implements this interface\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // http://www.gamedev.net/topic/638959-interface-inheritance-issue/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("test", "shared interface ielement \n" "{ \n" " int func1(); \n" "} \n" "shared interface iscreen : ielement \n" "{ \n" " int func2(); \n" "} \n" "mixin class celementbase \n" "{ \n" " int func1() { return 1; } \n" "} \n" "class cscreen : celementbase, iscreen \n" "{ \n" " int func2() { return 2; } \n" "} \n" "void stuff( iscreen@ scr ) \n" "{ \n" " assert( scr.func1() == 1 ); \n" " assert( scr.func2() == 2 ); \n" "} \n"); bout.buffer = ""; r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "cscreen s; stuff(s);", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Success return fail; }
bool Test() { bool fail = false; fail = Test2() || fail; int r; COutStream out; CBufferedOutStream bout; asIScriptContext *ctx; asIScriptEngine *engine; // Compile array with default value in list { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptString(engine); // ref type RegisterScriptArray(engine, false); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); r = ExecuteString(engine, "array<string> a = {'a', , 'c', , 'e'}; assert( a[1] == '' );"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Compile array with default value in list { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterStdString(engine); // value type RegisterScriptArray(engine, false); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); r = ExecuteString(engine, "array<string> a = {'a', , 'c', , 'e'}; assert( a[1] == '' );"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Compile nested array init list { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, false); r = ExecuteString(engine, "array<array<int>> a = {{1,2},{3,4}};"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptString(engine); RegisterScriptArray(engine, false); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); // Test sorting on array of handles mod->AddScriptSection(TESTNAME, "class Test { \n" " Test(int v) {val = v;} \n" " int opCmp(const Test & o) const { return val - o.val; } \n" " int val; \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; ctx = engine->CreateContext(); r = ExecuteString(engine, "array<Test @> a = { Test(1), Test(4), Test(2), null, Test(3) }; \n" "a.sortAsc(); \n" "Assert( a[0] is null ); \n" "Assert( a[1].val == 1 ); \n" "Assert( a[2].val == 2 ); \n" "Assert( a[3].val == 3 ); \n" "Assert( a[4].val == 4 ); \n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( r == asEXECUTION_EXCEPTION ) PrintException(ctx); ctx->Release(); // Test different signatures on opCmp and opEquals mod->AddScriptSection(TESTNAME, "class C \n" "{ \n" " C(int i) {i_ = i;} \n" // " bool opEquals (const C &in other) const\n" // " { \n" // " return i_ == other.i_; \n" // " } \n" // " int opCmp (const C &in other) const\n" // " { \n" // " return i_ - other.i_; \n" // " } \n" " bool opEquals (const C @ other) const\n" " { \n" " return i_ == other.i_; \n" " } \n" " int opCmp (const C @ other) const\n" " { \n" " return i_ - other.i_; \n" " } \n" " int i_; \n" "} \n" "void main (void) \n" "{ \n" " array<const C @> a2; \n" " a2.insertLast(@C(2)); \n" " a2.insertLast(@C(1)); \n" " a2.sortAsc(); \n" " Assert( a2[0].i_ == 1 ); \n" " Assert( a2[1].i_ == 2 ); \n" " C f(2); \n" " Assert( a2.find(f) == 1 ); \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; ctx = engine->CreateContext(); r = ExecuteString(engine, "main()", mod, ctx); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( r == asEXECUTION_EXCEPTION ) PrintException(ctx); ctx->Release(); // Multiple tests in one mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("%s: Failed to compile the script\n", TESTNAME); } ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArray()", mod, ctx); if( r != asEXECUTION_FINISHED ) { if( r == asEXECUTION_EXCEPTION ) PrintException(ctx); printf("%s: Failed to execute script\n", TESTNAME); TEST_FAILED; } if( ctx ) ctx->Release(); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("%s: Failed to compile the script\n", TESTNAME); } r = ExecuteString(engine, "TestArrayException()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: No exception\n", TESTNAME); TEST_FAILED; } // Must be possible to declare array of arrays mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script3, strlen(script3), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("%s: Failed to compile the script\n", TESTNAME); } ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArrayMulti()", mod, ctx); if( r != asEXECUTION_FINISHED ) { printf("%s: Failure\n", TESTNAME); TEST_FAILED; } if( r == asEXECUTION_EXCEPTION ) { PrintException(ctx); } if( ctx ) ctx->Release(); ctx = 0; mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script4, strlen(script4), 0); r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("%s: Failed to compile the script\n", TESTNAME); } ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArrayChar()", mod, ctx); if( r != asEXECUTION_FINISHED ) { printf("%s: Failure\n", TESTNAME); TEST_FAILED; } if( r == asEXECUTION_EXCEPTION ) { PrintException(ctx); } if( ctx ) ctx->Release(); // Initialization lists must work for array template mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script5, strlen(script5), 0); r = mod->Build(); if( r < 0 ) TEST_FAILED; ctx = engine->CreateContext(); r = ExecuteString(engine, "TestArrayInitList()", mod, ctx); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( r == asEXECUTION_EXCEPTION ) PrintException(ctx); if( ctx ) ctx->Release(); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script6, strlen(script6), 0); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "Test_Addon_ScriptArray (1, 1) : Info : Compiling void Test()\n" "Test_Addon_ScriptArray (3, 20) : Error : Initialization lists cannot be used with 'array<int>@'\n" "Test_Addon_ScriptArray (4, 21) : Error : Initialization lists cannot be used with 'int'\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Array object must call default constructor of the script classes engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script7, strlen(script7), 0); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "Test()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Test bool[] on Mac OS X with PPC CPU // Submitted by Edward Rudd const char *script8 = "array<bool> f(10); \n" "for (int i=0; i<10; i++) { \n" " f[i] = false; \n" "} \n" "Assert(f[0] == false); \n" "Assert(f[1] == false); \n" "f[0] = true; \n" "Assert(f[0] == true); \n" "Assert(f[1] == false); \n"; r = ExecuteString(engine, script8, mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Test reserve() { const char *script = "array<int> f; \n" "f.reserve(10); \n" "for( uint n = 0; n < 10; n++ ) \n" " f.insertAt(n, n); \n" "Assert( f.length() == 10 ); \n"; r = ExecuteString(engine, script, mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; } // Make sure it is possible to do multiple assignments with the array type r = ExecuteString(engine, "array<int> a, b, c; a = b = c;"); if( r < 0 ) TEST_FAILED; // Must support syntax as: array<array<int>>, i.e. without white space between the closing angled brackets. r = ExecuteString(engine, "array<array<int>> a(2); Assert( a.length() == 2 );"); if( r < 0 ) TEST_FAILED; // Must support arrays of handles r = ExecuteString(engine, "array<array<int>@> a(1); @a[0] = @array<int>(4);"); if( r < 0 ) TEST_FAILED; // Do not allow the instantiation of a template with a subtype that cannot be created bout.buffer = ""; engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); engine->RegisterObjectType("single", 0, asOBJ_REF | asOBJ_NOHANDLE); r = ExecuteString(engine, "array<single> a;"); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 7) : Error : Can't instanciate template 'array' with subtype 'single'\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Test too large arrays { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptArray(engine, false); ctx = engine->CreateContext(); r = ExecuteString(engine, "array<int> a; a.resize(0xFFFFFFFF);", 0, ctx); if( r != asEXECUTION_EXCEPTION ) TEST_FAILED; else if( strcmp(ctx->GetExceptionString(), "Too large array size") != 0 ) TEST_FAILED; r = ExecuteString(engine, "array<int> a(0xFFFFFFFF);", 0, ctx); if( r != asEXECUTION_EXCEPTION ) TEST_FAILED; else if( strcmp(ctx->GetExceptionString(), "Too large array size") != 0 ) TEST_FAILED; r = ExecuteString(engine, "array<int> list;\n" "list.resize(3);\n" "list.reserve(-1);\n", 0, ctx); if( r != asEXECUTION_EXCEPTION ) TEST_FAILED; else if( strcmp(ctx->GetExceptionString(), "Too large array size") != 0 ) TEST_FAILED; ctx->Release(); engine->Release(); } // Test garbage collect with script class that holds array member { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptArray(engine, false); asIScriptModule *mod = engine->GetModule("module", asGM_ALWAYS_CREATE); const char *script = "class MyTest \n" "{ \n" " array<int> myList; \n" "} \n"; mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; asIScriptObject *obj = (asIScriptObject*)engine->CreateScriptObject(mod->GetObjectTypeByName("MyTest")); obj->Release(); engine->Release(); } // Test the default value constructor { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, false); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule("module", asGM_ALWAYS_CREATE); engine->SetEngineProperty(asEP_OPTIMIZE_BYTECODE, false); const char *script = "void main() \n" "{ \n" " array<int> arr(2, 42); \n" " assert(arr[0] == 42); \n" " assert(arr[1] == 42); \n" " array<array<int>> arr2(2, array<int>(2)); \n" " assert(arr2[0].length() == 2); \n" " assert(arr2[1].length() == 2); \n" " array<array<int>@> arr3(2, arr); \n" " assert(arr3[0] is arr); \n" " assert(arr3[1] is arr); \n" "} \n"; mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test potential memory leak situation with circular reference between types { // Create the script engine asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); // Register array class RegisterScriptArray(engine, false); // Compile asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", "class Hoge" "{" " HogeManager@ hogeManager;" "};" "class HogeManager" "{" " array< Hoge >@ hoges;" "};" , 0); mod->Build(); // Release engine engine->Release(); } // Test creating script array from application { if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { printf("Subtest: Skipped due to AS_MAX_PORTABILITY\n"); } else { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptArray(engine, false); RegisterScriptString(engine); r = engine->RegisterGlobalFunction("array<string@>@ CreateArrayOfStrings()", asFUNCTION(CreateArrayOfStrings), asCALL_CDECL); assert( r >= 0 ); r = ExecuteString(engine, "array<string@>@ arr = CreateArrayOfStrings()"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Release engine engine->Release(); } } // Test insertAt, removeAt { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptArray(engine, false); RegisterScriptString(engine); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); r = ExecuteString(engine, "array<string> arr = {'1','2','3'}; \n" "arr.insertAt(1, 'test'); \n" "assert( arr[1] == 'test' );\n" "arr.insertAt(4, '4'); \n" "assert( arr[4] == '4' );\n" "arr.removeAt(0); \n" "assert( arr[0] == 'test' );\n" "assert( arr[3] == '4' );\n"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // This test was failing on XBOX 360 { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); const char *script = "class ArrayOf \n" "{ \n" " uint8[] _boolList; \n" " int _numOfStockedObject; \n" " ArrayOf(int arraySizeMax) \n" " { \n" " _boolList.resize(arraySizeMax); \n" " _numOfStockedObject = 0; \n" " for(int i = 0; i < arraySizeMax; ++i) \n" " { \n" " _boolList[i] = 0; \n" " } \n" " } \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "ArrayOf(100)", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Array should call subtypes' opAssign when it exists { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "int calls = 0; \n" "class Value \n" "{ \n" " int val; \n" " Value(int v) {val = v;} \n" " Value() {} \n" " Value &opAssign(const Value &in o) { calls++; return this; } \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "array<Value> arr = {Value(2), Value(3), Value(0)}; \n" "assert( calls == 0 ); \n" "array<Value> arr2; \n" "arr2 = arr; \n" "assert( calls == 3 ); \n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // test sorting { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "class Value \n" "{ \n" " int val; \n" " Value(int v) {val = v;} \n" " Value() {} \n" " int opCmp(const Value &in o) {return val - o.val;} \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "Value[] arr = {Value(2), Value(3), Value(0)}; \n" "arr.sortAsc(); \n" "assert(arr[0].val == 0); \n" "assert(arr[1].val == 2); \n" "assert(arr[2].val == 3);", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "bool TestSort() \n" "{ \n" " array<int> A = {1, 5, 2, 4, 3}; \n" " array<int> B = {1, 5, 2, 4, 3}; \n" " A.sortAsc(); \n" " B.sortDesc(); \n" " return \n" " A[0] == 1 && A[1] == 2 && A[2] == 3 && A[3] == 4 && A[4] == 5 && \n" " B[0] == 5 && B[1] == 4 && B[2] == 3 && B[3] == 2 && B[4] == 1; \n" "} \n" "bool TestReverse() \n" "{ \n" " array<int> A = {5, 4, 3, 2, 1}; \n" " A.reverse(); \n" " return A[0] == 1 && A[1] == 2 && A[2] == 3 && A[3] == 4 && A[4] == 5; \n" "} \n" "class cOpCmp \n" "{ \n" " cOpCmp() \n" " { \n" " a = 0; \n" " b = 0.0; \n" " } \n" " cOpCmp(int _a, float _b) \n" " { \n" " a = _a; \n" " b = _b; \n" " } \n" " void set(int _a, float _b) \n" " { \n" " a = _a; \n" " b = _b; \n" " } \n" " int opCmp(cOpCmp &in other) \n" " { \n" " return a - other.a; \n" " } \n" " int a; \n" " float b; \n" "} \n" "class cOpEquals \n" "{ \n" " cOpEquals() \n" " { \n" " a = 0; \n" " b = 0.0; \n" " } \n" " cOpEquals(int _a, float _b) \n" " { \n" " a = _a; \n" " b = _b; \n" " } \n" " void set(int _a, float _b) \n" " { \n" " a = _a; \n" " b = _b; \n" " } \n" " bool opEquals(cOpEquals &in other) \n" " { \n" " return a == other.a; \n" " } \n" " int a; \n" " float b; \n" "} \n" "bool TestFind() \n" "{ \n" " array<int> A = {5, 8, 3, 2, 0, 0, 2, 1}; \n" " if (A.find(10) != -1) \n" " return false; \n" " if (A.find(0) != 4) \n" " return false; \n" " if (A.find(1, 8) != 1) \n" " return false; \n" " if (A.find(2, 8) != -1) \n" " return false; \n" " array<cOpCmp> CMP(5); \n" " CMP[0].set(0, 0.0); \n" " CMP[1].set(1, 0.0); \n" " CMP[2].set(2, 0.0); \n" " CMP[3].set(3, 0.0); \n" " CMP[4].set(4, 0.0); \n" " if (CMP.find(cOpCmp(5, 0.0)) != -1) \n" " return false; \n" " if (CMP.find(2, cOpCmp(2, 1.0)) != 2) \n" " return false; \n" " if (CMP.find(3, cOpCmp(2, 1.0)) != -1) \n" " return false; \n" " array<cOpEquals> EQ(5); \n" " EQ[0].set(0, 0.0); \n" " EQ[1].set(1, 0.0); \n" " EQ[2].set(2, 0.0); \n" " EQ[3].set(3, 0.0); \n" " EQ[4].set(4, 0.0); \n" " if (EQ.find(cOpEquals(5, 0.0)) != -1) \n" " return false; \n" " if (EQ.find(2, cOpEquals(2, 1.0)) != 2) \n" " return false; \n" " if (EQ.find(3, cOpEquals(2, 1.0)) != -1) \n" " return false; \n" " return true; \n" "} \n" "int main() \n" "{ \n" " assert( TestSort() ); \n" " assert( TestReverse() ); \n" " assert( TestFind() ); \n" " return 789; \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "assert( main() == 789 ); \n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test array, with objects that don't have default constructor/factory { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "class CTest \n" "{ \n" " CTest(int v) {} \n" // With an explicit non-default constructor the compiler won't create the default constructor "} \n" "array<CTest> arr; \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); bout.buffer = ""; r = mod->Build(); if( r > 0 ) TEST_FAILED; if( bout.buffer != "script (5, 7) : Error : Can't instanciate template 'array' with subtype 'CTest'\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, true); const char *script = "class T { }; \n" "array<T> arr; \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); bout.buffer = ""; r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "array<T> arr(1); \n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test problem with arrays of enums reported by Philip Bennefall { const char *script = "enum fruit \n" "{ \n" " APPLE, ORANGE, BANANA \n" "} \n" "void main() \n" "{ \n" " fruit[] basket; \n" " basket.insertLast(APPLE); \n" " basket.insertLast(ORANGE); \n" " basket.sortDesc(); \n" " int index = basket.find(APPLE); \n" " assert( index == 1 ); \n" "} \n"; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); bout.buffer = ""; r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test problem with arrays and opEquals reported by Philip Bennefall { const char *script = "class fish \n" "{ \n" " bool opEquals(fish@ other) \n" // handles should be supported too " { \n" " return false; \n" " } \n" "} \n" "void main() \n" "{ \n" " fish[] ocean(100); \n" " fish nemo; \n" " int index = ocean.find(nemo); \n" "} \n"; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, true); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); bout.buffer = ""; r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test problem with arrays and opEquals reported by Philip Bennefall { const char *script = "class fish \n" "{ \n" " bool opEquals(fish@ other) \n" " { \n" " return false; \n" " } \n" "} \n" "void main() \n" "{ \n" " fish@[] ocean(100); \n" " for(uint i=0; i<ocean.length(); i++) \n" " { \n" " fish fred; \n" " @(ocean[i]) = fred; \n" " } \n" " fish nemo; \n" " int index = ocean.find(nemo); \n" "} \n"; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, true); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); bout.buffer = ""; r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test problem with arrays and opAssign reported by Philip Bennefall { const char *script = "array<uint> a, b = {0,1,2,3}; \n" "a.reserve(10); \n" "a = b; \n" "assert( a.length() == b.length() ); \n" "assert( a.length() == 4 ); \n" "for( uint n = 0; n < a.length(); n++ ) \n" " assert( a[n] == n ); \n"; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); r = ExecuteString(engine, script); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test findByRef { const char *script = "class Obj {} \n" "array<int> ia = {1,2,3}; \n" "array<Obj> oa = {Obj(), Obj()}; \n" "array<Obj@> ha = {Obj(), Obj()}; \n"; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "assert( ia.findByRef(ia[1]) == -1 ); \n" "Obj @obj = oa[1]; assert( oa.findByRef(obj) == 1 ); \n" "@obj = ha[1]; assert( ha.findByRef(obj) == 1 ); \n" "ha.insertLast(null); assert( ha.findByRef(null) == 2 ); \n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Success return fail; }
void RegisterScriptFunction(asCScriptEngine *engine) { // Register the gc behaviours for the script functions int r = 0; UNUSED_VAR(r); // It is only used in debug mode engine->functionBehaviours.engine = engine; engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC | asOBJ_SCRIPT_FUNCTION; engine->functionBehaviours.name = "_builtin_function_"; #ifndef AS_MAX_PORTABILITY r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptFunction,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptFunction,Release), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCScriptFunction,GetRefCount), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCScriptFunction,SetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptFunction,GetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptFunction,EnumReferences), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptFunction,ReleaseAllHandles), asCALL_THISCALL, 0); asASSERT( r >= 0 ); // TODO: 2.29.0: Need some way to allow the arg type to adapt when the funcdefs are instanciated // r = engine->RegisterMethodToObjectType(&engine->functionBehaviours, "bool opEquals(const int &in)", asMETHOD(asCScriptFunction,operator==), asCALL_THISCALL); asASSERT( r >= 0 ); #else r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptFunction_AddRef_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptFunction_Release_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptFunction_GetRefCount_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptFunction_SetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptFunction_GetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptFunction_EnumReferences_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptFunction_ReleaseAllHandles_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); // r = engine->RegisterMethodToObjectType(&engine->functionBehaviours, "bool opEquals(const int &in)", asFUNCTION(ScriptFunction_opEquals_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); #endif // Register the builtin function for creating delegates // This function returns a handle to the delegate, but since the type is not known at this time it is // registered to return a void then the return type is changed manually to the builtin function type // The name of the function is an invalid identifier so it cannot be invoked accidentally from the script #ifndef AS_MAX_PORTABILITY r = engine->RegisterGlobalFunction("void f(int &in, int &in)", asFUNCTION(CreateDelegate), asCALL_CDECL); asASSERT( r >= 0 ); #else r = engine->RegisterGlobalFunction("void f(int &in, int &in)", asFUNCTION(ScriptFunction_CreateDelegate_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); #endif // Rename the function so that it cannot be called manually by the script int idx = engine->registeredGlobalFuncs.GetIndex(engine->scriptFunctions[r]); engine->registeredGlobalFuncs.Erase(idx); engine->scriptFunctions[r]->name = DELEGATE_FACTORY; engine->registeredGlobalFuncs.Put(engine->scriptFunctions[r]); // Change the return type so the VM will know the function really returns a handle engine->scriptFunctions[r]->returnType = asCDataType::CreateObject(&engine->functionBehaviours, false); engine->scriptFunctions[r]->returnType.MakeHandle(true); }
bool Test() { if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { // Skipping this due to not supporting native calling conventions printf("Skipped due to AS_MAX_PORTABILITY\n"); return false; } bool fail = false; int r; int suspendId, exceptionId; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->RegisterObjectType("Object", sizeof(CObject), asOBJ_VALUE | asOBJ_APP_CLASS_CD); r = engine->RegisterObjectType("RefObj", sizeof(CRefObject), asOBJ_REF); assert(r >= 0); if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Construct2), asCALL_GENERIC); engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct_gen), asCALL_GENERIC); engine->RegisterObjectBehaviour("Object", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destruct_gen), asCALL_GENERIC); engine->RegisterObjectMethod("Object", "Object &opAssign(const Object &in)", asFUNCTION(Assign_gen), asCALL_GENERIC); r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_FACTORY, "RefObj@ f()", asFUNCTION(RefObjFactory_gen), asCALL_GENERIC); assert(r >= 0); r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_ADDREF, "void f()", asFUNCTION(AddRef_gen), asCALL_GENERIC); assert(r >= 0); r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_RELEASE, "void f()", asFUNCTION(Release_gen), asCALL_GENERIC); assert(r >= 0); engine->RegisterGlobalFunction("void RaiseException()", asFUNCTION(RaiseException), asCALL_GENERIC); suspendId = engine->RegisterGlobalFunction("Object SuspendObj()", asFUNCTION(SuspendObj_gen), asCALL_GENERIC); exceptionId = engine->RegisterGlobalFunction("Object ExceptionObj()", asFUNCTION(ExceptionObj_gen), asCALL_GENERIC); engine->RegisterGlobalFunction("RefObj@ ExceptionHandle()", asFUNCTION(ExceptionHandle_gen), asCALL_GENERIC); } else { engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(Construct2), asCALL_GENERIC); engine->RegisterObjectBehaviour("Object", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Construct), asCALL_CDECL_OBJLAST); engine->RegisterObjectBehaviour("Object", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Destruct), asCALL_CDECL_OBJLAST); engine->RegisterObjectMethod("Object", "Object &opAssign(const Object &in)", asFUNCTION(Assign_gen), asCALL_GENERIC); r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_FACTORY, "RefObj@ f()", asFUNCTION(RefObjFactory), asCALL_CDECL); assert(r >= 0); r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_ADDREF, "void f()", asMETHOD(CRefObject, AddRef), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectBehaviour("RefObj", asBEHAVE_RELEASE, "void f()", asMETHOD(CRefObject, Release), asCALL_THISCALL); assert(r >= 0); engine->RegisterGlobalFunction("void RaiseException()", asFUNCTION(RaiseException), asCALL_CDECL); suspendId = engine->RegisterGlobalFunction("Object SuspendObj()", asFUNCTION(SuspendObj), asCALL_CDECL); exceptionId = engine->RegisterGlobalFunction("Object ExceptionObj()", asFUNCTION(ExceptionObj), asCALL_CDECL); engine->RegisterGlobalFunction("RefObj@ ExceptionHandle()", asFUNCTION(ExceptionHandle), asCALL_CDECL); } COutStream out; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0); mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("%s: Failed to compile the script\n", TESTNAME); } // The object has been initialized r = ExecuteString(engine, "Test1()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // The object has not yet been initialized r = ExecuteString(engine, "Test2()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // An object has been initialized and passed by value to function that throws exception r = ExecuteString(engine, "Test3()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // An object has been initialized and passed by value to a function, but // the function cannot be called due to the stack being full engine->SetEngineProperty(asEP_MAX_STACK_SIZE, 4); r = ExecuteString(engine, "Test3()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // An object is allocated and initialized with a call to // a function that returns an object by value. The function // suspends the thread. The context is then aborted. asIScriptContext *ctx = engine->CreateContext(); engine->SetEngineProperty(asEP_MAX_STACK_SIZE, 0); r = ExecuteString(engine, "Test4()", mod, ctx); if( r != asEXECUTION_SUSPENDED ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } ctx->Abort(); ctx->Release(); // An object is allocated and initialized with a call to // a function that returns an object by value. The function // sets a script exception. r = ExecuteString(engine, "Test5()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // The object constructor sets the exception r = ExecuteString(engine, "Test6()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // A function that is supposed to return a handle sets an exception r = ExecuteString(engine, "Test7()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // Attempt to call method on null class pointer mod->AddScriptSection("script", script3, strlen(script3)); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "calc()", mod); if( r != asEXECUTION_EXCEPTION ) { printf("%s: Failed\n", TESTNAME); TEST_FAILED; } // Exception happens after value object has already been destroyed r = ExecuteString(engine, "{\n" " Object o;\n" "}\n" "RaiseException();"); if( r != asEXECUTION_EXCEPTION ) TEST_FAILED; // Exception happens after the value object has been destroyed and, // the same position would also be used again after the exception r = ExecuteString(engine, "{ Object o; } \n" "RaiseException(); \n" "Object o; \n"); if( r != asEXECUTION_EXCEPTION ) TEST_FAILED; // The code has two places where the object is destroyed, one in the if case, and // and one at the end of the function. If the code doesn't go in to the if case, // and the exception happens afterwards, the exception handler must not think the // object was already destroyed. r = ExecuteString(engine, "Object o; bool a = false; \n" "if( a ) return; \n" "RaiseException(); \n"); if( r != asEXECUTION_EXCEPTION ) TEST_FAILED; // Calling a function that returns an object directly must release the object upon releasing the context ctx = engine->CreateContext(); ctx->Prepare(suspendId); ctx->Execute(); ctx->Release(); // Calling a function that returns an object but raised an exception shouldn't try to destroy the object ctx = engine->CreateContext(); ctx->Prepare(exceptionId); ctx->Execute(); ctx->Release(); engine->Release(); // Success return fail; }
bool TestCDecl_ClassA() { if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { printf("%s: Skipped due to AS_MAX_PORTABILITY\n", TESTNAME); return false; } bool fail = false; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->RegisterObjectType("class1", sizeof(ClassA1), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_A | asOBJ_APP_CLASS_ALLINTS); engine->RegisterObjectType("class2", sizeof(ClassA2), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_A | asOBJ_APP_CLASS_ALLINTS); engine->RegisterObjectType("class3", sizeof(ClassA3), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS_A | asOBJ_APP_CLASS_ALLINTS); engine->RegisterGlobalProperty("class1 c1", &c1); engine->RegisterGlobalProperty("class2 c2", &c2); engine->RegisterGlobalProperty("class3 c3", &c3); engine->RegisterGlobalFunction("class1 _class1()", asFUNCTION(classA1), asCALL_CDECL); engine->RegisterGlobalFunction("class2 _class2()", asFUNCTION(classA2), asCALL_CDECL); engine->RegisterGlobalFunction("class3 _class3()", asFUNCTION(classA3), asCALL_CDECL); COutStream out; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); c1.a = 0; int r = ExecuteString(engine, "c1 = _class1();"); if( r < 0 ) { printf("%s: ExecuteString() failed %d\n", TESTNAME, r); TEST_FAILED; } if( c1.a != 0xDEADC0DE ) { printf("%s: Failed to assign object returned from function. c1.a = %X\n", TESTNAME, (unsigned int)c1.a); TEST_FAILED; } c2.a = 0; c2.b = 0; r = ExecuteString(engine, "c2 = _class2();"); if( r < 0 ) { printf("%s: ExecuteString() failed %d\n", TESTNAME, r); TEST_FAILED; } if( c2.a != 0xDEADC0DE ) { printf("%s: Failed to assign object returned from function. c2.a = %X\n", TESTNAME, (unsigned int)c2.a); TEST_FAILED; } if( c2.b != 0x01234567 ) { printf("%s: Failed to assign object returned from function. c2.b = %X\n", TESTNAME, (unsigned int)c2.b); TEST_FAILED; } c3.a = 0; c3.b = 0; c3.c = 0; r = ExecuteString(engine, "c3 = _class3();"); if( r < 0 ) { printf("%s: ExecuteString() failed %d\n", TESTNAME, r); TEST_FAILED; } if( c3.a != 0xDEADC0DE ) { printf("%s: Failed to assign object returned from function. c3.a = %X\n", TESTNAME, (unsigned int)c3.a); TEST_FAILED; } if( c3.b != 0x01234567 ) { printf("%s: Failed to assign object returned from function. c3.b = %X\n", TESTNAME, (unsigned int)c3.b); TEST_FAILED; } if( c3.c != 0x89ABCDEF ) { printf("%s: Failed to assign object returned from function. c3.c = %X\n", TESTNAME, (unsigned int)c3.c); TEST_FAILED; } // Test passing the object types by value to a system function r = engine->RegisterGlobalFunction("void class1ByVal(class1)", asFUNCTION(class1ByVal), asCALL_CDECL); assert( r >= 0 ); r = ExecuteString(engine, "class1 c = _class1(); class1ByVal(c)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = engine->RegisterGlobalFunction("void class2ByVal(class2)", asFUNCTION(class2ByVal), asCALL_CDECL); assert( r >= 0 ); r = ExecuteString(engine, "class2 c = _class2(); class2ByVal(c)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = engine->RegisterGlobalFunction("void class3ByVal(class3)", asFUNCTION(class3ByVal), asCALL_CDECL); assert( r >= 0 ); r = ExecuteString(engine, "class3 c = _class3(); class3ByVal(c)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); return fail; }
static bool TestEnum() { RET_ON_MAX_PORT asIScriptEngine *engine; CBufferedOutStream bout; int r; bool fail = false; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); r = engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); // Register the enum value r = engine->RegisterEnum("TEST_ENUM"); assert(r >= 0); r = engine->RegisterEnumValue("TEST_ENUM", "ENUM1", ENUM1); assert(r >= 0); r = engine->RegisterEnumValue("TEST_ENUM", "ENUM2", ENUM2); assert(r >= 0); r = engine->RegisterEnumValue("TEST_ENUM", "ENUM3", ENUM3); assert(r >= 0); r = engine->RegisterGlobalFunction("void funce(TEST_ENUM)", asFUNCTION(func), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterGlobalFunction("void output(int val1)", asFUNCTION(scriptOutput), asCALL_CDECL); assert(r >= 0); // Test calling generic function with enum value r = ExecuteString(engine, "funce(ENUM1);"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = ExecuteString(engine, "funce(TEST_ENUM::ENUM3);"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Test using the registered enum values r = ExecuteString(engine, "output(ENUM1); output(ENUM2)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "1\n10\n" ) TEST_FAILED; // Test script that declare an enum // enum value can be given as expression of constants // enum can be implicitly cast to number buffer = ""; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); r = mod->AddScriptSection(NULL, script, strlen(script), 0); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "Test1()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "-1\n1\n2\n1200\n1201\n1202\n1203\n1205\n0\n1\n2\n" ) { TEST_FAILED; PRINTF("%s", buffer.c_str()); } // Registered enums are literal constants // variable of enum type can be implictly cast to primitive buffer = ""; r = ExecuteString(engine, "TEST_ENUM e = ENUM1; switch( e ) { case ENUM1: output(e); }"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "1\n" ) TEST_FAILED; // Script declared enums behave the same buffer = ""; r = ExecuteString(engine, "TEST2_ENUM e = TEST_1; switch( e ) {case TEST_1: output(e); }", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "-1\n" ) TEST_FAILED; // Different enum types can declare the same enum value mod->AddScriptSection(NULL, "enum ENUMA { VALUE = 1 } \n" "enum ENUMB { VALUE = 2 } \n" "enum ENUMC { VAL = 3 } \n" "int a = VALUE; \n" // fails with ambiguity "int b = ENUMA::VALUE; \n" // ok "int c = ENUMB::VALUE; \n" // ok "ENUMC d = VALUE; \n"); // fails with ambiguity bout.buffer = ""; r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != " (4, 5) : Info : Compiling int a\n" " (4, 9) : Error : Found multiple matching enum values\n" " (7, 7) : Info : Compiling ENUMC d\n" " (7, 11) : Error : Found multiple matching enum values\n" " (7, 11) : Error : Can't implicitly convert from 'int' to 'ENUMC&'.\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Automatically resolving ambiguous enums if possible bout.buffer = ""; mod->AddScriptSection(NULL, "enum ENUMA { VALUE = 1 } \n" "enum ENUMB { VALUE = 2 } \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "ENUMA a = VALUE; assert( a == 1 );\n" "ENUMB b = VALUE; assert( b == 2 );\n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( bout.buffer != "" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // enum values can't be declared with expressions including subsequent values bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); const char *script2 = "enum TEST_ERR { ERR1 = ERR2, ERR2 }"; mod = engine->GetModule("error", asGM_ALWAYS_CREATE); r = mod->AddScriptSection("error", script2, strlen(script2)); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "error (1, 17) : Info : Compiling TEST_ERR ERR1\n" "error (1, 24) : Error : 'ERR2' is not declared\n" "error (1, 30) : Info : Compiling TEST_ERR ERR2\n" "error (1, 30) : Error : Use of uninitialized global variable 'ERR1'.\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // enum type name can't be overloaded with variable name in another scope bout.buffer = ""; r = ExecuteString(engine, "int TEST_ENUM = 999"); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 5) : Error : Illegal variable name 'TEST_ENUM'.\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); // enum value name can be overloaded with variable name in another scope buffer = ""; r = ExecuteString(engine, "int ENUM1 = 999; output(ENUM1)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "999\n" ) TEST_FAILED; // number cannot be implicitly cast to enum type bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); r = ExecuteString(engine, "TEST_ENUM val = 1"); if( r >= 0 ) TEST_FAILED; r = ExecuteString(engine, "float f = 1.2f; TEST_ENUM val = f"); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 17) : Error : Can't implicitly convert from 'int' to 'TEST_ENUM'.\n" "ExecuteString (1, 33) : Error : Can't implicitly convert from 'float' to 'TEST_ENUM'.\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); // constant number can be explicitly cast to enum type r = ExecuteString(engine, "TEST_ENUM val = TEST_ENUM(1)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // primitive value can be explicitly cast to enum type r = ExecuteString(engine, "float f = 1.2f; TEST_ENUM val = TEST_ENUM(f)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // math operator with enums buffer = ""; r = ExecuteString(engine, "int a = ENUM2 * 10; output(a); output(ENUM2 + ENUM1)"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "100\n11\n" ) TEST_FAILED; // comparison operator with enums buffer = ""; r = ExecuteString(engine, "if( ENUM2 > ENUM1 ) output(1);"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "1\n" ) TEST_FAILED; // bitwise operators with enums buffer = ""; r = ExecuteString(engine, "output( ENUM2 << ENUM1 )"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "20\n" ) TEST_FAILED; // circular reference between enum and global variable are // allowed if they can be resolved const char *script3 = "enum TEST_EN \n" "{ \n" " EN1, \n" " EN2 = gvar, \n" " EN3, \n" "} \n" "const int gvar = EN1 + 10; \n"; mod = engine->GetModule("en", asGM_ALWAYS_CREATE); mod->AddScriptSection("en", script3, strlen(script3)); r = mod->Build(); if( r < 0 ) TEST_FAILED; buffer = ""; r = ExecuteString(engine, "output(EN2); output(EN3)", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "10\n11\n" ) TEST_FAILED; // functions can be overloaded for parameters with enum type const char *script4 = "void func(TEST_ENUM) { output(1); } \n" "void func(int) { output(2); } \n"; mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script4, strlen(script4)); r = mod->Build(); if( r < 0 ) TEST_FAILED; buffer = ""; r = ExecuteString(engine, "func(1); func(1.0f); TEST_ENUM e = ENUM1; func(e)", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "2\n2\n1\n" ) TEST_FAILED; // Using registered enum type in a script engine->RegisterEnum("game_type_t"); const char *script5 = "game_type_t random_game_type;\n" "void foo(game_type_t game_type)\n" "{\n" " random_game_type = game_type;\n" "};\n"; r = mod->AddScriptSection("script", script5, strlen(script5)); r = mod->Build(); if( r < 0 ) TEST_FAILED; // enum with assignment without comma const char *script6 = "enum test_wo_comma { value = 0 }"; r = mod->AddScriptSection("script", script6, strlen(script6)); r = mod->Build(); if( r < 0 ) TEST_FAILED; // Enums are not object types int eid; const char *ename = mod->GetEnumByIndex(0, &eid); if( eid < 0 || ename == 0 ) TEST_FAILED; asIObjectType *eot = engine->GetObjectTypeById(eid); if( eot ) TEST_FAILED; // enum must allow negate and binary complement operators bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); r = ExecuteString(engine, "int a = -ENUM1; int b = ~ENUM1;"); if( r < 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 25) : Warning : Implicit conversion changed sign of value\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Test specifying an unknown enum type name bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); const char *script7 = "void f() { funce(UNKNOWN_ENUM::ENUM1); }"; mod = engine->GetModule("error", asGM_ALWAYS_CREATE); r = mod->AddScriptSection("error", script7, strlen(script7)); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "error (1, 1) : Info : Compiling void f()\n" "error (1, 18) : Error : Unknown scope 'UNKNOWN_ENUM'\n") { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Test specifying a non enum type name before the scope bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); const char *script8 = "class SomeClass\n" "{\n" " int SOMEVALUE;\n" "}\n" "void f() { funce(SomeClass::SOMEVALUE); }"; mod = engine->GetModule("error", asGM_ALWAYS_CREATE); r = mod->AddScriptSection("error", script8, strlen(script8)); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "error (5, 1) : Info : Compiling void f()\n" "error (5, 18) : Error : 'SomeClass::SOMEVALUE' is not declared\n") { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } // Test engine property r = engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, 1); if( r != 0 ) TEST_FAILED; bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); const char *script9 = "void f() { funce(ENUM1); }"; mod = engine->GetModule("error", asGM_ALWAYS_CREATE); r = mod->AddScriptSection("error", script9, strlen(script9)); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "error (1, 1) : Info : Compiling void f()\n" "error (1, 18) : Error : 'ENUM1' is not declared\n") { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } buffer = ""; r = ExecuteString(engine, "output(TEST_ENUM::ENUM1);"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "1\n" ) TEST_FAILED; // Test enum in param to class method assert( sizeof(TEST_ENUM) == 4 ); r = engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, 0); r = engine->RegisterObjectType("Obj", 0, asOBJ_REF | asOBJ_NOHANDLE); assert( r >= 0 ); r = engine->RegisterObjectMethod("Obj", "bool TestEnum(TEST_ENUM)", asMETHOD(CTestObject, TestEnum), asCALL_THISCALL); assert( r >= 0 ); CTestObject obj; obj.val = ENUM1; r = engine->RegisterGlobalProperty("Obj obj", &obj); assert( r >= 0 ); bout.buffer = ""; r = ExecuteString(engine, "if( !obj.TestEnum(ENUM2) ) assert(false); "); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( bout.buffer != "" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } if( obj.val != ENUM2 ) TEST_FAILED; // Repeated enum values would enter an infinit loop bout.buffer = ""; const char *script10 = "enum Infinite { inf, inf }"; mod->AddScriptSection("test", script10); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "test (1, 22) : Error : Name conflict. 'inf' is already used.\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); { COutStream out; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterStdString(engine); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", "enum waveformType \n" "{ \n" " sawtoothWave = 1, \n" " squareWave = 2, \n" " sineWave = 3 \n" "} \n" "void main() \n" "{ \n" " tone_synth synth; \n" " synth.waveform_type = sineWave; \n" " assert( '' + sineWave + '' == '3' ); \n" " assert( synth.waveform_type == 3 ); \n" "} \n" "class tone_synth { void set_waveform_type(double v) {prop = v;} double get_waveform_type() {return prop;} double prop; }\n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } //paste at the end of TestEnum() { COutStream out; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, 1); assert(r >= 0); r = engine->RegisterEnum("RENUM_1"); assert(r >= 0); r = engine->RegisterEnumValue("RENUM_1", "R_GLOBAL", 0); assert(r >= 0); r = engine->RegisterEnumValue("RENUM_1", "RE1_1", 1); assert(r >= 0); r = engine->RegisterEnumValue("RENUM_1", "RE1_2", 2); assert(r >= 0); r = engine->RegisterEnum("RENUM_2"); assert(r >= 0); r = engine->RegisterEnumValue("RENUM_2", "R_GLOBAL", 13); assert(r >= 0); r = engine->RegisterEnumValue("RENUM_2", "RE2_1", 1); assert(r >= 0); r = engine->RegisterEnumValue("RENUM_2", "RE2_2", 2); assert(r >= 0); r = engine->RegisterGlobalFunction("void output(int val1)", asFUNCTION(scriptOutput), asCALL_CDECL); assert(r >= 0); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", "enum ENUM_1 \n" "{ \n" " TEST_GLOBAL = 0, \n" " E1_VAL1, \n" " E1_VAL2, \n" " RE1_2 \n" "} \n" "enum ENUM_2 \n" "{ \n" " TEST_GLOBAL = 0, \n" " E2_VAL1, \n" " E2_VAL2 \n" "} \n" "ENUM_1 g_e1 = ENUM_1::E1_VAL1; \n" "RENUM_1 rg_e1 = RENUM_1::RE1_2; \n" " \n" "void main() \n" "{ \n" " ENUM_1 l_e1 = ENUM_1::E1_VAL1; \n" " g_e1 = ENUM_1::E1_VAL1; \n" " rg_e1 = RENUM_1::R_GLOBAL; \n" " RENUM_2 rl_e2 = RENUM_2::R_GLOBAL; \n" " output(rg_e1); \n" " output(rl_e2); \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; buffer = ""; r = ExecuteString(engine, "main();", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( buffer != "0\n13\n" ) TEST_FAILED; engine->Release(); } // Some validations that must be done { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); r = engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, 1); assert(r >= 0); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", "enum ENUM_1 \n" "{ \n" " E1_VAL1 \n" "}; \n" // Semi colon after enum declaration is allowed, but optional "ENUM_1 g_e1 = ENUM_1::E1_VAL1; \n" "ENUM_1 g_e2 = E2_VAL1; \n"); // <- that shouldn't (?) r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "script (6, 8) : Info : Compiling ENUM_1 g_e2\n" "script (6, 15) : Error : 'E2_VAL1' is not declared\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } r = engine->RegisterEnum("RENUM_1"); assert(r >= 0); r = engine->RegisterEnumValue("RENUM_1", "@#$%", 777); // shouldn't work if( r >= 0 ) TEST_FAILED; engine->Release(); } // Test problem reported by Andrew Ackermann // The code crashed in ALLOC as the enum was copied as 8bytes on 64bit platforms { const char *script = "enum TestEnum { \n" " TE_0, \n" " TE_1, \n" "}; \n" "class TestClass { \n" " TestClass(TestEnum en) { \n" " } \n" "}; \n" "void init() { \n" " TestClass@ cl = TestClass(TE_1); \n" "} \n"; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "init()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test problem reported by SadSingleton // http://www.gamedev.net/topic/622524-crash-using-the-identity-operator-with-enum-values/ { const char *script = "enum MyEnum { MyEnumValue = 1 } \n" "void Update() \n" "{ \n" " MyEnum enumValue = MyEnumValue; \n" " bool condition = true; \n" " if (condition) \n" " { \n" " if(enumValue is MyEnumValue) \n" " { \n" " int i = 0; \n" " } \n" " } \n" " else \n" " { \n" " int j = 1; \n" " } \n" "} \n"; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "script (2, 1) : Info : Compiling void Update()\n" "script (8, 30) : Error : Both operands must be handles when comparing identity\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // http://www.gamedev.net/topic/624715-bug-in-compiler/ { const char *script = "enum E \n" "{ \n" " VALUE1 = 20somegarbage, \n" " VALUE2 = 30moregarbage \n" "} \n"; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); bout.buffer = ""; r = engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "script (3, 3) : Info : Compiling E VALUE1\n" "script (3, 14) : Error : Unexpected token '<identifier>'\n" "script (4, 3) : Info : Compiling E VALUE2\n" "script (4, 14) : Error : Unexpected token '<identifier>'\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Success return fail; }
void RegisterScriptObject(asCScriptEngine *engine) { // Register the default script class behaviours int r = 0; UNUSED_VAR(r); // It is only used in debug mode engine->scriptTypeBehaviours.engine = engine; engine->scriptTypeBehaviours.flags = asOBJ_SCRIPT_OBJECT | asOBJ_REF | asOBJ_GC; engine->scriptTypeBehaviours.name = "_builtin_object_"; #ifndef AS_MAX_PORTABILITY r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptObject_Construct), asCALL_CDECL_OBJLAST, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptObject,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptObject,Release), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterMethodToObjectType(&engine->scriptTypeBehaviours, "int &opAssign(int &in)", asFUNCTION(ScriptObject_Assignment), asCALL_CDECL_OBJLAST); asASSERT( r >= 0 ); // Weakref behaviours r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GET_WEAKREF_FLAG, "int &f()", asMETHOD(asCScriptObject,GetWeakRefFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 ); // Register GC behaviours r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCScriptObject,GetRefCount), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCScriptObject,SetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptObject,GetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptObject,EnumReferences), asCALL_THISCALL, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptObject,ReleaseAllHandles), asCALL_THISCALL, 0); asASSERT( r >= 0 ); #else r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_CONSTRUCT, "void f(int&in)", asFUNCTION(ScriptObject_Construct_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptObject_AddRef_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptObject_Release_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterMethodToObjectType(&engine->scriptTypeBehaviours, "int &opAssign(int &in)", asFUNCTION(ScriptObject_Assignment_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); // Weakref behaviours r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GET_WEAKREF_FLAG, "int &f()", asFUNCTION(ScriptObject_GetWeakRefFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); // Register GC behaviours r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptObject_GetRefCount_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptObject_SetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptObject_GetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptObject_EnumReferences_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->scriptTypeBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptObject_ReleaseAllHandles_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 ); #endif }
bool Test() { bool fail = false; int r; CBufferedOutStream bout; asIScriptContext *ctx; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); ctx = engine->CreateContext(); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); // Compile a single function asIScriptFunction *func = 0; r = mod->CompileFunction("My func", "void func() {}", 0, 0, &func); if( r < 0 ) TEST_FAILED; // Execute the function r = ctx->Prepare(func->GetId()); if( r < 0 ) TEST_FAILED; r = ctx->Execute(); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // The function's section name should be correct if( std::string(func->GetScriptSectionName()) != "My func" ) TEST_FAILED; // We must release the function afterwards if( func ) { func->Release(); func = 0; } // It must not be allowed to include more than one function in the code bout.buffer = ""; r = mod->CompileFunction("two funcs", "void func() {} void func2() {}", 0, 0, 0); if( r >= 0 ) TEST_FAILED; r = mod->CompileFunction("no code", "", 0, 0, 0); if( r >= 0 ) TEST_FAILED; r = mod->CompileFunction("var", "int a;", 0, 0, 0); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "two funcs (0, 0) : Error : The code must contain one and only one function\n" "no code (0, 0) : Error : The code must contain one and only one function\n" "var (0, 0) : Error : The code must contain one and only one function\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Compiling without giving the function pointer shouldn't leak memory r = mod->CompileFunction(0, "void func() {}", 0, 0, 0); if( r < 0 ) TEST_FAILED; // If the code is not provided, a proper error should be given r = mod->CompileFunction(0,0,0,0,0); if( r != asINVALID_ARG ) TEST_FAILED; // Don't permit recursive calls, unless the function is added to the module scope // TODO: It may be possible to compile a recursive function even without adding // it to the scope, but the application needs to explicitly allows it bout.buffer = ""; r = mod->CompileFunction(0, "void func() {\n func(); \n}", -1, 0, 0); if( r >= 0 ) TEST_FAILED; if( bout.buffer != " (1, 2) : Error : No matching signatures to 'func()'\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // It should be possible to add the compiled function to the scope of the module if( mod->GetFunctionCount() > 0 ) TEST_FAILED; r = mod->CompileFunction(0, "void func() {}", 0, asCOMP_ADD_TO_MODULE, 0); if( r < 0 ) TEST_FAILED; if( mod->GetFunctionCount() != 1 ) TEST_FAILED; // It should be possible to remove a function from the scope of the module r = mod->RemoveFunction(mod->GetFunctionIdByIndex(0)); if( r < 0 ) TEST_FAILED; if( mod->GetFunctionCount() != 0 ) TEST_FAILED; // Compiling recursive functions that are added to the module is OK r = mod->CompileFunction(0, "void func() {\n func(); \n}", -1, asCOMP_ADD_TO_MODULE, 0); if( r < 0 ) TEST_FAILED; // It should be possible to remove global variables from the scope of the module mod->AddScriptSection(0, "int g_var; void func() { g_var = 1; }"); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( mod->GetGlobalVarCount() != 1 ) TEST_FAILED; r = mod->RemoveGlobalVar(0); if( r < 0 ) TEST_FAILED; if( mod->GetGlobalVarCount() != 0 ) TEST_FAILED; r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // It should be possible to add new variables r = mod->CompileGlobalVar(0, "int g_var;", 0); if( r < 0 ) TEST_FAILED; r = mod->CompileGlobalVar(0, "int g_var2 = g_var;", 0); if( r < 0 ) TEST_FAILED; if( mod->GetGlobalVarCount() != 2 ) TEST_FAILED; // Shouldn't be possible to add function with the same name as a global variable bout.buffer = ""; r = mod->CompileFunction(0, "void g_var() {}", 0, asCOMP_ADD_TO_MODULE, 0); if( r >= 0 ) TEST_FAILED; if( bout.buffer != " (1, 1) : Error : Name conflict. 'g_var' is a global property.\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } if( ctx ) ctx->Release(); engine->Release(); // TODO: Removing a function from the scope of the module shouldn't free it // immediately if it is still used by another function. This is working. // I just need a formal test for regression testing. // TODO: Make sure cyclic references between functions are resolved so we don't get memory leaks // This is working. I just need a formal test for regression testing. // TODO: Do not allow adding functions that already exist in the module // TODO: Maybe we can allow replacing an existing function // TODO: It should be possible to serialize these dynamic functions // TODO: The dynamic functions should also be JIT compiled // TODO: What should happen if a function in the module scope references another function that has // been removed from the scope but is still alive, and then the byte code for the module is saved? // Make sure a circular reference between global variable, class, and class method is properly released engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); mod = engine->GetModule("script", asGM_ALWAYS_CREATE); const char *script = "obj o; class obj { void d() { o.val = 1; } int val; }"; mod->AddScriptSection("script", script); bout.buffer = ""; r = mod->Build(); if( r != 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); // Success return fail; }
bool Test() { bool fail = false; asIScriptEngine *engine; int r; COutStream out; CBufferedOutStream bout; { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "int func() { return var; } \n" "int func2() { return var; } \n" "int var = 0; \n" "class cl { cl() {v = 0;} int v; } \n" "interface i {} \n" "enum e { e1 = 0 } \n" "funcdef void fd(); \n" // Namespaces allow same entities to be declared again "namespace a { \n" " int func() { return var; } \n" // Should find the global var in the same namespace " int func2() { return func(); } \n" // Should find the global function in the same namespace " int var = 1; \n" " class cl { cl() {v = 1;} int v; } \n" " interface i {} \n" " enum e { e1 = 1 } \n" " funcdef void fd(); \n" " ::e MyFunc() { return ::e1; } \n" // Nested namespaces are allowed " namespace b { \n" " int var = 2; \n" " void funcParams(int a, float b) { a+b; } \n" " } \n" // Accessing global variables from within a namespace is also possible " int getglobalvar() { return ::var; } \n" "} \n" // The class should be able to declare methods to return and take types from other namespaces "class MyClass { \n" " a::e func(a::e val) { return val; } \n" " ::e func(::e val) { return val; } \n" "} \n" // Global functions must also be able to return and take types from other namespaces "a::e MyFunc(a::e val) { return val; } \n" // It's possible to specify exactly which one is wanted "cl gc; \n" "a::cl gca; \n" "void main() \n" "{ \n" " assert(var == 0); \n" " assert(::var == 0); \n" " assert(a::var == 1); \n" " assert(a::b::var == 2); \n" " assert(func() == 0); \n" " assert(a::func() == 1); \n" " assert(func2() == 0); \n" " assert(a::func2() == 1); \n" " assert(e1 == 0); \n" " assert(::e1 == 0); \n" " assert(e::e1 == 0); \n" " assert(::e::e1 == 0); \n" " assert(a::e1 == 1); \n" " assert(a::e::e1 == 1); \n" " cl c; \n" " a::cl ca; \n" " assert(c.v == 0); \n" " assert(ca.v == 1); \n" " assert(gc.v == 0); \n" " assert(gca.v == 1); \n" " assert(a::getglobalvar() == 0); \n" "} \n"; asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // Retrieving entities should work properly with namespace mod->SetDefaultNamespace("a"); asIScriptFunction *f1 = mod->GetFunctionByDecl("int func()"); asIScriptFunction *f2 = mod->GetFunctionByDecl("int a::func()"); asIScriptFunction *f3 = mod->GetFunctionByName("func"); if( f1 == 0 || f1 != f2 || f1 != f3 ) TEST_FAILED; int v1 = mod->GetGlobalVarIndexByName("var"); int v2 = mod->GetGlobalVarIndexByDecl("int var"); int v3 = mod->GetGlobalVarIndexByDecl("int a::var"); if( v1 < 0 || v1 != v2 || v1 != v3 ) TEST_FAILED; int t1 = mod->GetTypeIdByDecl("cl"); int t2 = mod->GetTypeIdByDecl("a::cl"); if( t1 < 0 || t1 != t2 ) TEST_FAILED; // Functions with parameters must work too asIScriptFunction *f = mod->GetFunctionByDecl("void a::b::funcParams(int, float)"); if( f == 0 || std::string(f->GetDeclaration(true, true)) != "void a::b::funcParams(int, float)" ) TEST_FAILED; // Test saving and loading CBytecodeStream s(""); mod->SaveByteCode(&s); asIScriptModule *mod2 = engine->GetModule("mod2", asGM_ALWAYS_CREATE); r = mod2->LoadByteCode(&s); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main()", mod2); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test registering interface with namespace { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); r = engine->SetDefaultNamespace("test"); assert( r >= 0 ); r = engine->RegisterObjectType("t", 0, asOBJ_REF); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("t", asBEHAVE_ADDREF, "void f()", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectMethod("t", "void f()", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectProperty("t", "int a", 0); assert( r >= 0 ); int t1 = engine->GetTypeIdByDecl("t"); int t2 = engine->GetTypeIdByDecl("test::t"); if( t1 < 0 || t1 != t2 ) TEST_FAILED; r = engine->RegisterInterface("i"); assert( r >= 0 ); r = engine->RegisterInterfaceMethod("i", "void f()"); assert( r >= 0 ); t1 = engine->GetTypeIdByDecl("test::i"); if( t1 < 0 ) TEST_FAILED; r = engine->RegisterEnum("e"); assert( r >= 0 ); r = engine->RegisterEnumValue("e", "e1", 0); assert( r >= 0 ); t1 = engine->GetTypeIdByDecl("test::e"); if( t1 < 0 ) TEST_FAILED; r = engine->RegisterFuncdef("void f()"); assert( r >= 0 ); t1 = engine->GetTypeIdByDecl("test::f"); if( t1 < 0 ) TEST_FAILED; r = engine->RegisterGlobalFunction("void gf()", asFUNCTION(0), asCALL_GENERIC); assert( r >= 0 ); asIScriptFunction *f1 = engine->GetGlobalFunctionByDecl("void test::gf()"); asIScriptFunction *f2 = engine->GetGlobalFunctionByDecl("void gf()"); if( f1 == 0 || f1 != f2 ) TEST_FAILED; r = engine->RegisterGlobalProperty("int gp", (void*)1); assert( r >= 0 ); int g1 = engine->GetGlobalPropertyIndexByName("gp"); int g2 = engine->GetGlobalPropertyIndexByDecl("int gp"); int g3 = engine->GetGlobalPropertyIndexByDecl("int test::gp"); if( g1 < 0 || g1 != g2 || g1 != g3 ) TEST_FAILED; r = engine->RegisterTypedef("td", "int"); assert( r >= 0 ); t1 = engine->GetTypeIdByDecl("test::td"); if( t1 < 0 ) TEST_FAILED; engine->Release(); } // Test accessing registered properties in different namespaces from within function in another namespace // http://www.gamedev.net/topic/624376-accessing-global-property-from-within-script-namespace/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); int a = 0, b = 0; r = engine->RegisterGlobalProperty("int a", &a); r = engine->SetDefaultNamespace("test"); r = engine->RegisterGlobalProperty("int b", &b); asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", "namespace script { \n" "void func() \n" "{ \n" " a = 1; \n" "} \n" "} \n"); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) TEST_FAILED; // TODO: Should have better error message. Perhaps show variables declared in other scopes if( bout.buffer != "test (2, 1) : Info : Compiling void func()\n" "test (4, 3) : Error : 'a' is not declared\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } mod->AddScriptSection("test", "namespace script { \n" "void func() \n" "{ \n" " ::a = 1; \n" " test::b = 2; \n" "} \n" "} \n"); bout.buffer = ""; r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "script::func()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; if( a != 1 || b != 2 ) TEST_FAILED; engine->Release(); } // Test registering enum with the same name in two different namespaces // http://www.gamedev.net/topic/625214-enum-collision-across-namespaces/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); engine->SetDefaultNamespace("A"); r = engine->RegisterEnum("ENUM"); assert( r >= 0 ); r = engine->RegisterEnumValue("ENUM", "VALUE", 1); assert( r >= 0 ); engine->SetDefaultNamespace("B"); r = engine->RegisterEnum("ENUM"); assert( r >= 0 ); r = engine->RegisterEnumValue("ENUM", "VALUE", 2); assert( r >= 0 ); engine->SetDefaultNamespace(""); r = engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); assert( r >= 0 ); r = ExecuteString(engine, "int a = A::ENUM::VALUE; assert(a == 1)", 0, 0); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = ExecuteString(engine, "int b = B::ENUM::VALUE; assert(b == 2)", 0, 0); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // It shouldn't be necessary to inform the name of the enum // type as the engine property is not set to enforce that r = ExecuteString(engine, "int a = A::VALUE; assert(a == 1)", 0, 0); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = ExecuteString(engine, "int b = B::VALUE; assert(b == 2)", 0, 0); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); bout.buffer = ""; engine->SetEngineProperty(asEP_REQUIRE_ENUM_SCOPE, true); r = ExecuteString(engine, "int a = A::VALUE; assert(a == 1)", 0, 0); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 9) : Error : 'A::VALUE' is not declared\n" "ExecuteString (1, 28) : Warning : 'a' is not initialized.\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // http://www.gamedev.net/topic/626970-2240-cannot-instantiate-a-class-outside-of-its-namespace/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", "namespace TestNamespace \n" "{ \n" " class MyHappyClass \n" " { \n" " MyHappyClass () \n" " { \n" " } \n" " void DoSomething () \n" " { \n" " } \n" " } \n" "} \n" "void main () \n" "{ \n" " TestNamespace::MyHappyClass ClassInstance; \n" " \n" " ClassInstance.DoSomething (); \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; engine->Release(); } // http://www.gamedev.net/topic/626314-compiler-error-when-using-namespace-with-the-array-addon/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", "namespace A \n" "{ \n" " class Test {} \n" "} \n" "void main () \n" "{ \n" " array<A::Test@> a; \n" " A::Test@[] b; \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; engine->Release(); } // It should be possible to register types with the same name in different namespaces { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); r = engine->RegisterObjectType("TestObj", 0, asOBJ_REF); if( r < 0 ) TEST_FAILED; engine->SetDefaultNamespace("A"); r = engine->RegisterObjectType("TestObj", 0, asOBJ_REF); if( r < 0 ) TEST_FAILED; r = engine->RegisterObjectType("TestObj", 0, asOBJ_REF); if( r != asALREADY_REGISTERED ) TEST_FAILED; engine->SetDefaultNamespace(""); asIObjectType *o1 = engine->GetObjectTypeByName("TestObj"); engine->SetDefaultNamespace("A"); asIObjectType *o2 = engine->GetObjectTypeByName("TestObj"); if( o1 == 0 || o2 == 0 ) TEST_FAILED; if( o1 == o2 ) TEST_FAILED; engine->Release(); } // Dynamically adding functions/variables to modules should also support namespaces { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule("test", asGM_ALWAYS_CREATE); asIScriptFunction *f1; r = mod->CompileFunction("", "void func() {}", 0, asCOMP_ADD_TO_MODULE, &f1); if( r < 0 ) TEST_FAILED; mod->SetDefaultNamespace("A"); asIScriptFunction *f2; r = mod->CompileFunction("", "void func() {}", 0, asCOMP_ADD_TO_MODULE, &f2); if( r < 0 ) TEST_FAILED; mod->SetDefaultNamespace(""); asIScriptFunction *f3 = mod->GetFunctionByName("func"); mod->SetDefaultNamespace("A"); asIScriptFunction *f4 = mod->GetFunctionByName("func"); if( f1 != f3 ) TEST_FAILED; if( f2 != f4 ) TEST_FAILED; if( f1 == f2 ) TEST_FAILED; // The functions received from CompileFunction must be released if( f1 ) f1->Release(); if( f2 ) f2->Release(); mod->SetDefaultNamespace(""); r = mod->CompileGlobalVar("", "int var;", 0); if( r < 0 ) TEST_FAILED; mod->SetDefaultNamespace("A"); r = mod->CompileGlobalVar("", "int var;", 0); if( r < 0 ) TEST_FAILED; mod->SetDefaultNamespace(""); int v1 = mod->GetGlobalVarIndexByName("var"); mod->SetDefaultNamespace("A"); int v2 = mod->GetGlobalVarIndexByName("var"); if( v1 < 0 || v2 < 0 ) TEST_FAILED; if( v1 == v2 ) TEST_FAILED; engine->Release(); } // Inheritance from class in a different namespace // http://www.gamedev.net/topic/626970-2240-cannot-instantiate-a-class-outside-of-its-namespace/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule("test", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", "namespace A \n" "{ \n" " interface i {} \n" " class a {} \n" " class a2 : a, i {} \n" "} \n" "class b : A::a, A::i {} \n" "namespace C \n" "{ \n" " class c : ::b {} \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; asIObjectType *type = mod->GetObjectTypeByName("b"); if( type == 0 ) TEST_FAILED; else { mod->SetDefaultNamespace("A"); if( !type->DerivesFrom(mod->GetObjectTypeByName("a")) ) TEST_FAILED; if( !type->Implements(mod->GetObjectTypeByName("i")) ) TEST_FAILED; } engine->Release(); } // Registering types with namespaces // http://www.gamedev.net/topic/628401-problem-binding-two-similarly-named-objects-in-different-namespaces/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); engine->SetDefaultNamespace("A"); engine->RegisterEnum("ETest"); engine->RegisterObjectType("CTest", 0, asOBJ_REF| asOBJ_NOCOUNT); r = engine->RegisterObjectProperty("CTest", "ETest e", 0); if( r < 0 ) TEST_FAILED; engine->RegisterObjectType("CTest2", 0, asOBJ_REF| asOBJ_NOCOUNT); if( r < 0 ) TEST_FAILED; r = engine->RegisterObjectMethod("CTest2", "ETest Method(ETest)", asFUNCTION(0), asCALL_GENERIC); if( r < 0 ) TEST_FAILED; // Make sure it's possible to retrieve the enum again int typeId; const char *ns; const char *e = engine->GetEnumByIndex(0, &typeId, &ns); if( std::string(e) != "ETest" ) TEST_FAILED; if( std::string(ns) != "A" ) TEST_FAILED; if( typeId != engine->GetTypeIdByDecl("ETest") ) TEST_FAILED; engine->SetDefaultNamespace(""); e = engine->GetEnumByIndex(0, &typeId, &ns); if( std::string(e) != "ETest" ) TEST_FAILED; if( std::string(ns) != "A" ) TEST_FAILED; if( typeId != engine->GetTypeIdByDecl("A::ETest") ) TEST_FAILED; engine->Release(); } // Registering properties using types from other namespaces // http://www.gamedev.net/topic/629088-looks-like-bug-with-namespaces-in-revision-1380/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterStdString(engine); engine->SetDefaultNamespace("mynamespace"); r = engine->RegisterGlobalProperty("::string val", (void*)1); // TODO: Once recursive searches in the namespaces is implemented the scope operator is not needed if( r < 0 ) TEST_FAILED; engine->Release(); } // Test problem reported by Andrew Ackermann { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); const char *script = "namespace Test { \n" " class A { \n" " } \n" "}; \n" "void init() { \n" " Test::A@ a = Test::A(); \n" "} \n"; asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; engine->Release(); } // Test property accessors with namespaces // http://www.gamedev.net/topic/635042-indexed-property-accessors-and-namespaces/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "int get_foo() { return 42; } \n" "namespace nm { int get_foo2() { return 42; } } \n" "void test() { \n" " assert( foo == 42 ); \n" // ok " assert( ::foo == 42 ); \n" // ok " assert( nm::foo == 42 ); \n" // should fail to compile " assert( nm::foo2 == 42 ); \n" // ok " assert( foo2 == 42 ); \n" // should fail to compile "} \n" "namespace nm { \n" "void test2() { \n" " ::assert( foo == 42 ); \n" // should fail to compile " ::assert( ::foo == 42 ); \n" // ok " ::assert( nm::foo == 42 ); \n" // should fail to compile " ::assert( nm::foo2 == 42 ); \n" // ok " ::assert( foo2 == 42 ); \n" // ok "} \n" "} \n"; bout.buffer = ""; asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "test (3, 1) : Info : Compiling void test()\n" "test (6, 11) : Error : 'nm::foo' is not declared\n" "test (8, 11) : Error : 'foo2' is not declared\n" "test (11, 1) : Info : Compiling void test2()\n" "test (12, 13) : Error : 'foo' is not declared\n" "test (14, 13) : Error : 'nm::foo' is not declared\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Indexed property accessors script = "int get_foo(uint) { return 42; } \n" "namespace nm { int get_foo2(uint) { return 42; } } \n" "void test() { \n" " assert( foo[0] == 42 ); \n" // ok " assert( ::foo[0] == 42 ); \n" // ok " assert( nm::foo[0] == 42 ); \n" // should fail to compile " assert( nm::foo2[0] == 42 ); \n" // ok " assert( foo2[0] == 42 ); \n" // should fail to compile "} \n" "namespace nm { \n" "void test2() { \n" " ::assert( foo[0] == 42 ); \n" // should fail to compile " ::assert( ::foo[0] == 42 ); \n" // ok " ::assert( nm::foo[0] == 42 ); \n" // should fail to compile " ::assert( nm::foo2[0] == 42 ); \n" // ok " ::assert( foo2[0] == 42 ); \n" // ok "} \n" "} \n"; bout.buffer = ""; mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "test (3, 1) : Info : Compiling void test()\n" "test (6, 11) : Error : 'nm::foo' is not declared\n" "test (8, 11) : Error : 'foo2' is not declared\n" "test (11, 1) : Info : Compiling void test2()\n" "test (12, 13) : Error : 'foo' is not declared\n" "test (14, 13) : Error : 'nm::foo' is not declared\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Test types in namespace // http://www.gamedev.net/topic/636336-member-function-chaining/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "namespace Default { \n" " void func(ButtonRenderer @) {} \n" " void Init() \n" " { \n" " func(ButtonRenderer()); \n" " } \n" " class ButtonRenderer {} \n" "} \n"; bout.buffer = ""; asIScriptModule *mod = engine->GetModule("mod", asGM_ALWAYS_CREATE); mod->AddScriptSection("test", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Success return fail; }
void Test() { printf("---------------------------------------------\n"); printf("%s\n\n", TESTNAME); printf("AngelScript 2.25.1 WIP 0: 1.59 secs\n"); printf("AngelScript 2.25.1 WIP 1: 1.66 secs (local bytecode optimizations)\n"); printf("AngelScript 2.25.1 WIP 2: 1.60 secs (reversed order)\n"); printf("AngelScript 2.28.1 WIP: 1.08 secs\n"); asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); COutStream out; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); RegisterStdString(engine); engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_CDECL); //////////////////////////////////////////// printf("\nGenerating...\n"); const int numArrays = 2; #ifdef _DEBUG const int numElements = 10; #else const int numElements = 100000; #endif string script; std::stringstream script_buffer; for (unsigned i = 0; i < numArrays; i++) { script_buffer << "int[] array_" << i << " = {"; if (numElements > 0) { script_buffer << 0; } for (unsigned j = 1; j < numElements; j++) { script_buffer << ", " << j; } script_buffer << "};"; } script_buffer << std::endl << "int main() { print (\"elem 999 = \" + array_0[999] + \"\\n\"); return 0; }"; script = script_buffer.str(); //////////////////////////////////////////// printf("\nBuilding...\n"); double time = GetSystemTimer(); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script.c_str(), script.size(), 0); int r = mod->Build(); time = GetSystemTimer() - time; if( r != 0 ) printf("Build failed\n", TESTNAME); else printf("Time = %f secs\n", time); //////////////////////////////////////////// printf("\nSaving...\n"); time = GetSystemTimer(); CBytecodeStream stream(""); mod->SaveByteCode(&stream); time = GetSystemTimer() - time; printf("Time = %f secs\n", time); printf("Size = %d\n", int(stream.buffer.size())); //////////////////////////////////////////// printf("\nLoading...\n"); time = GetSystemTimer(); asIScriptModule *mod2 = engine->GetModule(0, asGM_ALWAYS_CREATE); mod2->LoadByteCode(&stream); time = GetSystemTimer() - time; printf("Time = %f secs\n", time); engine->Release(); }
void ScriptRegistrar::RegisterLegacyFFC(asIScriptEngine* engine) { int r; r = engine->RegisterObjectType("FFC", sizeof(int32), asOBJ_APP_PRIMITIVE); Assert(r >= 0); // Setters r = engine->RegisterObjectMethod("sFFC", "void set_Data()", asMETHOD(sFFC, SetData), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Script()", asMETHOD(sFFC, SetScript), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_CSet()", asMETHOD(sFFC, SetCSet), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Delay()", asMETHOD(sFFC, SetDelay), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_X()", asMETHOD(sFFC, SetX), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Y()", asMETHOD(sFFC, SetY), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Vx()", asMETHOD(sFFC, SetVx), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Vy()", asMETHOD(sFFC, SetVy), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Ax()", asMETHOD(sFFC, SetAx), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Ay()", asMETHOD(sFFC, SetAy), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Flags(int)", asMETHOD(sFFC, SetFlags), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_TileWidth()", asMETHOD(sFFC, SetTileWidth), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_TileHeight()", asMETHOD(sFFC, SetTileHeight), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_EffectWidth()", asMETHOD(sFFC, SetEffectWidth), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_EffectHeight()", asMETHOD(sFFC, SetEffectHeight), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Link()", asMETHOD(sFFC, SetLink), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_InitD(int)", asMETHOD(sFFC, SetInitD), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "void set_Misc(int)", asMETHOD(sFFC, SetMisc), asCALL_THISCALL); Assert(r >= 0); // Getters r = engine->RegisterObjectMethod("sFFC", "int32 get_Data()", asMETHOD(sFFC, GetData), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_Script()", asMETHOD(sFFC, GetScript), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_CSet()", asMETHOD(sFFC, GetCSet), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_Delay()", asMETHOD(sFFC, GetDelay), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_X()", asMETHOD(sFFC, GetX), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_Y()", asMETHOD(sFFC, GetY), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_Vx()", asMETHOD(sFFC, GetVx), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_Vy()", asMETHOD(sFFC, GetVy), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_Ax()", asMETHOD(sFFC, GetAx), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_Ay()", asMETHOD(sFFC, GetAy), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "bool get_Flags(int)", asMETHOD(sFFC, GetFlags), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_TileWidth()", asMETHOD(sFFC, GetTileWidth), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_TileHeight()", asMETHOD(sFFC, GetTileHeight), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_EffectWidth()", asMETHOD(sFFC, GetEffectWidth), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_EffectHeight()", asMETHOD(sFFC, GetEffectHeight), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "int32 get_Link()", asMETHOD(sFFC, GetLink), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_InitD(int)", asMETHOD(sFFC, GetInitD), asCALL_THISCALL); Assert(r >= 0); r = engine->RegisterObjectMethod("sFFC", "float get_Misc(int)", asMETHOD(sFFC, GetMisc), asCALL_THISCALL); Assert(r >= 0); }
bool Test() { bool fail = Test2(); int r; COutStream out; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptString(engine); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script, strlen(script)); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "uint8 newmask = 0xFF, mask = 0x15; Assert( (newmask & ~mask) == 0xEA );"); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = ExecuteString(engine, "uint8 newmask = 0xFF; newmask = newmask & (~mask2) & (~mask3) & (~mask5); Assert( newmask == 0xD3 );", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = ExecuteString(engine, "uint8 newmask = 0XFE; Assert( (newmask & mask0) == 0 );", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; r = ExecuteString(engine, "uint8 b = 0xFF; b &= ~mask4; BitsTest(b);", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->RegisterGlobalFunction("uint8 ReturnByte(uint8)", asFUNCTION(ReturnByte), asCALL_GENERIC); engine->RegisterGlobalFunction("uint16 ReturnWord(uint16)", asFUNCTION(ReturnWord), asCALL_GENERIC); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script2, strlen(script2)); engine->SetEngineProperty(asEP_OPTIMIZE_BYTECODE, false); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "Test()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // bitwise operators should maintain signed/unsigned type of left hand operand CBufferedOutStream bout; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); r = ExecuteString(engine, "int a = 0, b = 0; bool c = (a < (b>>1));"); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "uint a = 0, b = 0; bool c = (a < (b>>1));"); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); // Success return fail; }
static void RegisterInput(asIScriptEngine* engine) { engine->RegisterObjectType("TouchState", 0, asOBJ_REF); engine->RegisterObjectBehaviour("TouchState", asBEHAVE_ADDREF, "void f()", asFUNCTION(FakeAddRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectBehaviour("TouchState", asBEHAVE_RELEASE, "void f()", asFUNCTION(FakeReleaseRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectProperty("TouchState", "const int touchID", offsetof(TouchState, touchID_)); engine->RegisterObjectProperty("TouchState", "const IntVector2 position", offsetof(TouchState, position_)); engine->RegisterObjectProperty("TouchState", "const IntVector2 delta", offsetof(TouchState, delta_)); engine->RegisterObjectProperty("TouchState", "const float pressure", offsetof(TouchState, pressure_)); engine->RegisterObjectType("JoystickState", 0, asOBJ_REF); engine->RegisterObjectBehaviour("JoystickState", asBEHAVE_ADDREF, "void f()", asFUNCTION(FakeAddRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectBehaviour("JoystickState", asBEHAVE_RELEASE, "void f()", asFUNCTION(FakeReleaseRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectProperty("JoystickState", "const String name", offsetof(JoystickState, name_)); engine->RegisterObjectMethod("JoystickState", "uint get_numButtons() const", asMETHOD(JoystickState, GetNumButtons), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "uint get_numAxes() const", asMETHOD(JoystickState, GetNumAxes), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "uint get_numHats() const", asMETHOD(JoystickState, GetNumHats), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "bool get_buttonDown(uint) const", asMETHOD(JoystickState, GetButtonDown), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "bool get_buttonPress(uint) const", asMETHOD(JoystickState, GetButtonPress), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "float get_axisPosition(uint) const", asMETHOD(JoystickState, GetAxisPosition), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "int get_hatPosition(uint) const", asMETHOD(JoystickState, GetHatPosition), asCALL_THISCALL); RegisterObject<Input>(engine, "Input"); engine->RegisterObjectMethod("Input", "bool OpenJoystick(uint)", asMETHOD(Input, OpenJoystick), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void CloseJoystick(uint)", asMETHOD(Input, CloseJoystick), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool DetectJoysticks()", asMETHOD(Input, DetectJoysticks), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_mouseVisible(bool)", asMETHOD(Input, SetMouseVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_mouseVisible() const", asMETHOD(Input, IsMouseVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_screenKeyboardVisible(bool)", asMETHOD(Input, SetScreenKeyboardVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_screenKeyboardVisible() const", asMETHOD(Input, IsScreenKeyboardVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_screenKeyboardSupport() const", asMETHOD(Input, GetScreenKeyboardSupport), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_toggleFullscreen(bool)", asMETHOD(Input, SetToggleFullscreen), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_toggleFullscreen() const", asMETHOD(Input, GetToggleFullscreen), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_keyDown(int) const", asMETHOD(Input, GetKeyDown), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_keyPress(int) const", asMETHOD(Input, GetKeyPress), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_mouseButtonDown(int) const", asMETHOD(Input, GetMouseButtonDown), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_mouseButtonPress(int) const", asMETHOD(Input, GetMouseButtonPress), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_qualifierDown(int) const", asMETHOD(Input, GetQualifierDown), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_qualifierPress(int) const", asMETHOD(Input, GetQualifierPress), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_qualifiers() const", asMETHOD(Input, GetQualifiers), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "IntVector2 get_mousePosition() const", asMETHOD(Input, GetMousePosition), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "const IntVector2& get_mouseMove() const", asMETHOD(Input, GetMouseMove), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_mouseMoveX() const", asMETHOD(Input, GetMouseMoveX), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_mouseMoveY() const", asMETHOD(Input, GetMouseMoveY), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_mouseMoveWheel() const", asMETHOD(Input, GetMouseMoveWheel), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "uint get_numTouches() const", asMETHOD(Input, GetNumTouches), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "TouchState@+ get_touches(uint) const", asMETHOD(Input, GetTouch), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "uint get_numJoysticks() const", asMETHOD(Input, GetNumJoysticks), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "const String& get_joystickNames(uint) const", asMETHOD(Input, GetJoystickName), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "JoystickState@+ get_joysticks(uint)", asMETHOD(Input, GetJoystick), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_focus() const", asMETHOD(Input, HasFocus), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_minimized() const", asMETHOD(Input, IsMinimized), asCALL_THISCALL); engine->RegisterGlobalFunction("Input@+ get_input()", asFUNCTION(GetInput), asCALL_CDECL); }
bool Test() { bool fail = false; int r; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptString_Generic(engine); engine->RegisterGlobalProperty("float[] @floatArray", &floatArray); engine->RegisterGlobalProperty("string[] @stringArray", &stringArray); COutStream out; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = mod->Build(); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "Test()"); if( r != asEXECUTION_FINISHED ) fail = true; else { if( (floatArray->GetArrayTypeId() & asTYPEID_MASK_OBJECT) != asTYPEID_SCRIPTARRAY ) fail = true; if( floatArray->GetArrayTypeId() != engine->GetTypeIdByDecl("float[]") ) fail = true; if( floatArray->GetElementTypeId() != engine->GetTypeIdByDecl("float") ) fail = true; if( floatArray->GetElementCount() != 2 ) fail = true; if( *(float*)floatArray->GetElementPointer(0) != 1.1f ) fail = true; if( *(float*)floatArray->GetElementPointer(1) != 1.2f ) fail = true; if( stringArray->GetArrayTypeId() != engine->GetTypeIdByDecl("string[]") ) fail = true; if( stringArray->GetElementTypeId() != engine->GetTypeIdByDecl("string") ) fail = true; if( stringArray->GetElementCount() != 1 ) fail = true; if( ((CScriptString*)stringArray->GetElementPointer(0))->buffer != "test" ) fail = true; stringArray->Resize(2); } if( floatArray ) floatArray->Release(); if( stringArray ) stringArray->Release(); engine->Release(); // Success return fail; }
PODVector<Vector3> dest; ptr->FindPath(dest, start, end, extents); return VectorToArray<Vector3>(dest, "Array<Vector3>"); } static CScriptArray* DetourCrowdManagerGetActiveAgents(DetourCrowdManager* crowd) { const PODVector<CrowdAgent*>& agents = crowd->GetActiveAgents(); return VectorToHandleArray<CrowdAgent>(agents, "Array<CrowdAgent@>"); } template<class T> static void RegisterNavMeshBase(asIScriptEngine* engine, const char* name) { engine->RegisterObjectMethod(name, "bool Build()", asMETHODPR(T, Build, (void), bool), asCALL_THISCALL); engine->RegisterObjectMethod(name, "bool Build(const BoundingBox&in)", asMETHODPR(T, Build, (const BoundingBox&), bool), asCALL_THISCALL); engine->RegisterObjectMethod(name, "void SetAreaCost(uint, float)", asMETHOD(T, SetAreaCost), asCALL_THISCALL); engine->RegisterObjectMethod(name, "float GetAreaCost(uint) const", asMETHOD(T, GetAreaCost), asCALL_THISCALL); engine->RegisterObjectMethod(name, "Vector3 FindNearestPoint(const Vector3&in, const Vector3&in extents = Vector3(1.0, 1.0, 1.0))", asMETHOD(T, FindNearestPoint), asCALL_THISCALL); engine->RegisterObjectMethod(name, "Vector3 MoveAlongSurface(const Vector3&in, const Vector3&in, const Vector3&in extents = Vector3(1.0, 1.0, 1.0), uint = 3)", asMETHOD(T, MoveAlongSurface), asCALL_THISCALL); engine->RegisterObjectMethod(name, "Vector3 GetRandomPoint()", asMETHOD(T, GetRandomPoint), asCALL_THISCALL); engine->RegisterObjectMethod(name, "Vector3 GetRandomPointInCircle(const Vector3&in, float, const Vector3&in extents = Vector3(1.0, 1.0, 1.0))", asMETHOD(T, GetRandomPointInCircle), asCALL_THISCALL); engine->RegisterObjectMethod(name, "float GetDistanceToWall(const Vector3&in, float, const Vector3&in extents = Vector3(1.0, 1.0, 1.0))", asMETHOD(T, GetDistanceToWall), asCALL_THISCALL); engine->RegisterObjectMethod(name, "Vector3 Raycast(const Vector3&in, const Vector3&in, const Vector3&in extents = Vector3(1.0, 1.0, 1.0))", asMETHOD(T, Raycast), asCALL_THISCALL); engine->RegisterObjectMethod(name, "void DrawDebugGeometry(bool)", asMETHODPR(NavigationMesh, DrawDebugGeometry, (bool), void), asCALL_THISCALL); engine->RegisterObjectMethod(name, "void set_tileSize(int)", asMETHOD(T, SetTileSize), asCALL_THISCALL); engine->RegisterObjectMethod(name, "int get_tileSize() const", asMETHOD(T, GetTileSize), asCALL_THISCALL); engine->RegisterObjectMethod(name, "void set_cellSize(float)", asMETHOD(T, SetCellSize), asCALL_THISCALL); engine->RegisterObjectMethod(name, "float get_cellSize() const", asMETHOD(T, GetCellSize), asCALL_THISCALL); engine->RegisterObjectMethod(name, "void set_cellHeight(float)", asMETHOD(T, SetCellHeight), asCALL_THISCALL); engine->RegisterObjectMethod(name, "float get_cellHeight() const", asMETHOD(T, GetCellHeight), asCALL_THISCALL); engine->RegisterObjectMethod(name, "void set_agentHeight(float)", asMETHOD(T, SetAgentHeight), asCALL_THISCALL);
bool Test() { bool fail = false; int r; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptString_Generic(engine); RegisterScriptAny(engine); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_GENERIC); engine->RegisterGlobalFunction("void Analyze(any &inout)", asFUNCTION(Analyze), asCALL_GENERIC); COutStream out; CBufferedOutStream bout; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script1, strlen(script1), 0); r = mod->Build(); if( r < 0 ) fail = true; asIScriptContext *ctx = 0; r = engine->ExecuteString(0, "Test()", &ctx); if( r != asEXECUTION_FINISHED ) { if( r == asEXECUTION_EXCEPTION ) PrintException(ctx); fail = true; } if( ctx ) ctx->Release(); // Make sure that the error message for wrong constructor name works bout.buffer = ""; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "class t{ s() {} };", 18, 0); r = mod->Build(); if( r >= 0 ) fail = true; if( bout.buffer != "TestScriptClassMethod (1, 10) : Error : The constructor name must be the same as the class\n" ) fail = true; // Make sure the default constructor can be overloaded engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod = engine->GetModule("test", asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script2, strlen(script2), 0); r = mod->Build(); if( r < 0 ) fail = true; r = engine->ExecuteString("test", "Test()"); if( r != asEXECUTION_FINISHED ) { fail = true; } int typeId = engine->GetModule("test")->GetTypeIdByDecl("myclass"); asIScriptObject *s = (asIScriptObject*)engine->CreateScriptObject(typeId); if( s == 0 ) fail = true; else { // Validate the property int *v = 0; int n = s->GetPropertyCount(); for( int c = 0; c < n; c++ ) { std::string str = "value"; if( str == s->GetPropertyName(c) ) { v = (int*)s->GetAddressOfProperty(c); if( *v != 1 ) fail = true; } } // Call the script class method asIObjectType *type = engine->GetObjectTypeById(typeId); if( type->GetMethodCount() != 2 ) fail = true; int methodId = type->GetMethodIdByDecl("void method2()"); if( methodId < 0 ) fail = true; else { asIScriptContext *ctx = engine->CreateContext(); ctx->Prepare(methodId); ctx->SetObject(s); int r = ctx->Execute(); if( r != asEXECUTION_FINISHED ) fail = true; if( (!v) || (*v != 3) ) fail = true; ctx->Release(); } s->Release(); } engine->Release(); //---------------------------------- engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptAny(engine); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("test3", script3, strlen(script3), 0); r = mod->Build(); if( r < 0 ) fail = true; typeId = engine->GetModule(0)->GetTypeIdByDecl("myclass"); asIObjectType *type = engine->GetObjectTypeById(typeId); int mtdId = type->GetMethodIdByDecl("void func()"); asIScriptObject *obj = (asIScriptObject *)engine->GetModule(0)->GetAddressOfGlobalVar(engine->GetModule(0)->GetGlobalVarIndexByName("c")); if( mtdId < 0 || obj == 0 ) fail = true; else { asIScriptContext *ctx = engine->CreateContext(); ctx->Prepare(mtdId); ctx->SetObject(obj); r = ctx->Execute(); if( r != asEXECUTION_FINISHED ) fail = true; ctx->Release(); } type = engine->GetObjectTypeById(typeId); mtdId = type->GetMethodIdByDecl("void func(int, int)"); if( mtdId < 0 || obj == 0 ) fail = true; else { asIScriptContext *ctx = engine->CreateContext(); ctx->Prepare(mtdId); ctx->SetObject(obj); ctx->SetArgDWord(0, 1); ctx->SetArgDWord(1, 1); r = ctx->Execute(); if( r != asEXECUTION_FINISHED ) fail = true; ctx->Release(); } engine->Release(); //---------------------------- // Verify that global functions and class methods with the same name doesn't conflict engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptAny(engine); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("test4", script4, strlen(script4), 0); r = mod->Build(); if( r < 0 ) fail = true; int func = mod->GetFunctionIdByDecl("void func()"); if( func < 0 ) fail = true; engine->Release(); //---------------------------- // Accessing member variables without this engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterScriptAny(engine); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("test5", script5, strlen(script5), 0); r = mod->Build(); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "test()", 0, 0); if( r != asEXECUTION_FINISHED ) { fail = true; } engine->Release(); //----------------------------- // Name conflict with class method and object type engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptString(engine); engine->RegisterGlobalFunction("void print(const string &in)", asFUNCTION(print), asCALL_GENERIC); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("test6", script6, strlen(script6), 0); r = mod->Build(); if( r < 0 ) fail = true; outbuffer = ""; r = engine->ExecuteString(0, "Test t; t.Set(1); t.Test2();"); if( r != asEXECUTION_FINISHED ) { fail = true; } if( outbuffer != "Test::Set\nTest::Set\nSet::Set\n" ) { printf(outbuffer.c_str()); fail = true; } engine->Release(); //------------------------------ // The scope operator should permit calling global functions if the class has a method of the same name engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); const char *script = "class A { \n" " void func() { \n" " g = 0; \n" " testScope(); \n" " assert(g == 3); \n" " ::testScope(); \n" " assert(g == 2); \n" " } \n" " void testScope() { g = 3; } \n" "} \n" "void testScope() { g = 2; } \n" "int g; \n"; mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) { fail = true; } r = engine->ExecuteString(0, "A a; a.func(); assert( g == 2 );"); if( r != asEXECUTION_FINISHED ) { fail = true; } engine->Release(); // Success return fail; }
bool Test() { bool fail = false; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); COutStream out; CBufferedOutStream bout; float f = 0; double d = 0; asUINT ui = 0; asINT64 i64 = 0; int i = 0; signed char i8 = 0; asQWORD ui64 = 0; short i16 = 0; unsigned char ui8 = 0; unsigned short ui16 = 0; engine->RegisterGlobalProperty("float f", &f); engine->RegisterGlobalProperty("double d", &d); engine->RegisterGlobalProperty("uint ui", &ui); engine->RegisterGlobalProperty("uint8 ui8", &ui8); engine->RegisterGlobalProperty("uint16 ui16", &ui16); engine->RegisterGlobalProperty("uint64 ui64", &ui64); engine->RegisterGlobalProperty("int i", &i); engine->RegisterGlobalProperty("int8 i8", &i8); engine->RegisterGlobalProperty("int16 i16", &i16); engine->RegisterGlobalProperty("int64 i64", &i64); engine->RegisterGlobalFunction("void TestDouble(double)", asFUNCTION(TestDouble), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestFloat(float)", asFUNCTION(TestFloat), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestI64(int16)", asFUNCTION(TestI64), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestInt(int)", asFUNCTION(TestInt), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestI16(int16)", asFUNCTION(TestI16), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestI8(int8)", asFUNCTION(TestI8), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUI64(uint)", asFUNCTION(TestUI64), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUInt(uint)", asFUNCTION(TestUInt), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUI16(uint16)", asFUNCTION(TestUI16), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUI8(uint8)", asFUNCTION(TestUI8), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestDoubleByRef(double &in)", asFUNCTION(TestDoubleByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestFloatByRef(float &in)", asFUNCTION(TestFloatByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestI64ByRef(int &in)", asFUNCTION(TestI64ByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestIntByRef(int &in)", asFUNCTION(TestIntByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestI16ByRef(int16 &in)", asFUNCTION(TestI16ByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestI8ByRef(int8 &in)", asFUNCTION(TestI8ByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUI64ByRef(uint &in)", asFUNCTION(TestUI64ByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUIntByRef(uint &in)", asFUNCTION(TestUIntByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUI16ByRef(uint16 &in)", asFUNCTION(TestUI16ByRef), asCALL_GENERIC); engine->RegisterGlobalFunction("void TestUI8ByRef(uint8 &in)", asFUNCTION(TestUI8ByRef), asCALL_GENERIC); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "d = double(d);"); if( d != 12.3 ) fail = true; f = 12.3f; engine->ExecuteString(0, "d = double(f);"); if( d != 12.3f ) fail = true; ui = 123; engine->ExecuteString(0, "d = double(ui);"); if( d != 123.0 ) fail = true; ui8 = 123; engine->ExecuteString(0, "d = double(ui8);"); if( d != 123.0 ) fail = true; ui16 = 123; engine->ExecuteString(0, "d = double(ui16);"); if( d != 123.0 ) fail = true; ui64 = 123; engine->ExecuteString(0, "d = double(ui64);"); if( d != 123.0 ) fail = true; i = -123; engine->ExecuteString(0, "d = double(i);"); if( d != -123.0 ) fail = true; i8 = -123; engine->ExecuteString(0, "d = double(i8);"); if( d != -123.0 ) fail = true; i16 = -123; engine->ExecuteString(0, "d = double(i16);"); if( d != -123.0 ) fail = true; i64 = -123; engine->ExecuteString(0, "d = double(i64);"); if( d != -123.0 ) fail = true; ui64 = asQWORD(I64(-1000000000000000000)); double d2 = 18446744073709551615.0 + double(asINT64(ui64)); engine->ExecuteString(0, "d = double(ui64);"); if( d != d2 ) fail = true; d = 12.3; engine->ExecuteString(0, "d = d;"); if( d != 12.3 ) fail = true; f = 12.3f; engine->ExecuteString(0, "d = f;"); if( d != 12.3f ) fail = true; ui = 123; engine->ExecuteString(0, "d = ui;"); if( d != 123.0 ) fail = true; ui8 = 123; engine->ExecuteString(0, "d = ui8;"); if( d != 123.0 ) fail = true; ui16 = 123; engine->ExecuteString(0, "d = ui16;"); if( d != 123.0 ) fail = true; ui64 = 123; engine->ExecuteString(0, "d = ui64;"); if( d != 123.0 ) fail = true; i = -123; engine->ExecuteString(0, "d = i;"); if( d != -123.0 ) fail = true; i8 = -123; engine->ExecuteString(0, "d = i8;"); if( d != -123.0 ) fail = true; i16 = -123; engine->ExecuteString(0, "d = i16;"); if( d != -123.0 ) fail = true; i64 = -123; engine->ExecuteString(0, "d = i64;"); if( d != -123.0 ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "d = 12.3; "); if( !CompareDouble(d,12.3) ) fail = true; engine->ExecuteString(0, "d = 12.3f;"); if( !CompareDouble(d,12.3f) ) fail = true; engine->ExecuteString(0, "d = 123; "); if( !CompareDouble(d,123.0) ) fail = true; engine->ExecuteString(0, "d = -123; "); if( !CompareDouble(d,-123.0) ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "f = float(d);"); if( f != 12.3f ) fail = true; f = 12.3f; engine->ExecuteString(0, "f = float(f);"); if( f != 12.3f ) fail = true; ui = 123; engine->ExecuteString(0, "f = float(ui);"); if( f != 123.0f ) fail = true; ui8 = 123; engine->ExecuteString(0, "f = float(ui8);"); if( f != 123.0f ) fail = true; ui16 = 123; engine->ExecuteString(0, "f = float(ui16);"); if( f != 123.0f ) fail = true; ui64 = 123; engine->ExecuteString(0, "f = float(ui64);"); if( f != 123.0f ) fail = true; i = -123; engine->ExecuteString(0, "f = float(i);"); if( f != -123.0f ) fail = true; i8 = -123; engine->ExecuteString(0, "f = float(i8);"); if( f != -123.0f ) fail = true; i16 = -123; engine->ExecuteString(0, "f = float(i16);"); if( f != -123.0f ) fail = true; i64 = -123; engine->ExecuteString(0, "f = float(i64);"); if( f != -123.0f ) fail = true; d = 12.3; engine->ExecuteString(0, "f = d;"); if( f != 12.3f ) fail = true; f = 12.3f; engine->ExecuteString(0, "f = f;"); if( f != 12.3f ) fail = true; ui = 123; engine->ExecuteString(0, "f = ui;"); if( f != 123.0f ) fail = true; ui8 = 123; engine->ExecuteString(0, "f = ui8;"); if( f != 123.0f ) fail = true; ui16 = 123; engine->ExecuteString(0, "f = ui16;"); if( f != 123.0f ) fail = true; ui64 = 123; engine->ExecuteString(0, "f = ui64;"); if( f != 123.0f ) fail = true; i = -123; engine->ExecuteString(0, "f = i;"); if( f != -123.0f ) fail = true; i8 = -123; engine->ExecuteString(0, "f = i8;"); if( f != -123.0f ) fail = true; i16 = -123; engine->ExecuteString(0, "f = i16;"); if( f != -123.0f ) fail = true; i64 = -123; engine->ExecuteString(0, "f = i64;"); if( f != -123.0f ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "f = 12.3; "); if( f != 12.3f ) fail = true; engine->ExecuteString(0, "f = 12.3f;"); if( f != 12.3f ) fail = true; engine->ExecuteString(0, "f = 123; "); if( f != 123.0f ) fail = true; engine->ExecuteString(0, "f = -123; "); if( f != -123.0f ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "i64 = int64(d);"); if( i64 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i64 = int64(f);"); if( i64 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i64 = int64(ui);"); if( i64 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i64 = int64(ui8);"); if( i64 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i64 = int64(ui16);"); if( i64 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i64 = int64(ui64);"); if( i64 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i64 = int64(i);"); if( i64 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i64 = int64(i8);"); if( i64 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i64 = int64(i16);"); if( i64 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i64 = int64(i64);"); if( i64 != -123 ) fail = true; d = 12.3; engine->ExecuteString(0, "i64 = d;"); if( i64 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i64 = f;"); if( i64 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i64 = ui;"); if( i64 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i64 = ui8;"); if( i64 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i64 = ui16;"); if( i64 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i64 = ui64;"); if( i64 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i64 = i;"); if( i64 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i64 = i8;"); if( i64 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i64 = i16;"); if( i64 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i64 = i64;"); if( i64 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "i64 = 12.3; "); if( i64 != 12 ) fail = true; engine->ExecuteString(0, "i64 = -12.3f;"); if( i64 != - 12 ) fail = true; engine->ExecuteString(0, "i64 = 123; "); if( i64 != 123 ) fail = true; engine->ExecuteString(0, "i64 = -123; "); if( i64 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "i = int(d);"); if( i != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i = int(f);"); if( i != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i = int(ui);"); if( i != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i = int(ui8);"); if( i != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i = int(ui16);"); if( i != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i = int(ui64);"); if( i != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i = int(i);"); if( i != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i = int(i8);"); if( i != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i = int(i16);"); if( i != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i = int(i64);"); if( i != -123 ) fail = true; d = 12.3; engine->ExecuteString(0, "i = d;"); if( i != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i = f;"); if( i != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i = ui;"); if( i != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i = ui8;"); if( i != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i = ui16;"); if( i != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i = ui64;"); if( i != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i = i;"); if( i != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i = i8;"); if( i != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i = i16;"); if( i != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i = i64;"); if( i != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "i = 12.3; "); if( i != 12 ) fail = true; engine->ExecuteString(0, "i = -12.3f;"); if( i != - 12 ) fail = true; engine->ExecuteString(0, "i = 123; "); if( i != 123 ) fail = true; engine->ExecuteString(0, "i = -123; "); if( i != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "i8 = int8(d);"); if( i8 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i8 = int8(f);"); if( i8 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i8 = int8(ui);"); if( i8 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i8 = int8(ui8);"); if( i8 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i8 = int8(ui16);"); if( i8 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i8 = int8(ui64);"); if( i8 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i8 = int8(i);"); if( i8 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i8 = int8(i8);"); if( i8 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i8 = int8(i16);"); if( i8 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i8 = int8(i64);"); if( i8 != -123 ) fail = true; d = 12.3; engine->ExecuteString(0, "i8 = d;"); if( i8 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i8 = f;"); if( i8 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i8 = ui;"); if( i8 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i8 = ui8;"); if( i8 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i8 = ui16;"); if( i8 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i8 = ui64;"); if( i8 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i8 = i;"); if( i8 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i8 = i8;"); if( i8 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i8 = i16;"); if( i8 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i8 = i64;"); if( i8 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "i8 = 12.3; "); if( i8 != 12 ) fail = true; engine->ExecuteString(0, "i8 = -12.3f;"); if( i8 != - 12 ) fail = true; engine->ExecuteString(0, "i8 = 123; "); if( i8 != 123 ) fail = true; engine->ExecuteString(0, "i8 = -123; "); if( i8 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "i16 = int16(d);"); if( i16 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i16 = int16(f);"); if( i16 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i16 = int16(ui);"); if( i16 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i16 = int16(ui8);"); if( i16 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i16 = int16(ui16);"); if( i16 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i16 = int16(ui64);"); if( i16 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i16 = int16(i);"); if( i16 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i16 = int16(i8);"); if( i16 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i16 = int16(i16);"); if( i16 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i16 = int16(i64);"); if( i16 != -123 ) fail = true; d = 12.3; engine->ExecuteString(0, "i16 = d;"); if( i16 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "i16 = f;"); if( i16 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "i16 = ui;"); if( i16 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "i16 = ui8;"); if( i16 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "i16 = ui16;"); if( i16 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "i16 = ui64;"); if( i16 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "i16 = i;"); if( i16 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "i16 = i8;"); if( i16 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "i16 = i16;"); if( i16 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "i16 = i64;"); if( i16 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "i16 = 12.3; "); if( i16 != 12 ) fail = true; engine->ExecuteString(0, "i16 = -12.3f;"); if( i16 != - 12 ) fail = true; engine->ExecuteString(0, "i16 = 123; "); if( i16 != 123 ) fail = true; engine->ExecuteString(0, "i16 = -123; "); if( i16 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "ui64 = uint64(d);"); if( ui64 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui64 = uint64(f);"); if( ui64 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "ui64 = uint64(ui);"); if( ui64 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui64 = uint64(ui8);"); if( ui64 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui64 = uint64(ui16);"); if( ui64 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui64 = uint64(ui64);"); if( ui64 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui64 = uint64(i);"); if( ui64 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "ui64 = uint64(i8);"); if( ui64 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "ui64 = uint64(i16);"); if( ui64 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "ui64 = uint64(i64);"); if( ui64 != -123 ) fail = true; d = 12.3; engine->ExecuteString(0, "ui64 = d;"); if( ui64 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui64 = f;"); if( ui64 != - 12 ) fail = true; ui = 123; engine->ExecuteString(0, "ui64 = ui;"); if( ui64 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui64 = ui8;"); if( ui64 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui64 = ui16;"); if( ui64 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui64 = ui64;"); if( ui64 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui64 = i;"); if( ui64 != -123 ) fail = true; i8 = -123; engine->ExecuteString(0, "ui64 = i8;"); if( ui64 != -123 ) fail = true; i16 = -123; engine->ExecuteString(0, "ui64 = i16;"); if( ui64 != -123 ) fail = true; i64 = -123; engine->ExecuteString(0, "ui64 = i64;"); if( ui64 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "ui64 = 12.3; "); if( ui64 != 12 ) fail = true; engine->ExecuteString(0, "ui64 = -12.3f;"); if( ui64 != - 12 ) fail = true; engine->ExecuteString(0, "ui64 = 123; "); if( ui64 != 123 ) fail = true; engine->ExecuteString(0, "ui64 = -123; "); if( ui64 != -123 ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "ui = uint(d);"); if( ui != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui = uint(f);"); if( ui != asUINT(-12) ) fail = true; ui = 123; engine->ExecuteString(0, "ui = uint(ui);"); if( ui != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui = uint(ui8);"); if( ui != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui = uint(ui16);"); if( ui != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui = uint(ui64);"); if( ui != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui = uint(i);"); if( ui != asUINT(-123) ) fail = true; i8 = -123; engine->ExecuteString(0, "ui = uint(i8);"); if( ui != asUINT(-123) ) fail = true; i16 = -123; engine->ExecuteString(0, "ui = uint(i16);"); if( ui != asUINT(-123) ) fail = true; i64 = -123; engine->ExecuteString(0, "ui = uint(i64);"); if( ui != asUINT(-123) ) fail = true; d = 12.3; engine->ExecuteString(0, "ui = d;"); if( ui != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui = f;"); if( ui != asUINT(-12) ) fail = true; ui = 123; engine->ExecuteString(0, "ui = ui;"); if( ui != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui = ui8;"); if( ui != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui = ui16;"); if( ui != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui = ui64;"); if( ui != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui = i;"); if( ui != asUINT(-123) ) fail = true; i8 = -123; engine->ExecuteString(0, "ui = i8;"); if( ui != asUINT(-123) ) fail = true; i16 = -123; engine->ExecuteString(0, "ui = i16;"); if( ui != asUINT(-123) ) fail = true; i64 = -123; engine->ExecuteString(0, "ui = i64;"); if( ui != asUINT(-123) ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "ui = 12.3; "); if( ui != 12 ) fail = true; engine->ExecuteString(0, "ui = -12.3f;"); if( ui != asUINT(-12) ) fail = true; engine->ExecuteString(0, "ui = 123; "); if( ui != 123 ) fail = true; engine->ExecuteString(0, "ui = -123; "); if( ui != asUINT(-123) ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "ui8 = uint8(d);"); if( ui8 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui8 = uint8(f);"); if( ui8 != asBYTE(-12) ) fail = true; ui = 123; engine->ExecuteString(0, "ui8 = uint8(ui);"); if( ui8 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui8 = uint8(ui8);"); if( ui8 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui8 = uint8(ui16);"); if( ui8 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui8 = uint8(ui64);"); if( ui8 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui8 = uint8(i);"); if( ui8 != asBYTE(-123) ) fail = true; i8 = -123; engine->ExecuteString(0, "ui8 = uint8(i8);"); if( ui8 != asBYTE(-123) ) fail = true; i16 = -123; engine->ExecuteString(0, "ui8 = uint8(i16);"); if( ui8 != asBYTE(-123) ) fail = true; i64 = -123; engine->ExecuteString(0, "ui8 = uint8(i64);"); if( ui8 != asBYTE(-123) ) fail = true; d = 12.3; engine->ExecuteString(0, "ui8 = d;"); if( ui8 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui8 = f;"); if( ui8 != asBYTE(-12) ) fail = true; ui = 123; engine->ExecuteString(0, "ui8 = ui;"); if( ui8 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui8 = ui8;"); if( ui8 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui8 = ui16;"); if( ui8 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui8 = ui64;"); if( ui8 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui8 = i;"); if( ui8 != asBYTE(-123) ) fail = true; i8 = -123; engine->ExecuteString(0, "ui8 = i8;"); if( ui8 != asBYTE(-123) ) fail = true; i16 = -123; engine->ExecuteString(0, "ui8 = i16;"); if( ui8 != asBYTE(-123) ) fail = true; i64 = -123; engine->ExecuteString(0, "ui8 = i64;"); if( ui8 != asBYTE(-123) ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "ui8 = 12.3; "); if( ui8 != 12 ) fail = true; engine->ExecuteString(0, "ui8 = -12.3f;"); if( ui8 != asBYTE(-12) ) fail = true; // asBYTE(-12.3f) doesn't seem to produce the same result on MSVC and GNUC engine->ExecuteString(0, "ui8 = 123; "); if( ui8 != 123 ) fail = true; engine->ExecuteString(0, "ui8 = -123; "); if( ui8 != asBYTE(-123) ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); d = 12.3; engine->ExecuteString(0, "ui16 = uint16(d);"); if( ui16 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui16 = uint16(f);"); if( ui16 != asWORD(-12) ) fail = true; ui = 123; engine->ExecuteString(0, "ui16 = uint16(ui);"); if( ui16 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui16 = uint16(ui8);"); if( ui16 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui16 = uint16(ui16);"); if( ui16 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui16 = uint16(ui64);"); if( ui16 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui16 = uint16(i);"); if( ui16 != asWORD(-123) ) fail = true; i8 = -123; engine->ExecuteString(0, "ui16 = uint16(i8);"); if( ui16 != asWORD(-123) ) fail = true; i16 = -123; engine->ExecuteString(0, "ui16 = uint16(i16);"); if( ui16 != asWORD(-123) ) fail = true; i64 = -123; engine->ExecuteString(0, "ui16 = uint16(i64);"); if( ui16 != asWORD(-123) ) fail = true; d = 12.3; engine->ExecuteString(0, "ui16 = d;"); if( ui16 != 12 ) fail = true; f = -12.3f; engine->ExecuteString(0, "ui16 = f;"); if( ui16 != asWORD(-12) ) fail = true; ui = 123; engine->ExecuteString(0, "ui16 = ui;"); if( ui16 != 123 ) fail = true; ui8 = 123; engine->ExecuteString(0, "ui16 = ui8;"); if( ui16 != 123 ) fail = true; ui16 = 123; engine->ExecuteString(0, "ui16 = ui16;"); if( ui16 != 123 ) fail = true; ui64 = 123; engine->ExecuteString(0, "ui16 = ui64;"); if( ui16 != 123 ) fail = true; i = -123; engine->ExecuteString(0, "ui16 = i;"); if( ui16 != asWORD(-123) ) fail = true; i8 = -123; engine->ExecuteString(0, "ui16 = i8;"); if( ui16 != asWORD(-123) ) fail = true; i16 = -123; engine->ExecuteString(0, "ui16 = i16;"); if( ui16 != asWORD(-123) ) fail = true; i64 = -123; engine->ExecuteString(0, "ui16 = i64;"); if( ui16 != asWORD(-123) ) fail = true; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "ui16 = 12.3; "); if( ui16 != 12 ) fail = true; engine->ExecuteString(0, "ui16 = -12.3f;"); if( ui16 != asWORD(-12) ) fail = true; // asWORD(-12.3f) doesn't seem to produce the same result on MSVC and GNUC engine->ExecuteString(0, "ui16 = 123; "); if( ui16 != 123 ) fail = true; engine->ExecuteString(0, "ui16 = -123; "); if( ui16 != asWORD(-123) ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); engine->ExecuteString(0, "TestDouble(d); TestFloat(d); TestInt(d); TestI16(d); TestI8(d); TestUInt(d); TestUI16(d); TestUI8(d);"); engine->ExecuteString(0, "TestDouble(f); TestFloat(f); TestInt(f); TestI16(f); TestI8(f); TestUInt(f); TestUI16(f); TestUI8(f);"); engine->ExecuteString(0, "TestDouble(ui); TestFloat(ui); TestInt(ui); TestI16(ui); TestI8(ui); TestUInt(ui); TestUI16(ui); TestUI8(ui);"); engine->ExecuteString(0, "TestDouble(ui8); TestFloat(ui8); TestInt(ui8); TestI16(ui8); TestI8(ui8); TestUInt(ui8); TestUI16(ui8); TestUI8(ui8);"); engine->ExecuteString(0, "TestDouble(ui16); TestFloat(ui16); TestInt(ui16); TestI16(ui16); TestI8(ui16); TestUInt(ui16); TestUI16(ui16); TestUI8(ui16);"); engine->ExecuteString(0, "TestDouble(ui64); TestFloat(ui64); TestInt(ui64); TestI16(ui64); TestI8(ui64); TestUInt(ui64); TestUI16(ui64); TestUI8(ui64);"); engine->ExecuteString(0, "TestDouble(i); TestFloat(i); TestInt(i); TestI16(i); TestI8(i); TestUInt(i); TestUI16(i); TestUI8(i);"); engine->ExecuteString(0, "TestDouble(i8); TestFloat(i8); TestInt(i8); TestI16(i8); TestI8(i8); TestUInt(i8); TestUI16(i8); TestUI8(i8);"); engine->ExecuteString(0, "TestDouble(i16); TestFloat(i16); TestInt(i16); TestI16(i16); TestI8(i16); TestUInt(i16); TestUI16(i16); TestUI8(i16);"); engine->ExecuteString(0, "TestDouble(i64); TestFloat(i64); TestInt(i64); TestI16(i64); TestI8(i64); TestUInt(i64); TestUI16(i64); TestUI8(i64);"); d = 0; i8 = -22; engine->ExecuteString(0, "d = d + i8"); if( d != -22 ) fail = true; engine->ExecuteString(0, "int[] a(1); a[0] = 0; a[0] == 1"); engine->ExecuteString(0, "ui + i"); engine->ExecuteString(0, "int a = 0, ui = 0; (a+ui)&1;"); // There is no bitwise conversion between uint to float anymore // f = 0; engine->ExecuteString(0, "f = float(0x3f800000)"); if( f != 1 ) fail = true; bout.buffer = ""; engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->ExecuteString(0, "i == ui"); if( bout.buffer != "ExecuteString (1, 3) : Warning : Signed/Unsigned mismatch\n" ) fail = true; bout.buffer = ""; int r; // TODO: PPC: We cannot allow this with PPC // Allow the conversion of a type to another even for reference parameters (C++ doesn't allow this) r = engine->ExecuteString(0, "TestDoubleByRef(d); TestFloatByRef(d); TestIntByRef(d); TestI16ByRef(d); TestI8ByRef(d); TestUIntByRef(d); TestUI16ByRef(d); TestUI8ByRef(d);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(f); TestFloatByRef(f); TestIntByRef(f); TestI16ByRef(f); TestI8ByRef(f); TestUIntByRef(f); TestUI16ByRef(f); TestUI8ByRef(f);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(ui); TestFloatByRef(ui); TestIntByRef(ui); TestI16ByRef(ui); TestI8ByRef(ui); TestUIntByRef(ui); TestUI16ByRef(ui); TestUI8ByRef(ui);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(ui8); TestFloatByRef(ui8); TestIntByRef(ui8); TestI16ByRef(ui8); TestI8ByRef(ui8); TestUIntByRef(ui8); TestUI16ByRef(ui8); TestUI8ByRef(ui8);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(ui16); TestFloatByRef(ui16); TestIntByRef(ui16); TestI16ByRef(ui16); TestI8ByRef(ui16); TestUIntByRef(ui16); TestUI16ByRef(ui16); TestUI8ByRef(ui16);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(ui64); TestFloatByRef(ui64); TestIntByRef(ui64); TestI16ByRef(ui64); TestI8ByRef(ui64); TestUIntByRef(ui64); TestUI16ByRef(ui64); TestUI8ByRef(ui64);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(i); TestFloatByRef(i); TestIntByRef(i); TestI16ByRef(i); TestI8ByRef(i); TestUIntByRef(i); TestUI16ByRef(i); TestUI8ByRef(i);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(i8); TestFloatByRef(i8); TestIntByRef(i8); TestI16ByRef(i8); TestI8ByRef(i8); TestUIntByRef(i8); TestUI16ByRef(i8); TestUI8ByRef(i8);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(i16); TestFloatByRef(i16); TestIntByRef(i16); TestI16ByRef(i16); TestI8ByRef(i16); TestUIntByRef(i16); TestUI16ByRef(i16); TestUI8ByRef(i16);"); if( r < 0 ) fail = true; r = engine->ExecuteString(0, "TestDoubleByRef(i64); TestFloatByRef(i64); TestIntByRef(i64); TestI16ByRef(i64); TestI8ByRef(i64); TestUIntByRef(i64); TestUI16ByRef(i64); TestUI8ByRef(i64);"); if( r < 0 ) fail = true; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script, strlen(script)); mod->Build(); // This test is to make sure that the float is in fact converted to a double engine->ExecuteString(0, "TestScript();"); // Make sure uint and int can be converted to bits when using the ~ operator engine->ExecuteString(0, "uint x = 0x34; x = ~x;"); engine->ExecuteString(0, "int x = 0x34; x = ~x;"); engine->Release(); if( fail ) printf("%s: failed\n", TESTNAME); // Success return fail; }
bool Test2() { bool fail = false; int r; COutStream out; asIScriptEngine *engine; asIScriptModule *mod; // An interface that is declared equally in two different modules should receive the same type id // As of release 2.23.0, the interface must be explicitly marked as shared { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); const char *script = "shared interface Simple { void function(int); }"; mod = engine->GetModule("a", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script, strlen(script)); r = mod->Build(); if( r < 0 ) TEST_FAILED; mod = engine->GetModule("b", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script, strlen(script)); r = mod->Build(); if( r < 0 ) TEST_FAILED; int typeA = engine->GetModule("a")->GetTypeIdByDecl("Simple"); int typeB = engine->GetModule("b")->GetTypeIdByDecl("Simple"); if( typeA != typeB ) TEST_FAILED; // Test recompiling a module mod = engine->GetModule("a", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script, strlen(script)); r = mod->Build(); if( r < 0 ) TEST_FAILED; typeA = engine->GetModule("a")->GetTypeIdByDecl("Simple"); if( typeA != typeB ) TEST_FAILED; // Test interface that references itself const char *script1 = "shared interface A { A@ f(); }"; mod = engine->GetModule("a", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script1, strlen(script1)); r = mod->Build(); if( r < 0 ) TEST_FAILED; mod = engine->GetModule("b", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script1, strlen(script1)); r = mod->Build(); if( r < 0 ) TEST_FAILED; int typeAA = engine->GetModule("a")->GetTypeIdByDecl("A"); int typeBA = engine->GetModule("b")->GetTypeIdByDecl("A"); if( typeAA != typeBA ) TEST_FAILED; engine->Release(); } // Test with more complex interfaces { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); const char *script2 = "shared interface A { B@ f(); } \n" "shared interface B { A@ f1(); C@ f2(); } \n" "shared interface C { A@ f(); } \n"; mod = engine->GetModule("a", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script2, strlen(script2)); r = mod->Build(); if( r < 0 ) TEST_FAILED; mod = engine->GetModule("b", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script2, strlen(script2)); r = mod->Build(); if( r < 0 ) TEST_FAILED; int typeAA = engine->GetModule("a")->GetTypeIdByDecl("A"); int typeAB = engine->GetModule("a")->GetTypeIdByDecl("B"); int typeAC = engine->GetModule("a")->GetTypeIdByDecl("C"); int typeBA = engine->GetModule("b")->GetTypeIdByDecl("A"); int typeBB = engine->GetModule("b")->GetTypeIdByDecl("B"); int typeBC = engine->GetModule("b")->GetTypeIdByDecl("C"); if( typeAA != typeBA || typeAB != typeBB || typeAC != typeBC ) TEST_FAILED; engine->Release(); } // Test interfaces that are not equal { CBufferedOutStream bout; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); const char *script3 = "shared interface A { B@ f(); } shared interface B { int f(); }"; const char *script4 = "shared interface A { B@ f(); } shared interface B { float f(); }"; mod = engine->GetModule("a", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script3, strlen(script3)); r = mod->Build(); if( r < 0 ) TEST_FAILED; // Shared interfaces won't allow compiling two interfaces with the same name but different methods mod = engine->GetModule("b", asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script4, strlen(script4)); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "script (1, 53) : Error : Shared type 'B' doesn't match the original declaration in other module\n" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Interfaces that uses the interfaces that are substituted must be updated { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); const char *script5 = "shared interface A { float f(); }"; const char *script6 = "shared interface B { A@ f(); }"; mod = engine->GetModule("a", asGM_ALWAYS_CREATE); mod->AddScriptSection("script5", script5, strlen(script5)); r = mod->Build(); if( r < 0 ) TEST_FAILED; mod = engine->GetModule("b", asGM_ALWAYS_CREATE); mod->AddScriptSection("script5", script5, strlen(script5)); mod->AddScriptSection("script6", script6, strlen(script6)); r = mod->Build(); if( r < 0 ) TEST_FAILED; int typeBA = engine->GetModule("b")->GetTypeIdByDecl("A@"); int typeBB = engine->GetModule("b")->GetTypeIdByDecl("B"); asIObjectType *objType = engine->GetObjectTypeById(typeBB); asIScriptFunction *func = objType->GetMethodByIndex(0); if( func->GetReturnTypeId() != typeBA ) TEST_FAILED; engine->Release(); } // This must work for pre-compiled byte code as well, i.e. when loading the byte code // the interface ids must be resolved in the same way it is for compiled scripts { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod = engine->GetModule("a", asGM_ALWAYS_CREATE); const char *script1 = "shared interface A { A@ f(); }"; mod->AddScriptSection("script", script1, strlen(script1)); r = mod->Build(); if( r < 0 ) TEST_FAILED; CBytecodeStream stream(__FILE__"1"); asIScriptModule *module = engine->GetModule("a"); module->SaveByteCode(&stream); module = engine->GetModule("b", asGM_CREATE_IF_NOT_EXISTS); r = module->LoadByteCode(&stream); if( r < 0 ) TEST_FAILED; int typeAA = engine->GetModule("a")->GetTypeIdByDecl("A"); int typeBA = engine->GetModule("b")->GetTypeIdByDecl("A"); if( typeAA != typeBA ) TEST_FAILED; // TODO: The interfaces should be equal if they use enums declared in the // scripts as well (we don't bother checking the enum values) engine->Release(); } // Test multiple indirect implementations of interfaces // http://www.gamedev.net/topic/639243-funcdef-inside-shared-interface-interface-already-implement-warning/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); CBufferedOutStream bout; engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule("A", asGM_ALWAYS_CREATE); mod->AddScriptSection("A", "shared interface ielement\n" "{\n" " void dummy1();\n" "}\n" "shared interface isprite : ielement\n" "{\n" " void dummy2();\n" "}\n" "class celement : ielement\n" "{\n" " void dummy1() {}\n" "}\n" "class csprite : celement, isprite\n" "{\n" " csprite()\n" " {\n" " super();\n" " }\n" " void dummy2() {}\n" "}\n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { PRINTF("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } return fail; }
bool Test() { RET_ON_MAX_PORT bool fail = false; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); COutStream out; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); engine->RegisterGlobalFunction("void TestMe(uint val)", asMETHOD(Class1, TestMe), asCALL_THISCALL_ASGLOBAL, &c1); c1.a = 0; int r = ExecuteString(engine, "TestMe(0xDEADC0DE);"); if( r < 0 ) { PRINTF("%s: ExecuteString() failed %d\n", TESTNAME, r); TEST_FAILED; } if( c1.a != 0xDEADC0DE ) { PRINTF("Class member wasn't updated correctly\n"); TEST_FAILED; } // Register and call a derived method Base *obj = new Derived(); engine->RegisterGlobalFunction("void Print()", asMETHOD(Base, Print), asCALL_THISCALL_ASGLOBAL, obj); r = ExecuteString(engine, "Print()"); if( r < 0 ) TEST_FAILED; if( obj->str != "Called from Derived" ) TEST_FAILED; delete obj; // It must not be possible to register without the object pointer CBufferedOutStream bout; engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); r = engine->RegisterGlobalFunction("void Fail()", asMETHOD(Class1, TestMe), asCALL_THISCALL_ASGLOBAL, 0); if( r != asINVALID_ARG ) TEST_FAILED; if( bout.buffer != " (0, 0) : Error : Failed in call to function 'RegisterGlobalFunction' with 'void Fail()' (Code: -5)\n" ) { PRINTF("%s", bout.buffer.c_str()); } engine->Release(); // Test proper clean-up args passed by value // http://www.gamedev.net/topic/670017-weird-crash-in-userfree-on-android/ { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); bout.buffer = ""; r = engine->RegisterObjectType("PointF", sizeof(PointF), asOBJ_VALUE|asOBJ_POD|asOBJ_APP_CLASS_CK); assert( r >= 0); r = engine->RegisterObjectBehaviour( "PointF", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(PointF::ConstructorDefaultPointF), asCALL_CDECL_OBJLAST); assert( r >= 0); r = engine->RegisterObjectBehaviour( "PointF", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(PointF::DestructorPointF), asCALL_CDECL_OBJLAST); assert( r >= 0); Renderer render; r = engine->RegisterGlobalFunction( "void DrawSprite( int,int,PointF)", asMETHOD(Renderer, DrawSprite), asCALL_THISCALL_ASGLOBAL, &render); assert(r >= 0); r = ExecuteString(engine, "PointF p; DrawSprite(1,2,p);"); if( r < 0 ) TEST_FAILED; if( !render.allOK ) TEST_FAILED; if( bout.buffer != "" ) { PRINTF("%s", bout.buffer.c_str()); } engine->Release(); } return fail; }
bool Test() { if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { printf("Skipped due to AS_MAX_PORTABILITY\n"); return false; } bool fail = false; int r; CBufferedOutStream bout; COutStream out; asIScriptModule *mod; asIScriptEngine *engine; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, true); RegisterScriptString(engine); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); mod = engine->GetModule(0, asGM_ALWAYS_CREATE); // The getter can return a handle while the setter takes a reference { const char *script = "class Test \n" "{ \n" " string @get_s() { return 'test'; } \n" " void set_s(const string &in) {} \n" "} \n" "void func() \n" "{ \n" " Test t; \n" " string s = t.s; \n" " t.s = s; \n" "} \n"; mod->AddScriptSection("script", script); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } r = ExecuteString(engine, "Test t; @t.s = 'test';", mod); if( r >= 0 ) { TEST_FAILED; printf("Shouldn't be allowed\n"); } if( bout.buffer != "ExecuteString (1, 14) : Error : It is not allowed to perform a handle assignment on a non-handle property\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } } // main1 and main2 should produce the same bytecode const char *script1 = "class Test \n" "{ \n" " int get_prop() { return _prop; } \n" " void set_prop(int v) { _prop = v; } \n" " int _prop; \n" "} \n" "void main1() \n" "{ \n" " Test t; \n" " t.set_prop(42); \n" " assert( t.get_prop() == 42 ); \n" "} \n" "void main2() \n" "{ \n" " Test t; \n" " t.prop = 42; \n" " assert( t.prop == 42 ); \n" "} \n"; mod->AddScriptSection("script", script1); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "main1()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } r = ExecuteString(engine, "main2()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Test compound assignment with accessors (not allowed) const char *script2 = "class Test \n" "{ \n" " void set_prop(int v) { _prop = v; } \n" " int _prop; \n" "} \n" "void main1() \n" "{ \n" " Test t; \n" " t.prop += 42; \n" "} \n"; mod->AddScriptSection("script", script2); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) { TEST_FAILED; } if( bout.buffer != "script (6, 1) : Info : Compiling void main1()\n" "script (9, 10) : Error : Compound assignments with property accessors are not allowed\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test get accessor with boolean operators const char *script3 = "class Test \n" "{ \n" " bool get_boolProp() { return true; } \n" "} \n" "void main1() \n" "{ \n" " Test t; \n" " if( t.boolProp ) {} \n" " if( t.boolProp && true ) {} \n" " if( false || t.boolProp ) {} \n" " if( t.boolProp ^^ t.boolProp ) {} \n" " if( !t.boolProp ) {} \n" " t.boolProp ? t.boolProp : t.boolProp; \n" "} \n"; mod->AddScriptSection("script", script3); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test get accessor with math operators const char *script4 = "class Test \n" "{ \n" " float get_prop() { return 1.0f; } \n" "} \n" "void main1() \n" "{ \n" " Test t; \n" " float f = t.prop * 1; \n" " f = (t.prop) + 1; \n" " 10 / t.prop; \n" " -t.prop; \n" "} \n"; mod->AddScriptSection("script", script4); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test get accessor with bitwise operators const char *script5 = "class Test \n" "{ \n" " uint get_prop() { return 1; } \n" "} \n" "void main1() \n" "{ \n" " Test t; \n" " t.prop << t.prop; \n" " t.prop & t.prop; \n" " ~t.prop; \n" "} \n"; mod->AddScriptSection("script", script5); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test multiple get accessors for same property. Should give error // Test multiple set accessors for same property. Should give error const char *script6 = "class Test \n" "{ \n" " uint get_p() {return 0;} \n" " float get_p() {return 0;} \n" " void set_s(float) {} \n" " void set_s(uint) {} \n" "} \n" "void main() \n" "{ \n" " Test t; \n" " t.p; \n" " t.s = 0; \n" "} \n"; mod->AddScriptSection("script", script6); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "script (8, 1) : Info : Compiling void main()\n" "script (11, 4) : Error : Found multiple get accessors for property 'p'\n" "script (11, 4) : Info : uint Test::get_p()\n" "script (11, 4) : Info : float Test::get_p()\n" "script (12, 4) : Error : Found multiple set accessors for property 's'\n" "script (12, 4) : Info : void Test::set_s(float)\n" "script (12, 4) : Info : void Test::set_s(uint)\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test mismatching type between get accessor and set accessor. Should give error const char *script7 = "class Test \n" "{ \n" " uint get_p() {return 0;} \n" " void set_p(float) {} \n" "} \n" "void main() \n" "{ \n" " Test t; \n" " t.p; \n" "} \n"; mod->AddScriptSection("script", script7); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "script (6, 1) : Info : Compiling void main()\n" "script (9, 4) : Error : The property 'p' has mismatching types for the get and set accessors\n" "script (9, 4) : Info : uint Test::get_p()\n" "script (9, 4) : Info : void Test::set_p(float)\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test only set accessor for read expression // Test only get accessor for write expression const char *script8 = "class Test \n" "{ \n" " uint get_g() {return 0;} \n" " void set_s(float) {} \n" "} \n" "void main() \n" "{ \n" " Test t; \n" " t.g = 0; \n" " t.s + 1; \n" "} \n"; mod->AddScriptSection("script", script8); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "script (6, 1) : Info : Compiling void main()\n" "script (9, 7) : Error : The property has no set accessor\n" "script (10, 7) : Error : The property has no get accessor\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test pre and post ++. Should fail, since the expression is not a variable const char *script9 = "class Test \n" "{ \n" " uint get_p() {return 0;} \n" " void set_p(uint) {} \n" "} \n" "void main() \n" "{ \n" " Test t; \n" " t.p++; \n" " --t.p; \n" "} \n"; mod->AddScriptSection("script", script9); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) { TEST_FAILED; printf("Didn't fail to compile the script\n"); } if( bout.buffer != "script (6, 1) : Info : Compiling void main()\n" "script (9, 6) : Error : Invalid reference. Property accessors cannot be used in combined read/write operations\n" "script (10, 3) : Error : Invalid reference. Property accessors cannot be used in combined read/write operations\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test using property accessors from within class methods without 'this' // Test accessor where the object is a handle const char *script10 = "class Test \n" "{ \n" " uint get_p() {return 0;} \n" " void set_p(uint) {} \n" " void test() \n" " { \n" " p = 0; \n" " int a = p; \n" " } \n" "} \n" "void func() \n" "{ \n" " Test @a = Test(); \n" " a.p = 1; \n" " int b = a.p; \n" "} \n"; mod->AddScriptSection("script", script10); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Test accessors with function arguments (by value, in ref, out ref) const char *script11 = "class Test \n" "{ \n" " uint get_p() {return 0;} \n" " void set_p(uint) {} \n" "} \n" "void func() \n" "{ \n" " Test a(); \n" " byVal(a.p); \n" " inArg(a.p); \n" " outArg(a.p); \n" "} \n" "void byVal(int v) {} \n" "void inArg(int &in v) {} \n" "void outArg(int &out v) {} \n"; mod->AddScriptSection("script", script11); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // When the property is an object type, then the set accessor should be // used instead of the overloaded assignment operator to set the value. // Properties of object properties, must allow having different // types for get and set. IsEqualExceptConstAndRef should be used. const char *script12 = "class Test \n" "{ \n" " string get_s() {return _s;} \n" " void set_s(const string &in n) {_s = n;} \n" " string _s; \n" "} \n" "void func() \n" "{ \n" " Test t; \n" " t.s = 'hello'; \n" " assert(t.s == 'hello'); \n" "} \n"; mod->AddScriptSection("script", script12); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Compound assignments for object properties will not be allowed r = ExecuteString(engine, "Test t; t.s += 'hello';", mod); if( r >= 0 ) { TEST_FAILED; } if( bout.buffer != "ExecuteString (1, 13) : Error : Compound assignments with property accessors are not allowed\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test @t.prop = @obj; Property is a handle, and the property is assigned a new handle. Should work const char *script13 = "class Test \n" "{ \n" " string@ get_s() {return _s;} \n" " void set_s(string @n) {@_s = @n;} \n" " string@ _s; \n" "} \n" "void func() \n" "{ \n" " Test t; \n" " string s = 'hello'; \n" " @t.s = @s; \n" // handle assignment " assert(t.s is s); \n" " t.s = 'other'; \n" // value assignment " assert(s == 'other'); \n" "} \n"; mod->AddScriptSection("script", script13); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Test accessing members of an object property const char *script14 = "class Test \n" "{ \n" " string get_s() {return _s;} \n" " void set_s(string n) {_s = n;} \n" " string _s; \n" "} \n" "void func() \n" "{ \n" " Test t; \n" " t.s = 'hello'; \n" // value assignment " assert(t.s == 'hello'); \n" " assert(t.s.length() == 5); \n" // this should work as length is const "} \n"; mod->AddScriptSection("script", script14); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Test accessing a non-const method on an object through a get accessor // Should at least warn since the object is just a temporary one bout.buffer.c_str(); r = ExecuteString(engine, "Test t; t.s.resize(4);", mod); if( r < 0 ) TEST_FAILED; if( (sizeof(void*) == 4 && bout.buffer != "ExecuteString (1, 13) : Warning : A non-const method is called on temporary object. Changes to the object may be lost.\n" "ExecuteString (1, 13) : Info : void string::resize(uint)\n") || (sizeof(void*) == 8 && bout.buffer != "ExecuteString (1, 13) : Warning : A non-const method is called on temporary object. Changes to the object may be lost.\n" "ExecuteString (1, 13) : Info : void string::resize(uint64)\n") ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test opNeg for object through get accessor const char *script15 = "class Val { int opNeg() const { return -1; } } \n" "class Test \n" "{ \n" " Val get_s() const {return Val();} \n" "} \n" "void func() \n" "{ \n" " Test t; \n" " assert( -t.s == -1 ); \n" "} \n"; mod->AddScriptSection("script", script15); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Test index operator for object through get accessor const char *script16 = "class Test \n" "{ \n" " int[] get_s() const { int[] a(1); a[0] = 42; return a; } \n" "} \n" "void func() \n" "{ \n" " Test t; \n" " assert( t.s[0] == 42 ); \n" "} \n"; mod->AddScriptSection("script", script16); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "script (5, 1) : Info : Compiling void func()\n" "script (8, 14) : Warning : A non-const method is called on temporary object. Changes to the object may be lost.\n" "script (8, 14) : Info : int& array::opIndex(uint)\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Test accessing normal properties for object through get accessor const char *script17 = "class Val { int val; } \n" "class Test \n" "{ \n" " Val get_s() const { Val v; v.val = 42; return v;} \n" "} \n" "void func() \n" "{ \n" " Test t; \n" " assert( t.s.val == 42 ); \n" "} \n"; mod->AddScriptSection("script", script17); bout.buffer = ""; r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("Failed to compile the script\n"); } if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "func()", mod); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; } // Test const/non-const get and set accessors const char *script18 = "class Test \n" "{ \n" " int get_p() { return 42; } \n" " int get_c() const { return 42; } \n" " void set_s(int) {} \n" "} \n" "void func() \n" "{ \n" " const Test @t = @Test(); \n" " assert( t.p == 42 ); \n" // Fail " assert( t.c == 42 ); \n" // Success " t.s = 42; \n" // Fail "} \n"; mod->AddScriptSection("script", script18); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "script (7, 1) : Info : Compiling void func()\n" "script (10, 15) : Error : Non-const method call on read-only object reference\n" "script (10, 15) : Info : int Test::get_p()\n" "script (12, 7) : Error : Non-const method call on read-only object reference\n" "script (12, 7) : Info : void Test::set_s(int)\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } // Test accessor with property of the same name const char *script19 = "int direction; \n" "void set_direction(int val) { direction = val; } \n" "void test_set() \n" "{ \n" " direction = 9; \n" // calls the set_direction property accessor "} \n" "void test_get() \n" "{ \n" " assert( direction == 9 ); \n" // fails, since there is no get accessor "} \n"; mod->AddScriptSection("script", script19); bout.buffer = ""; r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "script (7, 1) : Info : Compiling void test_get()\n" "script (9, 21) : Error : The property has no get accessor\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } const char *script20 = "class Test { \n" " int direction; \n" " void set_direction(int val) { direction = val; } \n" "} \n"; mod->AddScriptSection("script", script20); bout.buffer = ""; r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "Test t; t.set_direction(3);", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; // TODO: Test non-const get accessor for object type with const overloaded dual operator // TODO: Test get accessor that returns a reference (only from application func to start with) // TODO: Test property accessor with inout references. Shouldn't be allowed as the value is not a valid reference // TODO: Test set accessor with parameter declared as out ref (shouldn't be found) // TODO: What should be done with expressions like t.prop; Should the get accessor be called even though // the value is never used? // TODO: Accessing a class member from within the property accessor with the same name as the property // shouldn't call the accessor again. Instead it should access the real member. FindPropertyAccessor() // shouldn't find any if the function being compiler is the property accessor itself engine->Release(); // Test property accessor on temporary object handle { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterStdString(engine); const char *script = "class Obj { void set_opacity(float v) {} }\n" "Obj @GetObject() { return @Obj(); } \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "GetObject().opacity = 1.0f;", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test bug reported by Scarabus2 // The bug was an incorrect reusage of temporary variable by the // property get accessor when compiling a binary operator { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "class Object { \n" " Object() {rot = 0;} \n" " void set_rotation(float r) {rot = r;} \n" " float get_rotation() const {return rot;} \n" " float rot; } \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "Object obj; \n" "float elapsed = 1.0f; \n" "float temp = obj.rotation + elapsed * 1.0f; \n" "obj.rotation = obj.rotation + elapsed * 1.0f; \n" "assert( obj.rot == 1 ); \n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test global property accessor { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "int _s = 0; \n" "int get_s() { return _s; } \n" "void set_s(int v) { _s = v; } \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "s = 10; assert( s == 10 );", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); // The global property accessors are available to initialize global // variables, but can possibly throw an exception if used inappropriately. // This test also verifies that circular references between global // properties and functions is properly resolved by the GC. engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); RegisterStdString(engine); bout.buffer = ""; script = "string _s = s; \n" "string get_s() { return _s; } \n"; mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r != asINIT_GLOBAL_VARS_FAILED ) TEST_FAILED; if( bout.buffer != "script (1, 13) : Error : Failed to initialize global variable '_s'\n" "script (2, 0) : Info : Exception 'Null pointer access' in 'string get_s()'\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Test property accessor for object in array { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "class MyObj { bool get_Active() { return true; } } \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "MyObj[] a(1); if( a[0].Active == true ) { } if( a[0].get_Active() == true ) { }", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test property accessor from within class method { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); const char *script = "class Vector3 \n" "{ \n" " float x; \n" " float y; \n" " float z; \n" "}; \n" "class Hoge \n" "{ \n" " const Vector3 get_pos() { return mPos; } \n" " const Vector3 foo() { return pos; } \n" " const Vector3 zoo() { return get_pos(); } \n" " Vector3 mPos; \n" "}; \n" "void main() \n" "{ \n" " Hoge h; \n" " Vector3 vec; \n" " vec = h.zoo(); \n" // ok " vec = h.foo(); \n" // runtime exception "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test property accessor in type conversion { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); const char *script = "class sound \n" "{ \n" " int get_pitch() { return 1; } \n" " void set_pitch(int p) {} \n" "} \n" "void main() \n" "{ \n" " sound[] sounds(1) ; \n" " sounds[0].pitch = int(sounds[0].pitch)/2; \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test property accessor in type conversion (2) { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); const char *script = "class sound \n" "{ \n" " const int &get_id() const { return i; } \n" " int i; \n" "} \n" "void main() \n" "{ \n" " sound s; \n" " if( s.id == 1 ) \n" " return; \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test property accessors for opIndex { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, false); RegisterScriptString(engine); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "class CTest \n" "{ \n" " CTest() { arr.resize(5); } \n" " int get_opIndex(int i) const { return arr[i]; } \n" " void set_opIndex(int i, int v) { arr[i] = v; } \n" " array<int> arr; \n" "} \n" "void main() \n" "{ \n" " CTest s; \n" " s[0] = 42; \n" " assert( s[0] == 42 ); \n" " s[1] = 24; \n" " assert( s[1] == 24 ); \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test global property accessors with index argument { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, false); RegisterScriptString(engine); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = " int get_arr(int i) { arr.resize(5); return arr[i]; } \n" " void set_arr(int i, int v) { arr.resize(5); arr[i] = v; } \n" " array<int> arr; \n" "void main() \n" "{ \n" " arr[0] = 42; \n" " assert( arr[0] == 42 ); \n" " arr[1] = 24; \n" " assert( arr[1] == 24 ); \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test member property accessors with index argument { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream, Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, false); RegisterScriptString(engine); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); const char *script = "class CTest \n" "{ \n" " CTest() { arr.resize(5); } \n" " int get_arr(int i) { return arr[i]; } \n" " void set_arr(int i, int v) { arr[i] = v; } \n" " private array<int> arr; \n" " void test() \n" " { \n" " arr[0] = 42; \n" " assert( arr[0] == 42 ); \n" " arr[1] = 24; \n" " assert( arr[1] == 24 ); \n" " } \n" "} \n" "void main() \n" "{ \n" " CTest s; \n" " s.arr[0] = 42; \n" " assert( s.arr[0] == 42 ); \n" " s.arr[1] = 24; \n" " assert( s.arr[1] == 24 ); \n" " s.test(); \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "main()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test member property accessors with ++ where the set accessor takes a reference { engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL); bout.buffer = ""; const char *script = "class CTest \n" "{ \n" " double _vol; \n" " double get_vol() const { return _vol; } \n" " void set_vol(double &in v) { _vol = v; } \n" "} \n" "CTest t; \n" "void main() \n" "{ \n" " for( t.vol = 0; t.vol < 10; t.vol++ ); \n" "} \n"; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("script", script); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "script (8, 1) : Info : Compiling void main()\n" "script (10, 36) : Error : Invalid reference. Property accessors cannot be used in combined read/write operations\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } fail = Test2() || fail; // Success return fail; }
bool Test() { bool fail = false; int r; asIScriptEngine *engine; CBufferedOutStream bout; engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->ClearMessageCallback(); // Make sure this works engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); RegisterScriptArray(engine, true); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptFunction *func = engine->GetGlobalFunctionByDecl("void assert(bool)"); if( func == 0 ) TEST_FAILED; if( std::string(func->GetDeclaration()) != "void assert(bool)" ) TEST_FAILED; r = engine->RegisterGlobalFunction("void func(mytype)", asFUNCTION(0), asCALL_GENERIC); if( r >= 0 ) TEST_FAILED; r = engine->RegisterGlobalFunction("void func(int &)", asFUNCTION(0), asCALL_GENERIC); if( !engine->GetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES) ) { if( r >= 0 ) TEST_FAILED; } else { if( r < 0 ) TEST_FAILED; } r = engine->RegisterObjectType("mytype", 0, asOBJ_REF); if( r < 0 ) TEST_FAILED; r = engine->RegisterObjectBehaviour("mytype", asBEHAVE_CONSTRUCT, "void f(othertype)", asFUNCTION(0), asCALL_GENERIC); if( r >= 0 ) TEST_FAILED; r = engine->RegisterObjectMethod("mytype", "type opAdd(int) const", asFUNCTION(0), asCALL_GENERIC); if( r >= 0 ) TEST_FAILED; r = engine->RegisterGlobalProperty("type a", (void*)1); if( r >= 0 ) TEST_FAILED; r = engine->RegisterObjectMethod("mytype", "void method(int &)", asFUNCTION(0), asCALL_GENERIC); if( !engine->GetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES) ) { if( r >= 0 ) TEST_FAILED; } else { if( r < 0 ) TEST_FAILED; } r = engine->RegisterObjectProperty("mytype", "type a", 0); if( r >= 0 ) TEST_FAILED; r = engine->RegisterStringFactory("type", asFUNCTION(0), asCALL_GENERIC); if( r >= 0 ) TEST_FAILED; // Verify the output messages if( !engine->GetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES) ) { if( bout.buffer != "System function (1, 11) : Error : Identifier 'mytype' is not a data type\n" " (0, 0) : Error : Failed in call to function 'RegisterGlobalFunction' with 'void func(mytype)'\n" "System function (1, 15) : Error : Only object types that support object handles can use &inout. Use &in or &out instead\n" " (0, 0) : Error : Failed in call to function 'RegisterGlobalFunction' with 'void func(int &)'\n" "System function (1, 8) : Error : Identifier 'othertype' is not a data type\n" " (0, 0) : Error : Failed in call to function 'RegisterObjectBehaviour' with 'mytype' and 'void f(othertype)'\n" "System function (1, 1) : Error : Identifier 'type' is not a data type\n" " (0, 0) : Error : Failed in call to function 'RegisterObjectMethod' with 'mytype' and 'type opAdd(int) const'\n" "Property (1, 1) : Error : Identifier 'type' is not a data type\n" " (0, 0) : Error : Failed in call to function 'RegisterGlobalProperty' with 'type a'\n" "System function (1, 17) : Error : Only object types that support object handles can use &inout. Use &in or &out instead\n" " (0, 0) : Error : Failed in call to function 'RegisterObjectMethod' with 'mytype' and 'void method(int &)'\n" "Property (1, 1) : Error : Identifier 'type' is not a data type\n" " (0, 0) : Error : Failed in call to function 'RegisterObjectProperty' with 'mytype' and 'type a'\n" " (1, 1) : Error : Identifier 'type' is not a data type\n" " (0, 0) : Error : Failed in call to function 'RegisterStringFactory' with 'type'\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } } else { if( bout.buffer != "System function (1, 11) : Error : Identifier 'mytype' is not a data type\n" "System function (1, 8) : Error : Identifier 'othertype' is not a data type\n" "System function (1, 1) : Error : Identifier 'type' is not a data type\n" "System function (1, 8) : Error : Identifier 'type' is not a data type\n" "Property (1, 1) : Error : Identifier 'type' is not a data type\n" "Property (1, 1) : Error : Identifier 'type' is not a data type\n" " (1, 1) : Error : Identifier 'type' is not a data type\n") TEST_FAILED; } engine->Release(); // Success return fail; }
bool TestNotComplexStdcall() { if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { printf("%s: Skipped due to AS_MAX_PORTABILITY\n", TESTNAME); return false; } bool fail = false; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->RegisterObjectType("class1", sizeof(Class1), asOBJ_CLASS); engine->RegisterObjectType("class2", sizeof(Class2), asOBJ_CLASS); engine->RegisterObjectType("class3", sizeof(Class3), asOBJ_CLASS); engine->RegisterGlobalProperty("class1 c1", &c1); engine->RegisterGlobalProperty("class2 c2", &c2); engine->RegisterGlobalProperty("class3 c3", &c3); engine->RegisterGlobalFunction("class1 notComplex1()", asFUNCTION(notComplex1), asCALL_STDCALL); engine->RegisterGlobalFunction("class2 notComplex2()", asFUNCTION(notComplex2), asCALL_STDCALL); engine->RegisterGlobalFunction("class3 notComplex3()", asFUNCTION(notComplex3), asCALL_STDCALL); COutStream out; c1.a = 0; engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); int r = engine->ExecuteString(0, "c1 = notComplex1();"); if( r < 0 ) { printf("%s: ExecuteString() failed %d\n", TESTNAME, r); fail = true; } if( c1.a != 0xDEADC0DE ) { printf("%s: Failed to assign object returned from function. c1.a = %X\n", TESTNAME, c1.a); fail = true; } c2.a = 0; c2.b = 0; r = engine->ExecuteString(0, "c2 = notComplex2();"); if( r < 0 ) { printf("%s: ExecuteString() failed %d\n", TESTNAME, r); fail = true; } if( c2.a != 0xDEADC0DE ) { printf("%s: Failed to assign object returned from function. c2.a = %X\n", TESTNAME, c2.a); fail = true; } if( c2.b != 0x01234567 ) { printf("%s: Failed to assign object returned from function. c2.b = %X\n", TESTNAME, c2.b); fail = true; } c3.a = 0; c3.b = 0; c3.c = 0; r = engine->ExecuteString(0, "c3 = notComplex3();"); if( r < 0 ) { printf("%s: ExecuteString() failed %d\n", TESTNAME, r); fail = true; } if( c3.a != 0xDEADC0DE ) { printf("%s: Failed to assign object returned from function. c3.a = %X\n", TESTNAME, c3.a); fail = true; } if( c3.b != 0x01234567 ) { printf("%s: Failed to assign object returned from function. c3.b = %X\n", TESTNAME, c3.b); fail = true; } if( c3.c != 0x89ABCDEF ) { printf("%s: Failed to assign object returned from function. c3.c = %X\n", TESTNAME, c3.c); fail = true; } engine->Release(); return fail; }
static void RegisterInput(asIScriptEngine* engine) { engine->RegisterObjectType("TouchState", 0, asOBJ_REF); engine->RegisterObjectBehaviour("TouchState", asBEHAVE_ADDREF, "void f()", asFUNCTION(FakeAddRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectBehaviour("TouchState", asBEHAVE_RELEASE, "void f()", asFUNCTION(FakeReleaseRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectProperty("TouchState", "const int touchID", offsetof(TouchState, touchID_)); engine->RegisterObjectProperty("TouchState", "const IntVector2 position", offsetof(TouchState, position_)); engine->RegisterObjectProperty("TouchState", "const IntVector2 lastPosition", offsetof(TouchState, lastPosition_)); engine->RegisterObjectProperty("TouchState", "const IntVector2 delta", offsetof(TouchState, delta_)); engine->RegisterObjectProperty("TouchState", "const float pressure", offsetof(TouchState, pressure_)); engine->RegisterObjectType("JoystickState", 0, asOBJ_REF); engine->RegisterObjectBehaviour("JoystickState", asBEHAVE_ADDREF, "void f()", asFUNCTION(FakeAddRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectBehaviour("JoystickState", asBEHAVE_RELEASE, "void f()", asFUNCTION(FakeReleaseRef), asCALL_CDECL_OBJLAST); engine->RegisterObjectProperty("JoystickState", "const String name", offsetof(JoystickState, name_)); engine->RegisterObjectProperty("JoystickState", "const int joystickID", offsetof(JoystickState, joystickID_)); engine->RegisterObjectMethod("JoystickState", "bool get_controller() const", asMETHOD(JoystickState, IsController), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "uint get_numButtons() const", asMETHOD(JoystickState, GetNumButtons), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "uint get_numAxes() const", asMETHOD(JoystickState, GetNumAxes), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "uint get_numHats() const", asMETHOD(JoystickState, GetNumHats), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "bool get_buttonDown(uint) const", asMETHOD(JoystickState, GetButtonDown), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "bool get_buttonPress(uint) const", asMETHOD(JoystickState, GetButtonPress), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "float get_axisPosition(uint) const", asMETHOD(JoystickState, GetAxisPosition), asCALL_THISCALL); engine->RegisterObjectMethod("JoystickState", "int get_hatPosition(uint) const", asMETHOD(JoystickState, GetHatPosition), asCALL_THISCALL); RegisterObject<Input>(engine, "Input"); engine->RegisterObjectMethod("Input", "int AddScreenJoystick(XMLFile@+ layoutFile = null, XMLFile@+ styleFile = null)", asMETHOD(Input, AddScreenJoystick), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool RemoveScreenJoystick(int)", asMETHOD(Input, RemoveScreenJoystick), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool RecordGesture()", asMETHOD(Input, RecordGesture), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool SaveGestures(File@+)", asFUNCTION(InputSaveGestures), asCALL_CDECL_OBJLAST); engine->RegisterObjectMethod("Input", "bool SaveGestures(VectorBuffer&)", asFUNCTION(InputSaveGesturesVectorBuffer), asCALL_CDECL_OBJLAST); engine->RegisterObjectMethod("Input", "bool SaveGesture(File@+, uint)", asFUNCTION(InputSaveGesture), asCALL_CDECL_OBJLAST); engine->RegisterObjectMethod("Input", "bool SaveGesture(VectorBuffer&, uint)", asFUNCTION(InputSaveGestureVectorBuffer), asCALL_CDECL_OBJLAST); engine->RegisterObjectMethod("Input", "uint LoadGestures(File@+)", asFUNCTION(InputLoadGestures), asCALL_CDECL_OBJLAST); engine->RegisterObjectMethod("Input", "uint LoadGestures(VectorBuffer&)", asFUNCTION(InputLoadGesturesVectorBuffer), asCALL_CDECL_OBJLAST); engine->RegisterObjectMethod("Input", "bool RemoveGesture(uint)", asMETHOD(Input, RemoveGesture), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void RemoveAllGestures()", asMETHOD(Input, RemoveAllGestures), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int GetKeyFromName(const String&in) const", asMETHOD(Input, GetKeyFromName), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int GetKeyFromScancode(int) const", asMETHOD(Input, GetKeyFromScancode), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "String GetKeyName(int) const", asMETHOD(Input, GetKeyName), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int GetScancodeFromKey(int) const", asMETHOD(Input, GetScancodeFromKey), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int GetScancodeFromName(const String&in) const", asMETHOD(Input, GetScancodeFromName), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "String GetScancodeName(int) const", asMETHOD(Input, GetScancodeName), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_mouseVisible(bool)", asMETHOD(Input, SetMouseVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_mouseVisible() const", asMETHOD(Input, IsMouseVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_mouseGrabbed(bool)", asMETHOD(Input, SetMouseGrabbed), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_mouseGrabbed() const", asMETHOD(Input, IsMouseGrabbed), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_screenJoystickVisible(int, bool)", asMETHOD(Input, SetScreenJoystickVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_screenJoystickVisible(int)", asMETHOD(Input, IsScreenJoystickVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_screenKeyboardVisible(bool)", asMETHOD(Input, SetScreenKeyboardVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_screenKeyboardVisible() const", asMETHOD(Input, IsScreenKeyboardVisible), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_screenKeyboardSupport() const", asMETHOD(Input, GetScreenKeyboardSupport), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_touchEmulation(bool)", asMETHOD(Input, SetTouchEmulation), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_touchEmulation() const", asMETHOD(Input, GetTouchEmulation), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "void set_toggleFullscreen(bool)", asMETHOD(Input, SetToggleFullscreen), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_toggleFullscreen() const", asMETHOD(Input, GetToggleFullscreen), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_keyDown(int) const", asMETHOD(Input, GetKeyDown), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_keyPress(int) const", asMETHOD(Input, GetKeyPress), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_scancodeDown(int) const", asMETHOD(Input, GetScancodeDown), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_scancodePress(int) const", asMETHOD(Input, GetScancodePress), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_mouseButtonDown(int) const", asMETHOD(Input, GetMouseButtonDown), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_mouseButtonPress(int) const", asMETHOD(Input, GetMouseButtonPress), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_qualifierDown(int) const", asMETHOD(Input, GetQualifierDown), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_qualifierPress(int) const", asMETHOD(Input, GetQualifierPress), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_qualifiers() const", asMETHOD(Input, GetQualifiers), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "IntVector2 get_mousePosition() const", asMETHOD(Input, GetMousePosition), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "const IntVector2& get_mouseMove() const", asMETHOD(Input, GetMouseMove), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_mouseMoveX() const", asMETHOD(Input, GetMouseMoveX), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_mouseMoveY() const", asMETHOD(Input, GetMouseMoveY), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "int get_mouseMoveWheel() const", asMETHOD(Input, GetMouseMoveWheel), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "uint get_numTouches() const", asMETHOD(Input, GetNumTouches), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "TouchState@+ get_touches(uint) const", asMETHOD(Input, GetTouch), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "uint get_numJoysticks() const", asMETHOD(Input, GetNumJoysticks), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "JoystickState@+ get_joysticks(int)", asMETHOD(Input, GetJoystick), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "JoystickState@+ get_joysticksByIndex(uint)", asMETHOD(Input, GetJoystickByIndex), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_focus() const", asMETHOD(Input, HasFocus), asCALL_THISCALL); engine->RegisterObjectMethod("Input", "bool get_minimized() const", asMETHOD(Input, IsMinimized), asCALL_THISCALL); engine->RegisterGlobalFunction("Input@+ get_input()", asFUNCTION(GetInput), asCALL_CDECL); }
bool Test() { bool fail = false; int r; COutStream out; CBufferedOutStream bout; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptArray(engine, true); RegisterScriptString(engine); r = engine->RegisterGlobalFunction("void Assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); assert( r >= 0 ); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, script1); r = mod->Build(); if( r < 0 ) { TEST_FAILED; printf("%s: Failed to compile the script\n", TESTNAME); } asIScriptContext *ctx = engine->CreateContext(); r = ExecuteString(engine, "Test()", mod, ctx); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; printf("%s: Execution failed: %d\n", TESTNAME, r); } if( ctx ) ctx->Release(); engine->Release(); // Test value class with unsafe ref { asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); RegisterScriptMath3D(engine); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "class Good \n" "{ \n" " vector3 _val; \n" " Good(const vector3& in val) \n" " { \n" " _val = val; \n" " } \n" "}; \n" "class Bad \n" "{ \n" " vector3 _val; \n" " Bad(const vector3& val) \n" " { \n" " _val = val; \n" " } \n" "}; \n" "void test() \n" "{ \n" " // runs fine \n" " for (int i = 0; i < 2; i++) \n" " Good(vector3(1, 2, 3)); \n" " // causes vm stack corruption \n" " for (int i = 0; i < 2; i++) \n" " Bad(vector3(1, 2, 3)); \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; r = ExecuteString(engine, "test()", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test ref to primitives { bout.buffer = ""; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "void func(){ \n" " float a; \n" " uint8 b; \n" " int c; \n" " funcA(c, a, b); \n" "} \n" "void funcA(float& a, uint8& b, int& c) {} \n"); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "TestUnsafeRef (1, 1) : Info : Compiling void func()\n" "TestUnsafeRef (5, 3) : Error : No matching signatures to 'funcA(int, float, uint8)'\n" "TestUnsafeRef (5, 3) : Info : Candidates are:\n" "TestUnsafeRef (5, 3) : Info : void funcA(float&inout, uint8&inout, int&inout)\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Test problem found by TheAtom // Passing an inout reference to a handle to a function wasn't working properly { bout.buffer = ""; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "class T { int a; } \n" "void f(T@& p) { \n" " T t; \n" " t.a = 42; \n" " @p = t; \n" // or p=t; in which case t is copied "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "T @t; f(t); assert( t.a == 42 );\n", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // http://www.gamedev.net/topic/624722-bug-with/ { bout.buffer = ""; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "class T { T() { val = 123; } int val; } \n" "T g_t; \n" "T &GetTest() { return g_t; } \n" "void f(T@& t) { \n" " assert( t.val == 123 ); \n" "} \n" "void func() { \n" " f(GetTest()); \n" " f(@GetTest()); \n" " T @t = GetTest(); \n" " f(t); \n" "} \n"); r = mod->Build(); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "TestUnsafeRef (7, 1) : Info : Compiling void func()\n" "TestUnsafeRef (8, 3) : Error : No matching signatures to 'f(T)'\n" "TestUnsafeRef (8, 3) : Info : Candidates are:\n" "TestUnsafeRef (8, 3) : Info : void f(T@&inout)\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // http://www.gamedev.net/topic/624722-bug-with/ { bout.buffer = ""; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "class T { T() { val = 123; } int val; } \n" "T g_t; \n" "T &GetTest() { return g_t; } \n" "void f(T@& t) { \n" " assert( t.val == 123 ); \n" "} \n" "void func() { \n" " f(cast<T>(GetTest())); \n" " f(@GetTest()); \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } asIScriptContext *ctx = engine->CreateContext(); r = ExecuteString(engine, "func()", mod, ctx); if( r != asEXECUTION_FINISHED ) { TEST_FAILED; if( r == asEXECUTION_EXCEPTION ) PrintException(ctx, true); } ctx->Release(); engine->Release(); } // http://www.gamedev.net/topic/636443-there-is-no-copy-operator-for-the-type-val-available/ { bout.buffer = ""; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); engine->RegisterObjectType("Val", sizeof(int), asOBJ_VALUE | asOBJ_APP_PRIMITIVE); engine->RegisterObjectBehaviour("Val", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(0), asCALL_GENERIC); // With unsafe references the copy constructor doesn't have to be in, it can be inout too engine->RegisterObjectBehaviour("Val", asBEHAVE_CONSTRUCT, "void f(const Val &)", asFUNCTION(0), asCALL_GENERIC); engine->RegisterObjectBehaviour("Val", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(0), asCALL_GENERIC); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "Val GetVal() \n" "{ \n" " Val ret; \n" " return ret; \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); } // Test with copy constructor that takes unsafe reference // http://www.gamedev.net/topic/638613-asassert-in-file-as-compillercpp-line-675/ { bout.buffer = ""; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); r = engine->RegisterObjectType("string", sizeof(Str), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); r = engine->RegisterStringFactory("string", asFUNCTION(Str::StringFactory), asCALL_CDECL); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Str::StringConstruct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); // Copy constructor takes an unsafe reference r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &)", asFUNCTION(Str::StringCopyConstruct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Str::StringDestruct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in)", asMETHOD(Str, opEquals), asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "void SetTexture( string txt ) { assert( txt == 'test' ); } \n" "void startGame( ) \n" "{ \n" " SetTexture('test'); \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "startGame();", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Test with assignment operator that takes unsafe reference { bout.buffer = ""; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, 1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); engine->RegisterGlobalFunction("void assert(bool)", asFUNCTION(Assert), asCALL_GENERIC); r = engine->RegisterObjectType("string", sizeof(Str), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); r = engine->RegisterStringFactory("string", asFUNCTION(Str::StringFactory), asCALL_CDECL); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(Str::StringConstruct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(Str::StringDestruct), asCALL_CDECL_OBJLAST); assert( r >= 0 ); // Assignment operator takes an unsafe reference r = engine->RegisterObjectMethod("string", "string &opAssign(const string &)", asMETHOD(Str, opAssign), asCALL_THISCALL); assert( r >= 0 ); r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in)", asMETHOD(Str, opEquals), asCALL_THISCALL); asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection(TESTNAME, "void SetTexture( string txt ) { assert( txt == 'test' ); } \n" "void startGame( ) \n" "{ \n" " SetTexture('test'); \n" "} \n"); r = mod->Build(); if( r < 0 ) TEST_FAILED; if( bout.buffer != "" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } r = ExecuteString(engine, "startGame();", mod); if( r != asEXECUTION_FINISHED ) TEST_FAILED; engine->Release(); } // Success return fail; }
bool Test() { if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) { printf("%s: Skipped due to AS_MAX_PORTABILITY\n", TESTNAME); return false; } bool fail = false; asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); RegisterStdString(engine); engine->RegisterGlobalFunction("int a_int()", asFUNCTION(a_int), asCALL_CDECL); engine->RegisterGlobalFunction("int b_int()", asFUNCTION(b_int), asCALL_CDECL); engine->RegisterGlobalFunction("string a_str()", asFUNCTION(a_str), asCALL_CDECL); engine->RegisterGlobalFunction("string b_str()", asFUNCTION(b_str), asCALL_CDECL); engine->RegisterGlobalFunction("int &b_intref()", asFUNCTION(b_intref), asCALL_CDECL); engine->RegisterGlobalFunction("string &b_strref()", asFUNCTION(b_strref), asCALL_CDECL); engine->RegisterGlobalFunction("string &complex(string &out)", asFUNCTION(complex), asCALL_CDECL); engine->RegisterGlobalFunction("string &complex2()", asFUNCTION(complex2), asCALL_CDECL); engine->RegisterGlobalFunction("int &complex3(string &out)", asFUNCTION(complex3), asCALL_CDECL); string str; engine->RegisterGlobalProperty("string str", &str); engine->RegisterObjectType("prop", sizeof(CProp), asOBJ_REF); engine->RegisterObjectBehaviour("prop", asBEHAVE_ADDREF, "void f()", asMETHOD(CProp, AddRef), asCALL_THISCALL); engine->RegisterObjectBehaviour("prop", asBEHAVE_RELEASE, "void f()", asMETHOD(CProp, Release), asCALL_THISCALL); engine->RegisterObjectMethod("prop", "void Get(string &out)", asMETHOD(CProp,Get), asCALL_THISCALL); engine->RegisterGlobalFunction("prop @GetProp(string &in)", asFUNCTION(GetProp), asCALL_CDECL); COutStream out; asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE); mod->AddScriptSection("1", script1); mod->AddScriptSection("2", script2); mod->AddScriptSection("3", script3); mod->AddScriptSection("4", script4); mod->AddScriptSection("5", script5); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod->Build(); // Verify order of calculations output = ""; engine->ExecuteString(0, "a_str() + b_str()"); if( output != "ab" ) fail = true; output = ""; engine->ExecuteString(0, "b_strref() = a_str()"); if( output != "ab" ) fail = true; output = ""; engine->ExecuteString(0, "b_strref() += a_str()"); if( output != "ab" ) fail = true; output = ""; engine->ExecuteString(0, "a_int() + b_int()"); if( output != "ab" ) fail = true; output = ""; engine->ExecuteString(0, "b_intref() = a_int()"); if( output != "ab" ) fail = true; output = ""; engine->ExecuteString(0, "b_intref() += a_int()"); if( output != "ab" ) fail = true; // Nested output parameters with a returned reference ci = 0; cs = ""; str = ""; engine->ExecuteString(0, "complex3(complex(str)) = 1"); if( ci != 1 ) fail = true; if( cs != "outparm3" ) fail = true; if( str != "outparm" ) fail = true; str = ""; engine->ExecuteString(0, "GetProp(\"test\").Get(str);"); if( str != "PropOut" ) fail = true; engine->Release(); if( fail ) printf("%s: fail\n", TESTNAME); // Success return fail; }
void asCGlobalProperty::RegisterGCBehaviours(asCScriptEngine *engine) { // Register the gc behaviours for the global properties int r = 0; UNUSED_VAR(r); // It is only used in debug mode engine->globalPropertyBehaviours.engine = engine; engine->globalPropertyBehaviours.flags = asOBJ_REF | asOBJ_GC; engine->globalPropertyBehaviours.name = "_builtin_globalprop_"; #ifndef AS_MAX_PORTABILITY r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCGlobalProperty,AddRef), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCGlobalProperty,Release), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCGlobalProperty,GetRefCount), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCGlobalProperty,SetGCFlag), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCGlobalProperty,GetGCFlag), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCGlobalProperty,EnumReferences), asCALL_THISCALL); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCGlobalProperty,ReleaseAllHandles), asCALL_THISCALL); asASSERT( r >= 0 ); #else r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(GlobalProperty_AddRef_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(GlobalProperty_Release_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(GlobalProperty_GetRefCount_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(GlobalProperty_SetGCFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(GlobalProperty_GetGCFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(GlobalProperty_EnumReferences_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); r = engine->RegisterBehaviourToObjectType(&engine->globalPropertyBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(GlobalProperty_ReleaseAllHandles_Generic), asCALL_GENERIC); asASSERT( r >= 0 ); #endif }
bool Test() { bool fail = false; int r; CBufferedOutStream bout; COutStream out; asIScriptModule *mod; float val; //------------ // Test global properties asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->BeginConfigGroup("group"); assert( r >= 0 ); r = engine->RegisterGlobalProperty("float val", &val); assert( r >= 0 ); r = engine->EndConfigGroup(); assert( r >= 0 ); // Make sure the default access is granted r = ExecuteString(engine, "val = 1.3f"); if( r < 0 ) TEST_FAILED; // Make sure the default access can be turned off engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); mod = engine->GetModule("ExecuteString", asGM_ALWAYS_CREATE); mod->SetAccessMask(2); r = ExecuteString(engine, "val = 1.0f", mod); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 1) : Error : 'val' is not declared\n") TEST_FAILED; // Make sure the default access can be overridden engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); mod->SetAccessMask(1); r = ExecuteString(engine, "val = 1.0f", mod); if( r < 0 ) TEST_FAILED; engine->Release(); //---------- // Test global functions engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); engine->SetDefaultAccessMask(2); r = engine->BeginConfigGroup("group"); assert( r >= 0 ); r = engine->RegisterGlobalFunction("void Func()", asFUNCTION(Func), asCALL_GENERIC); assert( r >= 0 ); r = engine->EndConfigGroup(); assert( r >= 0 ); mod = engine->GetModule("ExecuteString", asGM_ALWAYS_CREATE); mod->SetAccessMask(1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); bout.buffer = ""; r = ExecuteString(engine, "Func()", mod); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 1) : Error : No matching signatures to 'Func()'\n" ) TEST_FAILED; mod->SetAccessMask(2); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = ExecuteString(engine, "Func()", mod); if( r < 0 ) TEST_FAILED; engine->Release(); //------------ // Test object types engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->BeginConfigGroup("group"); assert( r >= 0 ); r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 ); r = engine->EndConfigGroup(); assert( r >= 0 ); mod = engine->GetModule("ExecuteString", asGM_ALWAYS_CREATE); mod->SetAccessMask(2); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); bout.buffer = ""; r = ExecuteString(engine, "mytype a", mod); if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 1) : Error : Type 'mytype' is not available for this module\n") TEST_FAILED; engine->Release(); //------------ // Test class members in different config groups engine = asCreateScriptEngine(ANGELSCRIPT_VERSION); engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL); r = engine->RegisterObjectType("mytype", sizeof(int), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert( r >= 0 ); r = engine->SetDefaultAccessMask(2); r = engine->RegisterObjectMethod("mytype", "mytype opAdd(mytype &in)", asFUNCTION(TypeAdd), asCALL_GENERIC); assert( r >= 0 ); r = engine->RegisterObjectProperty("mytype", "int val", 0); assert( r >= 0 ); mod = engine->GetModule("ExecuteString", asGM_ALWAYS_CREATE); mod->SetAccessMask(1); engine->SetMessageCallback(asMETHOD(CBufferedOutStream,Callback), &bout, asCALL_THISCALL); bout.buffer = ""; r = ExecuteString(engine, "mytype a; a + a; a.val + a.val;", mod); // It should be possible to disallow individual class methods if( r >= 0 ) TEST_FAILED; if( bout.buffer != "ExecuteString (1, 13) : Error : No matching operator that takes the types 'mytype' and 'mytype' found\n" "ExecuteString (1, 19) : Error : 'val' is not a member of 'mytype'\n" ) { printf("%s", bout.buffer.c_str()); TEST_FAILED; } engine->Release(); // Success return fail; }