bool Test()
{
	bool fail = false;
	int r = 0;
	COutStream out;

	// TODO: Preprocessor directives should be alone on the line

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);

	// Test the parse token method
	asETokenClass t = engine->ParseToken("!is");
	if( t != asTC_KEYWORD )
		fail = true;

	// Compile a script with meta data strings
	CScriptBuilder builder;
	builder.DefineWord("COMPILE");
	r = builder.BuildScriptFromMemory(engine, 0, script);
#if AS_PROCESS_METADATA == 1
	if( r < 0 )
		fail = true;

	int funcId = engine->GetModule(0)->GetFunctionIdByName("func1");
	string metadata = builder.GetMetadataStringForFunc(funcId);
	if( metadata != " my meta data test " )
		fail = true;

	funcId = engine->GetModule(0)->GetFunctionIdByName("func2");
	metadata = builder.GetMetadataStringForFunc(funcId);
	if( metadata != " test['hello'] " )
		fail = true;

	int typeId = engine->GetModule(0)->GetTypeIdByDecl("MyClass");
	metadata = builder.GetMetadataStringForType(typeId);
	if( metadata != " myclass " )
		fail = true;

	typeId = engine->GetModule(0)->GetTypeIdByDecl("MyIntf");
	metadata = builder.GetMetadataStringForType(typeId);
	if( metadata != " myintf " )
		fail = true;

	int varIdx = engine->GetModule(0)->GetGlobalVarIndexByName("g_var");
	metadata = builder.GetMetadataStringForVar(varIdx);
	if( metadata != " init " )
		fail = true;

	varIdx = engine->GetModule(0)->GetGlobalVarIndexByName("g_obj");
	metadata = builder.GetMetadataStringForVar(varIdx);
	if( metadata != " var of type myclass " )
		fail = true;
