/xbmc/visualizations/Vortex/angelscript/angelscript/source/as_scriptengine.cpp
http://github.com/xbmc/xbmc · C++ · 4005 lines · 2955 code · 632 blank · 418 comment · 882 complexity · 865bdcb2382977594909b1cc468f8b12 MD5 · raw file
Large files are truncated click here to view the full file
- /*
- AngelCode Scripting Library
- Copyright (c) 2003-2009 Andreas Jonsson
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any
- damages arising from the use of this software.
- Permission is granted to anyone to use this software for any
- purpose, including commercial applications, and to alter it and
- redistribute it freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you
- must not claim that you wrote the original software. If you use
- this software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and
- must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source
- distribution.
- The original version of this library can be located at:
- http://www.angelcode.com/angelscript/
- Andreas Jonsson
- andreas@angelcode.com
- */
- //
- // as_scriptengine.cpp
- //
- // The implementation of the script engine interface
- //
- #include <stdlib.h>
- #include "as_config.h"
- #include "as_scriptengine.h"
- #include "as_builder.h"
- #include "as_context.h"
- #include "as_string_util.h"
- #include "as_tokenizer.h"
- #include "as_texts.h"
- #include "as_module.h"
- #include "as_callfunc.h"
- #include "as_arrayobject.h"
- #include "as_generic.h"
- #include "as_scriptobject.h"
- #include "as_compiler.h"
- BEGIN_AS_NAMESPACE
- extern "C"
- {
- AS_API const char * asGetLibraryVersion()
- {
- #ifdef _DEBUG
- return ANGELSCRIPT_VERSION_STRING " DEBUG";
- #else
- return ANGELSCRIPT_VERSION_STRING;
- #endif
- }
- AS_API const char * asGetLibraryOptions()
- {
- const char *string = " "
- // Options
- #ifdef AS_MAX_PORTABILITY
- "AS_MAX_PORTABILITY "
- #endif
- #ifdef AS_DEBUG
- "AS_DEBUG "
- #endif
- #ifdef AS_NO_CLASS_METHODS
- "AS_NO_CLASS_METHODS "
- #endif
- #ifdef AS_USE_DOUBLE_AS_FLOAT
- "AS_USE_DOUBLE_AS_FLOAT "
- #endif
- #ifdef AS_64BIT_PTR
- "AS_64BIT_PTR "
- #endif
- #ifdef AS_NO_THREADS
- "AS_NO_THREADS "
- #endif
- #ifdef AS_NO_ATOMIC
- "AS_NO_ATOMIC "
- #endif
- // Target system
- #ifdef AS_WIN
- "AS_WIN "
- #endif
- #ifdef AS_LINUX
- "AS_LINUX "
- #endif
- #ifdef AS_MAC
- "AS_MAC "
- #endif
- #ifdef AS_BSD
- "AS_BSD "
- #endif
- #ifdef AS_XBOX
- "AS_XBOX "
- #endif
- #ifdef AS_XBOX360
- "AS_XBOX360 "
- #endif
- #ifdef AS_PSP
- "AS_PSP "
- #endif
- #ifdef AS_PS2
- "AS_PS2 "
- #endif
- #ifdef AS_PS3
- "AS_PS3 "
- #endif
- #ifdef AS_DC
- "AS_DC "
- #endif
- #ifdef AS_GC
- "AS_GC "
- #endif
- #ifdef AS_WII
- "AS_WII "
- #endif
- #ifdef AS_IPHONE
- "AS_IPHONE "
- #endif
- #ifdef AS_ANDROID
- "AS_ANDROID "
- #endif
- // CPU family
- #ifdef AS_PPC
- "AS_PPC "
- #endif
- #ifdef AS_PPC_64
- "AS_PPC_64 "
- #endif
- #ifdef AS_X86
- "AS_X86 "
- #endif
- #ifdef AS_MIPS
- "AS_MIPS "
- #endif
- #ifdef AS_SH4
- "AS_SH4 "
- #endif
- #ifdef AS_XENON
- "AS_XENON "
- #endif
- #ifdef AS_ARM
- "AS_ARM "
- #endif
- ;
- return string;
- }
- AS_API asIScriptEngine *asCreateScriptEngine(asDWORD version)
- {
- // Verify the version that the application expects
- if( (version/10000) != (ANGELSCRIPT_VERSION/10000) )
- return 0;
- if( (version/100)%100 != (ANGELSCRIPT_VERSION/100)%100 )
- return 0;
- if( (version%100) > (ANGELSCRIPT_VERSION%100) )
- return 0;
- // Verify the size of the types
- asASSERT( sizeof(asBYTE) == 1 );
- asASSERT( sizeof(asWORD) == 2 );
- asASSERT( sizeof(asDWORD) == 4 );
- asASSERT( sizeof(asQWORD) == 8 );
- asASSERT( sizeof(asPWORD) == sizeof(void*) );
- // Verify the boolean type
- asASSERT( sizeof(bool) == AS_SIZEOF_BOOL );
- asASSERT( true == VALUE_OF_BOOLEAN_TRUE );
- // Verify endianess
- #ifdef AS_BIG_ENDIAN
- asASSERT( *(asDWORD*)"\x00\x01\x02\x03" == 0x00010203 );
- asASSERT( *(asQWORD*)"\x00\x01\x02\x03\x04\x05\x06\x07" == I64(0x0001020304050607) );
- #else
- asASSERT( *(asDWORD*)"\x00\x01\x02\x03" == 0x03020100 );
- asASSERT( *(asQWORD*)"\x00\x01\x02\x03\x04\x05\x06\x07" == I64(0x0706050403020100) );
- #endif
- return asNEW(asCScriptEngine)();
- }
- int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
- {
- switch( property )
- {
- case asEP_ALLOW_UNSAFE_REFERENCES:
- ep.allowUnsafeReferences = value ? true : false;
- break;
- case asEP_OPTIMIZE_BYTECODE:
- ep.optimizeByteCode = value ? true : false;
- break;
- case asEP_COPY_SCRIPT_SECTIONS:
- ep.copyScriptSections = value ? true : false;
- break;
- case asEP_MAX_STACK_SIZE:
- // The size is given in bytes, but we only store dwords
- ep.maximumContextStackSize = (int)value/4;
- if( initialContextStackSize > ep.maximumContextStackSize )
- initialContextStackSize = ep.maximumContextStackSize;
- break;
- case asEP_USE_CHARACTER_LITERALS:
- ep.useCharacterLiterals = value ? true : false;
- break;
- case asEP_ALLOW_MULTILINE_STRINGS:
- ep.allowMultilineStrings = value ? true : false;
- break;
- case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
- ep.allowImplicitHandleTypes = value ? true : false;
- break;
- case asEP_BUILD_WITHOUT_LINE_CUES:
- ep.buildWithoutLineCues = value ? true : false;
- break;
- case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
- ep.initGlobalVarsAfterBuild = value ? true : false;
- break;
- case asEP_REQUIRE_ENUM_SCOPE:
- ep.requireEnumScope = value ? true : false;
- break;
- case asEP_SCRIPT_SCANNER:
- if( value <= 1 )
- ep.scanner = (int)value;
- else
- return asINVALID_ARG;
- break;
- case asEP_INCLUDE_JIT_INSTRUCTIONS:
- ep.includeJitInstructions = value ? true : false;
- break;
- case asEP_STRING_ENCODING:
- if( value <= 1 )
- ep.stringEncoding = (int)value;
- else
- return asINVALID_ARG;
- break;
- default:
- return asINVALID_ARG;
- }
- return asSUCCESS;
- }
- asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property)
- {
- switch( property )
- {
- case asEP_ALLOW_UNSAFE_REFERENCES:
- return ep.allowUnsafeReferences;
- case asEP_OPTIMIZE_BYTECODE:
- return ep.optimizeByteCode;
- case asEP_COPY_SCRIPT_SECTIONS:
- return ep.copyScriptSections;
- case asEP_MAX_STACK_SIZE:
- return ep.maximumContextStackSize*4;
- case asEP_USE_CHARACTER_LITERALS:
- return ep.useCharacterLiterals;
- case asEP_ALLOW_MULTILINE_STRINGS:
- return ep.allowMultilineStrings;
- case asEP_ALLOW_IMPLICIT_HANDLE_TYPES:
- return ep.allowImplicitHandleTypes;
- case asEP_BUILD_WITHOUT_LINE_CUES:
- return ep.buildWithoutLineCues;
- case asEP_INIT_GLOBAL_VARS_AFTER_BUILD:
- return ep.initGlobalVarsAfterBuild;
- case asEP_REQUIRE_ENUM_SCOPE:
- return ep.requireEnumScope;
- case asEP_SCRIPT_SCANNER:
- return ep.scanner;
- case asEP_INCLUDE_JIT_INSTRUCTIONS:
- return ep.includeJitInstructions;
- case asEP_STRING_ENCODING:
- return ep.stringEncoding;
- }
- return 0;
- }
- } // extern "C"
- asCScriptEngine::asCScriptEngine()
- {
- // Instanciate the thread manager
- if( threadManager == 0 )
- threadManager = asNEW(asCThreadManager);
- else
- threadManager->AddRef();
- // Engine properties
- ep.allowUnsafeReferences = false;
- ep.optimizeByteCode = true;
- ep.copyScriptSections = true;
- ep.maximumContextStackSize = 0; // no limit
- ep.useCharacterLiterals = false;
- ep.allowMultilineStrings = false;
- ep.allowImplicitHandleTypes = false;
- ep.buildWithoutLineCues = false;
- ep.initGlobalVarsAfterBuild = true;
- ep.requireEnumScope = false;
- ep.scanner = 1; // utf8. 0 = ascii
- ep.includeJitInstructions = false;
- ep.stringEncoding = 0; // utf8. 1 = utf16
- gc.engine = this;
- refCount.set(1);
- stringFactory = 0;
- configFailed = false;
- isPrepared = false;
- isBuilding = false;
- lastModule = 0;
- userData = 0;
- initialContextStackSize = 1024; // 1 KB
- typeIdSeqNbr = 0;
- currentGroup = &defaultGroup;
- msgCallback = 0;
- jitCompiler = 0;
- // Reserve function id 0 for no function
- scriptFunctions.PushLast(0);
- // Make sure typeId for the built-in primitives are defined according to asETypeIdFlags
- int id;
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttVoid, false)); asASSERT( id == asTYPEID_VOID );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttBool, false)); asASSERT( id == asTYPEID_BOOL );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt8, false)); asASSERT( id == asTYPEID_INT8 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt16, false)); asASSERT( id == asTYPEID_INT16 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt, false)); asASSERT( id == asTYPEID_INT32 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttInt64, false)); asASSERT( id == asTYPEID_INT64 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt8, false)); asASSERT( id == asTYPEID_UINT8 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt16, false)); asASSERT( id == asTYPEID_UINT16 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt, false)); asASSERT( id == asTYPEID_UINT32 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttUInt64, false)); asASSERT( id == asTYPEID_UINT64 );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttFloat, false)); asASSERT( id == asTYPEID_FLOAT );
- id = GetTypeIdFromDataType(asCDataType::CreatePrimitive(ttDouble, false)); asASSERT( id == asTYPEID_DOUBLE );
- defaultArrayObjectType = 0;
- RegisterArrayObject(this);
- RegisterScriptObject(this);
- RegisterScriptFunction(this);
- RegisterObjectTypeGCBehaviours(this);
- }
- asCScriptEngine::~asCScriptEngine()
- {
- asASSERT(refCount.get() == 0);
- asUINT n;
- // The modules must be deleted first, as they may use
- // object types from the config groups
- for( n = (asUINT)scriptModules.GetLength(); n-- > 0; )
- {
- if( scriptModules[n] )
- {
- asDELETE(scriptModules[n],asCModule);
- }
- }
- scriptModules.SetLength(0);
- GarbageCollect(asGC_FULL_CYCLE);
- // Delete the functions for template types that may references object types
- for( n = 0; n < templateTypes.GetLength(); n++ )
- {
- if( templateTypes[n] )
- {
- asUINT f;
- // Delete the factory stubs first
- for( f = 0; f < templateTypes[n]->beh.factories.GetLength(); f++ )
- {
- scriptFunctions[templateTypes[n]->beh.factories[f]]->Release();
- }
- templateTypes[n]->beh.factories.Allocate(0, false);
- // Delete the specialized functions
- for( f = 1; f < templateTypes[n]->beh.operators.GetLength(); f += 2 )
- {
- if( scriptFunctions[templateTypes[n]->beh.operators[f]]->objectType == templateTypes[n] )
- {
- scriptFunctions[templateTypes[n]->beh.operators[f]]->Release();
- templateTypes[n]->beh.operators[f] = 0;
- }
- }
- }
- }
- // Do one more garbage collect to free gc objects that were global variables
- GarbageCollect(asGC_FULL_CYCLE);
- FreeUnusedGlobalProperties();
- ClearUnusedTypes();
- // Break all relationship between remaining class types and functions
- for( n = 0; n < classTypes.GetLength(); n++ )
- {
- if( classTypes[n] )
- classTypes[n]->ReleaseAllFunctions();
- if( classTypes[n]->derivedFrom )
- {
- classTypes[n]->derivedFrom->Release();
- classTypes[n]->derivedFrom = 0;
- }
- }
- GarbageCollect(asGC_FULL_CYCLE);
- FreeUnusedGlobalProperties();
- ClearUnusedTypes();
- asSMapNode<int,asCDataType*> *cursor = 0;
- while( mapTypeIdToDataType.MoveFirst(&cursor) )
- {
- asDELETE(mapTypeIdToDataType.GetValue(cursor),asCDataType);
- mapTypeIdToDataType.Erase(cursor);
- }
- defaultGroup.RemoveConfiguration(this);
- while( configGroups.GetLength() )
- {
- // Delete config groups in the right order
- asCConfigGroup *grp = configGroups.PopLast();
- if( grp )
- {
- asDELETE(grp,asCConfigGroup);
- }
- }
- for( n = 0; n < registeredGlobalProps.GetLength(); n++ )
- {
- if( registeredGlobalProps[n] )
- {
- asDELETE(registeredGlobalProps[n],asCGlobalProperty);
- }
- }
- registeredGlobalProps.SetLength(0);
- FreeUnusedGlobalProperties();
- for( n = 0; n < templateTypes.GetLength(); n++ )
- {
- if( templateTypes[n] )
- {
- // Clear the sub type before deleting the template type so that the sub type isn't freed to soon
- templateTypes[n]->templateSubType = asCDataType::CreateNullHandle();
- asDELETE(templateTypes[n],asCObjectType);
- }
- }
- templateTypes.SetLength(0);
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] )
- {
- // Clear the sub type before deleting the template type so that the sub type isn't freed to soon
- objectTypes[n]->templateSubType = asCDataType::CreateNullHandle();
- asDELETE(objectTypes[n],asCObjectType);
- }
- }
- objectTypes.SetLength(0);
- for( n = 0; n < templateSubTypes.GetLength(); n++ )
- {
- if( templateSubTypes[n] )
- {
- asDELETE(templateSubTypes[n], asCObjectType);
- }
- }
- templateSubTypes.SetLength(0);
- registeredTypeDefs.SetLength(0);
- registeredEnums.SetLength(0);
- registeredObjTypes.SetLength(0);
- for( n = 0; n < registeredGlobalFuncs.GetLength(); n++ )
- {
- if( registeredGlobalFuncs[n] )
- registeredGlobalFuncs[n]->Release();
- }
- registeredGlobalFuncs.SetLength(0);
- scriptTypeBehaviours.ReleaseAllFunctions();
- functionBehaviours.ReleaseAllFunctions();
- objectTypeBehaviours.ReleaseAllFunctions();
- // Free string constants
- for( n = 0; n < stringConstants.GetLength(); n++ )
- {
- asDELETE(stringConstants[n],asCString);
- }
- stringConstants.SetLength(0);
- // Free the script section names
- for( n = 0; n < scriptSectionNames.GetLength(); n++ )
- {
- asDELETE(scriptSectionNames[n],asCString);
- }
- scriptSectionNames.SetLength(0);
- // Release the thread manager
- threadManager->Release();
- }
- // interface
- int asCScriptEngine::AddRef()
- {
- return refCount.atomicInc();
- }
- // interface
- int asCScriptEngine::Release()
- {
- int r = refCount.atomicDec();
- if( r == 0 )
- {
- asDELETE(this,asCScriptEngine);
- return 0;
- }
- return r;
- }
- // interface
- void *asCScriptEngine::SetUserData(void *data)
- {
- void *old = userData;
- userData = data;
- return old;
- }
- // interface
- void *asCScriptEngine::GetUserData()
- {
- return userData;
- }
- // interface
- int asCScriptEngine::SetMessageCallback(const asSFuncPtr &callback, void *obj, asDWORD callConv)
- {
- msgCallback = true;
- msgCallbackObj = obj;
- bool isObj = false;
- if( (unsigned)callConv == asCALL_GENERIC )
- {
- msgCallback = false;
- return asNOT_SUPPORTED;
- }
- if( (unsigned)callConv >= asCALL_THISCALL )
- {
- isObj = true;
- if( obj == 0 )
- {
- msgCallback = false;
- return asINVALID_ARG;
- }
- }
- int r = DetectCallingConvention(isObj, callback, callConv, &msgCallbackFunc);
- if( r < 0 ) msgCallback = false;
- return r;
- }
- // interface
- int asCScriptEngine::ClearMessageCallback()
- {
- msgCallback = false;
- return 0;
- }
- // interface
- int asCScriptEngine::WriteMessage(const char *section, int row, int col, asEMsgType type, const char *message)
- {
- // Validate input parameters
- if( section == 0 ||
- message == 0 )
- return asINVALID_ARG;
- // If there is no callback then there's nothing to do
- if( !msgCallback )
- return 0;
- asSMessageInfo msg;
- msg.section = section;
- msg.row = row;
- msg.col = col;
- msg.type = type;
- msg.message = message;
- if( msgCallbackFunc.callConv < ICC_THISCALL )
- CallGlobalFunction(&msg, msgCallbackObj, &msgCallbackFunc, 0);
- else
- CallObjectMethod(msgCallbackObj, &msg, &msgCallbackFunc, 0);
- return 0;
- }
- int asCScriptEngine::SetJITCompiler(asIJITCompiler *compiler)
- {
- jitCompiler = compiler;
- return asSUCCESS;
- }
- asIJITCompiler *asCScriptEngine::GetJITCompiler()
- {
- return jitCompiler;
- }
- // interface
- asETokenClass asCScriptEngine::ParseToken(const char *string, size_t stringLength, int *tokenLength)
- {
- if( stringLength == 0 )
- stringLength = strlen(string);
- size_t len;
- asCTokenizer t;
- asETokenClass tc;
- t.GetToken(string, stringLength, &len, &tc);
- if( tokenLength )
- *tokenLength = (int)len;
- return tc;
- }
- // interface
- asIScriptModule *asCScriptEngine::GetModule(const char *module, asEGMFlags flag)
- {
- asCModule *mod = GetModule(module, false);
- if( flag == asGM_ALWAYS_CREATE )
- {
- if( mod != 0 )
- {
- asDELETE(mod, asCModule);
- }
- return GetModule(module, true);
- }
- if( mod == 0 && flag == asGM_CREATE_IF_NOT_EXISTS )
- {
- return GetModule(module, true);
- }
- return mod;
- }
- // interface
- int asCScriptEngine::DiscardModule(const char *module)
- {
- asCModule *mod = GetModule(module, false);
- if( mod == 0 ) return asNO_MODULE;
- asDELETE(mod, asCModule);
- FreeUnusedGlobalProperties();
- ClearUnusedTypes();
- return 0;
- }
- void asCScriptEngine::ClearUnusedTypes()
- {
- // Build a list of all types to check for
- asCArray<asCObjectType*> types;
- types = classTypes;
- types.Concatenate(templateInstanceTypes);
- // Go through all modules
- asUINT n;
- for( n = 0; n < scriptModules.GetLength() && types.GetLength(); n++ )
- {
- asCModule *mod = scriptModules[n];
- if( mod )
- {
- // Functions/Methods/Globals are handled after this
- // Go through all type declarations
- asUINT m;
- for( m = 0; m < mod->classTypes.GetLength() && types.GetLength(); m++ )
- RemoveTypeAndRelatedFromList(types, mod->classTypes[m]);
- for( m = 0; m < mod->enumTypes.GetLength() && types.GetLength(); m++ )
- RemoveTypeAndRelatedFromList(types, mod->enumTypes[m]);
- for( m = 0; m < mod->typeDefs.GetLength() && types.GetLength(); m++ )
- RemoveTypeAndRelatedFromList(types, mod->typeDefs[m]);
- }
- }
- // Go through all function parameters and remove used types
- for( n = 0; n < scriptFunctions.GetLength() && types.GetLength(); n++ )
- {
- asCScriptFunction *func = scriptFunctions[n];
- if( func )
- {
- // Ignore factory stubs
- if( func->name == "factstub" )
- continue;
- asCObjectType *ot = func->returnType.GetObjectType();
- if( ot != 0 && ot != func->objectType )
- if( func->name != ot->name )
- RemoveTypeAndRelatedFromList(types, ot);
- for( asUINT p = 0; p < func->parameterTypes.GetLength(); p++ )
- {
- ot = func->parameterTypes[p].GetObjectType();
- if( ot != 0 && ot != func->objectType )
- if( func->name != ot->name )
- RemoveTypeAndRelatedFromList(types, ot);
- }
- }
- }
- // Go through all global properties
- for( n = 0; n < globalProperties.GetLength() && types.GetLength(); n++ )
- {
- if( globalProperties[n] && globalProperties[n]->type.GetObjectType() )
- RemoveTypeAndRelatedFromList(types, globalProperties[n]->type.GetObjectType());
- }
- // All that remains in the list after this can be discarded, since they are no longer used
- for(;;)
- {
- bool didClearTemplateInstanceType = false;
- for( n = 0; n < types.GetLength(); n++ )
- {
- // Template types and script classes will have two references for each factory stub
- int refCount = ((types[n]->flags & asOBJ_TEMPLATE) || (types[n]->flags & asOBJ_SCRIPT_OBJECT)) ? 2*(int)types[n]->beh.factories.GetLength() : 0;
- if( types[n]->GetRefCount() == refCount )
- {
- if( types[n]->flags & asOBJ_TEMPLATE )
- {
- didClearTemplateInstanceType = true;
- RemoveTemplateInstanceType(types[n]);
- }
- else
- {
- RemoveFromTypeIdMap(types[n]);
- asDELETE(types[n],asCObjectType);
- int i = classTypes.IndexOf(types[n]);
- if( i == (signed)classTypes.GetLength() - 1 )
- classTypes.PopLast();
- else
- classTypes[i] = classTypes.PopLast();
- }
- // Remove the type from the array
- if( n < types.GetLength() - 1 )
- types[n] = types.PopLast();
- else
- types.PopLast();
- n--;
- }
- }
- if( didClearTemplateInstanceType == false )
- break;
- }
- }
- void asCScriptEngine::RemoveTypeAndRelatedFromList(asCArray<asCObjectType*> &types, asCObjectType *ot)
- {
- // Remove the type from the list
- int i = types.IndexOf(ot);
- if( i == -1 ) return;
- if( i == (signed)types.GetLength() - 1 )
- types.PopLast();
- else
- types[i] = types.PopLast();
- // If the type is an template type, then remove all sub types as well
- if( ot->templateSubType.GetObjectType() )
- {
- while( ot->templateSubType.GetObjectType() )
- {
- ot = ot->templateSubType.GetObjectType();
- RemoveTypeAndRelatedFromList(types, ot);
- }
- return;
- }
- // If the type is a class, then remove all properties types as well
- if( ot->properties.GetLength() )
- {
- for( asUINT n = 0; n < ot->properties.GetLength(); n++ )
- RemoveTypeAndRelatedFromList(types, ot->properties[n]->type.GetObjectType());
- }
- }
- // internal
- int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *decl)
- {
- asCModule *mod = 0;
- // Is this a script class?
- if( ot->flags & asOBJ_SCRIPT_OBJECT && ot->size > 0 )
- mod = scriptFunctions[ot->beh.factory]->module;
- asCBuilder bld(this, mod);
- asCScriptFunction func(this, mod,-1);
- int r = bld.ParseFunctionDeclaration(0, decl, &func, false);
- if( r < 0 )
- return asINVALID_DECLARATION;
- // Search for matching factory function
- int id = -1;
- for( size_t n = 0; n < ot->beh.factories.GetLength(); n++ )
- {
- asCScriptFunction *f = scriptFunctions[ot->beh.factories[n]];
- if( f->IsSignatureEqual(&func) )
- {
- id = ot->beh.factories[n];
- break;
- }
- }
- if( id == -1 ) return asNO_FUNCTION;
- return id;
- }
- // internal
- int asCScriptEngine::GetMethodIdByDecl(const asCObjectType *ot, const char *decl, asCModule *mod)
- {
- asCBuilder bld(this, mod);
- asCScriptFunction func(this, mod, -1);
- int r = bld.ParseFunctionDeclaration(0, decl, &func, false);
- if( r < 0 )
- return asINVALID_DECLARATION;
- // Set the object type so that the signature can be properly compared
- // This cast is OK, it will only be used for comparison
- func.objectType = const_cast<asCObjectType*>(ot);
- // Search script functions for matching interface
- int id = -1;
- for( size_t n = 0; n < ot->methods.GetLength(); ++n )
- {
- if( func.IsSignatureEqual(scriptFunctions[ot->methods[n]]) )
- {
- if( id == -1 )
- id = ot->methods[n];
- else
- return asMULTIPLE_FUNCTIONS;
- }
- }
- if( id == -1 ) return asNO_FUNCTION;
- return id;
- }
- // Internal
- asCString asCScriptEngine::GetFunctionDeclaration(int funcID)
- {
- asCString str;
- asCScriptFunction *func = GetScriptFunction(funcID);
- if( func )
- str = func->GetDeclarationStr();
- return str;
- }
- asCScriptFunction *asCScriptEngine::GetScriptFunction(int funcId)
- {
- if( funcId < 0 || funcId >= (int)scriptFunctions.GetLength() )
- return 0;
- return scriptFunctions[funcId];
- }
- asIScriptContext *asCScriptEngine::CreateContext()
- {
- asIScriptContext *ctx = 0;
- CreateContext(&ctx, false);
- return ctx;
- }
- int asCScriptEngine::CreateContext(asIScriptContext **context, bool isInternal)
- {
- *context = asNEW(asCContext)(this, !isInternal);
- // We need to make sure the engine has been
- // prepared before any context is executed
- PrepareEngine();
- return 0;
- }
- int asCScriptEngine::RegisterObjectProperty(const char *obj, const char *declaration, int byteOffset)
- {
- int r;
- asCDataType dt;
- asCBuilder bld(this, 0);
- r = bld.ParseDataType(obj, &dt);
- if( r < 0 )
- return ConfigError(r);
- // Verify that the correct config group is used
- if( currentGroup->FindType(dt.GetObjectType()->name.AddressOf()) == 0 )
- return ConfigError(asWRONG_CONFIG_GROUP);
- asCDataType type;
- asCString name;
- if( (r = bld.VerifyProperty(&dt, declaration, name, type)) < 0 )
- return ConfigError(r);
- // Store the property info
- if( dt.GetObjectType() == 0 )
- return ConfigError(asINVALID_OBJECT);
- asCObjectProperty *prop = asNEW(asCObjectProperty);
- prop->name = name;
- prop->type = type;
- prop->byteOffset = byteOffset;
- dt.GetObjectType()->properties.PushLast(prop);
- currentGroup->RefConfigGroup(FindConfigGroupForObjectType(type.GetObjectType()));
- return asSUCCESS;
- }
- int asCScriptEngine::RegisterInterface(const char *name)
- {
- if( name == 0 ) return ConfigError(asINVALID_NAME);
- // Verify if the name has been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == name )
- return asALREADY_REGISTERED;
- }
- // Use builder to parse the datatype
- asCDataType dt;
- asCBuilder bld(this, 0);
- bool oldMsgCallback = msgCallback; msgCallback = false;
- int r = bld.ParseDataType(name, &dt);
- msgCallback = oldMsgCallback;
- if( r >= 0 ) return ConfigError(asERROR);
- // Make sure the name is not a reserved keyword
- asCTokenizer t;
- size_t tokenLen;
- int token = t.GetToken(name, strlen(name), &tokenLen);
- if( token != ttIdentifier || strlen(name) != tokenLen )
- return ConfigError(asINVALID_NAME);
- r = bld.CheckNameConflict(name, 0, 0);
- if( r < 0 )
- return ConfigError(asNAME_TAKEN);
- // Don't have to check against members of object
- // types as they are allowed to use the names
- // Register the object type for the interface
- asCObjectType *st = asNEW(asCObjectType)(this);
- st->flags = asOBJ_REF | asOBJ_SCRIPT_OBJECT;
- st->size = 0; // Cannot be instanciated
- st->name = name;
- // Use the default script class behaviours
- st->beh.factory = 0;
- st->beh.addref = scriptTypeBehaviours.beh.addref;
- scriptFunctions[st->beh.addref]->AddRef();
- st->beh.release = scriptTypeBehaviours.beh.release;
- scriptFunctions[st->beh.release]->AddRef();
- st->beh.copy = 0;
- objectTypes.PushLast(st);
- registeredObjTypes.PushLast(st);
- currentGroup->objTypes.PushLast(st);
- return asSUCCESS;
- }
- int asCScriptEngine::RegisterInterfaceMethod(const char *intf, const char *declaration)
- {
- // Verify that the correct config group is set.
- if( currentGroup->FindType(intf) == 0 )
- return ConfigError(asWRONG_CONFIG_GROUP);
- asCDataType dt;
- asCBuilder bld(this, 0);
- int r = bld.ParseDataType(intf, &dt);
- if( r < 0 )
- return ConfigError(r);
- asCScriptFunction *func = asNEW(asCScriptFunction)(this, 0, asFUNC_INTERFACE);
- func->objectType = dt.GetObjectType();
- r = bld.ParseFunctionDeclaration(func->objectType, declaration, func, false);
- if( r < 0 )
- {
- asDELETE(func,asCScriptFunction);
- return ConfigError(asINVALID_DECLARATION);
- }
- // Check name conflicts
- r = bld.CheckNameConflictMember(dt, func->name.AddressOf(), 0, 0);
- if( r < 0 )
- {
- asDELETE(func,asCScriptFunction);
- return ConfigError(asNAME_TAKEN);
- }
- func->id = GetNextScriptFunctionId();
- SetScriptFunction(func);
- func->objectType->methods.PushLast(func->id);
- // The refCount was already set to 1
- func->ComputeSignatureId();
- // If parameter type from other groups are used, add references
- // TODO: The code for adding references to config groups is repeated in a lot of places
- if( func->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->returnType.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- for( asUINT n = 0; n < func->parameterTypes.GetLength(); n++ )
- {
- if( func->parameterTypes[n].GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(func->parameterTypes[n].GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- }
- // Return function id as success
- return func->id;
- }
- int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD flags)
- {
- int r;
- isPrepared = false;
- // Verify flags
- // Must have either asOBJ_REF or asOBJ_VALUE
- if( flags & asOBJ_REF )
- {
- // Can optionally have the asOBJ_GC, asOBJ_NOHANDLE, asOBJ_SCOPED, or asOBJ_TEMPLATE flag set, but nothing else
- if( flags & ~(asOBJ_REF | asOBJ_GC | asOBJ_NOHANDLE | asOBJ_SCOPED | asOBJ_TEMPLATE) )
- return ConfigError(asINVALID_ARG);
- // flags are exclusive
- if( (flags & asOBJ_GC) && (flags & (asOBJ_NOHANDLE|asOBJ_SCOPED)) )
- return ConfigError(asINVALID_ARG);
- if( (flags & asOBJ_NOHANDLE) && (flags & (asOBJ_GC|asOBJ_SCOPED)) )
- return ConfigError(asINVALID_ARG);
- if( (flags & asOBJ_SCOPED) && (flags & (asOBJ_GC|asOBJ_NOHANDLE)) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & asOBJ_VALUE )
- {
- // Cannot use reference flags
- // TODO: template: Should be possible to register a value type as template type
- if( flags & (asOBJ_REF | asOBJ_GC | asOBJ_SCOPED) )
- return ConfigError(asINVALID_ARG);
- // If the app type is given, we must validate the flags
- if( flags & asOBJ_APP_CLASS )
- {
- // Must not set the primitive or float flag
- if( flags & (asOBJ_APP_PRIMITIVE |
- asOBJ_APP_FLOAT) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & asOBJ_APP_PRIMITIVE )
- {
- // Must not set the class flags nor the float flag
- if( flags & (asOBJ_APP_CLASS |
- asOBJ_APP_CLASS_CONSTRUCTOR |
- asOBJ_APP_CLASS_DESTRUCTOR |
- asOBJ_APP_CLASS_ASSIGNMENT |
- asOBJ_APP_FLOAT) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & asOBJ_APP_FLOAT )
- {
- // Must not set the class flags nor the primitive flag
- if( flags & (asOBJ_APP_CLASS |
- asOBJ_APP_CLASS_CONSTRUCTOR |
- asOBJ_APP_CLASS_DESTRUCTOR |
- asOBJ_APP_CLASS_ASSIGNMENT |
- asOBJ_APP_PRIMITIVE) )
- return ConfigError(asINVALID_ARG);
- }
- else if( flags & (asOBJ_APP_CLASS_CONSTRUCTOR |
- asOBJ_APP_CLASS_DESTRUCTOR |
- asOBJ_APP_CLASS_ASSIGNMENT) )
- {
- // Must not set the class properties, without the class flag
- return ConfigError(asINVALID_ARG);
- }
- }
- else
- return ConfigError(asINVALID_ARG);
- // Don't allow anything else than the defined flags
- if( flags - (flags & asOBJ_MASK_VALID_FLAGS) )
- return ConfigError(asINVALID_ARG);
- // Value types must have a defined size
- if( (flags & asOBJ_VALUE) && byteSize == 0 )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_VALUE_TYPE_MUST_HAVE_SIZE);
- return ConfigError(asINVALID_ARG);
- }
- // Verify type name
- if( name == 0 )
- return ConfigError(asINVALID_NAME);
- asCString typeName;
- asCBuilder bld(this, 0);
- if( flags & asOBJ_TEMPLATE )
- {
- asCString subtypeName;
- r = bld.ParseTemplateDecl(name, &typeName, &subtypeName);
- if( r < 0 )
- return r;
- // Verify that the template name hasn't been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == typeName )
- return asALREADY_REGISTERED;
- }
- asCObjectType *type = asNEW(asCObjectType)(this);
- type->name = typeName;
- type->size = byteSize;
- type->flags = flags;
- // Store it in the object types
- objectTypes.PushLast(type);
- // Define a template subtype
- asCObjectType *subtype = 0;
- for( n = 0; n < templateSubTypes.GetLength(); n++ )
- {
- if( templateSubTypes[n]->name == subtypeName )
- {
- subtype = templateSubTypes[n];
- break;
- }
- }
- if( subtype == 0 )
- {
- // Create the new subtype if not already existing
- subtype = asNEW(asCObjectType)(this);
- subtype->name = subtypeName;
- subtype->size = 0;
- subtype->flags = asOBJ_TEMPLATE_SUBTYPE;
- templateSubTypes.PushLast(subtype);
- subtype->AddRef();
- }
- type->templateSubType = asCDataType::CreateObject(subtype, false);
- subtype->AddRef();
- currentGroup->objTypes.PushLast(type);
- if( defaultArrayObjectType == 0 )
- {
- // TODO: The default array object type should be defined by the application
- // The default array object type is registered by the engine itself
- defaultArrayObjectType = type;
- type->AddRef();
- }
- else
- {
- registeredObjTypes.PushLast(type);
- }
- }
- else
- {
- typeName = name;
- // Verify if the name has been registered as a type already
- asUINT n;
- for( n = 0; n < objectTypes.GetLength(); n++ )
- {
- if( objectTypes[n] && objectTypes[n]->name == typeName )
- return asALREADY_REGISTERED;
- }
- for( n = 0; n < templateTypes.GetLength(); n++ )
- {
- if( templateTypes[n] && templateTypes[n]->name == typeName )
- return asALREADY_REGISTERED;
- }
- // Verify the most recently created template instance type
- asCObjectType *mostRecentTemplateInstanceType = 0;
- if( templateInstanceTypes.GetLength() )
- mostRecentTemplateInstanceType = templateInstanceTypes[templateInstanceTypes.GetLength()-1];
- // Use builder to parse the datatype
- asCDataType dt;
- bool oldMsgCallback = msgCallback; msgCallback = false;
- r = bld.ParseDataType(name, &dt);
- msgCallback = oldMsgCallback;
- // If the builder fails, then the type name
- // is new and it should be registered
- if( r < 0 )
- {
- // Make sure the name is not a reserved keyword
- asCTokenizer t;
- size_t tokenLen;
- int token = t.GetToken(name, typeName.GetLength(), &tokenLen);
- if( token != ttIdentifier || typeName.GetLength() != tokenLen )
- return ConfigError(asINVALID_NAME);
- int r = bld.CheckNameConflict(name, 0, 0);
- if( r < 0 )
- return ConfigError(asNAME_TAKEN);
- // Don't have to check against members of object
- // types as they are allowed to use the names
- // Put the data type in the list
- asCObjectType *type = asNEW(asCObjectType)(this);
- type->name = typeName;
- type->size = byteSize;
- type->flags = flags;
- objectTypes.PushLast(type);
- registeredObjTypes.PushLast(type);
- currentGroup->objTypes.PushLast(type);
- }
- else
- {
- // The application is registering a template specialization so we
- // need to replace the template instance type with the new type.
- // TODO: Template: We don't require the lower dimensions to be registered first for registered template types
- // int[][] must not be allowed to be registered
- // if int[] hasn't been registered first
- if( dt.GetSubType().IsTemplate() )
- return ConfigError(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED);
- if( dt.IsReadOnly() ||
- dt.IsReference() )
- return ConfigError(asINVALID_TYPE);
- // Was the template instance type created before?
- if( templateInstanceTypes[templateInstanceTypes.GetLength()-1] == mostRecentTemplateInstanceType ||
- mostRecentTemplateInstanceType == dt.GetObjectType() )
- // TODO: Should have a better error message
- return ConfigError(asNOT_SUPPORTED);
- // TODO: Add this again. The type is used by the factory stubs so we need to discount that
- // Is the template instance type already being used?
- // if( dt.GetObjectType()->GetRefCount() > 1 )
- // return ConfigError(asNOT_SUPPORTED);
- // Put the data type in the list
- asCObjectType *type = asNEW(asCObjectType)(this);
- type->name = dt.GetObjectType()->name;
- type->templateSubType = dt.GetSubType();
- if( type->templateSubType.GetObjectType() ) type->templateSubType.GetObjectType()->AddRef();
- type->size = byteSize;
- type->flags = flags;
- templateTypes.PushLast(type);
- currentGroup->objTypes.PushLast(type);
- // Remove the template instance type, which will no longer be used.
- RemoveTemplateInstanceType(dt.GetObjectType());
- }
- }
- return asSUCCESS;
- }
- // interface
- int asCScriptEngine::RegisterObjectBehaviour(const char *datatype, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- if( datatype == 0 ) return ConfigError(asINVALID_ARG);
- // Determine the object type
- asCBuilder bld(this, 0);
- asCDataType type;
- int r = bld.ParseDataType(datatype, &type);
- if( r < 0 )
- return ConfigError(r);
- if( type.GetObjectType() == 0 )
- return ConfigError(asINVALID_TYPE);
- if( type.IsReadOnly() || type.IsReference() )
- return ConfigError(asINVALID_TYPE);
- return RegisterBehaviourToObjectType(type.GetObjectType(), behaviour, decl, funcPointer, callConv);
- }
- // internal
- int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, asEBehaviours behaviour, const char *decl, const asSFuncPtr &funcPointer, asDWORD callConv)
- {
- asSSystemFunctionInterface internal;
- if( behaviour == asBEHAVE_FACTORY ||
- behaviour == asBEHAVE_TEMPLATE_CALLBACK )
- {
- #ifdef AS_MAX_PORTABILITY
- if( callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #endif
- int r = DetectCallingConvention(false, funcPointer, callConv, &internal);
- if( r < 0 )
- return ConfigError(r);
- }
- else
- {
- #ifdef AS_MAX_PORTABILITY
- if( callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #else
- if( callConv != asCALL_THISCALL &&
- callConv != asCALL_CDECL_OBJLAST &&
- callConv != asCALL_CDECL_OBJFIRST &&
- callConv != asCALL_GENERIC )
- return ConfigError(asNOT_SUPPORTED);
- #endif
- int r = DetectCallingConvention(true, funcPointer, callConv, &internal);
- if( r < 0 )
- return ConfigError(r);
- }
- isPrepared = false;
- asSTypeBehaviour *beh = &objectType->beh;
- // Verify function declaration
- asCScriptFunction func(this, 0, -1);
- asCBuilder bld(this, 0);
- int r = bld.ParseFunctionDeclaration(objectType, decl, &func, true, &internal.paramAutoHandles, &internal.returnAutoHandle);
- if( r < 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.name.Format("_beh_%d_", behaviour);
- if( behaviour != asBEHAVE_FACTORY )
- func.objectType = objectType;
- // Check if the method restricts that use of the template to value types or reference types
- if( objectType->flags & asOBJ_TEMPLATE )
- {
- if( func.returnType.GetObjectType() == objectType->templateSubType.GetObjectType() )
- {
- if( func.returnType.IsObjectHandle() )
- objectType->acceptValueSubType = false;
- else if( !func.returnType.IsReference() )
- objectType->acceptRefSubType = false;
- }
- for( asUINT n = 0; n < func.parameterTypes.GetLength(); n++ )
- {
- if( func.parameterTypes[n].GetObjectType() == objectType->templateSubType.GetObjectType() )
- {
- // TODO: If unsafe references are allowed, then inout references allow value types
- if( func.parameterTypes[n].IsObjectHandle() || (func.parameterTypes[n].IsReference() && func.inOutFlags[n] == asTM_INOUTREF) )
- objectType->acceptValueSubType = false;
- else if( !func.parameterTypes[n].IsReference() )
- objectType->acceptRefSubType = false;
- }
- }
- }
- if( behaviour == asBEHAVE_CONSTRUCT )
- {
- // TODO: Add asBEHAVE_IMPLICIT_CONSTRUCT
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( objectType->flags & asOBJ_SCRIPT_OBJECT )
- {
- // The script object is a special case
- asASSERT(func.parameterTypes.GetLength() == 1);
- beh->construct = AddBehaviourFunction(func, internal);
- beh->factory = beh->construct;
- scriptFunctions[beh->factory]->AddRef();
- beh->constructors.PushLast(beh->construct);
- beh->factories.PushLast(beh->factory);
- func.id = beh->construct;
- }
- else
- {
- // Verify that it is a value type
- if( !(func.objectType->flags & asOBJ_VALUE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- // Implicit constructors must take one and only one parameter
- /* if( behaviour == asBEHAVE_IMPLICIT_CONSTRUCT &&
- func.parameterTypes.GetLength() != 1 )
- return ConfigError(asINVALID_DECLARATION);
- */
- // TODO: Verify that the same constructor hasn't been registered already
- // Store all constructors in a list
- if( func.parameterTypes.GetLength() == 0 )
- {
- func.id = beh->construct = AddBehaviourFunction(func, internal);
- beh->constructors.PushLast(beh->construct);
- }
- else
- {
- func.id = AddBehaviourFunction(func, internal);
- beh->constructors.PushLast(func.id);
- /*
- if( behaviour == asBEHAVE_IMPLICIT_CONSTRUCT )
- {
- beh->operators.PushLast(behaviour);
- beh->operators.PushLast(func.id);
- }
- */ }
- }
- }
- else if( behaviour == asBEHAVE_DESTRUCT )
- {
- // Must be a value type
- if( !(func.objectType->flags & asOBJ_VALUE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->destruct )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there are no parameters
- if( func.parameterTypes.GetLength() > 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->destruct = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_FACTORY )
- {
- // TODO: Add asBEHAVE_IMPLICIT_FACTORY
- // Must be a ref type and must not have asOBJ_NOHANDLE
- if( !(objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_NOHANDLE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- // Verify that the return type is a handle to the type
- if( func.returnType != asCDataType::CreateObjectHandle(objectType, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Implicit factories must take one and only one parameter
- /* if( behaviour == asBEHAVE_IMPLICIT_FACTORY &&
- func.parameterTypes.GetLength() != 1 )
- return ConfigError(asINVALID_DECLARATION);
- */
- // TODO: Verify that the same factory function hasn't been registered already
- // The templates take a hidden parameter with the object type
- if( (objectType->flags & asOBJ_TEMPLATE) &&
- (func.parameterTypes.GetLength() == 0 ||
- !func.parameterTypes[0].IsReference()) )
- {
- return ConfigError(asINVALID_DECLARATION);
- }
- // Store all factory functions in a list
- if( (func.parameterTypes.GetLength() == 0) ||
- (func.parameterTypes.GetLength() == 1 && (objectType->flags & asOBJ_TEMPLATE)) )
- {
- func.id = beh->factory = AddBehaviourFunction(func, internal);
- beh->factories.PushLast(beh->factory);
- }
- else
- {
- func.id = AddBehaviourFunction(func, internal);
- beh->factories.PushLast(func.id);
- /*
- if( behaviour == asBEHAVE_IMPLICIT_FACTORY )
- {
- beh->operators.PushLast(behaviour);
- beh->operators.PushLast(func.id);
- }
- */ }
- }
- else if( behaviour == asBEHAVE_ADDREF )
- {
- // Must be a ref type and must not have asOBJ_NOHANDLE, nor asOBJ_SCOPED
- if( !(func.objectType->flags & asOBJ_REF) ||
- (func.objectType->flags & asOBJ_NOHANDLE) ||
- (func.objectType->flags & asOBJ_SCOPED) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->addref )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there are no parameters
- if( func.parameterTypes.GetLength() > 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->addref = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_RELEASE )
- {
- // Must be a ref type and must not have asOBJ_NOHANDLE
- if( !(func.objectType->flags & asOBJ_REF) || (func.objectType->flags & asOBJ_NOHANDLE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->release )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is void
- if( func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there are no parameters
- if( func.parameterTypes.GetLength() > 0 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->release = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_TEMPLATE_CALLBACK )
- {
- // Must be a template type
- if( !(func.objectType->flags & asOBJ_TEMPLATE) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- if( beh->templateCallback )
- return ConfigError(asALREADY_REGISTERED);
- // Verify that the return type is bool
- if( func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there is one parameters
- if( func.parameterTypes.GetLength() != 1 )
- return ConfigError(asINVALID_DECLARATION);
- func.id = beh->templateCallback = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_INDEX )
- {
- // Verify that the var type is not used
- if( VerifyVarTypeNotInFunction(&func) < 0 )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that there is only one parameter
- if( func.parameterTypes.GetLength() != 1 )
- return ConfigError(asINVALID_DECLARATION);
- // Verify that the return type is not void
- if( func.returnType.GetTokenType() == ttVoid )
- return ConfigError(asINVALID_DECLARATION);
- // TODO: Verify that the operator hasn't been registered already
- beh->operators.PushLast(behaviour);
- func.id = AddBehaviourFunction(func, internal);
- beh->operators.PushLast(func.id);
- }
- else if( behaviour >= asBEHAVE_FIRST_GC &&
- behaviour <= asBEHAVE_LAST_GC )
- {
- // Only allow GC behaviours for types registered to be garbage collected
- if( !(func.objectType->flags & asOBJ_GC) )
- {
- WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
- return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE);
- }
- // Verify parameter count
- if( (behaviour == asBEHAVE_GETREFCOUNT ||
- behaviour == asBEHAVE_SETGCFLAG ||
- behaviour == asBEHAVE_GETGCFLAG) &&
- func.parameterTypes.GetLength() != 0 )
- return ConfigError(asINVALID_DECLARATION);
- if( (behaviour == asBEHAVE_ENUMREFS ||
- behaviour == asBEHAVE_RELEASEREFS) &&
- func.parameterTypes.GetLength() != 1 )
- return ConfigError(asINVALID_DECLARATION);
- // Verify return type
- if( behaviour == asBEHAVE_GETREFCOUNT &&
- func.returnType != asCDataType::CreatePrimitive(ttInt, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( behaviour == asBEHAVE_GETGCFLAG &&
- func.returnType != asCDataType::CreatePrimitive(ttBool, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( (behaviour == asBEHAVE_SETGCFLAG ||
- behaviour == asBEHAVE_ENUMREFS ||
- behaviour == asBEHAVE_RELEASEREFS) &&
- func.returnType != asCDataType::CreatePrimitive(ttVoid, false) )
- return ConfigError(asINVALID_DECLARATION);
- if( behaviour == asBEHAVE_GETREFCOUNT )
- func.id = beh->gcGetRefCount = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_SETGCFLAG )
- func.id = beh->gcSetFlag = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_GETGCFLAG )
- func.id = beh->gcGetFlag = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_ENUMREFS )
- func.id = beh->gcEnumReferences = AddBehaviourFunction(func, internal);
- else if( behaviour == asBEHAVE_RELEASEREFS )
- func.id = beh->gcReleaseAllReferences = AddBehaviourFunction(func, internal);
- }
- else if( behaviour == asBEHAVE_IMPLICIT_VALUE_CAST ||
- behaviour == asBEHAVE_VALUE_CAST )
- {
- // Verify parameter count
- if( func.parameterTypes.GetLength() != 0 )
- return ConfigError(asINVALID_DECLARATION);
- // Verify return type
- if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttBool, false)) )
- return ConfigError(asNOT_SUPPORTED);
- if( func.returnType.IsEqualExceptRefAndConst(asCDataType::CreatePrimitive(ttVoid, false)) )
- return ConfigError(asINVALID_DECLARATION);
- // TODO: verify that the same cast is not registered already (const or non-const is treated the same for the return type)
- beh->operators.PushLast(behaviour);
- func.id = AddBehaviourFunction(func, internal);
- beh->operators.PushLast(func.id);
- }
- else if( behaviour == asBEHAVE_REF_CAST ||
- behaviour == asBEHAVE_IMPLICIT_REF_CAST )
- {
- // Verify parameter count
- if( func.parameterTypes.GetLength() != 0 )
- return ConfigError(asINVALID_DECLARATION);
- // Verify return type
- if( !func.returnType.IsObjectHandle() )
- return ConfigError(asINVALID_DECLARATION);
- // TODO: verify that the same cast is not registered already (cosnt or non-const is treated the same for the return type)
- beh->operators.PushLast(behaviour);
- func.id = AddBehaviourFunction(func, internal);
- beh->operators.PushLast(func.id);
- }
- else
- {
- asASSERT(false);
- return ConfigError(asINVALID_ARG);
- }
- // Return function id as success
- return func.id;
- }
- int asCScriptEngine::VerifyVarTypeNotInFunction(asCScriptFunction *func)
- {
- // Don't allow var type in this function
- if( func->returnType.GetTokenType() == ttQuestion )
- return asINVALID_DECLARATION;
- for( unsigned int n = 0; n < func->parameterTypes.GetLength(); n++ )
- if( func->parameterTypes[n].GetTokenType() == ttQuestion )
- return asINVALID_DECLARATION;
- return 0;
- }
- int asCScriptEngine::AddBehaviourFunction(asCScriptFunction &func, asSSystemFunctionInterface &internal)
- {
- asUINT n;
- int id = GetNextScriptFunctionId();
- asSSystemFunctionInterface *newInterface = asNEW(asSSystemFunctionInterface);
- newInterface->func = internal.func;
- newInterface->baseOffset = internal.baseOffset;
- newInterface->callConv = internal.callConv;
- newInterface->scriptReturnSize = internal.scriptReturnSize;
- newInterface->hostReturnInMemory = internal.hostReturnInMemory;
- newInterface->hostReturnFloat = internal.hostReturnFloat;
- newInterface->hostReturnSize = internal.hostReturnSize;
- newInterface->paramSize = internal.paramSize;
- newInterface->takesObjByVal = internal.takesObjByVal;
- newInterface->paramAutoHandles = internal.paramAutoHandles;
- newInterface->returnAutoHandle = internal.returnAutoHandle;
- newInterface->hasAutoHandles = internal.hasAutoHandles;
- asCScriptFunction *f = asNEW(asCScriptFunction)(this, 0, asFUNC_SYSTEM);
- asASSERT(func.name != "" && func.name != "f");
- f->name = func.name;
- f->sysFuncIntf = newInterface;
- f->returnType = func.returnType;
- f->objectType = func.objectType;
- f->id = id;
- f->isReadOnly = func.isReadOnly;
- for( n = 0; n < func.parameterTypes.GetLength(); n++ )
- {
- f->parameterTypes.PushLast(func.parameterTypes[n]);
- f->inOutFlags.PushLast(func.inOutFlags[n]);
- }
- SetScriptFunction(f);
- // If parameter type from other groups are used, add references
- if( f->returnType.GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(f->returnType.GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- for( n = 0; n < f->parameterTypes.GetLength(); n++ )
- {
- if( f->parameterTypes[n].GetObjectType() )
- {
- asCConfigGroup *group = FindConfigGroupForObjectType(f->parameterTypes[n].GetObjectType());
- currentGroup->RefConfigGroup(group);
- }
- }
- return id;
- }
- // interface
- int asCScriptEngine::RegisterGlobalProperty(const char *declaration, void *pointer)
- {
- asCDataType type;
- asCString name;
- int r;
- asCBuilder bld(t…