#endif

	engine->Release();

	return fail;
}
bool ScriptManager::loadFromMemory(const std::string& name, const void* data, size_t len, ScriptType type)
{
	std::string lower;
	std::transform(name.begin(), name.end(), std::back_inserter(lower), ::tolower);

	if (type == Type_Autodetect)
	{
		if (lower.substr(lower.size() - 4) == ".asb")
			type = Type_Bytecode;
		else if (lower.substr(lower.size() - 3) == ".as")
			type = Type_Text;
		else
			return false;
	}

	bool reload = mScripts.count(lower) > 0;

	std::list<asIScriptObject*> changes;

	asIScriptModule* module = mEngine->GetModule(lower.c_str(), asGM_ONLY_IF_EXISTS);
	CSerializer serial;

	if (reload && module)
	{
		for (auto& reg : mSerializers)
			serial.AddUserType(reg.second(), reg.first);

		for (auto it = mChangeNotice.begin(); it != mChangeNotice.end();)
		{
			if (it->second.WeakRef->Get())
			{
				it->second.WeakRef->Release();
				it = mChangeNotice.erase(it);
				continue;
			}

			auto* obj = it->first;

			if (obj->GetObjectType()->GetModule() == module)
			{
				serial.AddExtraObjectToStore(obj);

				changes.push_back(it->first);
			}

			++it;
		}

		serial.Store(module);
	}

	BytecodeStore bcode;
	if (type == Type_Text)
	{
		static const char* scratchName = "!!ScratchSpace!!";
		CScriptBuilder builder;

		for (auto& def : mDefines)
			builder.DefineWord(def.c_str());

		builder.StartNewModule(mEngine, scratchName);

		for (auto& callback : mPreLoadCallbacks)
			if (!callback.second(builder.GetModule()))
			{
				mEngine->DiscardModule(scratchName);
				return false;
			}

		builder.AddSectionFromMemory(lower.c_str(), (const char*)data, len);

		int r = builder.BuildModule();
		if (r < 0)
		{
#ifndef NDEBUG
			puts(ASException::GetMessage(r));
#endif
			return false;
		}

#ifdef NDEBUG
		builder.GetModule()->SaveByteCode(&bcode, true);
#else
		builder.GetModule()->SaveByteCode(&bcode, false);
#endif

		mEngine->DiscardModule(scratchName);
	}
	else
	{
		bcode = BytecodeStore((const char*)data, len);
	}

	if (module)
		module->Discard();

	module = mEngine->GetModule(lower.c_str(), asGM_ALWAYS_CREATE);

	// FIXME? Preload callbacks can not act on bytecode anyway
	/*
	if (type == Type_Bytecode)
		for (auto& callback : mPreLoadCallbacks)
			if (!callback.second(module))
			{
				module->Discard();

				return false;
			}
	*/

	int r = module->LoadByteCode(&bcode);
	if (r < 0)
	{
		module->Discard();

		return false;
	}

	module->BindAllImportedFunctions();

	if (mScripts.count(lower) == 0)
	{
		mScripts[lower].Name = name;
		mScripts[lower].DirectLoad = true;
	}

	if (reload)
	{
		serial.Restore(module);

		for (auto& it : changes)
		{
			auto* newObj = (asIScriptObject*)serial.GetPointerToRestoredObject(it);

			auto notice = mChangeNotice[it];
			mChangeNotice.erase(it);

			notice.WeakRef->Release();
			notice.Callback(newObj);
		}

		mEngine->GarbageCollect(asGC_FULL_CYCLE);
	}

	return true;
}
Exemple #3
0
bool Test()
{
	bool fail = false;
	int r = 0;
	COutStream out;
	CBufferedOutStream bout;

	// TODO: Preprocessor directives should be alone on the line

	asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
	RegisterScriptArray(engine, true);

	engine->SetMessageCallback(asMETHOD(COutStream,Callback), &out, asCALL_THISCALL);
	if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
		RegisterScriptMathComplex(engine);
	else
		engine->RegisterObjectType("complex", 4, asOBJ_VALUE | asOBJ_POD);

	// Test the parse token method
	asETokenClass t = engine->ParseToken("!is");
	if( t != asTC_KEYWORD )
		TEST_FAILED;

	// Compile a script with meta data strings
	CScriptBuilder builder;
	builder.DefineWord("COMPILE");
	r = builder.StartNewModule(engine, 0);
	r = builder.AddSectionFromMemory("", script);
	r = builder.BuildModule();
#if AS_PROCESS_METADATA == 1
	if( r < 0 )
		TEST_FAILED;

	asIScriptFunction *func = engine->GetModule(0)->GetFunctionByName("func1");
	string metadata = builder.GetMetadataStringForFunc(func);
	if( metadata != " my meta data test " )
		TEST_FAILED;

	func = engine->GetModule(0)->GetFunctionByName("func2");
	metadata = builder.GetMetadataStringForFunc(func);
	if( metadata != " test['hello'] " )
		TEST_FAILED;

	engine->GetModule(0)->SetDefaultNamespace("NS");
	func = engine->GetModule(0)->GetFunctionByName("func");
	metadata = builder.GetMetadataStringForFunc(func);
	if( metadata != "func" )
		TEST_FAILED;
	engine->GetModule(0)->SetDefaultNamespace("");

	int typeId = engine->GetModule(0)->GetTypeIdByDecl("MyClass");
	metadata = builder.GetMetadataStringForType(typeId);
	if( metadata != " myclass " )
		TEST_FAILED;

	typeId = engine->GetModule(0)->GetTypeIdByDecl("NS::Class");
	metadata = builder.GetMetadataStringForType(typeId);
	if( metadata != "class" )
		TEST_FAILED;

	typeId = engine->GetModule(0)->GetTypeIdByDecl("MyClass2");
	metadata = builder.GetMetadataStringForTypeProperty(typeId, 0);
	if( metadata != " edit " )
		TEST_FAILED;
	metadata = builder.GetMetadataStringForTypeProperty(typeId, 1);
	if( metadata != " noedit " )
		TEST_FAILED;
	metadata = builder.GetMetadataStringForTypeProperty(typeId, 2);
	if( metadata != " edit,c " )
		TEST_FAILED;

	asIObjectType *type = engine->GetObjectTypeById(typeId);
	if( type == 0 )
		TEST_FAILED;
	else
	{
		metadata = builder.GetMetadataStringForTypeMethod(typeId, type->GetMethodByName("get_prop"));
		if( metadata != " prop " )
			TEST_FAILED;
		metadata = builder.GetMetadataStringForTypeMethod(typeId, type->GetMethodByName("set_prop"));
		if( metadata != " prop " )
			TEST_FAILED;
	}

	typeId = engine->GetModule(0)->GetTypeIdByDecl("MyIntf");
	metadata = builder.GetMetadataStringForType(typeId);
	if( metadata != " myintf " )
		TEST_FAILED;

	int varIdx = engine->GetModule(0)->GetGlobalVarIndexByName("g_var");
	metadata = builder.GetMetadataStringForVar(varIdx);
	if( metadata != " init " )
		TEST_FAILED;

	varIdx = engine->GetModule(0)->GetGlobalVarIndexByName("g_obj");
	metadata = builder.GetMetadataStringForVar(varIdx);
	if( metadata != " var of type myclass " )
		TEST_FAILED;
#endif

	// http://www.gamedev.net/topic/624445-cscriptbuilder-asset-string-subscript-out-of-range/
	{
		bout.buffer = "";
		CScriptBuilder builder;
		builder.StartNewModule(engine, "mod");
		builder.AddSectionFromMemory("", "#");
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		r = builder.BuildModule();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != " (1, 1) : Error   : Unexpected token '<unrecognized token>'\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
	}

	// Add a script section from memory with length
	{
		engine->SetMessageCallback(asMETHOD(COutStream, Callback), &bout, asCALL_THISCALL);
		CScriptBuilder builder;
		builder.StartNewModule(engine, "mod");
		builder.AddSectionFromMemory("", "void func() {} $#", 14);
		r = builder.BuildModule();
		if( r < 0 )
			TEST_FAILED;
	}

	// http://www.gamedev.net/topic/631848-cscriptbuilder-bug/
	{
		bout.buffer = "";
		CScriptBuilder builder;
		builder.StartNewModule(engine, "mod");
		builder.AddSectionFromMemory("", "class ");
		engine->SetMessageCallback(asMETHOD(CBufferedOutStream, Callback), &bout, asCALL_THISCALL);
		r = builder.BuildModule();
		if( r >= 0 )
			TEST_FAILED;
		if( bout.buffer != " (1, 7) : Error   : Expected identifier\n"
		                   " (1, 7) : Error   : Instead found '<end of file>'\n"
						   " (1, 7) : Error   : Expected '{'\n"
						   " (1, 7) : Error   : Instead found '<end of file>'\n" )
		{
			printf("%s", bout.buffer.c_str());
			TEST_FAILED;
		}
	}

	engine->Release();

	return fail;
}
Exemple #4
0
static void RegisterDefinedWords(const std::vector<gs2d::str_type::string>& definedWords, CScriptBuilder& builder, const bool isTesting)
{
	#if defined(_DEBUG) || defined(DEBUG)
		builder.DefineWord("DEBUG");
	#endif
	#ifdef ANDROID
		builder.DefineWord("ANDROID");
	#endif
	#ifdef APPLE_IOS
		builder.DefineWord("APPLE_IOS");
	#endif
	#ifdef MACOSX
		builder.DefineWord("MACOSX");
	#endif
	#ifdef WIN32
		builder.DefineWord("WINDOWS");
	#endif
	#ifdef LINUX
		builder.DefineWord("LINUX");
	#endif
	#if defined(APPLE_IOS) || defined(ANDROID)
		builder.DefineWord("MOBILE");
		builder.DefineWord("MOBILE_DEVICE");
		builder.DefineWord("HANDHELD");
		builder.DefineWord("HANDHELD_DEVICE");
	#endif
	#if defined(WIN32) || defined(MACOSX) || defined(LINUX)
		builder.DefineWord("DESKTOP");
	#endif

	if (isTesting)
	{
		builder.DefineWord("TESTING");
	}

	// register custom words (defined in the app.enml)
	for (std::size_t t = 0; t < definedWords.size(); t++)
	{
		builder.DefineWord(definedWords[t].c_str());
	}
}