Browse Source

Update to AngelScript 2.28.0 WIP to fix a ternary operator crash bug.

Lasse Öörni 12 years ago
parent
commit
56b453c25e
48 changed files with 3094 additions and 1520 deletions
  1. 1 1
      Docs/Urho3D.dox
  2. 1 1
      Readme.txt
  3. 107 1
      Source/Engine/Script/Addons.cpp
  4. 1 0
      Source/Engine/Script/Addons.h
  5. 21 15
      Source/ThirdParty/AngelScript/include/angelscript.h
  6. 4 4
      Source/ThirdParty/AngelScript/source/as_array.h
  7. 98 53
      Source/ThirdParty/AngelScript/source/as_builder.cpp
  8. 2 1
      Source/ThirdParty/AngelScript/source/as_builder.h
  9. 55 22
      Source/ThirdParty/AngelScript/source/as_bytecode.cpp
  10. 1 0
      Source/ThirdParty/AngelScript/source/as_bytecode.h
  11. 1 0
      Source/ThirdParty/AngelScript/source/as_callfunc.cpp
  12. 1 0
      Source/ThirdParty/AngelScript/source/as_callfunc_arm.cpp
  13. 276 195
      Source/ThirdParty/AngelScript/source/as_callfunc_arm_gcc.S
  14. 242 242
      Source/ThirdParty/AngelScript/source/as_callfunc_arm_msvc.asm
  15. 1 0
      Source/ThirdParty/AngelScript/source/as_callfunc_mips.cpp
  16. 2 1
      Source/ThirdParty/AngelScript/source/as_callfunc_ppc.cpp
  17. 2 1
      Source/ThirdParty/AngelScript/source/as_callfunc_ppc_64.cpp
  18. 1 0
      Source/ThirdParty/AngelScript/source/as_callfunc_sh4.cpp
  19. 1 0
      Source/ThirdParty/AngelScript/source/as_callfunc_x64_gcc.cpp
  20. 1 0
      Source/ThirdParty/AngelScript/source/as_callfunc_x64_mingw.cpp
  21. 2 1
      Source/ThirdParty/AngelScript/source/as_callfunc_x64_msvc.cpp
  22. 9 0
      Source/ThirdParty/AngelScript/source/as_callfunc_x86.cpp
  23. 2 1
      Source/ThirdParty/AngelScript/source/as_callfunc_xenon.cpp
  24. 420 196
      Source/ThirdParty/AngelScript/source/as_compiler.cpp
  25. 16 1
      Source/ThirdParty/AngelScript/source/as_compiler.h
  26. 1 4
      Source/ThirdParty/AngelScript/source/as_config.h
  27. 160 69
      Source/ThirdParty/AngelScript/source/as_context.cpp
  28. 1 1
      Source/ThirdParty/AngelScript/source/as_gc.cpp
  29. 28 7
      Source/ThirdParty/AngelScript/source/as_module.cpp
  30. 5 3
      Source/ThirdParty/AngelScript/source/as_objecttype.cpp
  31. 4 3
      Source/ThirdParty/AngelScript/source/as_objecttype.h
  32. 105 14
      Source/ThirdParty/AngelScript/source/as_parser.cpp
  33. 5 3
      Source/ThirdParty/AngelScript/source/as_parser.h
  34. 409 154
      Source/ThirdParty/AngelScript/source/as_restore.cpp
  35. 52 1
      Source/ThirdParty/AngelScript/source/as_restore.h
  36. 290 25
      Source/ThirdParty/AngelScript/source/as_scriptengine.cpp
  37. 12 6
      Source/ThirdParty/AngelScript/source/as_scriptengine.h
  38. 449 295
      Source/ThirdParty/AngelScript/source/as_scriptfunction.cpp
  39. 75 27
      Source/ThirdParty/AngelScript/source/as_scriptfunction.h
  40. 3 2
      Source/ThirdParty/AngelScript/source/as_scriptnode.h
  41. 9 0
      Source/ThirdParty/AngelScript/source/as_scriptobject.cpp
  42. 5 1
      Source/ThirdParty/AngelScript/source/as_scriptobject.h
  43. 8 1
      Source/ThirdParty/AngelScript/source/as_texts.h
  44. 102 99
      Source/ThirdParty/AngelScript/source/as_tokendef.h
  45. 56 58
      Source/ThirdParty/AngelScript/source/as_tokenizer.cpp
  46. 1 2
      Source/ThirdParty/AngelScript/source/as_tokenizer.h
  47. 40 7
      Source/ThirdParty/AngelScript/source/as_typeinfo.cpp
  48. 6 2
      Source/ThirdParty/AngelScript/source/as_typeinfo.h

+ 1 - 1
Docs/Urho3D.dox

@@ -88,7 +88,7 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org/) and Horde3D (http://
 
 Urho3D uses the following third-party libraries:
 
-- AngelScript 2.27.0 (http://www.angelcode.com/angelscript/)
+- AngelScript 2.28.0 WIP (http://www.angelcode.com/angelscript/)
 - Bullet 2.81 (http://www.bulletphysics.org/)
 - Civetweb (http://sourceforge.net/projects/civetweb/)
 - FreeType 2.3.12 (http://www.freetype.org/)

+ 1 - 1
Readme.txt

@@ -58,7 +58,7 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org) and Horde3D
   http://timothylottes.blogspot.com/2011/04/nvidia-fxaa-ii-for-console.html
 
 Urho3D uses the following third-party libraries:
-- AngelScript 2.27.0 (http://www.angelcode.com/angelscript/)
+- AngelScript 2.28.0 WIP (http://www.angelcode.com/angelscript/)
 - Bullet 2.81 (http://www.bulletphysics.org/)
 - Civetweb (http://sourceforge.net/projects/civetweb/)
 - FreeType 2.3.12 (http://www.freetype.org/)

+ 107 - 1
Source/Engine/Script/Addons.cpp

@@ -78,6 +78,22 @@ static CScriptArray* ScriptArrayFactory2(asIObjectType *ot, asUINT length)
     return a;
 }
 
+static CScriptArray* ScriptArrayListFactory(asIObjectType *ot, void *initList)
+{
+    CScriptArray *a = new CScriptArray(ot, initList);
+
+    // It's possible the constructor raised a script exception, in which case we 
+    // need to free the memory and return null instead, else we get a memory leak.
+    asIScriptContext *ctx = asGetActiveContext();
+    if( ctx && ctx->GetState() == asEXECUTION_EXCEPTION )
+    {
+        a->Release();
+        return 0;
+    }
+
+    return a;
+}
+
 static CScriptArray* ScriptArrayFactoryDefVal(asIObjectType *ot, asUINT length, void *defVal)
 {
     CScriptArray *a = new CScriptArray(length, defVal, ot);
@@ -201,6 +217,96 @@ CScriptArray &CScriptArray::operator=(const CScriptArray &other)
     return *this;
 }
 
+CScriptArray::CScriptArray(asIObjectType *ot, void *buf)
+{
+    refCount = 1;
+    gcFlag = false;
+    objType = ot;
+    objType->AddRef();
+    buffer = 0;
+
+    Precache();
+
+    asIScriptEngine *engine = ot->GetEngine();
+
+    // Determine element size
+    if( subTypeId & asTYPEID_MASK_OBJECT )
+        elementSize = sizeof(asPWORD);
+    else
+        elementSize = engine->GetSizeOfPrimitiveType(subTypeId);
+
+    // Determine the initial size from the buffer
+    asUINT length = *(asUINT*)buf;
+
+    // Make sure the array size isn't too large for us to handle
+    if( !CheckMaxSize(length) )
+    {
+        // Don't continue with the initialization
+        return;
+    }
+
+    // Copy the values of the array elements from the buffer
+    if( (ot->GetSubTypeId() & asTYPEID_MASK_OBJECT) == 0 )
+    {
+        CreateBuffer(&buffer, length);
+
+        // Copy the values of the primitive type into the internal buffer
+        memcpy(At(0), (((asUINT*)buf)+1), length * elementSize);
+    }
+    else if( ot->GetSubTypeId() & asTYPEID_OBJHANDLE )
+    {
+        CreateBuffer(&buffer, length);
+
+        // Copy the handles into the internal buffer
+        memcpy(At(0), (((asUINT*)buf)+1), length * elementSize);
+
+        // With object handles it is safe to clear the memory in the received buffer
+        // instead of increasing the ref count. It will save time both by avoiding the
+        // call the increase ref, and also relieve the engine from having to release
+        // its references too
+        memset((((asUINT*)buf)+1), 0, length * elementSize);
+    }
+    else if( ot->GetSubType()->GetFlags() & asOBJ_REF )
+    {
+        // Only allocate the buffer, but not the objects
+        subTypeId |= asTYPEID_OBJHANDLE;
+        CreateBuffer(&buffer, length);
+        subTypeId &= ~asTYPEID_OBJHANDLE;
+
+        // Copy the handles into the internal buffer
+        memcpy(buffer->data, (((asUINT*)buf)+1), length * elementSize);
+
+        // For ref types we can do the same as for handles, as they are 
+        // implicitly stored as handles.
+        memset((((asUINT*)buf)+1), 0, length * elementSize);
+    }
+    else
+    {
+        // TODO: Optimize by calling the copy constructor of the object instead of 
+        //       constructing with the default constructor and then assigning the value
+        // TODO: With C++11 ideally we should be calling the move constructor, instead
+        //       of the copy constructor as the engine will just discard the objects in the
+        //       buffer afterwards.
+        CreateBuffer(&buffer, length);
+
+        // For value types we need to call the opAssign for each individual object
+        for( asUINT n = 0; n < length; n++ )
+        {
+            void *obj = At(n);
+            asBYTE *srcObj = (asBYTE*)buf;
+            srcObj += 4 + n*ot->GetSubType()->GetSize();
+            engine->AssignScriptObject(obj, srcObj, ot->GetSubType());
+        }
+    }
+
+    // Urho3D: garbage collection disabled
+    /*
+    // Notify the GC of the successful creation
+    if( objType->GetFlags() & asOBJ_GC )
+        objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType);
+    */
+}
+
 CScriptArray::CScriptArray(asUINT length, asIObjectType *ot)
 {
     refCount = 1;
@@ -1391,7 +1497,7 @@ void RegisterArray(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("Array<T>", asBEHAVE_FACTORY, "Array<T>@ f(int& in)", asFUNCTIONPR(ScriptArrayFactory, (asIObjectType*), CScriptArray*), asCALL_CDECL);
     engine->RegisterObjectBehaviour("Array<T>", asBEHAVE_FACTORY, "Array<T>@ f(int& in, uint)", asFUNCTIONPR(ScriptArrayFactory2, (asIObjectType*, asUINT), CScriptArray*), asCALL_CDECL);
     engine->RegisterObjectBehaviour("Array<T>", asBEHAVE_FACTORY, "Array<T>@ f(int& in, uint, const T& in)", asFUNCTIONPR(ScriptArrayFactoryDefVal, (asIObjectType*, asUINT, void *), CScriptArray*), asCALL_CDECL);
-    engine->RegisterObjectBehaviour("Array<T>", asBEHAVE_LIST_FACTORY, "Array<T>@ f(int& in, uint)", asFUNCTIONPR(ScriptArrayFactory2, (asIObjectType*, asUINT), CScriptArray*), asCALL_CDECL);
+    engine->RegisterObjectBehaviour("Array<T>", asBEHAVE_LIST_FACTORY, "Array<T>@ f(int&in type, int&in list) {repeat T}", asFUNCTIONPR(ScriptArrayListFactory, (asIObjectType*, void*), CScriptArray*), asCALL_CDECL);
     engine->RegisterObjectBehaviour("Array<T>", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptArray,AddRef), asCALL_THISCALL);
     engine->RegisterObjectBehaviour("Array<T>", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptArray,Release), asCALL_THISCALL);
     engine->RegisterObjectMethod("Array<T>", "T& opIndex(uint)", asMETHODPR(CScriptArray, At, (unsigned), void*), asCALL_THISCALL);

+ 1 - 0
Source/Engine/Script/Addons.h

@@ -38,6 +38,7 @@ struct SArrayCache;
 class URHO3D_API CScriptArray
 {
 public:
+    CScriptArray(asIObjectType *ot, void *buf);
     CScriptArray(asUINT length, asIObjectType *ot);
     CScriptArray(asUINT length, void *defVal, asIObjectType *ot);
     CScriptArray(const CScriptArray &other);

+ 21 - 15
Source/ThirdParty/AngelScript/include/angelscript.h

@@ -59,8 +59,8 @@ BEGIN_AS_NAMESPACE
 
 // AngelScript version
 
-#define ANGELSCRIPT_VERSION        22700
-#define ANGELSCRIPT_VERSION_STRING "2.27.0"
+#define ANGELSCRIPT_VERSION        22800
+#define ANGELSCRIPT_VERSION_STRING "2.28.0 WIP"
 
 // Data types
 
@@ -1424,8 +1424,12 @@ enum asEBCInstr
 	asBC_RefCpyV		= 186,
 	asBC_JLowZ			= 187,
 	asBC_JLowNZ			= 188,
+	asBC_AllocMem		= 189,
+	asBC_SetListSize	= 190,
+	asBC_PshListElmnt	= 191,
+	asBC_SetListType	= 192,
 
-	asBC_MAXBYTECODE	= 189,
+	asBC_MAXBYTECODE	= 193,
 
 	// Temporary tokens. Can't be output to the final program
 	asBC_VarDecl		= 251,
@@ -1457,11 +1461,12 @@ enum asEBCType
 	asBCTYPE_QW_DW_ARG    = 16,
 	asBCTYPE_rW_QW_ARG    = 17,
 	asBCTYPE_W_DW_ARG     = 18,
-	asBCTYPE_rW_W_DW_ARG  = 19
+	asBCTYPE_rW_W_DW_ARG  = 19,
+	asBCTYPE_rW_DW_DW_ARG = 20
 };
 
 // Instruction type sizes
-const int asBCTypeSize[20] =
+const int asBCTypeSize[21] =
 {
 	0, // asBCTYPE_INFO
 	1, // asBCTYPE_NO_ARG
@@ -1482,7 +1487,8 @@ const int asBCTypeSize[20] =
 	4, // asBCTYPE_QW_DW_ARG
 	3, // asBCTYPE_rW_QW_ARG
 	2, // asBCTYPE_W_DW_ARG
-	3  // asBCTYPE_rW_W_DW_ARG
+	3, // asBCTYPE_rW_W_DW_ARG
+	3  // asBCTYPE_rW_DW_DW_ARG
 };
 
 // Instruction info
@@ -1706,11 +1712,11 @@ const asSBCInfo asBCInfo[256] =
 	asBCINFO(RefCpyV,	wW_PTR_ARG,		0),
 	asBCINFO(JLowZ,		DW_ARG,			0),
 	asBCINFO(JLowNZ,	DW_ARG,			0),
+	asBCINFO(AllocMem,	wW_DW_ARG,		0),
+	asBCINFO(SetListSize, rW_DW_DW_ARG,	0),
+	asBCINFO(PshListElmnt, rW_DW_ARG,	AS_PTR_SIZE),
+	asBCINFO(SetListType, rW_DW_DW_ARG,	0),
 
-	asBCINFO_DUMMY(189),
-	asBCINFO_DUMMY(190),
-	asBCINFO_DUMMY(191),
-	asBCINFO_DUMMY(192),
 	asBCINFO_DUMMY(193),
 	asBCINFO_DUMMY(194),
 	asBCINFO_DUMMY(195),
@@ -1778,11 +1784,11 @@ const asSBCInfo asBCInfo[256] =
 };
 
 // Macros to access bytecode instruction arguments
-#define asBC_DWORDARG(x)  (asDWORD(*(x+1)))
-#define asBC_INTARG(x)    (int(*(x+1)))
-#define asBC_QWORDARG(x)  (*(asQWORD*)(x+1))
-#define asBC_FLOATARG(x)  (*(float*)(x+1))
-#define asBC_PTRARG(x)    (*(asPWORD*)(x+1))
+#define asBC_DWORDARG(x)  (*(((asDWORD*)x)+1))
+#define asBC_INTARG(x)    (*(int*)(((asDWORD*)x)+1))
+#define asBC_QWORDARG(x)  (*(asQWORD*)(((asDWORD*)x)+1))
+#define asBC_FLOATARG(x)  (*(float*)(((asDWORD*)x)+1))
+#define asBC_PTRARG(x)    (*(asPWORD*)(((asDWORD*)x)+1))
 #define asBC_WORDARG0(x)  (*(((asWORD*)x)+1))
 #define asBC_WORDARG1(x)  (*(((asWORD*)x)+2))
 #define asBC_SWORDARG0(x) (*(((short*)x)+1))

+ 4 - 4
Source/ThirdParty/AngelScript/source/as_array.h

@@ -73,8 +73,8 @@ public:
 	void Concatenate(const asCArray<T> &);
 	void Concatenate(T*, unsigned int count);
 
-	bool Exists(T &element) const;
-	int  IndexOf(T &element) const;
+	bool Exists(const T &element) const;
+	int  IndexOf(const T &element) const;
 	void RemoveIndex(size_t index);          // Removes the entry without reordering the array
 	void RemoveValue(const T &element);      // Removes the value without reordering the array
 	void RemoveIndexUnordered(size_t index); // Removes the entry without keeping the order
@@ -463,13 +463,13 @@ void asCArray<T>::Concatenate(T* array, unsigned int count)
 }
 
 template <class T>
-bool asCArray<T>::Exists(T &e) const
+bool asCArray<T>::Exists(const T &e) const
 {
 	return IndexOf(e) == -1 ? false : true;
 }
 
 template <class T>
-int asCArray<T>::IndexOf(T &e) const
+int asCArray<T>::IndexOf(const T &e) const
 {
 	for( size_t n = 0; n < length; n++ )
 		if( array[n] == e ) return static_cast<int>(n);

+ 98 - 53
Source/ThirdParty/AngelScript/source/as_builder.cpp

@@ -365,9 +365,9 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
 
 	asCArray<asCString> parameterNames;
 	GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, parameterNames, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate, isFinal, isOverride, isShared, module->defaultNamespace);
-	func->id               = engine->GetNextScriptFunctionId();
-	func->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
-	func->nameSpace        = module->defaultNamespace;
+	func->id                           = engine->GetNextScriptFunctionId();
+	func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
+	func->nameSpace                    = module->defaultNamespace;
 
 	// Make sure the default args are declared correctly
 	int r = ValidateDefaultArgs(script, node, func);
@@ -929,7 +929,7 @@ asCGlobalProperty *asCBuilder::GetGlobalProperty(const char *prop, asSNameSpace
 	return 0;
 }
 
-int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns)
+int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle, asSNameSpace *ns, asCScriptNode **listPattern)
 {
 	asASSERT( objType || ns );
 
@@ -941,7 +941,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
 	source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);
 
 	asCParser parser(this);
-	int r = parser.ParseFunctionDefinition(&source);
+	int r = parser.ParseFunctionDefinition(&source, listPattern != 0);
 	if( r < 0 )
 		return asINVALID_DECLARATION;
 
@@ -971,7 +971,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
 	if( isSystemFunction &&
 		(func->returnType.GetObjectType() &&
 		 (func->returnType.GetObjectType()->flags & asOBJ_REF)) &&
-        !(func->returnType.IsReference() ||
+		!(func->returnType.IsReference() ||
 		  func->returnType.IsObjectHandle()) )
 		return asINVALID_DECLARATION;
 
@@ -1006,7 +1006,7 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
 		// Reference types cannot be passed by value to system functions
 		if( isSystemFunction &&
 			(type.GetObjectType() &&
-		     (type.GetObjectType()->flags & asOBJ_REF)) &&
+			 (type.GetObjectType()->flags & asOBJ_REF)) &&
 			!(type.IsReference() ||
 			  type.IsObjectHandle()) )
 			return asINVALID_DECLARATION;
@@ -1051,15 +1051,35 @@ int asCBuilder::ParseFunctionDeclaration(asCObjectType *objType, const char *dec
 	}
 
 	// Set the read-only flag if const is declared after parameter list
-	if( node->lastChild->nodeType == snUndefined && node->lastChild->tokenType == ttConst )
+	n = paramList->next;
+	if( n && n->nodeType == snUndefined && n->tokenType == ttConst )
 	{
 		if( objType == 0 )
 			return asINVALID_DECLARATION;
 		func->isReadOnly = true;
+
+		n = n->next;
 	}
 	else
 		func->isReadOnly = false;
 
+	// If the caller expects a list pattern, check for the existence, else report an error if not
+	if( listPattern )
+	{
+		if( n == 0 || n->nodeType != snListPattern ) 
+			return asINVALID_DECLARATION;
+		else
+		{
+			*listPattern = n;
+			n->DisconnectParent();
+		}
+	}
+	else
+	{
+		if( n )
+			return asINVALID_DECLARATION;
+	}
+	
 	// Make sure the default args are declared correctly
 	ValidateDefaultArgs(&source, node, func);
 
@@ -1302,10 +1322,7 @@ int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNam
 
 void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 {
-	asCDataType                returnType;
 	asCArray<asCString>        parameterNames;
-	asCArray<asCDataType>      parameterTypes;
-	asCArray<asETypeModifiers> inOutFlags;
 	asCArray<asCString *>      defaultArgs;
 	bool                       isConstMethod;
 	bool                       isConstructor;
@@ -1318,44 +1335,37 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 	asCScriptFunction *func = module->funcDefs[funcDef->idx];
 	asASSERT( func );
 
-	GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal, isShared, func->nameSpace);
+	GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, func->returnType, parameterNames, func->parameterTypes, func->inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal, isShared, func->nameSpace);
 
-	if( func )
-	{
-		func->returnType = returnType;
-		for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
-		{
-			func->parameterTypes.PushLast(parameterTypes[p]);
-			func->inOutFlags.PushLast(inOutFlags[p]);
+	// There should not be any defaultArgs, but if there are any we need to delete them to avoid leaks
+	for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+		if( defaultArgs[n] )
+			asDELETE(defaultArgs[n], asCString);
 
-			// Don't copy the default arg expression as it is not allowed for function definitions
-		}
+	// TODO: Should we force the use of 'shared' for this check to be done?
+	// Check if there is another identical funcdef from another module and if so reuse that instead
+	for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
+	{
+		asCScriptFunction *f2 = engine->funcDefs[n];
+		if( f2 == 0 || func == f2 )
+			continue;
 
-		// TODO: Should we force the use of 'shared' for this check to be done?
-		// Check if there is another identical funcdef from another module and if so reuse that instead
-		for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
+		if( f2->name == func->name &&
+			f2->nameSpace == func->nameSpace &&
+			f2->IsSignatureExceptNameEqual(func) )
 		{
-			asCScriptFunction *f2 = engine->funcDefs[n];
-			if( f2 == 0 || func == f2 )
-				continue;
-
-			if( f2->name == func->name &&
-				f2->nameSpace == func->nameSpace &&
-				f2->IsSignatureExceptNameEqual(func) )
-			{
-				// Replace our funcdef for the existing one
-				funcDef->idx = f2->id;
-				module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
-				f2->AddRef();
+			// Replace our funcdef for the existing one
+			funcDef->idx = f2->id;
+			module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
+			f2->AddRef();
 
-				engine->funcDefs.RemoveValue(func);
+			engine->funcDefs.RemoveValue(func);
 
-				func->Release();
+			func->Release();
 
-				// funcdefs aren't destroyed when the refCount reaches zero so we need to manually delete them
-				asDELETE(func, asCScriptFunction);
-				break;
-			}
+			// funcdefs aren't destroyed when the refCount reaches zero so we need to manually delete them
+			asDELETE(func, asCScriptFunction);
+			break;
 		}
 	}
 }
@@ -1760,7 +1770,7 @@ void asCBuilder::CompileGlobalVariables()
 				if( gvar->nextNode )
 				{
 					asCCompiler comp(engine);
-					asCScriptFunction func(engine, module, asFUNC_DUMMY);
+					asCScriptFunction func(engine, module, asFUNC_SCRIPT);
 
 					// Set the namespace that should be used during the compilation
 					func.nameSpace = gvar->datatype.GetObjectType()->nameSpace;
@@ -1771,6 +1781,9 @@ void asCBuilder::CompileGlobalVariables()
 					gvar->datatype = asCDataType::CreatePrimitive(ttInt, true);
 					r = comp.CompileGlobalVariable(this, gvar->script, gvar->nextNode, gvar, &func);
 					gvar->datatype = saveType;
+
+					// Make the function a dummy so it doesn't try to release objects while destroying the function
+					func.funcType = asFUNC_DUMMY;
 				}
 				else
 				{
@@ -1820,7 +1833,7 @@ void asCBuilder::CompileGlobalVariables()
 			else
 			{
 				// Compile the global variable
-				initFunc = asNEW(asCScriptFunction)(engine, module, asFUNC_DUMMY);
+				initFunc = asNEW(asCScriptFunction)(engine, module, asFUNC_SCRIPT);
 				if( initFunc == 0 )
 				{
 					// Out of memory
@@ -1841,6 +1854,7 @@ void asCBuilder::CompileGlobalVariables()
 				else
 				{
 					// Compilation failed
+					initFunc->funcType = asFUNC_DUMMY;
 					asDELETE(initFunc, asCScriptFunction);
 					initFunc = 0;
 				}
@@ -1861,16 +1875,15 @@ void asCBuilder::CompileGlobalVariables()
 					initOrder.Put(gvar->property);
 
 				// Does the function contain more than just a SUSPEND followed by a RET instruction?
-				if( initFunc && initFunc->byteCode.GetLength() > 2 )
+				if( initFunc && initFunc->scriptData->byteCode.GetLength() > 2 )
 				{
 					// Create the init function for this variable
 					initFunc->id = engine->GetNextScriptFunctionId();
 					engine->SetScriptFunction(initFunc);
 
 					// Finalize the init function for this variable
-					initFunc->funcType = asFUNC_SCRIPT;
 					initFunc->returnType = asCDataType::CreatePrimitive(ttVoid, false);
-					initFunc->scriptSectionIdx = engine->GetScriptSectionNameIndex(gvar->script->name.AddressOf());
+					initFunc->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(gvar->script->name.AddressOf());
 
 					gvar->property->SetInitFunc(initFunc);
 
@@ -1880,6 +1893,7 @@ void asCBuilder::CompileGlobalVariables()
 				else if( initFunc )
 				{
 					// Destroy the function as it won't be used
+					initFunc->funcType = asFUNC_DUMMY;
 					asDELETE(initFunc, asCScriptFunction);
 					initFunc = 0;
 				}
@@ -3051,7 +3065,6 @@ int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
 	vf->parameterTypes   = func->parameterTypes;
 	vf->inOutFlags       = func->inOutFlags;
 	vf->id               = engine->GetNextScriptFunctionId();
-	vf->scriptSectionIdx = func->scriptSectionIdx;
 	vf->isReadOnly       = func->isReadOnly;
 	vf->objectType       = func->objectType;
 	vf->signatureId      = func->signatureId;
@@ -3635,12 +3648,12 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 {
 	// Determine default namespace if not specified
 	if( ns == 0 )
-    {
+	{
 		if( objType )
 			ns = objType->nameSpace;
 		else
 			ns = engine->nameSpaces[0];
-    }
+	}
 
 	if( isExistingShared )
 	{
@@ -3674,6 +3687,11 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 			WriteError(str, file, node);
 		}
 
+		// Free the default args
+		for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+			if( defaultArgs[n] )
+				asDELETE(defaultArgs[n], asCString);
+
 		node->Destroy(engine);
 		return 0;
 	}
@@ -3697,6 +3715,12 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 		{
 			// Mixins cannot implement constructors/destructors
 			WriteError(TXT_MIXIN_CANNOT_HAVE_CONSTRUCTOR, file, node);
+
+			// Free the default args
+			for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+				if( defaultArgs[n] )
+					asDELETE(defaultArgs[n], asCString);
+
 			node->Destroy(engine);
 			return 0;
 		}
@@ -3715,7 +3739,14 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 	{
 		sFunctionDescription *func = asNEW(sFunctionDescription);
 		if( func == 0 )
+		{
+			// Free the default args
+			for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+				if( defaultArgs[n] )
+					asDELETE(defaultArgs[n], asCString);
+
 			return asOUT_OF_MEMORY;
+		}
 
 		functions.PushLast(func);
 
@@ -3793,6 +3824,12 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 					node->Destroy(engine);
 				sFunctionDescription *func = functions.PopLast();
 				asDELETE(func, sFunctionDescription);
+
+				// Free the default args
+				for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+					if( defaultArgs[n] )
+						asDELETE(defaultArgs[n], asCString);
+
 				return 0;
 			}
 
@@ -3804,6 +3841,11 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 	// Register the function
 	if( isExistingShared )
 	{
+		// Delete the default args as they won't be used anymore
+		for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+			if( defaultArgs[n] )
+				asDELETE(defaultArgs[n], asCString);
+
 		asCScriptFunction *f = engine->scriptFunctions[funcId];
 		module->AddScriptFunction(f);
 
@@ -4376,9 +4418,10 @@ asCDataType asCBuilder::CreateDataTypeFromNode(asCScriptNode *node, asCScriptCod
 			{
 				for( asUINT subtypeIndex = 0; subtypeIndex < currentType->templateSubTypes.GetLength(); subtypeIndex++)
 				{
-					if(str == currentType->templateSubTypes[subtypeIndex].GetObjectType()->name )
+					asCObjectType *type = currentType->templateSubTypes[subtypeIndex].GetObjectType();
+					if( type && str == type->name )
 					{
-						ot = currentType->templateSubTypes[subtypeIndex].GetObjectType();
+						ot = type;
 						break;
 					}
 				}
@@ -4621,7 +4664,9 @@ asCDataType asCBuilder::ModifyDataTypeFromNode(const asCDataType &type, asCScrip
 	if( n && n->tokenType == ttPlus )
 	{
 		// Autohandles are not supported for types with NOCOUNT
-		if( dt.GetObjectType()->flags & asOBJ_NOCOUNT )
+		// If the type is not a handle then there was an error with building the type, but 
+		// this error would already have been reported so no need to report another error here
+		if( dt.IsObjectHandle() && (dt.GetObjectType()->flags & asOBJ_NOCOUNT) )
 			WriteError(TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT, file, node->firstChild);
 
 		if( autoHandle ) *autoHandle = true;

+ 2 - 1
Source/ThirdParty/AngelScript/source/as_builder.h

@@ -138,7 +138,7 @@ public:
 	int VerifyProperty(asCDataType *dt, const char *decl, asCString &outName, asCDataType &outType, asSNameSpace *ns);
 	int ParseDataType(const char *datatype, asCDataType *result, asSNameSpace *implicitNamespace, bool isReturnType = false);
 	int ParseTemplateDecl(const char *decl, asCString *name, asCArray<asCString> &subtypeNames);
-	int ParseFunctionDeclaration(asCObjectType *type, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles = 0, bool *returnAutoHandle = 0, asSNameSpace *ns = 0);
+	int ParseFunctionDeclaration(asCObjectType *type, const char *decl, asCScriptFunction *func, bool isSystemFunction, asCArray<bool> *paramAutoHandles = 0, bool *returnAutoHandle = 0, asSNameSpace *ns = 0, asCScriptNode **listPattern = 0);
 	int ParseVariableDeclaration(const char *decl, asSNameSpace *implicitNamespace, asCString &outName, asSNameSpace *&outNamespace, asCDataType &outDt);
 	int CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns);
 	int CheckNameConflictMember(asCObjectType *type, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty);
@@ -154,6 +154,7 @@ public:
 protected:
 	friend class asCModule;
 	friend class asCParser;
+	friend class asCScriptFunction;
 
 	void               Reset();
 

+ 55 - 22
Source/ThirdParty/AngelScript/source/as_bytecode.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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
@@ -126,7 +126,8 @@ void asCByteCode::GetVarsUsed(asCArray<int> &vars)
 			     asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
 			     asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
 			     asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG ||
-				 asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG )
+				 asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG ||
+				 asBCInfo[curr->op].type == asBCTYPE_rW_DW_DW_ARG )
 		{
 			InsertIfNotExists(vars, curr->wArg[0]);
 		}
@@ -165,7 +166,8 @@ bool asCByteCode::IsVarUsed(int offset)
 				 asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
 				 asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
 				 asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG ||
-				 asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG )
+				 asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG ||
+				 asBCInfo[curr->op].type == asBCTYPE_rW_DW_DW_ARG )
 		{
 			if( curr->wArg[0] == offset )
 				return true;
@@ -211,7 +213,9 @@ void asCByteCode::ExchangeVar(int oldOffset, int newOffset)
 				 asBCInfo[curr->op].type == asBCTYPE_wW_W_ARG  ||
 				 asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
 				 asBCInfo[curr->op].type == asBCTYPE_wW_DW_ARG ||
-				 asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG )
+				 asBCInfo[curr->op].type == asBCTYPE_wW_QW_ARG ||
+				 asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG ||
+				 asBCInfo[curr->op].type == asBCTYPE_rW_DW_DW_ARG )
 		{
 			if( curr->wArg[0] == oldOffset )
 				curr->wArg[0] = (short)newOffset;
@@ -1176,6 +1180,7 @@ bool asCByteCode::IsTempVarReadByInstr(asCByteInstruction *curr, int offset)
 			  asBCInfo[curr->op].type == asBCTYPE_rW_DW_ARG ||
 			  asBCInfo[curr->op].type == asBCTYPE_rW_QW_ARG ||
 			  asBCInfo[curr->op].type == asBCTYPE_rW_W_DW_ARG ||
+			  asBCInfo[curr->op].type == asBCTYPE_rW_DW_DW_ARG ||
 			  curr->op == asBC_FREE) &&  // FREE both read and write to the variable
 			  int(curr->wArg[0]) == offset )
 		return true;
@@ -1483,6 +1488,8 @@ void asCByteCode::ExtractLineNumbers()
 
 void asCByteCode::ExtractObjectVariableInfo(asCScriptFunction *outFunc)
 {
+	asASSERT( outFunc->scriptData );
+
 	unsigned int pos = 0;
 	asCByteInstruction *instr = first;
 	int blockLevel = 0;
@@ -1497,17 +1504,17 @@ void asCByteCode::ExtractObjectVariableInfo(asCScriptFunction *outFunc)
 			if( info.option == asBLOCK_BEGIN )
 			{
 				blockLevel++;
-				outFunc->objVariableInfo.PushLast(info);
+				outFunc->scriptData->objVariableInfo.PushLast(info);
 			}
 			else
 			{
 				blockLevel--;
 				asASSERT( blockLevel >= 0 );
-				if( outFunc->objVariableInfo[outFunc->objVariableInfo.GetLength()-1].option == asBLOCK_BEGIN &&
-					outFunc->objVariableInfo[outFunc->objVariableInfo.GetLength()-1].programPos == pos )
-					outFunc->objVariableInfo.PopLast();
+				if( outFunc->scriptData->objVariableInfo[outFunc->scriptData->objVariableInfo.GetLength()-1].option == asBLOCK_BEGIN &&
+					outFunc->scriptData->objVariableInfo[outFunc->scriptData->objVariableInfo.GetLength()-1].programPos == pos )
+					outFunc->scriptData->objVariableInfo.PopLast();
 				else
-					outFunc->objVariableInfo.PushLast(info);
+					outFunc->scriptData->objVariableInfo.PushLast(info);
 			}
 		}
 		else if( instr->op == asBC_ObjInfo )
@@ -1516,11 +1523,11 @@ void asCByteCode::ExtractObjectVariableInfo(asCScriptFunction *outFunc)
 			info.programPos     = pos;
 			info.variableOffset = (short)instr->wArg[0];
 			info.option         = *(int*)ARG_DW(instr->arg);
-			outFunc->objVariableInfo.PushLast(info);
+			outFunc->scriptData->objVariableInfo.PushLast(info);
 		}
 		else if( instr->op == asBC_VarDecl )
 		{
-			outFunc->variables[instr->wArg[0]]->declaredAtProgramPos = pos;
+			outFunc->scriptData->variables[instr->wArg[0]]->declaredAtProgramPos = pos;
 		}
 		else
 			pos += instr->size;
@@ -1911,6 +1918,10 @@ void asCByteCode::Output(asDWORD *array)
 				*(((asWORD*)ap)+1) = 0; // Clear upper bytes
 				memcpy(ap+1, &instr->arg, instr->GetSize()*4-4);
 				break;
+			case asBCTYPE_rW_DW_DW_ARG:
+				*(((asWORD*)ap)+1) = instr->wArg[0];
+				memcpy(ap+1, &instr->arg, instr->GetSize()*4-4);
+				break;
 			default:
 				// How did we get here?
 				asASSERT(false);
@@ -2066,9 +2077,9 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
 	fprintf(file, "\n\n");
 
 	fprintf(file, "Variables: \n");
-	for( n = 0; n < func->variables.GetLength(); n++ )
+	for( n = 0; n < func->scriptData->variables.GetLength(); n++ )
 	{
-		fprintf(file, " %.3d: %s %s\n", func->variables[n]->stackOffset, func->variables[n]->type.Format().AddressOf(), func->variables[n]->name.AddressOf());
+		fprintf(file, " %.3d: %s %s\n", func->scriptData->variables[n]->stackOffset, func->scriptData->variables[n]->type.Format().AddressOf(), func->scriptData->variables[n]->name.AddressOf());
 	}
 	asUINT offset = 0;
 	if( func->objectType )
@@ -2079,9 +2090,9 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
 	for( n = 0; n < func->parameterTypes.GetLength(); n++ )
 	{
 		bool found = false;
-		for( asUINT v = 0; v < func->variables.GetLength(); v++ )
+		for( asUINT v = 0; v < func->scriptData->variables.GetLength(); v++ )
 		{
-			if( func->variables[v]->stackOffset == (int)offset )
+			if( func->scriptData->variables[v]->stackOffset == (int)offset )
 			{
 				found = true;
 				break;
@@ -2092,19 +2103,19 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
 
 		offset -= func->parameterTypes[n].GetSizeOnStackDWords();
 	}
-	for( n = 0; n < func->objVariablePos.GetLength(); n++ )
+	for( n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ )
 	{
 		bool found = false;
-		for( asUINT v = 0; v < func->variables.GetLength(); v++ )
+		for( asUINT v = 0; v < func->scriptData->variables.GetLength(); v++ )
 		{
-			if( func->variables[v]->stackOffset == func->objVariablePos[n] )
+			if( func->scriptData->variables[v]->stackOffset == func->scriptData->objVariablePos[n] )
 			{
 				found = true;
 				break;
 			}
 		}
 		if( !found )
-			fprintf(file, " %.3d: %s {noname}\n", func->objVariablePos[n], func->objVariableTypes[n]->name.AddressOf());
+			fprintf(file, " %.3d: %s {noname}\n", func->scriptData->objVariablePos[n], func->scriptData->objVariableTypes[n]->name.AddressOf());
 	}
 	fprintf(file, "\n\n");
 
@@ -2123,16 +2134,16 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
 		fprintf(file, "%5d ", pos);
 		pos += instr->GetSize();
 
-		fprintf(file, "%3d %c ", int(instr->stackSize + func->variableSpace), instr->marked ? '*' : ' ');
+		fprintf(file, "%3d %c ", int(instr->stackSize + func->scriptData->variableSpace), instr->marked ? '*' : ' ');
 
 		switch( asBCInfo[instr->op].type )
 		{
 		case asBCTYPE_W_ARG:
 			if( instr->op == asBC_STR )
 			{
-				int id = instr->wArg[0];
+				int id = asWORD(instr->wArg[0]);
 				const asCString &str = engine->GetConstantString(id);
-				fprintf(file, "   %-8s %d         (l:%ld s:\"%.10s\")\n", asBCInfo[instr->op].name, instr->wArg[0], (long int)str.GetLength(), str.AddressOf());
+				fprintf(file, "   %-8s %d         (l:%ld s:\"%.10s\")\n", asBCInfo[instr->op].name, asWORD(instr->wArg[0]), (long int)str.GetLength(), str.AddressOf());
 			}
 			else
 				fprintf(file, "   %-8s %d\n", asBCInfo[instr->op].name, instr->wArg[0]);
@@ -2252,6 +2263,10 @@ void asCByteCode::DebugOutput(const char *name, asCScriptEngine *engine, asCScri
 				fprintf(file, "   %-8s %u, %d\n", asBCInfo[instr->op].name, *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1));
 			break;
 
+		case asBCTYPE_rW_DW_DW_ARG:
+			fprintf(file, "   %-8s v%d, %u, %u\n", asBCInfo[instr->op].name, instr->wArg[0], *(int*)ARG_DW(instr->arg), *(int*)(ARG_DW(instr->arg)+1));
+			break;
+
 		case asBCTYPE_QW_DW_ARG:
 			if( instr->op == asBC_ALLOC )
 			{
@@ -2442,6 +2457,24 @@ int asCByteCode::InstrW_DW(asEBCInstr bc, asWORD a, asDWORD b)
 	return last->stackInc;
 }
 
+int asCByteCode::InstrSHORT_DW_DW(asEBCInstr bc, short a, asDWORD b, asDWORD c)
+{
+	asASSERT(asBCInfo[bc].type == asBCTYPE_rW_DW_DW_ARG);
+	asASSERT(asBCInfo[bc].stackInc == 0);
+
+	if( AddInstruction() < 0 )
+		return 0;
+
+	last->op       = bc;
+	last->wArg[0]  = a;
+	*(int*)ARG_DW(last->arg) = b;
+	*(int*)(ARG_DW(last->arg)+1) = c;
+	last->size     = asBCTypeSize[asBCInfo[bc].type];
+	last->stackInc = asBCInfo[bc].stackInc;
+
+	return last->stackInc;
+}
+
 int asCByteCode::InstrSHORT_B(asEBCInstr bc, short a, asBYTE b)
 {
 	asASSERT(asBCInfo[bc].type == asBCTYPE_wW_DW_ARG ||

+ 1 - 0
Source/ThirdParty/AngelScript/source/as_bytecode.h

@@ -128,6 +128,7 @@ public:
 	int InstrW_PTR(asEBCInstr bc, short a, void *param);
 	int InstrW_FLOAT(asEBCInstr bc, asWORD a, float b);
 	int InstrW_W(asEBCInstr bc, int w, int b);
+	int InstrSHORT_DW_DW(asEBCInstr bc, short a, asDWORD b, asDWORD c);
 
 	asCArray<int> lineNumbers;
 	asCArray<int> sectionIdxs;

+ 1 - 0
Source/ThirdParty/AngelScript/source/as_callfunc.cpp

@@ -41,6 +41,7 @@
 #include "as_callfunc.h"
 #include "as_scriptengine.h"
 #include "as_texts.h"
+#include "as_context.h"
 
 BEGIN_AS_NAMESPACE
 

+ 1 - 0
Source/ThirdParty/AngelScript/source/as_callfunc_arm.cpp

@@ -55,6 +55,7 @@
 #include "as_scriptengine.h"
 #include "as_texts.h"
 #include "as_tokendef.h"
+#include "as_context.h"
 
 #if !defined(AS_LINUX)
 

+ 276 - 195
Source/ThirdParty/AngelScript/source/as_callfunc_arm_gcc.S

@@ -50,7 +50,8 @@
 .global armFuncR0R1
 .global armFuncObjLast
 .global armFuncR0ObjLast
-    
+
+/* --------------------------------------------------------------------------------------------*/
 armFunc:
     stmdb   sp!, {r4-r8, lr}
     mov     r6, r0  /* arg table */
@@ -88,6 +89,7 @@ nomoreargs:
     add     sp, sp, r8
     ldmia   sp!, {r4-r8, pc}
 
+/* --------------------------------------------------------------------------------------------*/
 armFuncObjLast:
     stmdb   sp!, {r4-r8, lr}
     mov     r6, r0  /* arg table */
@@ -135,6 +137,7 @@ nomoreargsarmFuncObjLast:
     add     sp, sp, r8
     ldmia   sp!, {r4-r8, pc}
 
+/* --------------------------------------------------------------------------------------------*/
 armFuncR0ObjLast:
     stmdb   sp!, {r4-r8, lr}
     ldr     r5, [sp,#6*4]   /* objlast to temp reg */
@@ -181,7 +184,7 @@ nomoreargsarmFuncR0ObjLast:
     add     sp, sp, r8
     ldmia   sp!, {r4-r8, pc}
 
-
+/* --------------------------------------------------------------------------------------------*/
 armFuncR0:
     stmdb   sp!, {r4-r8, lr}
     mov     r6, r0  /* arg table */
@@ -219,7 +222,7 @@ nomoreargsarmFuncR0:
     add     sp, sp, r8
     ldmia   sp!, {r4-r8, pc}
 
-
+/* --------------------------------------------------------------------------------------------*/
 armFuncR0R1:
     stmdb   sp!, {r4-r8, lr}
     mov     r6, r0  /* arg table */
@@ -256,31 +259,51 @@ nomoreargsarmFuncR0R1:
     add     sp, sp, r8
     ldmia   sp!, {r4-r8, pc}
 
+/* --------------------------------------------------------------------------------------------*/
 #elif defined(__linux__)
 
 /* The Linux code goes here */
 
-.global armFunc
-.global armFuncR0
-.global armFuncR0R1
-.global armFuncObjLast
-.global armFuncR0ObjLast
-    
+
+/* These codes are suitable for armeabi + vfp  / armeabihf */
+/* when using armeabi + vfp, please set C_FLAGS -mfloat-abi=softfp -mfpu=vfp */
+/* using armeabihf, please set C_FLAGS -mfloat-abi=hard -mfpu=vfpv3-d16 */
+
+/* if you prefer to run in ARM mode, please add -marm to C_FLAGS */
+/* while using thumb mode, please add -mthumb -Wa,-mimplicit-it=thumb */
+
+
+/* SP is a multiple of 8 when control first enters a program.*/
+/* This places an obligation on authors of low level OS, RTOS, and runtime library code to align SP at all points */
+/* at which control first enters a body of (AAPCS-conforming) code. (please read "ARM IHI 0046B" document)*/
+
+
+.section .text
+
+    .align 2        /* Align the function code to a 4-byte (2^n) word boundary. */
+#if defined(__thumb__) || defined(__thumb2__)
+    .thumb
+    .syntax unified
+#else
+    .arm            /* Use ARM instructions instead of Thumb.*/
+#endif
+    .globl armFunc  /* Make the function globally accessible.*/
 armFunc:
-    stmfd   sp!, {r4-r8, r10, lr}
+    push    {r4-r8, r10, r11, lr}   /* sp must be 8-byte alignment for ABI compliance, so the pushed registers must be even */
+
     mov     r6, r0  /* arg table */
     movs    r7, r1  /* arg size (also set the condition code flags so that we detect if there are no arguments) */
     mov     r4, r2  /* function address */
-    mov     r8, #0
-    
+
     /* Load float and double args into d0-d7 and s0-s15 */
-    add		r10, r6, #272	/* r10 (r6 + 272) points to the first value for the VFP registers */
-    fldmiad r10, {d0-d7}	/* Load contents starting at r10 into registers d0-d7 */
-    
-	/* If there are no arguments to set into r0-r3 */
-	/* go check if there are arguments for the stack */
+    add       r10, r6, #272 /* r10 (r6 + 272) points to the first value for the VFP registers */
+    mov       r8, #0
+    vldmia.64 r10, {d0-d7}  /* Load contents starting at r10 into registers d0-d7 */
+
+    /* If there are no arguments to set into r0-r3 */
+    /* go check if there are arguments for the stack */
     beq     stackargs
-        
+
     /* Load the first 4 arguments into r0-r3 */
     cmp     r7, #4
     ldrge   r0, [r6]
@@ -289,62 +312,75 @@ armFunc:
     cmp     r7, #12
     ldrge   r2, [r6, #8]
     cmp     r7, #16
-    ldrge   r3, [r6, #12]        
-    
+    ldrge   r3, [r6, #12]
+
 stackargs:
-	ldr		r5, [r6, #268]	/* Load stack size into r5 */
-	movs	r7, r5			/* Load stack size into r7, checking for 0 args */
-	
-	/* If there are no args for the stack, branch */
-	beq		nomoreargs
+    ldr     r5, [r6, #268]  /* Load stack size into r5 */
+    movs    r7, r5          /* Load stack size into r7, checking for 0 args */
+
+    /* If there are no args for the stack, branch */
+    beq     nomoreargs
 
     /* Load the rest of the arguments onto the stack */
-	/* Ensure 8-byte stack alignment */
-	mov		r8, sp
-	sub		sp, sp, r7
-	sub		sp, sp, #8
-    bic     sp, sp, #7
-    sub     r8, r8, sp
-    mov     r12, sp				/* copy size != frame size, so store frame start sp	*/
-    add		r6, r6, #16			/* Set r6 to point to the first arg to be placed on the stack */
+    /* Ensure 8-byte stack alignment */
+    mov     r8, sp
+    sub     sp, sp, r7
+    add     r6, r6, #16     /* Set r6 to point to the first arg to be placed on the stack */
+
+    sub     r12, sp, #8
+    bic     r12, r12, #7    /* thumb mode couldn't support "bic  sp, sp, #7" instruction */
+    sub     r8, r8, r12
+    mov     sp, r12         /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
 
 stackargsloop:
     ldr     r5, [r6], #4
-    str     r5, [sp], #4
     subs    r7, r7, #4
+    str     r5, [sp], #4
     bne     stackargsloop
     mov     sp, r12
 
 nomoreargs:
+#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
+    mov    lr, pc   /* older ARM didn't support blx */
+    mov    pc, r4
+#else
     blx     r4
-    fstmiad	r10, {d0-d7}		/* Copy contents of registers d0-d7 to the address stored in r10 */
+#endif
     add     sp, sp, r8
-    
-    ldmfd   sp!, {r4-r8, r10, pc}
-    
-/* --------------------------------------------------------------------------------------------*/
+    vstmia.64 r10, {d0-d7}   /* Copy contents of registers d0-d7 to the address stored in r10 */
 
+    pop {r4-r8, r10, r11, pc}
+
+/* --------------------------------------------------------------------------------------------*/
+    .align 2        /* Align the function code to a 4-byte (2^n) word boundary. */
+#if defined(__thumb__) || defined(__thumb2__)
+    .thumb
+    .syntax unified
+#else
+    .arm            /* Use ARM instructions instead of Thumb.*/
+#endif
+    .globl armFuncObjLast       /* Make the function globally accessible.*/
 armFuncObjLast:
-    stmfd   sp!, {r4-r8, r10, r11, lr}	/* We´re storing r11 just to keep the stack aligned to an 8 byte boundary */
-    
+    push {r4-r8, r10, r11, lr}  /* We´re storing r11 just to keep the stack aligned to an 8 byte boundary */
+
     mov     r6, r0  /* arg table */
     movs    r7, r1  /* arg size (also set the condition code flags so that we detect if there are no arguments) */
     mov     r4, r2  /* function address */
-    mov     r8, #0
 
     mov     r0, r3          /* objlast. might get overwritten */
-    mov		r5, #0			/* This will hold an offset of #4 only if objlast couldn´t be placed into an "r" register */
-    
+    mov     r5, #0          /* This will hold an offset of #4 only if objlast couldn´t be placed into an "r" register */
+
     /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
-    add		r10, r6, #272	/* r10 (r6 + 272) points to the first value for the VFP registers */
-    fldmiad r10, {d0-d7}	/* Load contents starting at r10 into registers d0-d7 */
-    
-	/* If there are no arguments to set into r0-r3 */
-	/* go check if there are arguments for the stack */
+    add     r10, r6, #272   /* r10 (r6 + 272) points to the first value for the VFP registers */
+    mov     r8, #0
+    vldmia.64 r10, {d0-d7}  /* Load contents starting at r10 into registers d0-d7 */
+
+    /* If there are no arguments to set into r0-r3 */
+    /* go check if there are arguments for the stack */
     beq     stackargsFuncObjLast
-    
-    mov		r5, r3			/* store objlast in r5 temporarily */
-    
+
+    mov     r5, r3          /* store objlast in r5 temporarily */
+
     /* Load the first 4 arguments into r0-r3 */
     cmp     r7, #4
     ldrge   r0, [r6]
@@ -357,70 +393,83 @@ armFuncObjLast:
     cmp     r7, #16
     ldrge   r3, [r6,#12]
     movlt   r3, r5
-    movlt	r5, #0					/* If objlast got placed into a register, r5 = 0 */
-    blt     stackargsFuncObjLast	/* If objlast got placed into a register, go to stackargsFuncObjLast */
-    
-    str		r5, [r6, #12]			/* Put objlast in r6 + 12 */
-    mov		r5, #4					/* Set r5 with an offset of #4, so objlast can be loaded into the stack */
-    
+    movlt   r5, #0                  /* If objlast got placed into a register, r5 = 0 */
+    blt     stackargsFuncObjLast    /* If objlast got placed into a register, go to stackargsFuncObjLast */
+
+    str     r5, [r6, #12]           /* Put objlast in r6 + 12 */
+    mov     r5, #4                  /* Set r5 with an offset of #4, so objlast can be loaded into the stack */
+
 stackargsFuncObjLast:
-	ldr		r7, [r6, #268]	/* Load stack size into r7 */
-	add		r7, r7, r5		/* Add the offset placed in r5 (could be #0 or #4) */
-	cmp		r7, #0			/* Check for 0 args */
-	
-	/* If there are no args for the stack, branch */
-	beq		nomoreargsarmFuncObjLast
+    ldr     r7, [r6, #268]  /* Load stack size into r7 */
+    add     r7, r7, r5      /* Add the offset placed in r5 (could be #0 or #4) */
+    cmp     r7, #0          /* Check for 0 args */
+
+    /* If there are no args for the stack, branch */
+    beq     nomoreargsarmFuncObjLast
 
     /* Load the rest of the arguments onto the stack */
     /* Ensure 8-byte stack alignment */
-    mov		r8, sp
-	sub		sp, sp, r7
-	sub		sp, sp, #8
-    bic     sp, sp, #7
-    sub     r8, r8, sp
-    mov     r12, sp         /* copy size != frame size, so store frame start sp */
-    add		r6, r6, #16		/* Set r6 to point to the first arg to be placed on the stack */
-    sub		r6, r6, r5		/* r6 = r6 - r5 (r5 can be #0 or #4) */
+    mov     r8, sp
+    sub     sp, sp, r7
+    add     r6, r6, #16     /* Set r6 to point to the first arg to be placed on the stack */
+
+    sub     r12, sp, #8
+    sub     r6, r6, r5      /* r6 = r6 - r5 (r5 can be #0 or #4) */
+    bic     r12, r12, #7    /* thumb mode couldn't support "bic  sp, sp, #7" instruction */
+    sub     r8, r8, r12
+    mov     sp, r12         /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
 
 stackargslooparmFuncObjLast:
     ldr     r5, [r6], #4
-    str     r5, [sp], #4
     subs    r7, r7, #4
+    str     r5, [sp], #4
     bne     stackargslooparmFuncObjLast
     mov     sp, r12
-    
+
 nomoreargsarmFuncObjLast:
+#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
+    mov    lr, pc
+    mov    pc, r4
+#else
     blx     r4
-    fstmiad	r10, {d0-d7}	/* Copy contents of registers d0-d10 to the address stored in r10 */
+#endif
     add     sp, sp, r8
-    
-    ldmfd   sp!, {r4-r8, r10,r11, pc}
-    
-/* ------------------------------------------------------------------------------------------- */
+    vstmia.64   r10, {d0-d7}    /* Copy contents of registers d0-d10 to the address stored in r10 */
 
+    pop   {r4-r8, r10,r11, pc}
+
+/* ------------------------------------------------------------------------------------------- */
+    .align 2        /* Align the function code to a 4-byte (2^n) word boundary. */
+#if defined(__thumb__) || defined(__thumb2__)
+    .thumb
+    .syntax unified
+#else
+    .arm            /* Use ARM instructions instead of Thumb.*/
+#endif
+    .globl armFuncR0ObjLast     /* Make the function globally accessible.*/
 armFuncR0ObjLast:
-    stmfd   sp!, {r4-r8, r10, r11, lr}
-    
+    push    {r4-r8, r10, r11, lr}
+
     ldr     r5, [sp,#32]   /* objlast to temp reg */
 
     mov     r6, r0  /* arg table */
     movs    r7, r1  /* arg size (also set the condition code flags so that we detect if there are no arguments) */
     mov     r4, r2  /* function address */
-    mov     r8, #0
 
     mov     r0, r3      /* r0 explicitly set */
     mov     r1, r5      /* objlast.  might get overwritten */
-    mov		r5, #0		/* This will hold an offset of #4 or #8 if objlast or one arg couldn´t be placed into an "r" register */
-   
-	/* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
-    add		r10, r6, #272	/* r10 (r6 + 272) points to the first value for the VFP registers */
-    fldmiad r10, {d0-d7}	/* Load contents starting at r10 into registers d0-d7 */
-     
-	/* If there are no arguments to set into r0-r3 */
-	/* go check if there are arguments for the stack */
+    mov     r5, #0      /* This will hold an offset of #4 or #8 if objlast or one arg couldn´t be placed into an "r" register */
+
+    /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
+    add     r10, r6, #272   /* r10 (r6 + 272) points to the first value for the VFP registers */
+    mov     r8, #0
+    vldmia.64 r10, {d0-d7}  /* Load contents starting at r10 into registers d0-d7 */
+
+    /* If there are no arguments to set into r0-r3 */
+    /* go check if there are arguments for the stack */
     beq     stackargsFuncR0ObjLast
-    
-    mov		r5, r1			/* store objlast in r5 temporarily */
+
+    mov     r5, r1          /* store objlast in r5 temporarily */
 
     /* Load the first 3 arguments into r1-r3 */
     cmp     r7, #4
@@ -431,69 +480,82 @@ armFuncR0ObjLast:
     cmp     r7, #12
     ldrge   r3, [r6,#8]
     movlt   r3, r5
-    movlt	r5, #0					/* If objlast got placed into a register, r5 = 0 */
-    blt     stackargsFuncR0ObjLast	/* If objlast got placed into a register, go to stackargsFuncR0ObjLast */
-    
-    cmp		r7, #16					/* Else if we have one last arg set the offset accordingly and store the arg in the array */
-    ldrge	r7, [r6, #12]
-    strge	r7, [r6, #8]
-    
-    str		r5, [r6, #12]			/* Put objlast in r6 + 12 */
-    
-    movge	r5, #4					/* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
-    add		r5, r5, #4				/* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
-    
+    movlt   r5, #0                  /* If objlast got placed into a register, r5 = 0 */
+    blt     stackargsFuncR0ObjLast  /* If objlast got placed into a register, go to stackargsFuncR0ObjLast */
+
+    cmp     r7, #16                 /* Else if we have one last arg set the offset accordingly and store the arg in the array */
+    ldrge   r7, [r6, #12]
+    strge   r7, [r6, #8]
+
+    str     r5, [r6, #12]           /* Put objlast in r6 + 12 */
+
+    movge   r5, #4                  /* Set r5 with an offset of #4 if there´s one last arg that couldn´t be placed in r registers */
+    add     r5, r5, #4              /* Set r5 with an offset of + #4, so objlast can be loaded into the stack */
+
 stackargsFuncR0ObjLast:
-	ldr		r7, [r6, #268]	/* Load stack size into r7 */
-	add		r7, r7, r5		/* Add the offset placed in r5 (could be #0 or #4) */
-	cmp		r7, #0			/* Check for 0 args */
-	
-	/* If there are no args for the stack, branch */
-	beq		nomoreargsarmFuncR0ObjLast
-	
-	/* Load the rest of the arguments onto the stack */
+    ldr     r7, [r6, #268]  /* Load stack size into r7 */
+    add     r7, r7, r5      /* Add the offset placed in r5 (could be #0 or #4) */
+    cmp     r7, #0          /* Check for 0 args */
+
+    /* If there are no args for the stack, branch */
+    beq     nomoreargsarmFuncR0ObjLast
+
+    /* Load the rest of the arguments onto the stack */
     /* Ensure 8-byte stack alignment */
-    mov		r8, sp
-	sub		sp, sp, r7
-	sub		sp, sp, #8
-    bic     sp, sp, #7
-    sub     r8, r8, sp
-    mov     r12, sp         /* copy size != frame size, so store frame start sp */
-    add		r6, r6, #16		/* Set r6 to point to the first arg to be placed on the stack */
-    sub		r6, r6, r5		/* r6 = r6 - r5 (r5 can be #0 or #4) */
-    
+    mov     r8, sp
+    sub     sp, sp, r7
+    add     r6, r6, #16     /* Set r6 to point to the first arg to be placed on the stack */
+
+    sub     r12, sp, #8
+    sub     r6, r6, r5      /* r6 = r6 - r5 (r5 can be #0 or #4) */
+    bic     r12, r12, #7    /* thumb mode couldn't support "bic  sp, sp, #7" instruction */
+    sub     r8, r8, r12
+    mov     sp, r12         /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
+
 stackargslooparmFuncR0ObjLast:
     ldr     r5, [r6], #4
-    str     r5, [sp], #4
     subs    r7, r7, #4
+    str     r5, [sp], #4
     bne     stackargslooparmFuncR0ObjLast
     mov     sp, r12
-    
+
 nomoreargsarmFuncR0ObjLast:
+#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
+    mov    lr, pc
+    mov    pc, r4
+#else
     blx     r4
-    fstmiad	r10, {d0-d7}	/* Copy contents of registers d0-d10 to the address stored in r10 */
+#endif
     add     sp, sp, r8
-    
-    ldmfd   sp!, {r4-r8, r10, r11, pc}
-    
-/* ------------------------------------------------------------------------------------------- */
+    vstmia.64   r10, {d0-d7}    /* Copy contents of registers d0-d10 to the address stored in r10 */
 
+    pop {r4-r8, r10, r11, pc}
+
+/* ------------------------------------------------------------------------------------------- */
+    .align 2        /* Align the function code to a 4-byte (2^n) word boundary. */
+#if defined(__thumb__) || defined(__thumb2__)
+    .thumb
+    .syntax unified
+#else
+    .arm            /* Use ARM instructions instead of Thumb.*/
+#endif
+    .globl armFuncR0        /* Make the function globally accessible.*/
 armFuncR0:
-    stmfd   sp!, {r4-r8, r10, r11, lr}
-    
+    push {r4-r8, r10, r11, lr}
+
     mov     r6, r0  /* arg table */
     movs    r7, r1  /* arg size (also set the condition code flags so that we detect if there are no arguments) */
     mov     r4, r2  /* function address */
-    mov     r8, #0
-    mov		r11, #0	/* This will hold an offset of #4 only if the last arg that should have been placed into an "r" reg needs to go to the stack */
+    mov     r11, #0 /* This will hold an offset of #4 only if the last arg that should have been placed into an "r" reg needs to go to the stack */
     mov     r0, r3  /* r0 explicitly set */
-    
+
     /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
-    add		r10, r6, #272	/* r10 (r6 + 272) points to the first value for the VFP registers */
-    fldmiad r10, {d0-d7}	/* Load contents starting at r10 into registers d0-d7 */
-    
-	/* If there are no arguments to set into r0-r3 */
-	/* go check if there are arguments for the stack */
+    add     r10, r6, #272   /* r10 (r6 + 272) points to the first value for the VFP registers */
+    mov     r8, #0
+    vldmia.64 r10, {d0-d7}  /* Load contents starting at r10 into registers d0-d7 */
+
+    /* If there are no arguments to set into r0-r3 */
+    /* go check if there are arguments for the stack */
     beq     stackargsarmFuncR0
 
     /* Load the first 3 arguments into r1-r3 */
@@ -503,62 +565,75 @@ armFuncR0:
     ldrge   r2, [r6, #4]
     cmp     r7, #12
     ldrge   r3, [r6, #8]
-    cmp		r7, #16
-    movge	r11, #4			/* If there is still one arg to be placed, set the offset in r11 to #4 */
-    
+    cmp     r7, #16
+    movge   r11, #4         /* If there is still one arg to be placed, set the offset in r11 to #4 */
+
 stackargsarmFuncR0:
-	ldr		r5, [r6, #268]	/* Load stack size into r5 */
-	add		r5, r11			/* Add the offset placed in r11 (could be #0 or #4) */
-	movs	r7, r5			/* Load stack size into r7, checking for 0 args */
-	
-	/* If there are no args for the stack, branch */
-	beq		nomoreargsarmFuncR0
+    ldr     r5, [r6, #268]  /* Load stack size into r5 */
+    add     r5, r11         /* Add the offset placed in r11 (could be #0 or #4) */
+    movs    r7, r5          /* Load stack size into r7, checking for 0 args */
+
+    /* If there are no args for the stack, branch */
+    beq     nomoreargsarmFuncR0
 
     /* Load the rest of the arguments onto the stack */
     /* Ensure 8-byte stack alignment */
-    mov		r8, sp
-	sub		sp, sp, r7
-	sub		sp, sp, #8
-    bic     sp, sp, #7
-    sub     r8, r8, sp
-    mov     r12, sp         /* copy size != frame size, so store frame start sp */
-    add		r6, r6, #16		/* Set r6 to point to the first arg to be placed on the stack */
-    sub		r6, r6, r11		/* r6 = r6 - r11 (r11 can be #0 or #4) */
+    mov     r8, sp
+    sub     sp, sp, r7
+    add     r6, r6, #16     /* Set r6 to point to the first arg to be placed on the stack */
+
+    sub     r12, sp, #8
+    sub     r6, r6, r11     /* r6 = r6 - r11 (r11 can be #0 or #4) */
+    bic     r12, r12, #7    /* thumb mode couldn't support "bic  sp, sp, #7" instruction */
+    sub     r8, r8, r12
+    mov     sp, r12         /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
 
 stackargslooparmFuncR0:
     ldr     r5, [r6], #4
-    str     r5, [sp], #4
     subs    r7, r7, #4
+    str     r5, [sp], #4
     bne     stackargslooparmFuncR0
     mov     sp, r12
-    
+
 nomoreargsarmFuncR0:
+#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
+    mov    lr, pc
+    mov    pc, r4
+#else
     blx     r4
-    fstmiad	r10, {d0-d7}	/* Copy contents of registers d0-d10 to the address stored in r10 */
+#endif
     add     sp, sp, r8
-    
-    ldmfd   sp!, {r4-r8, r10, r11, pc}
+    vstmia.64   r10, {d0-d7}    /* Copy contents of registers d0-d10 to the address stored in r10 */
 
-/* ------------------------------------------------------------------------------------------- */
+    pop {r4-r8, r10, r11, pc}
 
+/* ------------------------------------------------------------------------------------------- */
+    .align 2        /* Align the function code to a 4-byte (2^n) word boundary. */
+#if defined(__thumb__) || defined(__thumb2__)
+    .thumb
+    .syntax unified
+#else
+    .arm            /* Use ARM instructions instead of Thumb.*/
+#endif
+    .globl armFuncR0R1      /* Make the function globally accessible.*/
 armFuncR0R1:
-    stmfd   sp!, {r4-r8, r10, r11, lr}
-    
+    push {r4-r8, r10, r11, lr}
+
     mov     r6, r0  /* arg table */
     movs    r7, r1  /* arg size (also set the condition code flags so that we detect if there are no arguments) */
     mov     r4, r2  /* function address */
-    mov     r8, #0
-    mov		r11, #0	/* This will hold an offset of #4 or #8 only if the last arg (or last 2 args) that should have been placed into "r" regs need to go to the stack */
+    mov     r11, #0 /* This will hold an offset of #4 or #8 only if the last arg (or last 2 args) that should have been placed into "r" regs need to go to the stack */
 
     mov     r0, r3          /* r0 explicitly set */
     ldr     r1, [sp, #32]   /* r1 explicitly set too */
-    
+
     /* Load float and double args into d0-d7 and s0-s15 (r10 holds pointer to first float value) */
-    add		r10, r6, #272	/* r10 (r6 + 272) points to the first value for the VFP registers */
-    fldmiad r10, {d0-d7}	/* Load contents starting at r10 into registers d0-d7 */
-    
+    add     r10, r6, #272   /* r10 (r6 + 272) points to the first value for the VFP registers */
+    mov     r8, #0
+    vldmia.64 r10, {d0-d7}  /* Load contents starting at r10 into registers d0-d7 */
+
     /* If there are no arguments to set into r2-r3 */
-	/* go check if there are arguments for the stack */
+    /* go check if there are arguments for the stack */
     beq     stackargsarmFuncR0R1
 
     /* Load the first 2 arguments into r2-r3 */
@@ -566,45 +641,51 @@ armFuncR0R1:
     ldrge   r2, [r6]
     cmp     r7, #8
     ldrge   r3, [r6, #4]
-    cmp		r7, #12
-    movge	r11, #4			/* If there is a third arg to be placed, set the offset in r11 to #4 */
-    cmp		r7, #16
-    movge	r11, #8			/* If there is a fourth arg to be placed, set the offset in r11 to #8 */
-    ldrlt	r7, [r6, #8]	/* Else copy the third arg to the correct place in the array */
-	strlt	r7, [r6, #12]
+    cmp     r7, #12
+    movge   r11, #4         /* If there is a third arg to be placed, set the offset in r11 to #4 */
+    cmp     r7, #16
+    movge   r11, #8         /* If there is a fourth arg to be placed, set the offset in r11 to #8 */
+    ldrlt   r7, [r6, #8]    /* Else copy the third arg to the correct place in the array */
+    strlt   r7, [r6, #12]
 
 stackargsarmFuncR0R1:
-	ldr		r5, [r6, #268]	/* Load stack size into r5 */
-	add		r5, r11			/* Add the offset placed in r11 (could be #0 or #4 or #8) */
-	movs	r7, r5			/* Load stack size into r7, checking for 0 args */
-	
-	/* If there are no args for the stack, branch */
-	beq		nomoreargsarmFuncR0R1
+    ldr     r5, [r6, #268]  /* Load stack size into r5 */
+    add     r5, r11         /* Add the offset placed in r11 (could be #0 or #4 or #8) */
+    movs    r7, r5          /* Load stack size into r7, checking for 0 args */
+
+    /* If there are no args for the stack, branch */
+    beq     nomoreargsarmFuncR0R1
 
     /* Load the rest of the arguments onto the stack */
     /* Ensure 8-byte stack alignment */
-    mov		r8, sp
-	sub		sp, sp, r7
-	sub		sp, sp, #8
-    bic     sp, sp, #7
-    sub     r8, r8, sp
-    mov     r12, sp         /* copy size != frame size, so store frame start sp */
-    add		r6, r6, #16		/* Set r6 to point to the first arg to be placed on the stack */
-    sub		r6, r6, r11		/* r6 = r6 - r11 (r11 can be #0 or #4 or #8) */
+    mov     r8, sp
+    sub     sp, sp, r7
+    add     r6, r6, #16     /* Set r6 to point to the first arg to be placed on the stack */
+
+    sub     r12, sp, #8
+    sub     r6, r6, r11     /* r6 = r6 - r11 (r11 can be #0 or #4 or #8) */
+    bic     r12, r12, #7    /* thumb mode couldn't support "bic  sp, sp, #7" instruction */
+    sub     r8, r8, r12
+    mov     sp, r12         /* copy size != frame size, so store frame start sp, r12(ip) is not callee saved register */
 
 stackargslooparmFuncR0R1:
     ldr     r5, [r6], #4
-    str     r5, [sp], #4
     subs    r7, r7, #4
+    str     r5, [sp], #4
     bne     stackargslooparmFuncR0R1
     mov     sp, r12
-    
+
 nomoreargsarmFuncR0R1:
+#if defined (___ARM_ARCH_4T__) || defined (__ARM_ARCH_4__)
+    mov    lr, pc
+    mov    pc, r4
+#else
     blx     r4
-    fstmiad	r10, {d0-d7}	/* Copy contents of registers d0-d10 to the address stored in r10 */
+#endif
     add     sp, sp, r8
-    
-    ldmfd   sp!, {r4-r8, r10, r11, pc}
+    vstmia.64   r10, {d0-d7}    /* Copy contents of registers d0-d10 to the address stored in r10 */
+
+    pop {r4-r8, r10, r11, pc}
 
 #endif
 

+ 242 - 242
Source/ThirdParty/AngelScript/source/as_callfunc_arm_msvc.asm

@@ -1,242 +1,242 @@
-;
-;  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
-;  [email protected]
-;
-
-
-; Assembly routines for the ARM call convention
-; Written by Fredrik Ehnbom in June 2009
-
-; MSVC currently doesn't support inline assembly for the ARM platform
-; so this separate file is needed.
-
-
-    AREA	|.rdata|, DATA, READONLY
-    EXPORT |armFunc|
-    EXPORT armFuncR0
-    EXPORT armFuncR0R1
-    EXPORT armFuncObjLast
-    EXPORT armFuncR0ObjLast
-    
-
-    AREA	|.text|, CODE, ARM
-
-|armFunc| PROC
-    stmdb   sp!, {r4-r8, lr}
-    mov     r6, r0  ; arg table
-    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
-    mov     r4, r2  ; function address
-    mov     r8, #0
-
-    beq     |nomoreargs|
-
-    ; Load the first 4 arguments into r0-r3
-    cmp     r7, #4
-    ldrge   r0, [r6],#4
-    cmp     r7, #2*4
-    ldrge   r1, [r6],#4
-    cmp     r7, #3*4
-    ldrge   r2, [r6],#4
-    cmp     r7, #4*4
-    ldrge   r3, [r6],#4
-    ble     |nomoreargs|
-
-    ; Load the rest of the arguments onto the stack
-    sub     r7, r7, #4*4    ; skip the 4 registers already loaded into r0-r3
-    sub     sp, sp, r7
-    mov     r8, r7
-|stackargsloop|
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     |stackargsloop|
-|nomoreargs|
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    ldmia   sp!, {r4-r8, pc}
-    ENDP
-
-armFuncObjLast PROC
-    stmdb   sp!, {r4-r8, lr}
-    mov     r6, r0  ; arg table
-    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
-    mov     r4, r2  ; function address
-    mov     r8, #0
-
-    mov     r0, r3          ; objlast. might get overwritten
-    str     r3, [sp, #-4]!  ; objlast again.
-
-    beq     |nomoreargs@armFuncObjLast|
-
-    ; Load the first 4 arguments into r0-r3
-    cmp     r7, #4
-    ldrge   r0, [r6],#4
-    cmp     r7, #2*4
-    ldrge   r1, [r6],#4
-    ldrlt   r1, [sp]    
-    cmp     r7, #3*4
-    ldrge   r2, [r6],#4
-    ldrlt   r2, [sp]
-    cmp     r7, #4*4
-    ldrge   r3, [r6],#4
-    ldrlt   r3, [sp]
-    ble     |nomoreargs@armFuncObjLast|
-
-    ; Load the rest of the arguments onto the stack
-    sub     r7, r7, #4*4    ; skip the 4 registers already loaded into r0-r3
-    sub     sp, sp, r7
-    mov     r8, r7
-|stackargsloop@armFuncObjLast|
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     |stackargsloop@armFuncObjLast|
-|nomoreargs@armFuncObjLast|
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    add     sp, sp, #4
-    ldmia   sp!, {r4-r8, pc}
-    ENDP
-
-armFuncR0ObjLast PROC
-    stmdb   sp!, {r4-r8, lr}
-    ldr     r7, [sp,#6*4]
-    str     r7, [sp,#-4]!
-
-    mov     r6, r0  ; arg table
-    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
-    mov     r4, r2  ; function address
-    mov     r8, #0
-
-    mov     r0, r3      ; r0 explicitly set
-    ldr     r1, [sp]    ; objlast.  might get overwritten
-
-    beq     |nomoreargs@armFuncR0ObjLast|
-
-    ; Load the first 3 arguments into r1-r3
-    cmp     r7, #1*4
-    ldrge   r1, [r6],#4
-    cmp     r7, #2*4
-    ldrge   r2, [r6],#4
-    ldrlt   r2, [sp]
-    cmp     r7, #3*4
-    ldrge   r3, [r6],#4
-    ldrlt   r3, [sp]
-    ble     |nomoreargs@armFuncR0ObjLast|
-
-    ; Load the rest of the arguments onto the stack
-    sub     r7, r7, #3*4    ; skip the 3 registers already loaded into r1-r3
-    sub     sp, sp, r7
-    mov     r8, r7
-|stackargsloop@armFuncR0ObjLast|
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     |stackargsloop@armFuncR0ObjLast|
-|nomoreargs@armFuncR0ObjLast|
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    add     sp, sp, #4
-    ldmia   sp!, {r4-r8, pc}
-    ENDP
-
-armFuncR0 PROC
-    stmdb   sp!, {r4-r8, lr}
-    mov     r6, r0  ; arg table
-    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
-    mov     r4, r2  ; function address
-    mov     r8, #0
-
-    mov     r0, r3  ; r0 explicitly set
-
-    beq     |nomoreargs@armFuncR0|
-
-    ; Load the first 3 arguments into r1-r3
-    cmp     r7, #1*4
-    ldrge   r1, [r6],#4
-    cmp     r7, #2*4
-    ldrge   r2, [r6],#4
-    cmp     r7, #3*4
-    ldrge   r3, [r6],#4
-    ble     |nomoreargs@armFuncR0|
-
-    ; Load the rest of the arguments onto the stack
-    sub     r7, r7, #3*4    ; skip the 3 registers already loaded into r1-r3
-    sub     sp, sp, r7
-    mov     r8, r7
-|stackargsloop@armFuncR0|
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     |stackargsloop@armFuncR0|
-|nomoreargs@armFuncR0|
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    ldmia   sp!, {r4-r8, pc}
-    ENDP
-
-armFuncR0R1 PROC
-    stmdb   sp!, {r4-r8, lr}
-    mov     r6, r0  ; arg table
-    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
-    mov     r4, r2  ; function address
-    mov     r8, #0
-
-    mov     r0, r3          ; r0 explicitly set
-    ldr     r1, [sp, #6*4]  ; r1 explicitly set too
-
-    beq     |nomoreargs@armFuncR0R1|
-
-    ; Load the first 2 arguments into r2-r3
-    cmp     r7, #1*4
-    ldrge   r2, [r6],#4
-    cmp     r7, #2*4
-    ldrge   r3, [r6],#4
-    ble     |nomoreargs@armFuncR0R1|
-
-    ; Load the rest of the arguments onto the stack
-    sub     r7, r7, #2*4    ; skip the 2 registers already loaded into r2-r3
-    sub     sp, sp, r7
-    mov     r8, r7
-|stackargsloop@armFuncR0R1|
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     |stackargsloop@armFuncR0R1|
-|nomoreargs@armFuncR0R1|
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    ldmia   sp!, {r4-r8, pc}
-    ENDP
-
-    END
+;
+;  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
+;  [email protected]
+;
+
+
+; Assembly routines for the ARM call convention
+; Written by Fredrik Ehnbom in June 2009
+
+; MSVC currently doesn't support inline assembly for the ARM platform
+; so this separate file is needed.
+
+
+    AREA	|.rdata|, DATA, READONLY
+    EXPORT |armFunc|
+    EXPORT armFuncR0
+    EXPORT armFuncR0R1
+    EXPORT armFuncObjLast
+    EXPORT armFuncR0ObjLast
+    
+
+    AREA	|.text|, CODE, ARM
+
+|armFunc| PROC
+    stmdb   sp!, {r4-r8, lr}
+    mov     r6, r0  ; arg table
+    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
+    mov     r4, r2  ; function address
+    mov     r8, #0
+
+    beq     |nomoreargs|
+
+    ; Load the first 4 arguments into r0-r3
+    cmp     r7, #4
+    ldrge   r0, [r6],#4
+    cmp     r7, #2*4
+    ldrge   r1, [r6],#4
+    cmp     r7, #3*4
+    ldrge   r2, [r6],#4
+    cmp     r7, #4*4
+    ldrge   r3, [r6],#4
+    ble     |nomoreargs|
+
+    ; Load the rest of the arguments onto the stack
+    sub     r7, r7, #4*4    ; skip the 4 registers already loaded into r0-r3
+    sub     sp, sp, r7
+    mov     r8, r7
+|stackargsloop|
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     |stackargsloop|
+|nomoreargs|
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    ldmia   sp!, {r4-r8, pc}
+    ENDP
+
+armFuncObjLast PROC
+    stmdb   sp!, {r4-r8, lr}
+    mov     r6, r0  ; arg table
+    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
+    mov     r4, r2  ; function address
+    mov     r8, #0
+
+    mov     r0, r3          ; objlast. might get overwritten
+    str     r3, [sp, #-4]!  ; objlast again.
+
+    beq     |nomoreargs@armFuncObjLast|
+
+    ; Load the first 4 arguments into r0-r3
+    cmp     r7, #4
+    ldrge   r0, [r6],#4
+    cmp     r7, #2*4
+    ldrge   r1, [r6],#4
+    ldrlt   r1, [sp]    
+    cmp     r7, #3*4
+    ldrge   r2, [r6],#4
+    ldrlt   r2, [sp]
+    cmp     r7, #4*4
+    ldrge   r3, [r6],#4
+    ldrlt   r3, [sp]
+    ble     |nomoreargs@armFuncObjLast|
+
+    ; Load the rest of the arguments onto the stack
+    sub     r7, r7, #4*4    ; skip the 4 registers already loaded into r0-r3
+    sub     sp, sp, r7
+    mov     r8, r7
+|stackargsloop@armFuncObjLast|
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     |stackargsloop@armFuncObjLast|
+|nomoreargs@armFuncObjLast|
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    add     sp, sp, #4
+    ldmia   sp!, {r4-r8, pc}
+    ENDP
+
+armFuncR0ObjLast PROC
+    stmdb   sp!, {r4-r8, lr}
+    ldr     r7, [sp,#6*4]
+    str     r7, [sp,#-4]!
+
+    mov     r6, r0  ; arg table
+    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
+    mov     r4, r2  ; function address
+    mov     r8, #0
+
+    mov     r0, r3      ; r0 explicitly set
+    ldr     r1, [sp]    ; objlast.  might get overwritten
+
+    beq     |nomoreargs@armFuncR0ObjLast|
+
+    ; Load the first 3 arguments into r1-r3
+    cmp     r7, #1*4
+    ldrge   r1, [r6],#4
+    cmp     r7, #2*4
+    ldrge   r2, [r6],#4
+    ldrlt   r2, [sp]
+    cmp     r7, #3*4
+    ldrge   r3, [r6],#4
+    ldrlt   r3, [sp]
+    ble     |nomoreargs@armFuncR0ObjLast|
+
+    ; Load the rest of the arguments onto the stack
+    sub     r7, r7, #3*4    ; skip the 3 registers already loaded into r1-r3
+    sub     sp, sp, r7
+    mov     r8, r7
+|stackargsloop@armFuncR0ObjLast|
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     |stackargsloop@armFuncR0ObjLast|
+|nomoreargs@armFuncR0ObjLast|
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    add     sp, sp, #4
+    ldmia   sp!, {r4-r8, pc}
+    ENDP
+
+armFuncR0 PROC
+    stmdb   sp!, {r4-r8, lr}
+    mov     r6, r0  ; arg table
+    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
+    mov     r4, r2  ; function address
+    mov     r8, #0
+
+    mov     r0, r3  ; r0 explicitly set
+
+    beq     |nomoreargs@armFuncR0|
+
+    ; Load the first 3 arguments into r1-r3
+    cmp     r7, #1*4
+    ldrge   r1, [r6],#4
+    cmp     r7, #2*4
+    ldrge   r2, [r6],#4
+    cmp     r7, #3*4
+    ldrge   r3, [r6],#4
+    ble     |nomoreargs@armFuncR0|
+
+    ; Load the rest of the arguments onto the stack
+    sub     r7, r7, #3*4    ; skip the 3 registers already loaded into r1-r3
+    sub     sp, sp, r7
+    mov     r8, r7
+|stackargsloop@armFuncR0|
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     |stackargsloop@armFuncR0|
+|nomoreargs@armFuncR0|
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    ldmia   sp!, {r4-r8, pc}
+    ENDP
+
+armFuncR0R1 PROC
+    stmdb   sp!, {r4-r8, lr}
+    mov     r6, r0  ; arg table
+    movs    r7, r1  ; arg size (also set the condition code flags so that we detect if there are no arguments)
+    mov     r4, r2  ; function address
+    mov     r8, #0
+
+    mov     r0, r3          ; r0 explicitly set
+    ldr     r1, [sp, #6*4]  ; r1 explicitly set too
+
+    beq     |nomoreargs@armFuncR0R1|
+
+    ; Load the first 2 arguments into r2-r3
+    cmp     r7, #1*4
+    ldrge   r2, [r6],#4
+    cmp     r7, #2*4
+    ldrge   r3, [r6],#4
+    ble     |nomoreargs@armFuncR0R1|
+
+    ; Load the rest of the arguments onto the stack
+    sub     r7, r7, #2*4    ; skip the 2 registers already loaded into r2-r3
+    sub     sp, sp, r7
+    mov     r8, r7
+|stackargsloop@armFuncR0R1|
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     |stackargsloop@armFuncR0R1|
+|nomoreargs@armFuncR0R1|
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    ldmia   sp!, {r4-r8, pc}
+    ENDP
+
+    END

+ 1 - 0
Source/ThirdParty/AngelScript/source/as_callfunc_mips.cpp

@@ -48,6 +48,7 @@
 #include "as_scriptengine.h"
 #include "as_texts.h"
 #include "as_tokendef.h"
+#include "as_context.h"
 
 #include <stdio.h>
 #include <stdlib.h>

+ 2 - 1
Source/ThirdParty/AngelScript/source/as_callfunc_ppc.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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
@@ -48,6 +48,7 @@
 #include "as_scriptengine.h"
 #include "as_texts.h"
 #include "as_tokendef.h"
+#include "as_context.h"
 
 #include <stdlib.h>
 

+ 2 - 1
Source/ThirdParty/AngelScript/source/as_callfunc_ppc_64.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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
@@ -46,6 +46,7 @@
 #include "as_scriptengine.h"
 #include "as_texts.h"
 #include "as_tokendef.h"
+#include "as_context.h"
 
 #include <stdio.h>
 #include <stdlib.h>

+ 1 - 0
Source/ThirdParty/AngelScript/source/as_callfunc_sh4.cpp

@@ -52,6 +52,7 @@
 #include "as_scriptengine.h"
 #include "as_texts.h"
 #include "as_tokendef.h"
+#include "as_context.h"
 
 #include <stdio.h>
 #include <stdlib.h>

+ 1 - 0
Source/ThirdParty/AngelScript/source/as_callfunc_x64_gcc.cpp

@@ -43,6 +43,7 @@
 
 #include "as_scriptengine.h"
 #include "as_texts.h"
+#include "as_context.h"
 
 BEGIN_AS_NAMESPACE
 

+ 1 - 0
Source/ThirdParty/AngelScript/source/as_callfunc_x64_mingw.cpp

@@ -42,6 +42,7 @@
 #include "as_callfunc.h"
 #include "as_scriptengine.h"
 #include "as_texts.h"
+#include "as_context.h"
 
 BEGIN_AS_NAMESPACE
 

+ 2 - 1
Source/ThirdParty/AngelScript/source/as_callfunc_x64_msvc.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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
@@ -39,6 +39,7 @@
 #include "as_callfunc.h"
 #include "as_scriptengine.h"
 #include "as_texts.h"
+#include "as_context.h"
 
 BEGIN_AS_NAMESPACE
 

+ 9 - 0
Source/ThirdParty/AngelScript/source/as_callfunc_x86.cpp

@@ -46,6 +46,7 @@
 #include "as_scriptengine.h"
 #include "as_texts.h"
 #include "as_tokendef.h"
+#include "as_context.h"
 
 BEGIN_AS_NAMESPACE
 
@@ -115,6 +116,14 @@ asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr,
 #endif
 				{
 					// Copy the object's memory to the buffer
+					// TODO: bug: Must call the object's copy constructor instead of doing a memcpy, 
+					//            as the object may hold a pointer to itself. It's not enough to 
+					//            change only this memcpy as the assembler routine also makes a copy
+					//            of paramBuffer to the final stack location. To avoid the second 
+					//            copy the C++ routine should point paramBuffer to the final stack
+					//            position and copy the values directly to that location. The assembler
+					//            routines then don't need to copy anything, and will just be 
+					//            responsible for setting up the registers and the stack frame appropriately.
 					memcpy(&paramBuffer[dpos], *(void**)(args+spos), descr->parameterTypes[n].GetSizeInMemoryBytes());
 
 					// Delete the original memory

+ 2 - 1
Source/ThirdParty/AngelScript/source/as_callfunc_xenon.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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
@@ -101,6 +101,7 @@
 #include "as_scriptengine.h"
 #include "as_texts.h"
 #include "as_tokendef.h"
+#include "as_context.h"
 
 #include <stdio.h>
 #include <stdlib.h>

+ 420 - 196
Source/ThirdParty/AngelScript/source/as_compiler.cpp

@@ -163,7 +163,7 @@ int asCCompiler::CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *s
 
 	// Count total variable size
 	int varSize = GetVariableOffset((int)variableAllocations.GetLength()) - 1;
-	outFunc->variableSpace = varSize;
+	outFunc->scriptData->variableSpace = varSize;
 
 	FinalizeFunction();
 
@@ -197,7 +197,7 @@ int asCCompiler::CompileFactory(asCBuilder *builder, asCScriptCode *script, asCS
 	// Allocate the class and instanciate it with the constructor
 	int varOffset = AllocateVariable(dt, true);
 
-	outFunc->variableSpace = AS_PTR_SIZE;
+	outFunc->scriptData->variableSpace = AS_PTR_SIZE;
 	byteCode.InstrSHORT(asBC_PSF, (short)varOffset);
 
 	// Copy all arguments to the top of the stack
@@ -254,6 +254,7 @@ void asCCompiler::FinalizeFunction()
 {
 	TimeIt("asCCompiler::FinalizeFunction");
 
+	asASSERT( outFunc->scriptData );
 	asUINT n;
 
 	// Finalize the bytecode
@@ -269,43 +270,43 @@ void asCCompiler::FinalizeFunction()
 		{
 			if( variableIsOnHeap[n] )
 			{
-				outFunc->objVariableTypes.PushLast(variableAllocations[n].GetObjectType());
-				outFunc->funcVariableTypes.PushLast(variableAllocations[n].GetFuncDef());
-				outFunc->objVariablePos.PushLast(GetVariableOffset(n));
+				outFunc->scriptData->objVariableTypes.PushLast(variableAllocations[n].GetObjectType());
+				outFunc->scriptData->funcVariableTypes.PushLast(variableAllocations[n].GetFuncDef());
+				outFunc->scriptData->objVariablePos.PushLast(GetVariableOffset(n));
 			}
 		}
 	}
-	outFunc->objVariablesOnHeap = asUINT(outFunc->objVariablePos.GetLength());
+	outFunc->scriptData->objVariablesOnHeap = asUINT(outFunc->scriptData->objVariablePos.GetLength());
 	for( n = 0; n < variableAllocations.GetLength(); n++ )
 	{
 		if( variableAllocations[n].IsObject() && !variableAllocations[n].IsReference() )
 		{
 			if( !variableIsOnHeap[n] )
 			{
-				outFunc->objVariableTypes.PushLast(variableAllocations[n].GetObjectType());
-				outFunc->funcVariableTypes.PushLast(variableAllocations[n].GetFuncDef());
-				outFunc->objVariablePos.PushLast(GetVariableOffset(n));
+				outFunc->scriptData->objVariableTypes.PushLast(variableAllocations[n].GetObjectType());
+				outFunc->scriptData->funcVariableTypes.PushLast(variableAllocations[n].GetFuncDef());
+				outFunc->scriptData->objVariablePos.PushLast(GetVariableOffset(n));
 			}
 		}
 	}
 
 	// Copy byte code to the function
-	asASSERT( outFunc->byteCode.GetLength() == 0 );
-	outFunc->byteCode.SetLength(byteCode.GetSize());
-	byteCode.Output(outFunc->byteCode.AddressOf());
+	asASSERT( outFunc->scriptData->byteCode.GetLength() == 0 );
+	outFunc->scriptData->byteCode.SetLength(byteCode.GetSize());
+	byteCode.Output(outFunc->scriptData->byteCode.AddressOf());
 	outFunc->AddReferences();
-	outFunc->stackNeeded = byteCode.largestStackUsed + outFunc->variableSpace;
-	outFunc->lineNumbers = byteCode.lineNumbers;
+	outFunc->scriptData->stackNeeded = byteCode.largestStackUsed + outFunc->scriptData->variableSpace;
+	outFunc->scriptData->lineNumbers = byteCode.lineNumbers;
 
 	// Extract the script section indexes too if there are any entries that are different from the function's script section
-	int lastIdx = outFunc->scriptSectionIdx;
+	int lastIdx = outFunc->scriptData->scriptSectionIdx;
 	for( n = 0; n < byteCode.sectionIdxs.GetLength(); n++ )
 	{
 		if( byteCode.sectionIdxs[n] != lastIdx )
 		{
 			lastIdx = byteCode.sectionIdxs[n];
-			outFunc->sectionIdxs.PushLast(byteCode.lineNumbers[n*2]);
-			outFunc->sectionIdxs.PushLast(lastIdx);
+			outFunc->scriptData->sectionIdxs.PushLast(byteCode.lineNumbers[n*2]);
+			outFunc->scriptData->sectionIdxs.PushLast(lastIdx);
 		}
 	}
 }
@@ -391,7 +392,7 @@ int asCCompiler::SetupParametersAndReturnVariable(asCArray<asCString> &parameter
 			}
 
 			// Add marker for variable declaration
-			byteCode.VarDecl((int)outFunc->variables.GetLength());
+			byteCode.VarDecl((int)outFunc->scriptData->variables.GetLength());
 			outFunc->AddVariable(name, type, stackPos);
 		}
 		else
@@ -630,7 +631,7 @@ int asCCompiler::CompileFunction(asCBuilder *builder, asCScriptCode *script, asC
 
 	// Count total variable size
 	int varSize = GetVariableOffset((int)variableAllocations.GetLength()) - 1;
-	outFunc->variableSpace = varSize;
+	outFunc->scriptData->variableSpace = varSize;
 
 	// Deallocate all local variables
 	int n;
@@ -807,7 +808,7 @@ int asCCompiler::CallCopyConstructor(asCDataType &type, int offset, bool isObjec
 	return -1;
 }
 
-int asCCompiler::CallDefaultConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem, bool deferDest)
+int asCCompiler::CallDefaultConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem, bool derefDest)
 {
 	if( !type.IsObject() || type.IsObjectHandle() )
 		return 0;
@@ -901,7 +902,7 @@ int asCCompiler::CallDefaultConstructor(asCDataType &type, int offset, bool isOb
 				{
 					// Call the constructor as a normal function
 					bc->InstrSHORT(asBC_PSF, (short)offset);
-					if( deferDest )
+					if( derefDest )
 						bc->Instr(asBC_RDSPtr);
 					asSExprContext ctx(engine);
 					PerformFunctionCall(func, &ctx, false, 0, type.GetObjectType());
@@ -951,6 +952,10 @@ void asCCompiler::CallDestructor(asCDataType &type, int offset, bool isObjectOnH
 		// Call destructor for the data type
 		if( type.IsObject() )
 		{
+			// Nothing is done for list pattern types, as this is taken care of by the CompileInitList method
+			if( type.GetObjectType()->flags & asOBJ_LIST_PATTERN )
+				return;
+
 			if( isObjectOnHeap || type.IsObjectHandle() )
 			{
 				// Free the memory
@@ -1108,7 +1113,7 @@ int asCCompiler::CompileGlobalVariable(asCBuilder *builder, asCScriptCode *scrip
 	LineInstr(&byteCode, pos);
 
 	// Reserve space for all local variables
-	outFunc->variableSpace = varSize;
+	outFunc->scriptData->variableSpace = varSize;
 
 	ctx.bc.OptimizeLocally(tempVariableOffsets);
 
@@ -1148,7 +1153,7 @@ int asCCompiler::CompileGlobalVariable(asCBuilder *builder, asCScriptCode *scrip
 void asCCompiler::DetermineSingleFunc(asSExprContext *ctx, asCScriptNode *node)
 {
 	// Don't do anything if this is not a deferred global function
-	if( ctx->methodName == "" || ctx->type.dataType.GetObjectType() != 0 )
+	if( !ctx->IsGlobalFunc() )
 		return;
 
 	// Determine the namespace
@@ -1212,9 +1217,10 @@ void asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, a
 
 		// Since the function is expecting a var type ?, then we don't want to convert the argument to anything else
 		param = ctx->type.dataType;
-		param.MakeHandle(ctx->type.isExplicitHandle);
+		param.MakeHandle(ctx->type.isExplicitHandle || ctx->type.IsNullConstant());
 
-		// Reference types will always be passed as handles to ? parameters
+		// If value assign is disabled for reference types, then make
+		// sure to always pass the handle to ? parameters
 		if( builder->engine->ep.disallowValueAssignForRefType && 
 			ctx->type.dataType.GetObjectType() && (ctx->type.dataType.GetObjectType()->flags & asOBJ_REF) && !(ctx->type.dataType.GetObjectType()->flags & asOBJ_SCOPED) )
 		{
@@ -1328,7 +1334,12 @@ void asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, a
 
 					ReleaseTemporaryVariable(ctx->type, &ctx->bc);
 
-					ctx->type = type;
+					ctx->type.Set(dt);
+					ctx->type.isTemporary = true;
+					ctx->type.stackOffset = offset;
+					if( dt.IsObjectHandle() )
+						ctx->type.isExplicitHandle = true;
+					ctx->type.dataType.MakeReference(false);
 
 					ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
 					if( dt.IsObject() && !dt.IsObjectHandle() )
@@ -1462,7 +1473,7 @@ void asCCompiler::PrepareArgument(asCDataType *paramType, asSExprContext *ctx, a
 			// Make sure the reference to the value is on the stack
 			// For objects, the reference needs to be dereferenced so the pointer on the stack is to the actual object
 			// For handles, the reference shouldn't be changed because the pointer on the stack should be to the handle
-			if( ctx->type.dataType.IsObject() && ctx->type.dataType.IsReference() && !paramType->IsObjectHandle() )
+			if( ctx->type.dataType.IsObject() && ctx->type.dataType.IsReference() && !param.IsObjectHandle() )
 				Dereference(ctx, true);
 			else if( ctx->type.isVariable && !ctx->type.dataType.IsObject() )
 				ctx->bc.InstrSHORT(asBC_PSF, ctx->type.stackOffset);
@@ -2074,7 +2085,7 @@ void asCCompiler::CompileDeclaration(asCScriptNode *decl, asCByteCode *bc)
 		}
 
 		// Add marker that the variable has been declared
-		bc->VarDecl((int)outFunc->variables.GetLength());
+		bc->VarDecl((int)outFunc->scriptData->variables.GetLength());
 		outFunc->AddVariable(name, type, offset);
 
 		// Keep the node for the variable decl
@@ -2435,34 +2446,50 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte
 		return;
 	}
 
-	// Count the number of elements and initialize the array with the correct size
-	int countElements = 0;
-	asCScriptNode *el = node->firstChild;
-	while( el )
-	{
-		countElements++;
-		el = el->next;
-	}
-
-	// Construct the array with the size elements
-
-	// TODO: value on stack: This needs to support value types on the stack as well
+	// Construct the buffer with the elements
 
 	// Find the list factory
 	// TODO: initlist: Add support for value types as well
 	int funcId = var->dataType.GetBehaviour()->listFactory;
+	asASSERT( engine->scriptFunctions[funcId]->listPattern );
+
+	// TODO: runtime optimize: A future optimization should be to use the stack space directly
+	//                         for small buffers so that the dynamic allocation is skipped
+
+	// Create a new special object type for the lists. Both asCRestore and the 
+	// context exception handler will need this to know how to parse the buffer.
+	asCObjectType *listPatternType = engine->GetListPatternType(funcId);
+
+	// Allocate a temporary variable to hold the pointer to the buffer
+	int bufferVar = AllocateVariable(asCDataType::CreateObject(listPatternType, false), true);
+	asUINT bufferSize = 0;
 
+	// Evaluate all elements of the list
+	asSExprContext valueExpr(engine);
+	asCScriptNode *el = node;
+	asSListPatternNode *patternNode = engine->scriptFunctions[listPatternType->templateSubTypes[0].GetBehaviour()->listFactory]->listPattern;
+	int r = CompileInitListElement(patternNode, el, engine->GetTypeIdFromDataType(asCDataType::CreateObject(listPatternType, false)), bufferVar, bufferSize, valueExpr.bc);
+	asASSERT( r || patternNode == 0 );
+	UNUSED_VAR(r);
+
+	// After all values have been evaluated we know the final size of the buffer
+	asSExprContext allocExpr(engine);
+	allocExpr.bc.InstrSHORT_DW(asBC_AllocMem, bufferVar, bufferSize);
+
+	// Merge the bytecode into the final sequence
+	bc->AddCode(&allocExpr.bc);
+	bc->AddCode(&valueExpr.bc);
+
+	// The object itself is the last to be created and will receive the pointer to the buffer
 	asCArray<asSExprContext *> args;
 	asSExprContext arg1(engine);
-	arg1.bc.InstrDWORD(asBC_PshC4, countElements);
+	bc->InstrSHORT(asBC_PshVPtr, bufferVar);
 	arg1.type.Set(asCDataType::CreatePrimitive(ttUInt, false));
+	arg1.type.dataType.MakeReference(true);
 	args.PushLast(&arg1);
 
 	asSExprContext ctx(engine);
 
-	PrepareFunctionCall(funcId, &ctx.bc, args);
-	MoveArgsToStack(funcId, &ctx.bc, args, false);
-
 	if( var->isVariable )
 	{
 		asASSERT( isVarGlobOrMem == 0 );
@@ -2493,110 +2520,188 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte
 		ReleaseTemporaryVariable(ctx.type.stackOffset, &ctx.bc);
 	}
 
-
 	bc->AddCode(&ctx.bc);
 
-	// TODO: initlist: Should we have a special indexing operator for this? How can we support
-	//                 initialization lists with different types for different elements? Maybe
-	//                 by using the variable arguments the initialization can be done with one
-	//                 call, passing all the elements as arguments. The registered function can
-	//                 then traverse them however it wants.
-
-	// Find the indexing operator that is not read-only that will be used for all elements
-	asCDataType retType;
-	retType = var->dataType.GetSubType();
-	retType.MakeReference(true);
-	retType.MakeReadOnly(false);
-	funcId = 0;
-	for( asUINT n = 0; n < var->dataType.GetObjectType()->methods.GetLength(); n++ )
-	{
-		asCScriptFunction *desc = builder->GetFunctionDescription(var->dataType.GetObjectType()->methods[n]);
-		if( !desc->isReadOnly &&
-			 desc->parameterTypes.GetLength() == 1 &&
-			 (desc->parameterTypes[0] == asCDataType::CreatePrimitive(ttUInt, false) ||
-			  desc->parameterTypes[0] == asCDataType::CreatePrimitive(ttInt,  false)) &&
-			 desc->returnType == retType &&
-			 desc->name == "opIndex" )
-		{
-			funcId = var->dataType.GetObjectType()->methods[n];
-			break;
-		}
-	}
+	// Free the temporary buffer. The FREE instruction will make sure to destroy
+	// each element in the buffer so there is no need to do this manually
+	bc->InstrW_PTR(asBC_FREE, bufferVar, listPatternType);
+	ReleaseTemporaryVariable(bufferVar, bc);
+}
 
-	if( funcId == 0 )
+int asCCompiler::CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode)
+{
+	if( patternNode->type == asLPT_START )
 	{
-		Error(TXT_NO_APPROPRIATE_INDEX_OPERATOR, node);
-		return;
+		if( valueNode->nodeType != snInitList )
+		{
+			Error(TXT_EXPECTED_LIST, valueNode);
+			return -1;
+		}
+
+		// Compile all values until asLPT_END
+		patternNode = patternNode->next;
+		asCScriptNode *node = valueNode->firstChild;
+		while( patternNode->type != asLPT_END )
+		{
+			if( node == 0 )
+			{
+				Error(TXT_NOT_ENOUGH_VALUES_FOR_LIST, valueNode);
+				return -1;
+			}
+
+			int r = CompileInitListElement(patternNode, node, bufferTypeId, bufferVar, bufferSize, byteCode);
+			if( r < 0 ) return r;
+			asASSERT( patternNode );
+		}
+
+		if( node )
+		{
+			Error(TXT_TOO_MANY_VALUES_FOR_LIST, valueNode);
+			return -1;
+		}
+		
+		// Move to the next node
+		valueNode = valueNode->next;
+		patternNode = patternNode->next;
 	}
+	else if( patternNode->type == asLPT_REPEAT )
+	{
+		// The following values will be repeated N times
+		patternNode = patternNode->next;
+
+		// Keep track of the patternNode so it can be reset
+		asSListPatternNode *nextNode = patternNode;
+
+		// The first dword will hold the number of elements in the list
+		asDWORD currSize = bufferSize;
+		bufferSize += 4;
+		asUINT countElements = 0;
+
+		asSExprContext ctx(engine);
+		while( valueNode )
+		{
+			patternNode = nextNode;
+			int r = CompileInitListElement(patternNode, valueNode, bufferTypeId, bufferVar, bufferSize, ctx.bc);
+			if( r < 0 ) return r;
+
+			countElements++;
+		}
+
+		// The first dword in the buffer will hold the number of elements
+		byteCode.InstrSHORT_DW_DW(asBC_SetListSize, bufferVar, currSize, countElements);
 
-	asUINT index = 0;
-	el = node->firstChild;
-	while( el )
+		// Add the values
+		byteCode.AddCode(&ctx.bc);
+	}
+	else if( patternNode->type == asLPT_TYPE )
 	{
-		if( el->nodeType == snAssignment || el->nodeType == snInitList )
+		// TODO: list: Values on the list must be aligned to 32bit boundaries, except if the type
+		//             is smaller than 32bit.
+
+		// Determine the size of the element
+		asUINT size = 0;
+
+		asCDataType dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
+
+		if( valueNode->nodeType == snAssignment || valueNode->nodeType == snInitList )
 		{
 			asSExprContext lctx(engine);
 			asSExprContext rctx(engine);
 
-			if( el->nodeType == snAssignment )
+			if( valueNode->nodeType == snAssignment )
 			{
 				// Compile the assignment expression
-				CompileAssignment(el, &rctx);
+				CompileAssignment(valueNode, &rctx);
+
+				if( dt.GetTokenType() == ttQuestion )
+				{
+					// We now know the type
+					dt = rctx.type.dataType;
+					dt.MakeReadOnly(false);
+
+					// Place the type id in the buffer
+					byteCode.InstrSHORT_DW_DW(asBC_SetListType, bufferVar, bufferSize, engine->GetTypeIdFromDataType(dt));
+					bufferSize += 4;
+				}
 			}
-			else if( el->nodeType == snInitList )
+			else if( valueNode->nodeType == snInitList )
 			{
-				int offset = AllocateVariable(var->dataType.GetSubType(), true);
+				if( dt.GetTokenType() == ttQuestion )
+				{
+					// Can't use init lists with var type as it is not possible to determine what type should be allocated
+					asCString str; 
+					str.Format(TXT_INIT_LIST_CANNOT_BE_USED_WITH_s, "?");
+					Error(str.AddressOf(), valueNode);
+					rctx.type.SetDummy();
+					dt = rctx.type.dataType;
+				}
+				else
+				{
+					// Allocate a temporary variable that will be initialized with the list
+					int offset = AllocateVariable(dt, true);
 
-				rctx.type.Set(var->dataType.GetSubType());
-				rctx.type.isVariable = true;
-				rctx.type.isTemporary = true;
-				rctx.type.stackOffset = (short)offset;
+					rctx.type.Set(dt);
+					rctx.type.isVariable = true;
+					rctx.type.isTemporary = true;
+					rctx.type.stackOffset = (short)offset;
 
-				CompileInitList(&rctx.type, el, &rctx.bc, 0);
+					CompileInitList(&rctx.type, valueNode, &rctx.bc, 0);
 
-				// Put the object on the stack
-				rctx.bc.InstrSHORT(asBC_PSF, rctx.type.stackOffset);
+					// Put the object on the stack
+					rctx.bc.InstrSHORT(asBC_PSF, rctx.type.stackOffset);
 
-				// It is a reference that we place on the stack
-				rctx.type.dataType.MakeReference(true);
+					// It is a reference that we place on the stack
+					rctx.type.dataType.MakeReference(true);
+				}
 			}
 
 			// Compile the lvalue
-			lctx.bc.InstrDWORD(asBC_PshC4, index);
-			if( var->isVariable )
-				lctx.bc.InstrSHORT(asBC_PSF, var->stackOffset);
-			else
+			lctx.bc.InstrSHORT_DW(asBC_PshListElmnt, bufferVar, bufferSize);
+			lctx.type.Set(dt);
+			lctx.type.isLValue = true;
+			if( dt.IsPrimitive() )
 			{
-				// TODO: runtime optimize: should copy a handle to a local variable to avoid
-				//                         accessing the global variable or class member for each element
-				if( isVarGlobOrMem == 1 )
-					lctx.bc.InstrPTR(asBC_PGA, engine->globalProperties[var->stackOffset]->GetAddressOfValue());
-				else
-				{
-					lctx.bc.InstrSHORT(asBC_PSF, 0);
-					lctx.bc.Instr(asBC_RDSPtr);
-					lctx.bc.InstrSHORT_DW(asBC_ADDSi, (short)var->stackOffset, engine->GetTypeIdFromDataType(asCDataType::CreateObject(outFunc->objectType, false)));
-				}
+				lctx.bc.Instr(asBC_PopRPtr);
+				lctx.type.dataType.MakeReference(true);
 			}
-			lctx.bc.Instr(asBC_RDSPtr);
-			lctx.bc.Call(asBC_CALLSYS, funcId, 1+AS_PTR_SIZE);
-
-			if( !var->dataType.GetSubType().IsPrimitive() )
-				lctx.bc.Instr(asBC_PshRPtr);
-
-			lctx.type.Set(var->dataType.GetSubType());
-
-			if( !lctx.type.dataType.IsObject() || lctx.type.dataType.IsObjectHandle() )
+			else if( dt.IsObjectHandle() ||
+					 dt.GetObjectType()->flags & asOBJ_REF )
+			{
+				lctx.type.isExplicitHandle = true;
 				lctx.type.dataType.MakeReference(true);
+			}
+			else
+			{
+				asASSERT( dt.GetObjectType()->flags & asOBJ_VALUE );
 
-			// If the element type is handles, then we're expected to do handle assignments
-			if( lctx.type.dataType.IsObjectHandle() )
-				lctx.type.isExplicitHandle = true;
+				// Make sure the object has been constructed before the assignment
+				// TODO: runtime optimize: Use copy constructor instead of assignment to initialize the objects
+				asSTypeBehaviour *beh = dt.GetBehaviour();
+				int func = 0;
+				if( beh ) func = beh->construct;
+				if( func == 0 && (dt.GetObjectType()->flags & asOBJ_POD) == 0 )
+				{
+					asCString str;
+					// TODO: funcdef: asCDataType should have a GetTypeName()
+					if( dt.GetFuncDef() )
+						str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetFuncDef()->GetName());
+					else
+						str.Format(TXT_NO_DEFAULT_CONSTRUCTOR_FOR_s, dt.GetObjectType()->GetName());
+					Error(str, valueNode);
+				}
+				else if( func )
+				{
+					// Call the constructor as a normal function
+					byteCode.InstrSHORT_DW(asBC_PshListElmnt, bufferVar, bufferSize);
 
-			lctx.type.isLValue = true;
+					asSExprContext ctx(engine);
+					PerformFunctionCall(func, &ctx, false, 0, dt.GetObjectType());
+					byteCode.AddCode(&ctx.bc);
+				}
+			}
 
 			asSExprContext ctx(engine);
-			DoAssignment(&ctx, &lctx, &rctx, el, el, ttAssignment, el);
+			DoAssignment(&ctx, &lctx, &rctx, valueNode, valueNode, ttAssignment, valueNode);
 
 			if( !lctx.type.dataType.IsPrimitive() )
 				ctx.bc.Instr(asBC_PopPtr);
@@ -2606,12 +2711,41 @@ void asCCompiler::CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByte
 
 			ProcessDeferredParams(&ctx);
 
-			bc->AddCode(&ctx.bc);
+			byteCode.AddCode(&ctx.bc);
 		}
+		else
+		{
+			// There is no specific value so we need to fill it with a default value
+			// TODO: list: For value types with default constructor we need to call the constructor
+
+			if( dt.GetTokenType() == ttQuestion )
+			{
+				// Place the type id for a null handle in the buffer
+				byteCode.InstrSHORT_DW_DW(asBC_SetListType, bufferVar, bufferSize, 0);
+				bufferSize += 4;
 
-		el = el->next;
-		index++;
+				dt = asCDataType::CreateNullHandle();
+
+				// No need to initialize the handle as the buffer is already initialized with zeroes
+			}
+		}
+
+		// Determine size of the element
+		if( dt.IsPrimitive() || (!dt.IsNullHandle() && (dt.GetObjectType()->flags & asOBJ_VALUE)) )
+			size = dt.GetSizeInMemoryBytes();
+		else
+			size = AS_PTR_SIZE*4;
+		asASSERT( size <= 4 || (size & 0x3) == 0 );
+		
+		// Move to the next element
+		bufferSize += size;
+		patternNode = patternNode->next;
+		valueNode = valueNode->next;
 	}
+	else
+		asASSERT( false );
+
+	return 0;
 }
 
 void asCCompiler::CompileStatement(asCScriptNode *statement, bool *hasReturn, asCByteCode *bc)
@@ -3465,10 +3599,8 @@ void asCCompiler::PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ct
 
 	asCTypeInfo lvalue;
 	lvalue.Set(dt);
-	lvalue.isTemporary = true;
-	lvalue.stackOffset = (short)offset;
-	lvalue.isVariable = true;
 	lvalue.isExplicitHandle = ctx->type.isExplicitHandle;
+	bool isExplicitHandle = ctx->type.isExplicitHandle;
 
 	if( !dt.IsObjectHandle() &&
 		dt.GetObjectType() && (dt.GetBehaviour()->copyconstruct || dt.GetBehaviour()->copyfactory) )
@@ -3498,8 +3630,12 @@ void asCCompiler::PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ct
 				Error(TXT_FAILED_TO_CREATE_TEMP_OBJ, node);
 			}
 
+			// Release any temp that may have been created as the result of opAssign
+			ReleaseTemporaryVariable(lvalue, &ctx->bc);
+
 			// Pop the original reference
-			ctx->bc.Instr(asBC_PopPtr);
+			if( !lvalue.dataType.IsPrimitive() )
+				ctx->bc.Instr(asBC_PopPtr);
 		}
 
 		// If the expression was holding off on releasing a
@@ -3510,9 +3646,13 @@ void asCCompiler::PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ct
 
 	// Push the reference to the temporary variable on the stack
 	ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
-	lvalue.dataType.MakeReference(IsVariableOnHeap(offset));
 
-	ctx->type = lvalue;
+	ctx->type.Set(dt);
+	ctx->type.isTemporary = true;
+	ctx->type.stackOffset = (short)offset;
+	ctx->type.isVariable = true;
+	ctx->type.isExplicitHandle = isExplicitHandle;
+	ctx->type.dataType.MakeReference(IsVariableOnHeap(offset));
 }
 
 void asCCompiler::CompileReturnStatement(asCScriptNode *rnode, asCByteCode *bc)
@@ -4263,20 +4403,23 @@ int asCCompiler::PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asC
 		// TODO: Should find the opAssign method that implements the default copy behaviour.
 		//       The beh->copy member will be removed.
 		asSTypeBehaviour *beh = lvalue->dataType.GetBehaviour();
-		if( beh->copy )
-		{
-			// Call the copy operator
-			asCScriptFunction *descr = builder->GetFunctionDescription(beh->copy);
-			if( descr->funcType == asFUNC_VIRTUAL )
-				bc->Call(asBC_CALLINTF, beh->copy, 2*AS_PTR_SIZE);
-			else if( descr->funcType == asFUNC_SCRIPT )
-				bc->Call(asBC_CALL, beh->copy, 2*AS_PTR_SIZE);
-			else
-			{
-				asASSERT( descr->funcType == asFUNC_SYSTEM );
-				bc->Call(asBC_CALLSYS, beh->copy, 2*AS_PTR_SIZE);
-			}
-			asASSERT( descr->returnType.IsReference() );
+		if( beh->copy && beh->copy != engine->scriptTypeBehaviours.beh.copy )
+		{
+			asSExprContext res(engine);
+			PerformFunctionCall(beh->copy, &res, false, 0, lvalue->dataType.GetObjectType());
+
+			bc->AddCode(&res.bc);
+			*lvalue = res.type;
+		}
+		else if( beh->copy == engine->scriptTypeBehaviours.beh.copy )
+		{
+			// Call the default copy operator for script classes
+			// This is done differently because the default copy operator
+			// is registered as returning int&, but in reality it returns
+			// a reference to the object. 
+			// TODO: Avoid this special case by implementing a copystub for
+			//       script classes that uses the default copy operator
+			bc->Call(asBC_CALLSYS, beh->copy, 2*AS_PTR_SIZE);
 			bc->Instr(asBC_PshRPtr);
 		}
 		else
@@ -5253,6 +5396,24 @@ asUINT asCCompiler::ImplicitConvObjectToObject(asSExprContext *ctx, const asCDat
 		{
 			if( generateCode )
 			{
+				// If the ASHANDLE receives a variable type parameter, then we need to 
+				// make sure the expression is treated as a handle and not as a value
+				asCScriptFunction *func = engine->scriptFunctions[funcs[0]];
+				if( func->parameterTypes[0].GetTokenType() == ttQuestion )
+				{
+					if( !ctx->type.isExplicitHandle )
+					{
+						asCDataType toHandle = ctx->type.dataType;
+						toHandle.MakeHandle(true);
+						toHandle.MakeReference(true);
+						toHandle.MakeHandleToConst(ctx->type.dataType.IsReadOnly());
+						ImplicitConversion(ctx, toHandle, node, asIC_IMPLICIT_CONV, true, false);
+
+						asASSERT( ctx->type.dataType.IsObjectHandle() );
+					}
+					ctx->type.isExplicitHandle = true;
+				}
+
 				// TODO: This should really reuse the code from CompileConstructCall
 
 				// Allocate the new object
@@ -5958,11 +6119,18 @@ void asCCompiler::ImplicitConversionConstant(asSExprContext *from, const asCData
 		else if( from->type.dataType.IsIntegerType() )
 		{
 			// Verify that it is possible to convert to unsigned without loosing negative
-			if( from->type.intValue < 0 )
+			if( (from->type.dataType.GetSizeInMemoryBytes() > 4 && asINT64(from->type.qwordValue) < 0) || 
+				(from->type.dataType.GetSizeInMemoryBytes() <= 4 && from->type.intValue < 0) )
 			{
 				if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_CHANGE_SIGN, node);
 			}
 
+			// Check if any data is lost
+			if( from->type.dataType.GetSizeInMemoryBytes() > 4 && (from->type.qwordValue >> 32) != 0 && (from->type.qwordValue >> 32) != 0xFFFFFFFF )
+			{
+				if( convType != asIC_EXPLICIT_VAL_CAST && node ) Warning(TXT_VALUE_TOO_LARGE_FOR_TYPE, node);
+			}
+
 			// Convert to 32bit
 			if( from->type.dataType.GetSizeInMemoryBytes() == 1 )
 				from->type.intValue = (signed char)from->type.byteValue;
@@ -6258,7 +6426,7 @@ int asCCompiler::DoAssignment(asSExprContext *ctx, asSExprContext *lctx, asSExpr
 {
 	// Don't allow any operators on expressions that take address of class method
 	// If methodName is set but the type is not an object, then it is a global function
-	if( lctx->methodName != "" || (rctx->type.dataType.GetObjectType() && rctx->methodName != "") )
+	if( lctx->methodName != "" || rctx->IsClassMethod() )
 	{
 		Error(TXT_INVALID_OP_ON_METHOD, opNode);
 		return -1;
@@ -6624,7 +6792,7 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx)
 		if( lr >= 0 && rr >= 0 )
 		{
 			// Don't allow any operators on expressions that take address of class method
-			if( le.methodName != "" || re.methodName != "" )
+			if( le.IsClassMethod() || re.IsClassMethod() )
 			{
 				Error(TXT_INVALID_OP_ON_METHOD, expr);
 				return -1;
@@ -6692,8 +6860,16 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx)
 				temp = le.type;
 				temp.dataType.MakeReference(false);
 				temp.dataType.MakeReadOnly(false);
-				// Make sure the variable isn't used in the initial expression
-				int offset = AllocateVariableNotIn(temp.dataType, true, false, &e);
+				
+				// Make sure the variable isn't used in any of the expressions, 
+				// as it would be overwritten which may cause crashes or less visible bugs
+				int l = int(reservedVariables.GetLength());
+				e.bc.GetVarsUsed(reservedVariables);
+				le.bc.GetVarsUsed(reservedVariables);
+				re.bc.GetVarsUsed(reservedVariables);
+				int offset = AllocateVariable(temp.dataType, true, false);
+				reservedVariables.SetLength(l);
+				
 				temp.SetVariable(temp.dataType, offset, true);
 
 				// TODO: copy: Use copy constructor if available. See PrepareTemporaryObject()
@@ -6725,8 +6901,10 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx)
 					ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
 					rtemp.dataType.MakeReference(IsVariableOnHeap(offset));
 				}
-				PerformAssignment(&rtemp, &le.type, &ctx->bc, cexpr->next);
-				if( !rtemp.dataType.IsPrimitive() )
+				asCTypeInfo result;
+				result = rtemp;
+				PerformAssignment(&result, &le.type, &ctx->bc, cexpr->next);
+				if( !result.dataType.IsPrimitive() )
 					ctx->bc.Instr(asBC_PopPtr); // Pop the original value (always a pointer)
 
 				// Release the old temporary variable
@@ -6746,8 +6924,9 @@ int asCCompiler::CompileCondition(asCScriptNode *expr, asSExprContext *ctx)
 					ctx->bc.InstrSHORT(asBC_PSF, (short)offset);
 					rtemp.dataType.MakeReference(IsVariableOnHeap(offset));
 				}
-				PerformAssignment(&rtemp, &re.type, &ctx->bc, cexpr->next);
-				if( !rtemp.dataType.IsPrimitive() )
+				result = rtemp;
+				PerformAssignment(&result, &re.type, &ctx->bc, cexpr->next);
+				if( !result.dataType.IsPrimitive() )
 					ctx->bc.Instr(asBC_PopPtr); // Pop the original value (always a pointer)
 
 				// Release the old temporary variable
@@ -7257,9 +7436,7 @@ int asCCompiler::CompileVariableAccess(const asCString &name, const asCString &s
 
 				// Defer the evaluation of which function until it is actually used
 				// Store the namespace and name of the function for later
-				ctx->type.SetNullConstant();
-				// Clear the explicit handle so that the script writer is allowed to explicitly set it
-				ctx->type.isExplicitHandle = false;
+				ctx->type.SetUndefinedFuncHandle(engine);
 				ctx->methodName = ns ? ns->name + "::" + name : name;
 			}
 		}
@@ -7410,7 +7587,9 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx
 			asQWORD val = asStringScanUInt64(value.AddressOf(), 10, 0);
 
 			// Do we need 64 bits?
-			if( val>>32 )
+			// If the 31st bit is set we'll treat the value as a signed 64bit number to avoid
+			// incorrect warnings about changing signs if the value is assigned to a 64bit variable
+			if( val>>31 )
 			{
 				// Only if the value uses the last bit of a 64bit word do we consider the number unsigned
 				if( val>>63 )
@@ -7593,6 +7772,11 @@ int asCCompiler::CompileExpressionValue(asCScriptNode *node, asSExprContext *ctx
 		// Implement the cast operator
 		CompileConversion(vnode, ctx);
 	}
+	else if( vnode->nodeType == snUndefined && vnode->tokenType == ttVoid )
+	{
+		// This is a void expression
+		ctx->type.SetVoidExpression();
+	}
 	else
 		asASSERT(false);
 
@@ -7924,14 +8108,14 @@ void asCCompiler::CompileConversion(asCScriptNode *node, asSExprContext *ctx)
 	ProcessPropertyGetAccessor(&expr, node);
 
 	// Don't allow any operators on expressions that take address of class method
-	if( expr.methodName != "" )
+	if( expr.IsClassMethod() )
 	{
 		Error(TXT_INVALID_OP_ON_METHOD, node);
 		return;
 	}
 
-	// We don't want a reference
-	if( expr.type.dataType.IsReference() )
+	// We don't want a reference for conversion casts
+	if( convType == asIC_EXPLICIT_VAL_CAST && expr.type.dataType.IsReference() )
 	{
 		if( expr.type.dataType.IsObject() )
 			Dereference(&expr, true);
@@ -8100,11 +8284,11 @@ void asCCompiler::ProcessDeferredParams(asSExprContext *ctx)
 			{
 				// We must still evaluate the expression
 				MergeExprBytecode(ctx, expr);
-				if( !expr->type.isConstant || expr->type.IsNullConstant() )
+				if( !expr->type.IsVoidExpression() && (!expr->type.isConstant || expr->type.IsNullConstant()) )
 					ctx->bc.Instr(asBC_PopPtr);
 
-				// Give a warning, except if the argument is null or 0 which indicate the argument is really to be ignored
-				if( !expr->type.IsNullConstant() && !(expr->type.isConstant && expr->type.qwordValue == 0) )
+				// Give a warning, except if the argument is void, null or 0 which indicate the argument is really to be ignored
+				if( !expr->type.IsVoidExpression() && !expr->type.IsNullConstant() && !(expr->type.isConstant && expr->type.qwordValue == 0) )
 					Warning(TXT_ARG_NOT_LVALUE, outParam.argNode);
 
 				ReleaseTemporaryVariable(outParam.argType, &ctx->bc);
@@ -8560,8 +8744,8 @@ int asCCompiler::CompileFunctionCall(asCScriptNode *node, asSExprContext *ctx, a
 
 	if( CompileArgumentList(node->lastChild, args) >= 0 )
 	{
-		// Special case: Allow calling func(void) with a void expression.
-		if( args.GetLength() == 1 && args[0]->type.dataType == asCDataType::CreatePrimitive(ttVoid, false) )
+		// Special case: Allow calling func(void) with an expression that evaluates to no datatype, but isn't exactly 'void' 
+		if( args.GetLength() == 1 && args[0]->type.dataType == asCDataType::CreatePrimitive(ttVoid, false) && !args[0]->type.IsVoidExpression() )
 		{
 			// Evaluate the expression before the function call
 			MergeExprBytecode(ctx, args[0]);
@@ -8694,12 +8878,19 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx
 	int op = node->tokenType;
 
 	// Don't allow any prefix operators except handle on expressions that take address of class method
-	if( ctx->methodName != "" && op != ttHandle )
+	if( ctx->IsClassMethod() && op != ttHandle )
 	{
 		Error(TXT_INVALID_OP_ON_METHOD, node);
 		return -1;
 	}
 
+	// Don't allow any operators on void expressions
+	if( ctx->type.IsVoidExpression() )
+	{
+		Error(TXT_VOID_CANT_BE_OPERAND, node);
+		return -1;
+	}
+
 	IsVariableInitialized(&ctx->type, node);
 
 	if( op == ttHandle )
@@ -8715,41 +8906,51 @@ int asCCompiler::CompileExpressionPreOp(asCScriptNode *node, asSExprContext *ctx
 		}
 		else
 		{
-			// Verify that the type allow its handle to be taken
-			if( ctx->type.isExplicitHandle ||
-				!ctx->type.dataType.IsObject() ||
-				!(((ctx->type.dataType.GetObjectType()->beh.addref && ctx->type.dataType.GetObjectType()->beh.release) || (ctx->type.dataType.GetObjectType()->flags & asOBJ_NOCOUNT)) ||
-				  (ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE)) )
+			// Don't allow taking handle of a handle, i.e. @@
+			if( ctx->type.isExplicitHandle )
 			{
 				Error(TXT_OBJECT_HANDLE_NOT_SUPPORTED, node);
 				return -1;
 			}
 
-			// Objects that are not local variables are not references
-			// Objects allocated on the stack are also not marked as references
-			if( !ctx->type.dataType.IsReference() &&
-				!(ctx->type.dataType.IsObject() && !ctx->type.isVariable) &&
-				!(ctx->type.isVariable && !IsVariableOnHeap(ctx->type.stackOffset)) )
+			// @null is allowed even though it is implicit
+			if( !ctx->type.IsNullConstant() )
 			{
-				Error(TXT_NOT_VALID_REFERENCE, node);
-				return -1;
-			}
+				// Verify that the type allow its handle to be taken
+				if( !ctx->type.dataType.IsObject() ||
+					!(((ctx->type.dataType.GetObjectType()->beh.addref && ctx->type.dataType.GetObjectType()->beh.release) || (ctx->type.dataType.GetObjectType()->flags & asOBJ_NOCOUNT)) ||
+					  (ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE)) )
+				{
+					Error(TXT_OBJECT_HANDLE_NOT_SUPPORTED, node);
+					return -1;
+				}
 
-			// Convert the expression to a handle
-			if( !ctx->type.dataType.IsObjectHandle() && !(ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE) )
-			{
-				asCDataType to = ctx->type.dataType;
-				to.MakeHandle(true);
-				to.MakeReference(true);
-				to.MakeHandleToConst(ctx->type.dataType.IsReadOnly());
-				ImplicitConversion(ctx, to, node, asIC_IMPLICIT_CONV, true, false);
+				// Objects that are not local variables are not references
+				// Objects allocated on the stack are also not marked as references
+				if( !ctx->type.dataType.IsReference() &&
+					!(ctx->type.dataType.IsObject() && !ctx->type.isVariable) &&
+					!(ctx->type.isVariable && !IsVariableOnHeap(ctx->type.stackOffset)) )
+				{
+					Error(TXT_NOT_VALID_REFERENCE, node);
+					return -1;
+				}
 
-				asASSERT( ctx->type.dataType.IsObjectHandle() );
-			}
-			else if( ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE )
-			{
-				// For the ASHANDLE type we'll simply set the expression as a handle
-				ctx->type.dataType.MakeHandle(true);
+				// Convert the expression to a handle
+				if( !ctx->type.dataType.IsObjectHandle() && !(ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE) )
+				{
+					asCDataType to = ctx->type.dataType;
+					to.MakeHandle(true);
+					to.MakeReference(true);
+					to.MakeHandleToConst(ctx->type.dataType.IsReadOnly());
+					ImplicitConversion(ctx, to, node, asIC_IMPLICIT_CONV, true, false);
+
+					asASSERT( ctx->type.dataType.IsObjectHandle() );
+				}
+				else if( ctx->type.dataType.GetObjectType()->flags & asOBJ_ASHANDLE )
+				{
+					// For the ASHANDLE type we'll simply set the expression as a handle
+					ctx->type.dataType.MakeHandle(true);
+				}
 			}
 		}
 
@@ -9539,12 +9740,19 @@ void asCCompiler::ProcessPropertyGetAccessor(asSExprContext *ctx, asCScriptNode
 int asCCompiler::CompileExpressionPostOp(asCScriptNode *node, asSExprContext *ctx)
 {
 	// Don't allow any postfix operators on expressions that take address of class method
-	if( ctx->methodName != "" )
+	if( ctx->IsClassMethod() )
 	{
 		Error(TXT_INVALID_OP_ON_METHOD, node);
 		return -1;
 	}
 
+	// Don't allow any operators on void expressions
+	if( ctx->type.IsVoidExpression() )
+	{
+		Error(TXT_VOID_CANT_BE_OPERAND, node);
+		return -1;
+	}
+
 	// Check if the variable is initialized (if it indeed is a variable)
 	IsVariableInitialized(&ctx->type, node);
 
@@ -10096,6 +10304,14 @@ asUINT asCCompiler::MatchArgument(asCArray<int> &funcs, asCArray<asSOverloadCand
 		if( (int)desc->parameterTypes.GetLength() <= paramNum )
 			continue;
 
+		// void expressions can match any out parameter, but nothing else
+		if( argExpr->type.IsVoidExpression() )
+		{
+			if( desc->inOutFlags[paramNum] == asTM_OUTREF )
+				matches.PushLast(asSOverloadCandidate(funcs[n], 0));
+			continue;
+		}
+
 		// Can we make the match by implicit conversion?
 		asSExprContext ti(engine);
 		ti.type = argExpr->type;
@@ -10566,16 +10782,24 @@ void asCCompiler::MakeFunctionCall(asSExprContext *ctx, int funcId, asCObjectTyp
 int asCCompiler::CompileOperator(asCScriptNode *node, asSExprContext *lctx, asSExprContext *rctx, asSExprContext *ctx)
 {
 	// Don't allow any operators on expressions that take address of class method, but allow it on global functions
-	if( (lctx->methodName != "" && lctx->type.dataType.GetObjectType()) || (rctx->methodName != "" && rctx->type.dataType.GetObjectType()) )
+	if( (lctx->IsClassMethod()) || (rctx->IsClassMethod()) )
 	{
 		Error(TXT_INVALID_OP_ON_METHOD, node);
 		return -1;
 	}
 
+	// Don't allow any operators on void expressions
+	if( lctx->type.IsVoidExpression() || rctx->type.IsVoidExpression() )
+	{
+		Error(TXT_VOID_CANT_BE_OPERAND, node);
+		return -1;
+	}
+
 	IsVariableInitialized(&lctx->type, node);
 	IsVariableInitialized(&rctx->type, node);
 
 	if( lctx->type.isExplicitHandle || rctx->type.isExplicitHandle ||
+		lctx->type.IsNullConstant() || rctx->type.IsNullConstant() ||
 		node->tokenType == ttIs || node->tokenType == ttNotIs )
 	{
 		CompileOperatorOnHandles(node, lctx, rctx, ctx);
@@ -11911,10 +12135,10 @@ void asCCompiler::CompileOperatorOnHandles(asCScriptNode *node, asSExprContext *
 		ReleaseTemporaryVariable(offset, 0);
 	}
 
-	// Warn if not both operands are explicit handles
+	// Warn if not both operands are explicit handles or null handles
 	if( (node->tokenType == ttEqual || node->tokenType == ttNotEqual) &&
-		((!lctx->type.isExplicitHandle && !(lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE))) ||
-		 (!rctx->type.isExplicitHandle && !(rctx->type.dataType.GetObjectType() && (rctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE)))) )
+		((!(lctx->type.isExplicitHandle || lctx->type.IsNullConstant()) && !(lctx->type.dataType.GetObjectType() && (lctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE))) ||
+		 (!(rctx->type.isExplicitHandle || rctx->type.IsNullConstant()) && !(rctx->type.dataType.GetObjectType() && (rctx->type.dataType.GetObjectType()->flags & asOBJ_IMPLICIT_HANDLE)))) )
 	{
 		Warning(TXT_HANDLE_COMPARISON, node);
 	}

+ 16 - 1
Source/ThirdParty/AngelScript/source/as_compiler.h

@@ -104,6 +104,20 @@ struct asSExprContext
 		property_ref    = false;
 		methodName      = "";
 	}
+	bool IsClassMethod()
+	{
+		if( type.dataType.GetObjectType() == 0 ) return false;
+		if( methodName == "" ) return false;
+		if( type.dataType.GetObjectType() == &type.dataType.GetObjectType()->engine->functionBehaviours ) return false;
+		return true;
+	}
+	bool IsGlobalFunc()
+	{
+		if( type.dataType.GetObjectType() == 0 ) return false;
+		if( methodName == "" ) return false;
+		if( type.dataType.GetObjectType() != &type.dataType.GetObjectType()->engine->functionBehaviours ) return false;
+		return true;
+	}
 
 	asCByteCode bc;
 	asCTypeInfo type;
@@ -200,8 +214,9 @@ protected:
 	int  CompileOverloadedDualOperator2(asCScriptNode *node, const char *methodName, asSExprContext *l, asSExprContext *r, asSExprContext *out, bool specificReturn = false, const asCDataType &returnType = asCDataType::CreatePrimitive(ttVoid, false));
 
 	void CompileInitList(asCTypeInfo *var, asCScriptNode *node, asCByteCode *bc, int isVarGlobOrMem);
+	int  CompileInitListElement(asSListPatternNode *&patternNode, asCScriptNode *&valueNode, int bufferTypeId, short bufferVar, asUINT &bufferSize, asCByteCode &byteCode);
 
-	int  CallDefaultConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem = 0, bool deferDest = false);
+	int  CallDefaultConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asCScriptNode *node, int isVarGlobOrMem = 0, bool derefDest = false);
 	int  CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc, asSExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false);
 	void CallDestructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc);
 	int  CompileArgumentList(asCScriptNode *node, asCArray<asSExprContext *> &args);

+ 1 - 4
Source/ThirdParty/AngelScript/source/as_config.h

@@ -28,7 +28,6 @@
    [email protected]
 */
 
-// Modified by Lasse Oorni for Urho3D
 
 //
 // as_config.h
@@ -39,9 +38,7 @@
 #ifndef AS_CONFIG_H
 #define AS_CONFIG_H
 
-// Urho3D: thread support or atomic operations are not needed, as SDL is not thread-safe in any case
-#define AS_NO_THREADS
-#define AS_NO_ATOMIC
+
 
 //
 // Features

+ 160 - 69
Source/ThirdParty/AngelScript/source/as_context.cpp

@@ -365,7 +365,9 @@ int asCContext::Prepare(asIScriptFunction *func)
 			m_returnValueSize = 0;
 
 		// Determine the minimum stack size needed
-		int stackSize = m_argumentsSize + m_returnValueSize + m_currentFunction->stackNeeded;
+		int stackSize = m_argumentsSize + m_returnValueSize;
+		if( m_currentFunction->scriptData )
+			stackSize += m_currentFunction->scriptData->stackNeeded;
 
 		// Make sure there is enough space on the stack for the arguments and return value
 		if( !ReserveStackSpace(stackSize) )
@@ -1111,7 +1113,7 @@ int asCContext::Execute()
 
 		if( m_currentFunction->funcType == asFUNC_SCRIPT )
 		{
-			m_regs.programPointer = m_currentFunction->byteCode.AddressOf();
+			m_regs.programPointer = m_currentFunction->scriptData->byteCode.AddressOf();
 
 			// Set up the internal registers for executing the script function
 			PrepareScriptFunction();
@@ -1378,12 +1380,14 @@ int asCContext::GetLineNumber(asUINT stackLevel, int *column, const char **secti
 	if( stackLevel == 0 )
 	{
 		func = m_currentFunction;
+		if( func->scriptData == 0 ) return 0;
 		bytePos = m_regs.programPointer;
 	}
 	else
 	{
 		asPWORD *s = m_callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
 		func = (asCScriptFunction*)s[1];
+		if( func->scriptData == 0 ) return 0;
 		bytePos = (asDWORD*)s[2];
 
 		// Subract 1 from the bytePos, because we want the line where
@@ -1400,7 +1404,7 @@ int asCContext::GetLineNumber(asUINT stackLevel, int *column, const char **secti
 	}
 
 	int sectionIdx;
-	asDWORD line = func->GetLineNumber(int(bytePos - func->byteCode.AddressOf()), &sectionIdx);
+	asDWORD line = func->GetLineNumber(int(bytePos - func->scriptData->byteCode.AddressOf()), &sectionIdx);
 	if( column ) *column = (line >> 20);
 	if( sectionName )
 	{
@@ -1488,17 +1492,19 @@ bool asCContext::ReserveStackSpace(asUINT size)
 // internal
 void asCContext::CallScriptFunction(asCScriptFunction *func)
 {
+	asASSERT( func->scriptData );
+
 	// Push the framepointer, function id and programCounter on the stack
 	PushCallState();
 
 	// Update the current function and program position before increasing the stack
 	// so the exception handler will know what to do if there is a stack overflow
 	m_currentFunction = func;
-	m_regs.programPointer = m_currentFunction->byteCode.AddressOf();
+	m_regs.programPointer = m_currentFunction->scriptData->byteCode.AddressOf();
 
 	// Make sure there is space on the stack to execute the function
 	asDWORD *oldStackPointer = m_regs.stackPointer;
-	if( !ReserveStackSpace(func->stackNeeded) )
+	if( !ReserveStackSpace(func->scriptData->stackNeeded) )
 		return;
 
 	// If a new stack block was allocated then we'll need to move
@@ -1514,20 +1520,22 @@ void asCContext::CallScriptFunction(asCScriptFunction *func)
 
 void asCContext::PrepareScriptFunction()
 {
+	asASSERT( m_currentFunction->scriptData );
+
 	// Update framepointer
 	m_regs.stackFramePointer = m_regs.stackPointer;
 
 	// Set all object variables to 0 to guarantee that they are null before they are used
 	// Only variables on the heap should be cleared. The rest will be cleared by calling the constructor
-	asUINT n = m_currentFunction->objVariablesOnHeap;
+	asUINT n = m_currentFunction->scriptData->objVariablesOnHeap;
 	while( n-- > 0 )
 	{
-		int pos = m_currentFunction->objVariablePos[n];
+		int pos = m_currentFunction->scriptData->objVariablePos[n];
 		*(asPWORD*)&m_regs.stackFramePointer[-pos] = 0;
 	}
 
 	// Initialize the stack pointer with the space needed for local variables
-	m_regs.stackPointer -= m_currentFunction->variableSpace;
+	m_regs.stackPointer -= m_currentFunction->scriptData->variableSpace;
 
 	// Call the line callback for each script function, to guarantee that infinitely recursive scripts can
 	// be interrupted, even if the scripts have been compiled with asEP_BUILD_WITHOUT_LINE_CUES
@@ -1662,7 +1670,7 @@ void asCContext::ExecuteNext()
 	// Swap the top 2 pointers on the stack
 	case asBC_SwapPtr:
 		{
-			asPWORD p = (asPWORD)*l_sp;
+			asPWORD p = *(asPWORD*)l_sp;
 			*(asPWORD*)l_sp = *(asPWORD*)(l_sp+AS_PTR_SIZE);
 			*(asPWORD*)(l_sp+AS_PTR_SIZE) = p;
 			l_bc++;
@@ -2523,6 +2531,8 @@ void asCContext::ExecuteNext()
 				{
 					if( beh->destruct )
 						m_engine->CallObjectMethod((void*)(asPWORD)*a, beh->destruct);
+					else if( objType->flags & asOBJ_LIST_PATTERN )
+						m_engine->DestroyList((asBYTE*)(asPWORD)*a, objType);
 
 					m_engine->CallFree((void*)(asPWORD)*a);
 				}
@@ -3413,7 +3423,7 @@ void asCContext::ExecuteNext()
 				return;
 			}
 			else if( divider == -1 )
-            {
+			{
 				// Need to check if the value that is divided is 1<<63
 				// as dividing it with -1 will cause an overflow exception
 				if( *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)) == (asINT64(1)<<63) )
@@ -3427,7 +3437,7 @@ void asCContext::ExecuteNext()
 					SetInternalException(TXT_DIVIDE_OVERFLOW);
 					return;
 				}
-            }
+			}
 
 			*(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)) / divider;
 		}
@@ -3449,7 +3459,7 @@ void asCContext::ExecuteNext()
 				return;
 			}
 			else if( divider == -1 )
-            {
+			{
 				// Need to check if the value that is divided is 1<<63
 				// as dividing it with -1 will cause an overflow exception
 				if( *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)) == (asINT64(1)<<63) )
@@ -3463,7 +3473,7 @@ void asCContext::ExecuteNext()
 					SetInternalException(TXT_DIVIDE_OVERFLOW);
 					return;
 				}
-            }
+			}
 			*(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)) % divider;
 		}
 		l_bc += 2;
@@ -3560,7 +3570,7 @@ void asCContext::ExecuteNext()
 
 	case asBC_JitEntry:
 		{
-			if( m_currentFunction->jitFunction )
+			if( m_currentFunction->scriptData->jitFunction )
 			{
 				asPWORD jitArg = asBC_PTRARG(l_bc);
 
@@ -3571,7 +3581,7 @@ void asCContext::ExecuteNext()
 					m_regs.stackPointer      = l_sp;
 					m_regs.stackFramePointer = l_fp;
 
-					(m_currentFunction->jitFunction)(&m_regs, jitArg);
+					(m_currentFunction->scriptData->jitFunction)(&m_regs, jitArg);
 
 					l_bc = m_regs.programPointer;
 					l_sp = m_regs.stackPointer;
@@ -3873,12 +3883,67 @@ void asCContext::ExecuteNext()
 			l_bc += 2;
 		break;
 
+	case asBC_AllocMem:
+		// Allocate a buffer and store the pointer in the local variable
+		{
+			// TODO: runtime optimize: As the list buffers are going to be short lived, it may be interesting
+			//                         to use a memory pool to avoid reallocating the memory all the time
+
+			asUINT size = asBC_DWORDARG(l_bc);
+			asBYTE **var = (asBYTE**)(l_fp - asBC_SWORDARG0(l_bc));
+			*var = asNEWARRAY(asBYTE, size);
+
+			// Clear the buffer for the pointers that will be placed in it
+			memset(*var, 0, size);
+		}
+		l_bc += 2;
+		break;
+
+	case asBC_SetListSize:
+		{
+			// Set the size element in the buffer 
+			asBYTE *var = *(asBYTE**)(l_fp - asBC_SWORDARG0(l_bc));
+			asUINT off  = asBC_DWORDARG(l_bc);
+			asUINT size = asBC_DWORDARG(l_bc+1);
+
+			asASSERT( var );
+
+			*(asUINT*)(var+off) = size;
+		}
+		l_bc += 3;
+		break;
+
+	case asBC_PshListElmnt:
+		{
+			// Push the pointer to the list element on the stack
+			// In essence it does the same as PSF, RDSPtr, ADDSi
+			asBYTE *var = *(asBYTE**)(l_fp - asBC_SWORDARG0(l_bc));
+			asUINT off = asBC_DWORDARG(l_bc);
+
+			asASSERT( var );
+			
+			l_sp -= AS_PTR_SIZE;
+			*(asPWORD*)l_sp = asPWORD(var+off);
+		}
+		l_bc += 2;
+		break;
+
+	case asBC_SetListType:
+		{
+			// Set the type id in the buffer 
+			asBYTE *var = *(asBYTE**)(l_fp - asBC_SWORDARG0(l_bc));
+			asUINT off  = asBC_DWORDARG(l_bc);
+			asUINT type = asBC_DWORDARG(l_bc+1);
+
+			asASSERT( var );
+
+			*(asUINT*)(var+off) = type;
+		}
+		l_bc += 3;
+		break;
+
 	// Don't let the optimizer optimize for size,
 	// since it requires extra conditions and jumps
-	case 189: l_bc = (asDWORD*)189; break;
-	case 190: l_bc = (asDWORD*)190; break;
-	case 191: l_bc = (asDWORD*)191; break;
-	case 192: l_bc = (asDWORD*)192; break;
 	case 193: l_bc = (asDWORD*)193; break;
 	case 194: l_bc = (asDWORD*)194; break;
 	case 195: l_bc = (asDWORD*)195; break;
@@ -3993,9 +4058,19 @@ void asCContext::SetInternalException(const char *descr)
 
 	m_exceptionString       = descr;
 	m_exceptionFunction     = m_currentFunction->id;
-	m_exceptionLine         = m_currentFunction->GetLineNumber(int(m_regs.programPointer - m_currentFunction->byteCode.AddressOf()), &m_exceptionSectionIdx);
-	m_exceptionColumn       = m_exceptionLine >> 20;
-	m_exceptionLine        &= 0xFFFFF;
+
+	if( m_currentFunction->scriptData )
+	{
+		m_exceptionLine    = m_currentFunction->GetLineNumber(int(m_regs.programPointer - m_currentFunction->scriptData->byteCode.AddressOf()), &m_exceptionSectionIdx);
+		m_exceptionColumn  = m_exceptionLine >> 20;
+		m_exceptionLine   &= 0xFFFFF;
+	}
+	else
+	{
+		m_exceptionSectionIdx = 0;
+		m_exceptionLine       = 0;
+		m_exceptionColumn     = 0;
+	}
 
 	if( m_exceptionCallback )
 		CallExceptionCallback();
@@ -4082,38 +4157,40 @@ bool asCContext::IsVarInScope(asUINT varIndex, asUINT stackLevel)
 	if( stackLevel == 0 )
 	{
 		func = m_currentFunction;
-		pos = asUINT(m_regs.programPointer - func->byteCode.AddressOf());
+		if( func->scriptData == 0 ) return false;
+		pos = asUINT(m_regs.programPointer - func->scriptData->byteCode.AddressOf());
 	}
 	else
 	{
 		asPWORD *s = m_callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
 		func = (asCScriptFunction*)s[1];
-		pos = asUINT((asDWORD*)s[2] - func->byteCode.AddressOf());
+		if( func->scriptData == 0 ) return false;
+		pos = asUINT((asDWORD*)s[2] - func->scriptData->byteCode.AddressOf());
 	}
 
 	// First determine if the program position is after the variable declaration
-	if( func->variables.GetLength() <= varIndex ) return false;
-	if( func->variables[varIndex]->declaredAtProgramPos > pos ) return false;
+	if( func->scriptData->variables.GetLength() <= varIndex ) return false;
+	if( func->scriptData->variables[varIndex]->declaredAtProgramPos > pos ) return false;
 
-	asUINT declaredAt = func->variables[varIndex]->declaredAtProgramPos;
+	asUINT declaredAt = func->scriptData->variables[varIndex]->declaredAtProgramPos;
 
 	// If the program position is after the variable declaration it is necessary
 	// determine if the program position is still inside the statement block where
 	// the variable was delcared.
-	for( int n = 0; n < (int)func->objVariableInfo.GetLength(); n++ )
+	for( int n = 0; n < (int)func->scriptData->objVariableInfo.GetLength(); n++ )
 	{
-		if( func->objVariableInfo[n].programPos >= declaredAt )
+		if( func->scriptData->objVariableInfo[n].programPos >= declaredAt )
 		{
 			// If the current block ends between the declaredAt and current
 			// program position, then we know the variable is no longer visible
 			int level = 0;
-			for( ; n < (int)func->objVariableInfo.GetLength(); n++ )
+			for( ; n < (int)func->scriptData->objVariableInfo.GetLength(); n++ )
 			{
-				if( func->objVariableInfo[n].programPos > pos )
+				if( func->scriptData->objVariableInfo[n].programPos > pos )
 					break;
 
-				if( func->objVariableInfo[n].option == asBLOCK_BEGIN ) level++;
-				if( func->objVariableInfo[n].option == asBLOCK_END && --level < 0 )
+				if( func->scriptData->objVariableInfo[n].option == asBLOCK_BEGIN ) level++;
+				if( func->scriptData->objVariableInfo[n].option == asBLOCK_END && --level < 0 )
 					return false;
 			}
 
@@ -4136,7 +4213,10 @@ void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLe
 	if( stackLevel == 0 )
 	{
 		func = m_currentFunction;
-		pos = asUINT(m_regs.programPointer - func->byteCode.AddressOf());
+		if( func->scriptData == 0 )
+			return;
+
+		pos = asUINT(m_regs.programPointer - func->scriptData->byteCode.AddressOf());
 
 		if( m_status == asEXECUTION_EXCEPTION )
 		{
@@ -4150,7 +4230,10 @@ void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLe
 	{
 		asPWORD *s = m_callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
 		func = (asCScriptFunction*)s[1];
-		pos = asUINT((asDWORD*)s[2] - func->byteCode.AddressOf());
+		if( func->scriptData == 0 )
+			return;
+
+		pos = asUINT((asDWORD*)s[2] - func->scriptData->byteCode.AddressOf());
 
 		// Don't consider the last instruction as executed, as the function that was called by it
 		// is still being executed. If we consider it as executed already, then a value object
@@ -4159,28 +4242,28 @@ void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLe
 	}
 
 	// Determine which object variables that are really live ones
-	liveObjects.SetLength(func->objVariablePos.GetLength());
+	liveObjects.SetLength(func->scriptData->objVariablePos.GetLength());
 	memset(liveObjects.AddressOf(), 0, sizeof(int)*liveObjects.GetLength());
-	for( int n = 0; n < (int)func->objVariableInfo.GetLength(); n++ )
+	for( int n = 0; n < (int)func->scriptData->objVariableInfo.GetLength(); n++ )
 	{
 		// Find the first variable info with a larger position than the current
 		// As the variable info are always placed on the instruction right after the
 		// one that initialized or freed the object, the current position needs to be
 		// considered as valid.
-		if( func->objVariableInfo[n].programPos > pos )
+		if( func->scriptData->objVariableInfo[n].programPos > pos )
 		{
 			// We've determined how far the execution ran, now determine which variables are alive
 			for( --n; n >= 0; n-- )
 			{
-				switch( func->objVariableInfo[n].option )
+				switch( func->scriptData->objVariableInfo[n].option )
 				{
 				case asOBJ_UNINIT: // Object was destroyed
 					{
 						// TODO: optimize: This should have been done by the compiler already
 						// Which variable is this?
 						asUINT var = 0;
-						for( asUINT v = 0; v < func->objVariablePos.GetLength(); v++ )
-							if( func->objVariablePos[v] == func->objVariableInfo[n].variableOffset )
+						for( asUINT v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
+							if( func->scriptData->objVariablePos[v] == func->scriptData->objVariableInfo[n].variableOffset )
 							{
 								var = v;
 								break;
@@ -4192,8 +4275,8 @@ void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLe
 					{
 						// Which variable is this?
 						asUINT var = 0;
-						for( asUINT v = 0; v < func->objVariablePos.GetLength(); v++ )
-							if( func->objVariablePos[v] == func->objVariableInfo[n].variableOffset )
+						for( asUINT v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
+							if( func->scriptData->objVariablePos[v] == func->scriptData->objVariableInfo[n].variableOffset )
 							{
 								var = v;
 								break;
@@ -4212,7 +4295,7 @@ void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLe
 						int nested = 1;
 						while( nested > 0 )
 						{
-							int option = func->objVariableInfo[--n].option;
+							int option = func->scriptData->objVariableInfo[--n].option;
 							if( option == 3 )
 								nested++;
 							if( option == 2 )
@@ -4234,8 +4317,10 @@ void asCContext::CleanArgsOnStack()
 	if( !m_needToCleanupArgs )
 		return;
 
+	asASSERT( m_currentFunction->scriptData );
+
 	// Find the instruction just before the current program pointer
-	asDWORD *instr = m_currentFunction->byteCode.AddressOf();
+	asDWORD *instr = m_currentFunction->scriptData->byteCode.AddressOf();
 	asDWORD *prevInstr = 0;
 	while( instr < m_regs.programPointer )
 	{
@@ -4262,10 +4347,10 @@ void asCContext::CleanArgsOnStack()
 		int var = asBC_SWORDARG0(prevInstr);
 
 		// Find the funcdef from the local variable
-		for( v = 0; v < m_currentFunction->objVariablePos.GetLength(); v++ )
-			if( m_currentFunction->objVariablePos[v] == var )
+		for( v = 0; v < m_currentFunction->scriptData->objVariablePos.GetLength(); v++ )
+			if( m_currentFunction->scriptData->objVariablePos[v] == var )
 			{
-				func = m_currentFunction->funcVariableTypes[v];
+				func = m_currentFunction->scriptData->funcVariableTypes[v];
 				break;
 			}
 
@@ -4345,25 +4430,26 @@ void asCContext::CleanStackFrame()
 		CleanArgsOnStack();
 
 		// Restore the stack pointer
-		m_regs.stackPointer += m_currentFunction->variableSpace;
+		asASSERT( m_currentFunction->scriptData );
+		m_regs.stackPointer += m_currentFunction->scriptData->variableSpace;
 
 		// Determine which object variables that are really live ones
 		asCArray<int> liveObjects;
 		DetermineLiveObjects(liveObjects, 0);
 
-		for( asUINT n = 0; n < m_currentFunction->objVariablePos.GetLength(); n++ )
+		for( asUINT n = 0; n < m_currentFunction->scriptData->objVariablePos.GetLength(); n++ )
 		{
-			int pos = m_currentFunction->objVariablePos[n];
-			if( n < m_currentFunction->objVariablesOnHeap )
+			int pos = m_currentFunction->scriptData->objVariablePos[n];
+			if( n < m_currentFunction->scriptData->objVariablesOnHeap )
 			{
 				// Check if the pointer is initialized
 				if( *(asPWORD*)&m_regs.stackFramePointer[-pos] )
 				{
 					// Call the object's destructor
-					asSTypeBehaviour *beh = &m_currentFunction->objVariableTypes[n]->beh;
-					if( m_currentFunction->objVariableTypes[n]->flags & asOBJ_REF )
+					asSTypeBehaviour *beh = &m_currentFunction->scriptData->objVariableTypes[n]->beh;
+					if( m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_REF )
 					{
-						asASSERT( (m_currentFunction->objVariableTypes[n]->flags & asOBJ_NOCOUNT) || beh->release );
+						asASSERT( (m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_NOCOUNT) || beh->release );
 						if( beh->release )
 							m_engine->CallObjectMethod((void*)*(asPWORD*)&m_regs.stackFramePointer[-pos], beh->release);
 						*(asPWORD*)&m_regs.stackFramePointer[-pos] = 0;
@@ -4372,6 +4458,8 @@ void asCContext::CleanStackFrame()
 					{
 						if( beh->destruct )
 							m_engine->CallObjectMethod((void*)*(asPWORD*)&m_regs.stackFramePointer[-pos], beh->destruct);
+						else if( m_currentFunction->scriptData->objVariableTypes[n]->flags & asOBJ_LIST_PATTERN )
+							m_engine->DestroyList((asBYTE*)*(asPWORD*)&m_regs.stackFramePointer[-pos], m_currentFunction->scriptData->objVariableTypes[n]);
 
 						// Free the memory
 						m_engine->CallFree((void*)*(asPWORD*)&m_regs.stackFramePointer[-pos]);
@@ -4381,12 +4469,12 @@ void asCContext::CleanStackFrame()
 			}
 			else
 			{
-				asASSERT( m_currentFunction->objVariableTypes[n]->GetFlags() & asOBJ_VALUE );
+				asASSERT( m_currentFunction->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE );
 
 				// Only destroy the object if it is truly alive
 				if( liveObjects[n] > 0 )
 				{
-					asSTypeBehaviour *beh = &m_currentFunction->objVariableTypes[n]->beh;
+					asSTypeBehaviour *beh = &m_currentFunction->scriptData->objVariableTypes[n]->beh;
 					if( beh->destruct )
 						m_engine->CallObjectMethod((void*)(asPWORD*)&m_regs.stackFramePointer[-pos], beh->destruct);
 				}
@@ -4396,7 +4484,7 @@ void asCContext::CleanStackFrame()
 		// If the object is a script declared object, then we must release it
 		// as the compiler adds a reference at the entry of the function. Make sure
 		// the function has actually been entered
-		if( m_currentFunction->objectType && m_regs.programPointer != m_currentFunction->byteCode.AddressOf() )
+		if( m_currentFunction->objectType && m_regs.programPointer != m_currentFunction->scriptData->byteCode.AddressOf() )
 		{
 			// Methods returning a reference or constructors don't add a reference
 			if( !m_currentFunction->returnType.IsReference() && m_currentFunction->name != m_currentFunction->objectType->name )
@@ -4735,27 +4823,30 @@ void *asCContext::GetAddressOfVar(asUINT varIndex, asUINT stackLevel)
 	if( func == 0 )
 		return 0;
 
-	if( varIndex >= func->variables.GetLength() )
+	if( func->scriptData == 0 ) 
+		return 0;
+
+	if( varIndex >= func->scriptData->variables.GetLength() )
 		return 0;
 
 	// For object variables it's necessary to dereference the pointer to get the address of the value
 	// Reference parameters must also be dereferenced to give the address of the value
-	int pos = func->variables[varIndex]->stackOffset;
-	if( (func->variables[varIndex]->type.IsObject() && !func->variables[varIndex]->type.IsObjectHandle()) || (pos <= 0) )
+	int pos = func->scriptData->variables[varIndex]->stackOffset;
+	if( (func->scriptData->variables[varIndex]->type.IsObject() && !func->scriptData->variables[varIndex]->type.IsObjectHandle()) || (pos <= 0) )
 	{
 		// Determine if the object is really on the heap
 		bool onHeap = false;
-		if( func->variables[varIndex]->type.IsObject() &&
-			!func->variables[varIndex]->type.IsObjectHandle() )
+		if( func->scriptData->variables[varIndex]->type.IsObject() &&
+			!func->scriptData->variables[varIndex]->type.IsObjectHandle() )
 		{
 			onHeap = true;
-			if( func->variables[varIndex]->type.GetObjectType()->GetFlags() & asOBJ_VALUE )
+			if( func->scriptData->variables[varIndex]->type.GetObjectType()->GetFlags() & asOBJ_VALUE )
 			{
-				for( asUINT n = 0; n < func->objVariablePos.GetLength(); n++ )
+				for( asUINT n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ )
 				{
-					if( func->objVariablePos[n] == pos )
+					if( func->scriptData->objVariablePos[n] == pos )
 					{
-						onHeap = n < func->objVariablesOnHeap;
+						onHeap = n < func->scriptData->objVariablesOnHeap;
 
 						if( !onHeap )
 						{
@@ -4799,10 +4890,10 @@ void *asCContext::GetAddressOfVar(asUINT varIndex, asUINT stackLevel)
 		}
 
 		if( onHeap )
-			return *(void**)(sf - func->variables[varIndex]->stackOffset);
+			return *(void**)(sf - func->scriptData->variables[varIndex]->stackOffset);
 	}
 
-	return sf - func->variables[varIndex]->stackOffset;
+	return sf - func->scriptData->variables[varIndex]->stackOffset;
 }
 
 // interface

+ 1 - 1
Source/ThirdParty/AngelScript/source/as_gc.cpp

@@ -151,7 +151,7 @@ int asCGarbageCollector::GetObjectInGC(asUINT idx, asUINT *seqNbr, void **obj, a
 
 	ENTERCRITICALSECTION(gcCritical);
 	asSObjTypePair *o = 0;
-	asUINT newObjs = gcNewObjects.GetLength();
+	asUINT newObjs = asUINT(gcNewObjects.GetLength());
 	if( idx < newObjs )
 		o = &gcNewObjects[idx];
 	else if( idx < gcOldObjects.GetLength() + newObjs )

+ 28 - 7
Source/ThirdParty/AngelScript/source/as_module.cpp

@@ -42,6 +42,7 @@
 #include "as_context.h"
 #include "as_texts.h"
 #include "as_debug.h"
+#include "as_restore.h"
 
 BEGIN_AS_NAMESPACE
 
@@ -65,7 +66,7 @@ asCModule::~asCModule()
 {
 	InternalReset();
 
-	if( builder ) 
+	if( builder )
 	{
 		asDELETE(builder,asCBuilder);
 		builder = 0;
@@ -190,10 +191,12 @@ int asCModule::AddScriptSection(const char *name, const char *code, size_t codeL
 // internal
 void asCModule::JITCompile()
 {
+	asIJITCompiler *jit = engine->GetJITCompiler();
+	if( !jit )
+		return;
+
 	for (unsigned int i = 0; i < scriptFunctions.GetLength(); i++)
-	{
 		scriptFunctions[i]->JITCompile();
-	}
 }
 
 // interface
@@ -240,9 +243,9 @@ int asCModule::Build()
 		return r;
 	}
 
-    JITCompile();
+	JITCompile();
 
- 	engine->PrepareEngine();
+	engine->PrepareEngine();
 
 #ifdef AS_DEBUG
 	// Verify that there are no unwanted gaps in the scriptFunctions array.
@@ -321,7 +324,7 @@ int asCModule::CallInit(asIScriptContext *myCtx)
 					msg.Format(TXT_FAILED_TO_INITIALIZE_s, desc->name.AddressOf());
 					asCScriptFunction *func = desc->GetInitFunc();
 
-					engine->WriteMessage(func->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptSectionIdx]->AddressOf() : "",
+					engine->WriteMessage(func->scriptData->scriptSectionIdx >= 0 ? engine->scriptSectionNames[func->scriptData->scriptSectionIdx]->AddressOf() : "",
 										 func->GetLineNumber(0, 0) & 0xFFFFF, 
 										 func->GetLineNumber(0, 0) >> 20,
 										 asMSGTYPE_ERROR,
@@ -814,7 +817,14 @@ int asCModule::AddScriptFunction(int sectionIdx, int id, const asCString &name,
 	// Store the function information
 	asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT);
 	if( func == 0 )
+	{
+		// Free the default args
+		for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+			if( defaultArgs[n] )
+				asDELETE(defaultArgs[n], asCString);
+
 		return asOUT_OF_MEMORY;
+	}
 
 	if( ns == 0 )
 		ns = engine->nameSpaces[0];
@@ -827,7 +837,8 @@ int asCModule::AddScriptFunction(int sectionIdx, int id, const asCString &name,
 	func->nameSpace        = ns;
 	func->id               = id;
 	func->returnType       = returnType;
-	func->scriptSectionIdx = sectionIdx;
+	if( func->funcType == asFUNC_SCRIPT )
+		func->scriptData->scriptSectionIdx = sectionIdx;
 	func->parameterTypes   = params;
 	func->inOutFlags       = inOutFlags;
 	func->defaultArgs      = defaultArgs;
@@ -880,7 +891,14 @@ int asCModule::AddImportedFunction(int id, const asCString &name, const asCDataT
 	// Store the function information
 	asCScriptFunction *func = asNEW(asCScriptFunction)(engine, this, asFUNC_IMPORTED);
 	if( func == 0 )
+	{
+		// Free the default args
+		for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+			if( defaultArgs[n] )
+				asDELETE(defaultArgs[n], asCString);
+
 		return asOUT_OF_MEMORY;
+	}
 
 	func->name           = name;
 	func->id             = id;
@@ -893,7 +911,10 @@ int asCModule::AddImportedFunction(int id, const asCString &name, const asCDataT
 
 	sBindInfo *info = asNEW(sBindInfo);
 	if( info == 0 )
+	{
+		asDELETE(func, asCScriptFunction);
 		return asOUT_OF_MEMORY;
+	}
 
 	info->importedFunctionSignature = func;
 	info->boundFunctionId           = -1;

+ 5 - 3
Source/ThirdParty/AngelScript/source/as_objecttype.cpp

@@ -254,6 +254,10 @@ void asCObjectType::SetGCFlag()
 
 asCObjectType::~asCObjectType()
 {
+	// Skip this for list patterns as they do not increase the references
+	if( flags & asOBJ_LIST_PATTERN )
+		return;
+
 	// Release the object types held by the templateSubTypes
 	for( asUINT subtypeIndex = 0; subtypeIndex < templateSubTypes.GetLength(); subtypeIndex++ )
 	{
@@ -264,18 +268,16 @@ asCObjectType::~asCObjectType()
 	if( derivedFrom )
 		derivedFrom->Release();
 
-	asUINT n;
-
 	ReleaseAllProperties();
 
 	ReleaseAllFunctions();
 
+	asUINT n;
 	for( n = 0; n < enumValues.GetLength(); n++ )
 	{
 		if( enumValues[n] )
 			asDELETE(enumValues[n],asSEnumValue);
 	}
-
 	enumValues.SetLength(0);
 
 	// Clean the user data

+ 4 - 3
Source/ThirdParty/AngelScript/source/as_objecttype.h

@@ -51,13 +51,14 @@ BEGIN_AS_NAMESPACE
 
 // TODO: memory: Need to minimize used memory here, because not all types use all properties of the class
 
-// TODO: The type id should have flags for diferenciating between value types and reference types. It should also have a flag for differenciating interface types.
+// TODO: The type id should have flags for differenciating between value types and reference types. It should also have a flag for differenciating interface types.
 
 // Additional flag to the class object type
 const asDWORD asOBJ_IMPLICIT_HANDLE  = 0x00400000;
-const asDWORD asOBJ_TYPEDEF          = 0x40000000;
+const asDWORD asOBJ_LIST_PATTERN     = 0x08000000;
 const asDWORD asOBJ_ENUM             = 0x10000000;
 const asDWORD asOBJ_TEMPLATE_SUBTYPE = 0x20000000;
+const asDWORD asOBJ_TYPEDEF          = 0x40000000;
 
 
 
@@ -157,7 +158,7 @@ public:
 	int              GetTypeId() const;
 	int              GetSubTypeId(asUINT subtypeIndex = 0) const;
 	asIObjectType   *GetSubType(asUINT subtypeIndex = 0) const;
-	asUINT			 GetSubTypeCount() const;
+	asUINT           GetSubTypeCount() const;
 
 	// Interfaces
 	asUINT           GetInterfaceCount() const;

+ 105 - 14
Source/ThirdParty/AngelScript/source/as_parser.cpp

@@ -91,7 +91,7 @@ asCScriptNode *asCParser::GetScriptNode()
 	return scriptNode;
 }
 
-int asCParser::ParseFunctionDefinition(asCScriptCode *script)
+int asCParser::ParseFunctionDefinition(asCScriptCode *script, bool expectListPattern)
 {
 	Reset();
 
@@ -102,6 +102,9 @@ int asCParser::ParseFunctionDefinition(asCScriptCode *script)
 
 	scriptNode = ParseFunctionDefinition();
 
+	if( expectListPattern )
+		scriptNode->AddChildLast(ParseListPattern());
+
 	// The declaration should end after the definition
 	if( !isSyntaxError )
 	{
@@ -610,7 +613,7 @@ asCScriptNode *asCParser::ParseParameterList()
 			node->AddChildLast(ParseTypeMod(true));
 			if( isSyntaxError ) return node;
 
-			// Parse identifier
+			// Parse optional identifier
 			GetToken(&t1);
 			if( t1.type == ttIdentifier )
 			{
@@ -620,17 +623,17 @@ asCScriptNode *asCParser::ParseParameterList()
 				if( isSyntaxError ) return node;
 
 				GetToken(&t1);
+			}
 
-				// Parse the expression for the default arg
-				if( t1.type == ttAssignment )
-				{
-					// Do a superficial parsing of the default argument
-					// The actual parsing will be done when the argument is compiled for a function call
-					node->AddChildLast(SuperficiallyParseExpression());
-					if( isSyntaxError ) return node;
+			// Parse optional expression for the default arg
+			if( t1.type == ttAssignment )
+			{
+				// Do a superficial parsing of the default argument
+				// The actual parsing will be done when the argument is compiled for a function call
+				node->AddChildLast(SuperficiallyParseExpression());
+				if( isSyntaxError ) return node;
 
-					GetToken(&t1);
-				}
+				GetToken(&t1);
 			}
 
 			// Check if list continues
@@ -928,7 +931,91 @@ asCString asCParser::ExpectedOneOf(const char **tokens, int count)
 	return str;
 }
 
-#ifndef AS_NO_COMPILER
+asCScriptNode *asCParser::ParseListPattern()
+{
+	asCScriptNode *node = CreateNode(snListPattern);
+	if( node == 0 ) return 0;
+
+	sToken t1;
+
+	GetToken(&t1);
+	if( t1.type != ttStartStatementBlock )
+	{
+		Error(ExpectedToken("{"), &t1);
+		return node;
+	}
+
+	node->UpdateSourcePos(t1.pos, t1.length);
+
+	sToken start = t1;
+
+	bool isBeginning = true;
+	bool afterType = false;
+	while( !isSyntaxError )
+	{
+		GetToken(&t1);
+		if( t1.type == ttEndStatementBlock )
+		{
+			if( !afterType )
+				Error(TXT_EXPECTED_DATA_TYPE, &t1);
+			break;
+		}
+		else if( t1.type == ttStartStatementBlock )
+		{
+			if( afterType )
+			{
+				asCString msg;
+				msg.Format(TXT_EXPECTED_s_OR_s, ",", "}");
+				Error(msg.AddressOf(), &t1);
+			}
+			RewindTo(&t1);
+			node->AddChildLast(ParseListPattern());
+			afterType = true;
+		}
+		else if( t1.type == ttIdentifier && IdentifierIs(t1, "repeat") )
+		{
+			if( !isBeginning )
+			{
+				asCString msg;
+				msg.Format(TXT_UNEXPECTED_TOKEN_s, "repeat");
+				Error(msg.AddressOf(), &t1);
+			}
+			RewindTo(&t1);
+			node->AddChildLast(ParseIdentifier());
+		}
+		else if( t1.type == ttEnd )
+		{
+			Error(TXT_UNEXPECTED_END_OF_FILE, &t1);
+			Info(TXT_WHILE_PARSING_STATEMENT_BLOCK, &start);
+			break;
+		}
+		else if( t1.type == ttListSeparator )
+		{
+			if( !afterType )
+				Error(TXT_EXPECTED_DATA_TYPE, &t1);
+			afterType = false;
+		}
+		else
+		{
+			if( afterType )
+			{
+				asCString msg;
+				msg.Format(TXT_EXPECTED_s_OR_s, ",", "}");
+				Error(msg.AddressOf(), &t1);
+			}
+			RewindTo(&t1);
+			node->AddChildLast(ParseType(true, true));
+			afterType = true;
+		}
+
+		isBeginning = false;
+	}
+
+	node->UpdateSourcePos(t1.pos, t1.length);
+
+	return node;
+}
+
 bool asCParser::IdentifierIs(const sToken &t, const char *str)
 {
 	if( t.type != ttIdentifier ) 
@@ -937,6 +1024,7 @@ bool asCParser::IdentifierIs(const sToken &t, const char *str)
 	return script->TokenEquals(t.pos, t.length, str);
 }
 
+#ifndef AS_NO_COMPILER
 bool asCParser::CheckTemplateType(sToken &t)
 {
 	// Is this a template type?
@@ -1079,7 +1167,10 @@ asCScriptNode *asCParser::ParseExprValue()
 	GetToken(&t2);
 	RewindTo(&t1);
 
-	if( IsRealType(t1.type) )
+	// 'void' is a special expression that doesn't do anything (normally used for skipping output arguments)
+	if( t1.type == ttVoid )
+		node->AddChildLast(ParseToken(ttVoid));
+	else if( IsRealType(t1.type) )
 		node->AddChildLast(ParseConstructCall());
 	else if( t1.type == ttIdentifier || t1.type == ttScope )
 	{
@@ -1871,7 +1962,7 @@ int asCParser::ParseStatementBlock(asCScriptCode *script, asCScriptNode *block)
 	this->script = script;
 	sourcePos = block->tokenPos;
 
-	scriptNode = ParseStatementBlock();	
+	scriptNode = ParseStatementBlock();
 
 	if( isSyntaxError || errorWhileParsing )
 		return -1;

+ 5 - 3
Source/ThirdParty/AngelScript/source/as_parser.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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 
@@ -53,7 +53,7 @@ public:
 	asCParser(asCBuilder *builder);
 	~asCParser();
 
-	int ParseFunctionDefinition(asCScriptCode *script);
+	int ParseFunctionDefinition(asCScriptCode *script, bool expectListPattern);
 	int ParsePropertyDeclaration(asCScriptCode *script);
 	int ParseDataType(asCScriptCode *script, bool isReturnType);
 	int ParseTemplateDecl(asCScriptCode *script);
@@ -90,8 +90,11 @@ protected:
 	asCScriptNode *ParseDataType(bool allowVariableType = false);
 	asCScriptNode *ParseIdentifier();
 
+	asCScriptNode *ParseListPattern();
+
 	bool IsRealType(int tokenType);
 	bool IsDataType(const sToken &token);
+	bool IdentifierIs(const sToken &t, const char *str);
 
 #ifndef AS_NO_COMPILER
 	// Statements
@@ -155,7 +158,6 @@ protected:
 	bool IsAssignOperator(int tokenType);
 	bool IsFunctionCall();
 
-	bool IdentifierIs(const sToken &t, const char *str);
 	bool CheckTemplateType(sToken &t);
 #endif
 

File diff suppressed because it is too large
+ 409 - 154
Source/ThirdParty/AngelScript/source/as_restore.cpp


+ 52 - 1
Source/ThirdParty/AngelScript/source/as_restore.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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 
@@ -117,6 +117,33 @@ protected:
 
 	asCMap<void*,bool>              existingShared;
 	asCMap<asCScriptFunction*,bool> dontTranslate;
+
+	// Helper class for adjusting offsets within initialization list buffers
+	struct SListAdjuster
+	{
+		SListAdjuster(asDWORD *bc, asCObjectType *ot);
+		void AdjustAllocMem();
+		int  AdjustOffset(int offset, asCObjectType *listPatternType);
+		void SetRepeatCount(asUINT rc);
+		void SetNextType(int typeId);
+
+		struct SInfo
+		{
+			asUINT              repeatCount;
+			asSListPatternNode *startNode;
+		};
+		asCArray<SInfo> stack;
+
+		asDWORD            *allocMemBC;
+		asUINT              maxOffset;
+		asCObjectType      *patternType;
+		asUINT              repeatCount;
+		int                 lastOffset;
+		asUINT              lastAdjustedOffset;
+		asSListPatternNode *patternNode;
+		int                 nextTypeId;
+	};
+	asCArray<SListAdjuster*> listAdjusters;
 };
 
 #ifndef AS_NO_COMPILER
@@ -189,6 +216,30 @@ protected:
 		int            offset;
 	};
 	asCArray<SObjProp>           usedObjectProperties;
+
+	// Helper class for adjusting offsets within initialization list buffers
+	struct SListAdjuster
+	{
+		SListAdjuster(asCObjectType *ot);
+		int  AdjustOffset(int offset, asCObjectType *listPatternType);
+		void SetRepeatCount(asUINT rc);
+		void SetNextType(int typeId);
+
+		struct SInfo
+		{
+			asUINT              repeatCount;
+			asSListPatternNode *startNode;
+		};
+		asCArray<SInfo> stack;
+
+		asCObjectType      *patternType;
+		asUINT              repeatCount;
+		asSListPatternNode *patternNode;
+		asUINT              entries;
+		int                 lastOffset;
+		int                 nextTypeId;
+	};
+	asCArray<SListAdjuster*> listAdjusters;
 };
 
 #endif

+ 290 - 25
Source/ThirdParty/AngelScript/source/as_scriptengine.cpp

@@ -1042,7 +1042,7 @@ int asCScriptEngine::ClearUnusedTypes()
 	// Build a list of all types to check for
 	asCArray<asCObjectType*> types;
 	types = classTypes;
-	types.Concatenate(templateInstanceTypes);
+	types.Concatenate(generatedTemplateTypes);
 
 	// Go through all modules
 	asUINT n;
@@ -1145,6 +1145,17 @@ int asCScriptEngine::ClearUnusedTypes()
 			break;
 	}
 
+	// Clear the list pattern types that are no longer used
+	for( n = 0; n < listPatternTypes.GetLength(); n++ )
+	{
+		if( listPatternTypes[n]->refCount.get() == 0 )
+		{
+			asDELETE(listPatternTypes[n], asCObjectType);
+			listPatternTypes.RemoveIndexUnordered(n);
+			n--;
+		}
+	}
+
 	return clearCount;
 }
 
@@ -1637,10 +1648,10 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD
 				return asALREADY_REGISTERED;
 		}
 
-		// Verify the most recently created template instance type
+		// Keep the most recent template generated instance type, so we know what it was before parsing the datatype
 		asCObjectType *mostRecentTemplateInstanceType = 0;
-		if( templateInstanceTypes.GetLength() )
-			mostRecentTemplateInstanceType = templateInstanceTypes[templateInstanceTypes.GetLength()-1];
+		if( generatedTemplateTypes.GetLength() )
+			mostRecentTemplateInstanceType = generatedTemplateTypes[generatedTemplateTypes.GetLength()-1];
 
 		// Use builder to parse the datatype
 		asCDataType dt;
@@ -1697,11 +1708,17 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD
 				return ConfigError(asINVALID_TYPE, "RegisterObjectType", name, 0);
 
 			// Was the template instance type created before?
-			if( templateInstanceTypes[templateInstanceTypes.GetLength()-1] == mostRecentTemplateInstanceType ||
+			if( (generatedTemplateTypes.GetLength() &&
+				 generatedTemplateTypes[generatedTemplateTypes.GetLength()-1] == mostRecentTemplateInstanceType) ||
 				mostRecentTemplateInstanceType == dt.GetObjectType() )
 				// TODO: Should have a better error message
 				return ConfigError(asNOT_SUPPORTED, "RegisterObjectType", name, 0);
 
+			// If this is not a template instance type, then it means it is an  
+			// already registered template specialization
+			if( !generatedTemplateTypes.Exists(dt.GetObjectType()) )
+				return ConfigError(asALREADY_REGISTERED, "RegisterObjectType", name, 0);
+
 			// 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 )
@@ -1807,10 +1824,15 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as
 	// Verify function declaration
 	asCScriptFunction func(this, 0, asFUNC_DUMMY);
 
+	asCScriptNode *listPattern = 0;
 	asCBuilder bld(this, 0);
-	int r = bld.ParseFunctionDeclaration(objectType, decl, &func, true, &internal.paramAutoHandles, &internal.returnAutoHandle);
+	int r = bld.ParseFunctionDeclaration(objectType, decl, &func, true, &internal.paramAutoHandles, &internal.returnAutoHandle, 0, behaviour == asBEHAVE_LIST_FACTORY ? &listPattern : 0);
 	if( r < 0 )
+	{
+		if( listPattern )
+			listPattern->Destroy(this);
 		return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
+	}
 	func.name.Format("_beh_%d_", behaviour);
 
 	if( behaviour != asBEHAVE_FACTORY && behaviour != asBEHAVE_LIST_FACTORY )
@@ -1923,13 +1945,19 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as
 		// Must be a ref type and must not have asOBJ_NOHANDLE
 		if( !(objectType->flags & asOBJ_REF) || (objectType->flags & asOBJ_NOHANDLE) )
 		{
+			if( listPattern )
+				listPattern->Destroy(this);
 			WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_ILLEGAL_BEHAVIOUR_FOR_TYPE);
 			return ConfigError(asILLEGAL_BEHAVIOUR_FOR_TYPE, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
 		}
 
 		// Verify that the return type is a handle to the type
 		if( func.returnType != asCDataType::CreateObjectHandle(objectType, false) )
+		{
+			if( listPattern )
+				listPattern->Destroy(this);
 			return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
+		}
 
 		// TODO: Add support for implicit factories
 
@@ -1940,8 +1968,10 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as
 			(func.parameterTypes.GetLength() == 0 ||
 			 !func.parameterTypes[0].IsReference()) )
 		{
-			// TODO: Give proper error message that explain that the first parameter is expected to be a reference
-			//       The library should try to avoid having to read the manual as much as possible.
+			if( listPattern )
+				listPattern->Destroy(this);
+
+			WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_FIRST_PARAM_MUST_BE_REF_FOR_TEMPLATE_FACTORY);
 			return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
 		}
 
@@ -1961,7 +1991,42 @@ int asCScriptEngine::RegisterBehaviourToObjectType(asCObjectType *objectType, as
 				 (func.parameterTypes.GetLength() == 2 && (objectType->flags & asOBJ_TEMPLATE)) )
 		{
 			if( behaviour == asBEHAVE_LIST_FACTORY )
+			{
 				beh->listFactory = func.id;
+
+				// Make sure the factory takes a reference as its last parameter
+				if( objectType->flags & asOBJ_TEMPLATE )
+				{
+					if( func.parameterTypes.GetLength() != 2 || !func.parameterTypes[1].IsReference() )
+					{
+						if( listPattern )
+							listPattern->Destroy(this);
+
+						WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_TEMPLATE_LIST_FACTORY_EXPECTS_2_REF_PARAMS);
+						return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
+					}
+				}
+				else
+				{
+					if( func.parameterTypes.GetLength() != 1 || !func.parameterTypes[0].IsReference() )
+					{
+						if( listPattern )
+							listPattern->Destroy(this);
+
+						WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM);
+						return ConfigError(asINVALID_DECLARATION, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
+					}
+				}
+
+				// Store the list pattern for this function
+				int r = scriptFunctions[func.id]->RegisterListPattern(decl, listPattern);
+
+				if( listPattern )
+					listPattern->Destroy(this);
+
+				if( r < 0 )
+					return ConfigError(r, "RegisterObjectBehaviour", objectType->name.AddressOf(), decl);
+			}
 			else
 			{
 				// Is this the copy factory?
@@ -3091,14 +3156,14 @@ void asCScriptEngine::RemoveTemplateInstanceType(asCObjectType *t)
 		}
 	}
 
-	for( n = (int)templateInstanceTypes.GetLength()-1; n >= 0; n-- )
+	for( n = (int)generatedTemplateTypes.GetLength()-1; n >= 0; n-- )
 	{
-		if( templateInstanceTypes[n] == t )
+		if( generatedTemplateTypes[n] == t )
 		{
-			if( n == (signed)templateInstanceTypes.GetLength()-1 )
-				templateInstanceTypes.PopLast();
+			if( n == (signed)generatedTemplateTypes.GetLength()-1 )
+				generatedTemplateTypes.PopLast();
 			else
-				templateInstanceTypes[n] = templateInstanceTypes.PopLast();
+				generatedTemplateTypes[n] = generatedTemplateTypes.PopLast();
 		}
 	}
 
@@ -3231,18 +3296,36 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
 	for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
 		scriptFunctions[ot->beh.constructors[n]]->AddRef();
 
+	// As the new template type is instanciated the engine should
+	// generate new functions to substitute the ones with the template subtype.
+	for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
+	{
+		int funcId = ot->beh.constructors[n];
+		asCScriptFunction *func = scriptFunctions[funcId];
+
+		if( GenerateNewTemplateFunction(templateType, ot, func, &func) )
+		{
+			// Release the old function, the new one already has its ref count set to 1
+			scriptFunctions[funcId]->Release();
+			ot->beh.constructors[n] = func->id;
+
+			if( ot->beh.construct == funcId )
+				ot->beh.construct = func->id;
+		}
+	}
+
 	ot->beh.factory = 0;
 
 	// Generate factory stubs for each of the factories
-	for( n = 0; n < templateType->beh.factories.GetLength(); n++ )
+	for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
 	{
-		asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, templateType->beh.factories[n]);
+		asCScriptFunction *func = GenerateTemplateFactoryStub(templateType, ot, ot->beh.constructors[n]);
 
 		// The function's refCount was already initialized to 1
 		ot->beh.factories.PushLast(func->id);
 
 		// Set the default factory as well
-		if( templateType->beh.factories[n] == templateType->beh.factory )
+		if( ot->beh.constructors[n] == ot->beh.construct )
 			ot->beh.factory = func->id;
 	}
 
@@ -3314,9 +3397,9 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
 
 	templateTypes.PushLast(ot);
 
-	// We need to store the object type somewhere for clean-up later
-	// TODO: Why do we need both templateTypes and templateInstanceTypes? It is possible to differ between template instance and template specialization by checking for the asOBJ_TEMPLATE flag
-	templateInstanceTypes.PushLast(ot);
+	// Store the template instance types that have been created automatically by the engine from a template type
+	// The object types in templateTypes that are not also in generatedTemplateTypes are registered template specializations
+	generatedTemplateTypes.PushLast(ot);
 
 	return ot;
 }
@@ -3402,6 +3485,7 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t
 	}
 
 	func->funcType         = asFUNC_SCRIPT;
+	func->AllocateScriptFunctionData();
 	func->name             = "factstub";
 	func->id               = GetNextScriptFunctionId();
 	func->returnType       = asCDataType::CreateObjectHandle(ot, false);
@@ -3415,7 +3499,7 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t
 		func->parameterTypes[p-1] = DetermineTypeForTemplate(factory->parameterTypes[p], templateType, ot);
 		func->inOutFlags[p-1] = factory->inOutFlags[p];
 	}
-	func->objVariablesOnHeap = 0;
+	func->scriptData->objVariablesOnHeap = 0;
 
 	SetScriptFunction(func);
 
@@ -3427,8 +3511,8 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t
 	if( ep.includeJitInstructions )
 		bcLength += asBCTypeSize[asBCInfo[asBC_JitEntry].type];
 
-	func->byteCode.SetLength(bcLength);
-	asDWORD *bc = func->byteCode.AddressOf();
+	func->scriptData->byteCode.SetLength(bcLength);
+	asDWORD *bc = func->scriptData->byteCode.AddressOf();
 
 	if( ep.includeJitInstructions )
 	{
@@ -3447,13 +3531,38 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t
 	*(((asWORD*)bc)+1) = (asWORD)func->GetSpaceNeededForArguments();
 
 	func->AddReferences();
-	func->stackNeeded = AS_PTR_SIZE;
+	func->scriptData->stackNeeded = AS_PTR_SIZE;
 
 	// Tell the virtual machine not to clean up the object on exception
 	func->dontCleanUpOnException = true;
 
 	func->JITCompile();
 
+	// Need to translate the list pattern too so the VM and compiler will know the correct type of the members
+	if( factory->listPattern )
+	{
+		asSListPatternNode *n = factory->listPattern;
+		asSListPatternNode *last = 0;
+		while( n )
+		{
+			asSListPatternNode *newNode = n->Duplicate();
+			if( newNode->type == asLPT_TYPE )
+			{
+				asSListPatternDataTypeNode *typeNode = reinterpret_cast<asSListPatternDataTypeNode*>(newNode);
+				typeNode->dataType = DetermineTypeForTemplate(typeNode->dataType, templateType, ot);
+			}
+
+			if( last )
+				last->next = newNode;
+			else
+				func->listPattern = newNode;
+
+			last = newNode;
+
+			n = n->next;
+		}
+	}
+
 	return func;
 }
 
@@ -3503,7 +3612,6 @@ bool asCScriptEngine::GenerateNewTemplateFunction(asCObjectType *templateType, a
 	func2->inOutFlags = func->inOutFlags;
 	func2->isReadOnly = func->isReadOnly;
 	func2->objectType = ot;
-	func2->stackNeeded = func->stackNeeded;
 	func2->sysFuncIntf = asNEW(asSSystemFunctionInterface)(*func->sysFuncIntf);
 
 	SetScriptFunction(func2);
@@ -4456,11 +4564,15 @@ void asCScriptEngine::ReleaseScriptObject(void *obj, const asIObjectType *type)
 	}
 	else
 	{
-		// TODO: interface: shouldn't work on non reference types
+		// There is really only one reason why the application would want to 
+		// call this method for a value type, and that is if it is calling it
+		// as from a JIT compiled asBC_FREE instruction.
 
 		// Call the destructor
 		if( objType->beh.destruct )
 			CallObjectMethod(obj, objType->beh.destruct);
+		else if( objType->flags & asOBJ_LIST_PATTERN )
+			DestroyList((asBYTE*)obj, objType);
 
 		// Then free the memory
 		CallFree(obj);
@@ -5256,5 +5368,158 @@ void asCScriptEngine::SetObjectTypeUserDataCleanupCallback(asCLEANOBJECTTYPEFUNC
 	RELEASEEXCLUSIVE(engineRWLock);
 }
 
+// internal
+asCObjectType *asCScriptEngine::GetListPatternType(int listPatternFuncId)
+{
+	asCObjectType *ot = scriptFunctions[listPatternFuncId]->returnType.GetObjectType();
+	asASSERT( ot );
+
+	for( asUINT n = 0; n < listPatternTypes.GetLength(); n++ )
+	{
+		if( listPatternTypes[n]->templateSubTypes[0].GetObjectType() == ot )
+			return listPatternTypes[n];
+	}
+
+	// Create a new list pattern type for the given object type
+	asCObjectType *lpt = asNEW(asCObjectType)(this);
+	lpt->templateSubTypes.PushLast(asCDataType::CreateObject(ot, false));
+	lpt->flags = asOBJ_LIST_PATTERN;
+	listPatternTypes.PushLast(lpt);
+
+	return lpt;
+}
+
+// internal
+void asCScriptEngine::DestroyList(asBYTE *buffer, const asCObjectType *listPatternType)
+{
+	asASSERT( listPatternType && (listPatternType->flags & asOBJ_LIST_PATTERN) );
+
+	// Get the list pattern from the listFactory function
+	// TODO: runtime optimize: Store the used list factory in the listPatternType itself
+	// TODO: runtime optimize: Keep a flag to indicate if there is really a need to free anything
+	asCObjectType *ot = listPatternType->templateSubTypes[0].GetObjectType();
+	asCScriptFunction *listFactory = scriptFunctions[ot->beh.listFactory];
+	asASSERT( listFactory );
+
+	asSListPatternNode *node = listFactory->listPattern;
+	DestroySubList(buffer, node);
+
+	asASSERT( node->type == asLPT_END );
+}
+
+// internal
+void asCScriptEngine::DestroySubList(asBYTE *&buffer, asSListPatternNode *&node)
+{
+	asASSERT( node->type == asLPT_START );
+
+	int count = 0;
+
+	node = node->next;
+	while( node )
+	{
+		if( node->type == asLPT_REPEAT )
+		{
+			// Determine how many times the pattern repeat
+			count = *(asUINT*)buffer;
+			buffer += 4;
+		}
+		else if( node->type == asLPT_TYPE )
+		{
+			// If we're not in a repeat iteration, then only 1 value should be destroyed
+			if( count <= 0 )
+				count = 1;
+
+			asCDataType dt = reinterpret_cast<asSListPatternDataTypeNode*>(node)->dataType;
+			bool isVarType = dt.GetTokenType() == ttQuestion;
+
+			while( count-- )
+			{
+				if( isVarType )
+				{
+					int typeId = *(int*)buffer;
+					buffer += 4;
+					dt = GetDataTypeFromTypeId(typeId);
+				}
+
+				asCObjectType *ot = dt.GetObjectType();
+				if( ot && (ot->flags & asOBJ_ENUM) == 0 )
+				{
+					// Free all instances of this type
+					if( ot->flags & asOBJ_VALUE )
+					{
+						if( ot->beh.destruct )
+						{
+							// Only call the destructor if the object has been created
+							// We'll assume the object has been created if any byte in
+							// the memory is different from 0.
+							// TODO: This is not really correct, as bytes may have been
+							//       modified by the constructor, but then an exception 
+							//       thrown aborting the initialization. The engine
+							//       really should be keeping track of which objects has
+							//       been successfully initialized.
+							asUINT size = ot->GetSize();
+							for( asUINT n = 0; n < size; n++ )
+							{
+								if( buffer[n] != 0 )
+								{
+									void *ptr = (void*)buffer;
+									CallObjectMethod(ptr, ot->beh.destruct);
+									break;
+								}
+							}
+							buffer += size;
+						}
+						else
+						{
+							// Advance the pointer in the buffer
+							buffer += ot->GetSize();
+						}
+					}
+					else
+					{
+						// Call the release behaviour
+						void *ptr = *(void**)buffer;
+						if( ptr )
+							ReleaseScriptObject(ptr, ot);
+						buffer += AS_PTR_SIZE*4;
+					}
+				}
+				else
+				{
+					// Advance the buffer
+					buffer += dt.GetSizeInMemoryBytes();
+				}
+			}
+		}
+		else if( node->type == asLPT_START )
+		{
+			// If we're not in a repeat iteration, then only 1 value should be destroyed
+			if( count <= 0 )
+				count = 1;
+
+			while( count-- )
+			{
+				asSListPatternNode *subList = node;
+				DestroySubList(buffer, subList);
+
+				asASSERT( subList->type == asLPT_END );
+
+				if( count == 0 )
+					node = subList;
+			}
+		}
+		else if( node->type == asLPT_END )
+		{
+			return;
+		}
+		else
+		{
+			asASSERT( false );
+		}
+
+		node = node->next;
+	}
+}
+
 END_AS_NAMESPACE
 

+ 12 - 6
Source/ThirdParty/AngelScript/source/as_scriptengine.h

@@ -47,7 +47,6 @@
 #include "as_datatype.h"
 #include "as_objecttype.h"
 #include "as_module.h"
-#include "as_restore.h"
 #include "as_callfunc.h"
 #include "as_configgroup.h"
 #include "as_memory.h"
@@ -64,8 +63,6 @@ struct sBindInfo;
 
 // TODO: DiscardModule should take an optional pointer to asIScriptModule instead of module name. If null, nothing is done.
 
-// TODO: Should have a CreateModule/GetModule instead of just GetModule with parameters.
-
 // TODO: Should allow enumerating modules, in case they have not been named.
 
 
@@ -271,6 +268,10 @@ public:
 
 	asCObjectType *GetObjectType(const char *type, asSNameSpace *ns);
 
+	asCObjectType *GetListPatternType(int listPatternFuncId);
+	void DestroyList(asBYTE *buffer, const asCObjectType *listPatternType);
+	void DestroySubList(asBYTE *&buffer, asSListPatternNode *&patternNode);
+
 	int AddBehaviourFunction(asCScriptFunction &func, asSSystemFunctionInterface &internal);
 
 	asCString GetFunctionDeclaration(int funcId);
@@ -344,8 +345,13 @@ public:
 	asCArray<asCObjectType *>      templateSubTypes;
 
 	// Store information about template types
+	// This list will contain all instances of templates, both registered specialized 
+	// types and those automacially instanciated from scripts
 	asCArray<asCObjectType *>      templateTypes;
 
+	// Store information about list patterns
+	asCArray<asCObjectType *>      listPatternTypes;
+
 	// Stores all global properties, both those registered by application, and those declared by scripts.
 	// The id of a global property is the index in this array.
 	asCArray<asCGlobalProperty *> globalProperties;
@@ -377,8 +383,8 @@ public:
 
 	// Stores script declared object types
 	asCArray<asCObjectType *> classTypes;
-	// This array stores the template instances types, that have been generated from template types
-	asCArray<asCObjectType *> templateInstanceTypes;
+	// This array stores the template instances types that have been automatically generated from template types
+	asCArray<asCObjectType *> generatedTemplateTypes;
 	// Stores the funcdefs
 	asCArray<asCScriptFunction *> funcDefs;
 
@@ -421,7 +427,7 @@ public:
 	asCArray<asPWORD>       userData;
 
 	struct SEngineClean { asPWORD type; asCLEANENGINEFUNC_t cleanFunc; };
-	asCArray<SEngineClean> cleanEngineFuncs;
+	asCArray<SEngineClean>  cleanEngineFuncs;
 	asCLEANMODULEFUNC_t     cleanModuleFunc;
 	asCLEANCONTEXTFUNC_t    cleanContextFunc;
 	asCLEANFUNCTIONFUNC_t   cleanFunctionFunc;

File diff suppressed because it is too large
+ 449 - 295
Source/ThirdParty/AngelScript/source/as_scriptfunction.cpp


+ 75 - 27
Source/ThirdParty/AngelScript/source/as_scriptfunction.h

@@ -52,6 +52,7 @@ class asCScriptEngine;
 class asCModule;
 class asCConfigGroup;
 class asCGlobalProperty;
+class asCScriptNode;
 struct asSNameSpace;
 
 struct asSScriptVariable
@@ -62,6 +63,30 @@ struct asSScriptVariable
 	asUINT      declaredAtProgramPos;
 };
 
+enum asEListPatternNodeType
+{
+	asLPT_REPEAT,
+	asLPT_START,
+	asLPT_END,
+	asLPT_TYPE
+};
+
+struct asSListPatternNode
+{
+	asSListPatternNode(asEListPatternNodeType t) : type(t), next(0) {}
+	virtual ~asSListPatternNode() {};
+	virtual asSListPatternNode *Duplicate() { return asNEW(asSListPatternNode)(type); }
+	asEListPatternNodeType  type;
+	asSListPatternNode     *next;
+};
+
+struct asSListPatternDataTypeNode : public asSListPatternNode
+{
+	asSListPatternDataTypeNode(const asCDataType &dt) : asSListPatternNode(asLPT_TYPE), dataType(dt) {}
+	asSListPatternNode *Duplicate() { return asNEW(asSListPatternDataTypeNode)(dataType); }
+	asCDataType dataType;
+};
+
 enum asEObjVarInfoOption
 {
 	asOBJ_UNINIT,
@@ -169,8 +194,13 @@ public:
 	bool      IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &inOutFlags, const asCObjectType *type, bool isReadOnly) const;
 	bool      IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const;
 
+	asCObjectType *GetObjectTypeOfLocalVar(short varOffset);
+
 	void      MakeDelegate(asCScriptFunction *func, void *obj);
 
+	int       RegisterListPattern(const char *decl, asCScriptNode *listPattern);
+	int       ParseListPattern(asSListPatternNode *&target, const char *decl, asCScriptNode *listPattern);
+
 	bool      DoesReturnOnStack() const;
 
 	void      JITCompile();
@@ -178,6 +208,8 @@ public:
 	void      AddReferences();
 	void      ReleaseReferences();
 
+	void      AllocateScriptFunctionData();
+	void      DeallocateScriptFunctionData();
 
 	asCGlobalProperty *GetPropertyByGlobalVarPtr(void *gvarPtr);
 
@@ -224,40 +256,56 @@ public:
 	void              *objForDelegate;
 	asCScriptFunction *funcForDelegate;
 
+	// Used by list factory behaviour
+	asSListPatternNode *listPattern;
+
 	// Used by asFUNC_SCRIPT
-	asCArray<asDWORD>               byteCode;
-	// The stack space needed for the local variables
-	asDWORD                         variableSpace;
-
-	// These hold information objects and function pointers, including temporary
-	// variables used by exception handler and when saving bytecode
-	asCArray<asCObjectType*>        objVariableTypes;
-	asCArray<asCScriptFunction*>    funcVariableTypes;
-	asCArray<int>	                objVariablePos;
-	// The first variables in above array are allocated on the heap, the rest on the stack.
-	// This variable shows how many are on the heap.
-	asUINT                          objVariablesOnHeap;
-
-	// Holds information on scope for object variables on the stack
-	asCArray<asSObjectVariableInfo> objVariableInfo;
-
-	// Holds information on explicitly declared variables
-	asCArray<asSScriptVariable*>    variables;        // debug info
-
-	int                             stackNeeded;
-	asCArray<int>                   lineNumbers;      // debug info
-	int                             scriptSectionIdx; // debug info
-	asCArray<int>                   sectionIdxs;      // debug info. Store position/index pairs if the bytecode is compiled from multiple script sections
-	bool                            dontCleanUpOnException;   // Stub functions don't own the object and parameters
+	struct ScriptFunctionData
+	{
+		// Bytecode for the script function
+		asCArray<asDWORD>               byteCode;
+
+		// The stack space needed for the local variables
+		asDWORD                         variableSpace;
+
+		// These hold information objects and function pointers, including temporary
+		// variables used by exception handler and when saving bytecode
+		asCArray<asCObjectType*>        objVariableTypes;
+		asCArray<asCScriptFunction*>    funcVariableTypes;
+		asCArray<int>                   objVariablePos;
+
+		// The first variables in above array are allocated on the heap, the rest on the stack.
+		// This variable shows how many are on the heap.
+		asUINT                          objVariablesOnHeap;
+
+		// Holds information on scope for object variables on the stack
+		asCArray<asSObjectVariableInfo> objVariableInfo;
+
+		// The stack needed to execute the function
+		int                             stackNeeded;
+
+		// JIT compiled code of this function
+		asJITFunction                   jitFunction;
+
+		// Holds debug information on explicitly declared variables
+		asCArray<asSScriptVariable*>    variables;
+		// Store position, line number pairs for debug information
+		asCArray<int>                   lineNumbers;
+		// Store the script section where the code was declared
+		int                             scriptSectionIdx;
+		// Store position/index pairs if the bytecode is compiled from multiple script sections
+		asCArray<int>                   sectionIdxs;
+	};
+	ScriptFunctionData          *scriptData;
+
+	// Stub functions and delegates don't own the object and parameters
+	bool                         dontCleanUpOnException;
 
 	// Used by asFUNC_VIRTUAL
 	int                          vfTableIdx;
 
 	// Used by asFUNC_SYSTEM
 	asSSystemFunctionInterface  *sysFuncIntf;
-
-    // JIT compiled code of this function
-    asJITFunction                jitFunction;
 };
 
 const char * const DELEGATE_FACTORY = "%delegate_factory";

+ 3 - 2
Source/ThirdParty/AngelScript/source/as_scriptnode.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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 
@@ -87,7 +87,8 @@ enum eScriptNode
 	snFuncDef,
 	snVirtualProperty,
 	snNamespace,
-	snMixin
+	snMixin,
+	snListPattern
 };
 
 struct sToken

+ 9 - 0
Source/ThirdParty/AngelScript/source/as_scriptobject.cpp

@@ -157,6 +157,12 @@ static void ScriptObject_GetFlag_Generic(asIScriptGeneric *gen)
 	*(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
 }
 
+static void ScriptObject_GetWeakRefFlag_Generic(asIScriptGeneric *gen)
+{
+	asCScriptObject *self = (asCScriptObject*)gen->GetObject();
+	*(asILockableSharedBool**)gen->GetAddressOfReturnLocation() = self->GetWeakRefFlag();
+}
+
 static void ScriptObject_EnumReferences_Generic(asIScriptGeneric *gen)
 {
 	asCScriptObject *self = (asCScriptObject*)gen->GetObject();
@@ -202,6 +208,9 @@ void RegisterScriptObject(asCScriptEngine *engine)
 	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 );

+ 5 - 1
Source/ThirdParty/AngelScript/source/as_scriptobject.h

@@ -125,13 +125,17 @@ public:
 
 	void CallDestructor();
 
+//=============================================
+// Properties
+//=============================================
+public:
 	asCObjectType *objType;
 
 protected:
 	mutable asCAtomic refCount;
 	mutable bool gcFlag;
-	mutable asCLockableSharedBool *weakRefFlag;
 	bool isDestructCalled;
+	mutable asCLockableSharedBool *weakRefFlag;
 	
 	// Urho3D: added userdata
 	void* userData;

+ 8 - 1
Source/ThirdParty/AngelScript/source/as_texts.h

@@ -84,6 +84,7 @@
 #define TXT_EXPECTED_DATA_TYPE            "Expected data type"
 #define TXT_EXPECTED_EXPRESSION_VALUE     "Expected expression value"
 #define TXT_EXPECTED_IDENTIFIER           "Expected identifier"
+#define TXT_EXPECTED_LIST                 "Expected a list enclosed by { } to match pattern"
 #define TXT_EXPECTED_METHOD_OR_PROPERTY   "Expected method or property"
 #define TXT_EXPECTED_ONE_OF               "Expected one of: "
 #define TXT_EXPECTED_OPERATOR             "Expected operator"
@@ -97,7 +98,7 @@
 #define TXT_FAILED_TO_COMPILE_DEF_ARG_d_IN_FUNC_s "Failed while compiling default arg for parameter %d in function '%s'"
 #define TXT_FAILED_TO_CREATE_TEMP_OBJ     "Previous error occurred while attempting to create a temporary copy of object"
 #define TXT_FOUND_MULTIPLE_ENUM_VALUES    "Found multiple matching enum values"
-#define TXT_FUNCTION_ALREADY_EXIST        "A function with the same name and parameters already exist"
+#define TXT_FUNCTION_ALREADY_EXIST        "A function with the same name and parameters already exists"
 #define TXT_FUNCTION_s_NOT_FOUND          "Function '%s' not found"
 
 #define TXT_GET_SET_ACCESSOR_TYPE_MISMATCH_FOR_s "The property '%s' has mismatching types for the get and set accessors"
@@ -169,6 +170,7 @@
 #define TXT_NONTERMINATED_STRING                   "Non-terminated string literal"
 #define TXT_NOT_A_FUNC_s_IS_VAR                    "Expression doesn't form a function call. '%s' is a variable of a non-function type"
 #define TXT_NOT_ALL_PATHS_RETURN                   "Not all paths return a value"
+#define TXT_NOT_ENOUGH_VALUES_FOR_LIST             "Not enough values to match pattern"
 #define TXT_s_NOT_DECLARED                         "'%s' is not declared"
 #define TXT_NOT_EXACT                              "Implicit conversion of value is not exact"
 #define TXT_s_NOT_INITIALIZED                      "'%s' is not initialized."
@@ -219,6 +221,7 @@
 #define TXT_TMPL_s_EXPECTS_d_SUBTYPES          "Template '%s' expects %d sub type(s)"
 #define TXT_TMPL_SUBTYPE_MUST_NOT_BE_READ_ONLY "Template subtype must not be read-only"
 #define TXT_TOO_MANY_JUMP_LABELS               "The function has too many jump labels to handle. Split the function into smaller ones."
+#define TXT_TOO_MANY_VALUES_FOR_LIST           "Too many values to match pattern"
 #define TXT_TYPE_s_NOT_AVAILABLE_FOR_MODULE    "Type '%s' is not available for this module"
 
 #define TXT_UNEXPECTED_END_OF_FILE        "Unexpected end of file"
@@ -230,6 +233,7 @@
 #define TXT_UNUSED_SCRIPT_NODE            "Unused script node"
 
 #define TXT_VALUE_TOO_LARGE_FOR_TYPE      "Value is too large for data type"
+#define TXT_VOID_CANT_BE_OPERAND          "Void cannot be an operand in expressions"
 
 #define TXT_WARNINGS_TREATED_AS_ERROR     "Warnings are treated as errors by the application"
 #define TXT_WHILE_PARSING_ARG_LIST        "While parsing argument list"
@@ -247,6 +251,7 @@
 // Engine message
 
 #define TXT_AUTOHANDLE_CANNOT_BE_USED_FOR_NOCOUNT     "Autohandles cannot be used with types that have been registered with NOCOUNT"
+#define TXT_FIRST_PARAM_MUST_BE_REF_FOR_TEMPLATE_FACTORY "First parameter to template factory must be a reference. This will be used to pass the object type of the template"
 #define TXT_INVALID_CONFIGURATION                     "Invalid configuration. Verify the registered application interface."
 #define TXT_VALUE_TYPE_MUST_HAVE_SIZE                 "A value type must be registered with a non-zero size"
 #define TXT_TYPE_s_IS_MISSING_BEHAVIOURS              "Type '%s' is missing behaviours"
@@ -266,6 +271,8 @@
 #define TXT_OBJECT_TYPE_s_DOESNT_EXIST                "Object type '%s' doesn't exist"
 #define TXT_TEMPLATE_TYPE_s_DOESNT_EXIST              "Template type '%s' doesn't exist"
 #define TXT_TEMPLATE_SUBTYPE_s_DOESNT_EXIST           "Template subtype '%s' doesn't exist"
+#define TXT_TEMPLATE_LIST_FACTORY_EXPECTS_2_REF_PARAMS "Template list factory expects two reference parameters. The last is the pointer to the initialization buffer"
+#define TXT_LIST_FACTORY_EXPECTS_1_REF_PARAM          "List factory expects only one reference parameter. The pointer to the initialization buffer will be passed in this parameter"
 #define TXT_FAILED_READ_SUBTYPE_OF_TEMPLATE_s         "Failed to read subtype of template type '%s'"
 #define TXT_INSTANCING_INVLD_TMPL_TYPE_s_s            "Attempting to instanciate invalid template type '%s<%s>'"
 #define TXT_FAILED_IN_FUNC_s_d                        "Failed in call to function '%s' (Code: %d)"

+ 102 - 99
Source/ThirdParty/AngelScript/source/as_tokendef.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2012 Andreas Jonsson
+   Copyright (c) 2003-2013 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 
@@ -176,112 +176,115 @@ enum eTokenType
 struct sTokenWord
 {
 	const char *word;
+	size_t      wordLength;
 	eTokenType  tokenType;
 };
 
+#define asTokenDef(str, tok) {str, sizeof(str)-1, tok}
+
 sTokenWord const tokenWords[] =
 {
-	{"+"         , ttPlus},
-	{"+="        , ttAddAssign},
-	{"++"        , ttInc},
-	{"-"         , ttMinus},
-	{"-="        , ttSubAssign},
-	{"--"        , ttDec},
-	{"*"         , ttStar},
-	{"*="        , ttMulAssign},
-	{"/"         , ttSlash},
-	{"/="        , ttDivAssign},
-	{"%"         , ttPercent},
-	{"%="        , ttModAssign},
-	{"="         , ttAssignment},
-	{"=="        , ttEqual},
-	{"."         , ttDot},
-	{"|"         , ttBitOr},
-	{"|="        , ttOrAssign},
-	{"||"        , ttOr},
-	{"&"         , ttAmp},
-	{"&="        , ttAndAssign},
-	{"&&"        , ttAnd},
-	{"^"         , ttBitXor},
-	{"^="        , ttXorAssign},
-	{"^^"        , ttXor},
-	{"<"         , ttLessThan},
-	{"<="        , ttLessThanOrEqual},
-	{"<<"        , ttBitShiftLeft},
-	{"<<="       , ttShiftLeftAssign},
-	{">"         , ttGreaterThan},
-	{">="        , ttGreaterThanOrEqual},
-	{">>"        , ttBitShiftRight},
-	{">>="       , ttShiftRightLAssign},
-	{">>>"       , ttBitShiftRightArith},
-	{">>>="      , ttShiftRightAAssign},
-	{"~"         , ttBitNot},
-	{";"         , ttEndStatement},
-	{","         , ttListSeparator},
-	{"{"         , ttStartStatementBlock},
-	{"}"         , ttEndStatementBlock},
-	{"("         , ttOpenParanthesis},
-	{")"         , ttCloseParanthesis},
-	{"["         , ttOpenBracket},
-	{"]"         , ttCloseBracket},
-	{"?"         , ttQuestion},
-	{":"         , ttColon},
-	{"::"        , ttScope},
-	{"!"         , ttNot},
-	{"!="        , ttNotEqual},
-	{"!is"       , ttNotIs},
-	{"@"         , ttHandle},
-	{"and"       , ttAnd},
-	{"bool"      , ttBool},
-	{"break"     , ttBreak},
-	{"case"      , ttCase}, 
-	{"cast"      , ttCast},
-	{"class"     , ttClass},
-	{"const"     , ttConst},
-	{"continue"  , ttContinue},
-	{"default"   , ttDefault},
-	{"do"        , ttDo},
+	asTokenDef("+"         , ttPlus),
+	asTokenDef("+="        , ttAddAssign),
+	asTokenDef("++"        , ttInc),
+	asTokenDef("-"         , ttMinus),
+	asTokenDef("-="        , ttSubAssign),
+	asTokenDef("--"        , ttDec),
+	asTokenDef("*"         , ttStar),
+	asTokenDef("*="        , ttMulAssign),
+	asTokenDef("/"         , ttSlash),
+	asTokenDef("/="        , ttDivAssign),
+	asTokenDef("%"         , ttPercent),
+	asTokenDef("%="        , ttModAssign),
+	asTokenDef("="         , ttAssignment),
+	asTokenDef("=="        , ttEqual),
+	asTokenDef("."         , ttDot),
+	asTokenDef("|"         , ttBitOr),
+	asTokenDef("|="        , ttOrAssign),
+	asTokenDef("||"        , ttOr),
+	asTokenDef("&"         , ttAmp),
+	asTokenDef("&="        , ttAndAssign),
+	asTokenDef("&&"        , ttAnd),
+	asTokenDef("^"         , ttBitXor),
+	asTokenDef("^="        , ttXorAssign),
+	asTokenDef("^^"        , ttXor),
+	asTokenDef("<"         , ttLessThan),
+	asTokenDef("<="        , ttLessThanOrEqual),
+	asTokenDef("<<"        , ttBitShiftLeft),
+	asTokenDef("<<="       , ttShiftLeftAssign),
+	asTokenDef(">"         , ttGreaterThan),
+	asTokenDef(">="        , ttGreaterThanOrEqual),
+	asTokenDef(">>"        , ttBitShiftRight),
+	asTokenDef(">>="       , ttShiftRightLAssign),
+	asTokenDef(">>>"       , ttBitShiftRightArith),
+	asTokenDef(">>>="      , ttShiftRightAAssign),
+	asTokenDef("~"         , ttBitNot),
+	asTokenDef(";"         , ttEndStatement),
+	asTokenDef(","         , ttListSeparator),
+	asTokenDef("{"         , ttStartStatementBlock),
+	asTokenDef("}"         , ttEndStatementBlock),
+	asTokenDef("("         , ttOpenParanthesis),
+	asTokenDef(")"         , ttCloseParanthesis),
+	asTokenDef("["         , ttOpenBracket),
+	asTokenDef("]"         , ttCloseBracket),
+	asTokenDef("?"         , ttQuestion),
+	asTokenDef(":"         , ttColon),
+	asTokenDef("::"        , ttScope),
+	asTokenDef("!"         , ttNot),
+	asTokenDef("!="        , ttNotEqual),
+	asTokenDef("!is"       , ttNotIs),
+	asTokenDef("@"         , ttHandle),
+	asTokenDef("and"       , ttAnd),
+	asTokenDef("bool"      , ttBool),
+	asTokenDef("break"     , ttBreak),
+	asTokenDef("case"      , ttCase), 
+	asTokenDef("cast"      , ttCast),
+	asTokenDef("class"     , ttClass),
+	asTokenDef("const"     , ttConst),
+	asTokenDef("continue"  , ttContinue),
+	asTokenDef("default"   , ttDefault),
+	asTokenDef("do"        , ttDo),
 #ifdef  AS_USE_DOUBLE_AS_FLOAT
-	{"double"    , ttFloat},
+	asTokenDef("double"    , ttFloat),
 #else
-	{"double"    , ttDouble},
+	asTokenDef("double"    , ttDouble),
 #endif
-	{"else"      , ttElse},
-	{"enum"      , ttEnum},
-	{"false"     , ttFalse},
-	{"float"     , ttFloat},
-	{"for"       , ttFor},
-	{"funcdef"   , ttFuncDef},
-	{"if"        , ttIf},
-	{"import"    , ttImport},
-	{"in"        , ttIn},
-	{"inout"     , ttInOut},
-	{"int"       , ttInt},
-	{"int8"      , ttInt8},
-	{"int16"     , ttInt16},
-	{"int32"     , ttInt},  
-	{"int64"     , ttInt64},
-	{"interface" , ttInterface},
-	{"is"        , ttIs},
-	{"mixin"     , ttMixin},
-	{"namespace" , ttNamespace},
-	{"not"       , ttNot},
-	{"null"      , ttNull},
-	{"or"        , ttOr},
-	{"out"       , ttOut},
-	{"private"   , ttPrivate},
-	{"return"    , ttReturn},
-	{"switch"    , ttSwitch},
-	{"true"      , ttTrue},
-	{"typedef"   , ttTypedef},
-	{"uint"      , ttUInt},
-	{"uint8"     , ttUInt8},
-	{"uint16"    , ttUInt16},
-	{"uint32"    , ttUInt},
-	{"uint64"    , ttUInt64},
-	{"void"      , ttVoid},
-	{"while"     , ttWhile},
-	{"xor"       , ttXor},
+	asTokenDef("else"      , ttElse),
+	asTokenDef("enum"      , ttEnum),
+	asTokenDef("false"     , ttFalse),
+	asTokenDef("float"     , ttFloat),
+	asTokenDef("for"       , ttFor),
+	asTokenDef("funcdef"   , ttFuncDef),
+	asTokenDef("if"        , ttIf),
+	asTokenDef("import"    , ttImport),
+	asTokenDef("in"        , ttIn),
+	asTokenDef("inout"     , ttInOut),
+	asTokenDef("int"       , ttInt),
+	asTokenDef("int8"      , ttInt8),
+	asTokenDef("int16"     , ttInt16),
+	asTokenDef("int32"     , ttInt),  
+	asTokenDef("int64"     , ttInt64),
+	asTokenDef("interface" , ttInterface),
+	asTokenDef("is"        , ttIs),
+	asTokenDef("mixin"     , ttMixin),
+	asTokenDef("namespace" , ttNamespace),
+	asTokenDef("not"       , ttNot),
+	asTokenDef("null"      , ttNull),
+	asTokenDef("or"        , ttOr),
+	asTokenDef("out"       , ttOut),
+	asTokenDef("private"   , ttPrivate),
+	asTokenDef("return"    , ttReturn),
+	asTokenDef("switch"    , ttSwitch),
+	asTokenDef("true"      , ttTrue),
+	asTokenDef("typedef"   , ttTypedef),
+	asTokenDef("uint"      , ttUInt),
+	asTokenDef("uint8"     , ttUInt8),
+	asTokenDef("uint16"    , ttUInt16),
+	asTokenDef("uint32"    , ttUInt),
+	asTokenDef("uint64"    , ttUInt64),
+	asTokenDef("void"      , ttVoid),
+	asTokenDef("while"     , ttWhile),
+	asTokenDef("xor"       , ttXor),
 };
 
 const unsigned int numTokenWords = sizeof(tokenWords)/sizeof(sTokenWord);

+ 56 - 58
Source/ThirdParty/AngelScript/source/as_tokenizer.cpp

@@ -50,20 +50,52 @@ BEGIN_AS_NAMESPACE
 asCTokenizer::asCTokenizer()
 {
 	engine = 0;
+	memset(keywordTable, 0, sizeof(keywordTable));
 
-	// Initialize the keyword map
+	// Initialize the jump table
 	for( asUINT n = 0; n < numTokenWords; n++ )
 	{
-		if( (tokenWords[n].word[0] >= 'a' && tokenWords[n].word[0] <= 'z') ||
-			(tokenWords[n].word[0] >= 'A' && tokenWords[n].word[0] <= 'Z') )
-			alphaKeywordMap.Insert(asCStringPointer(tokenWords[n].word, strlen(tokenWords[n].word)), tokenWords[n].tokenType);
-		else
-			nonAlphaKeywordMap.Insert(asCStringPointer(tokenWords[n].word, strlen(tokenWords[n].word)), tokenWords[n].tokenType);
+		const sTokenWord& current = tokenWords[n];
+		unsigned char start = current.word[0];
+
+		// Create new jump table entry if none exists
+		if( !keywordTable[start] )
+		{
+			// Surely there won't ever be more than 32 keywords starting with
+			// the same character. Right?
+			keywordTable[start] = asNEWARRAY(const sTokenWord*, 32);
+			memset(keywordTable[start], 0, sizeof(sTokenWord*)*32);
+		}
+
+		// Add the token sorted from longest to shortest so
+		// we check keywords greedily.
+		const sTokenWord** tok = keywordTable[start];
+		unsigned insert = 0, index = 0;
+		while( tok[index] )
+		{
+			if(tok[index]->wordLength >= current.wordLength)
+				++insert;
+			++index;
+		}
+
+		while( index > insert )
+		{
+			tok[index] = tok[index - 1];
+			--index;
+		}
+
+		tok[insert] = &current;
 	}
 }
 
 asCTokenizer::~asCTokenizer()
 {
+	// Deallocate the jump table
+	for( asUINT n = 0; n < 256; n++ )
+	{
+		if( keywordTable[n] )
+			asDELETEARRAY(keywordTable[n]);
+	}
 }
 
 // static
@@ -383,7 +415,7 @@ bool asCTokenizer::IsIdentifier(const char *source, size_t sourceLength, size_t
 		}
 
 		// Make sure the identifier isn't a reserved keyword
-		if( alphaKeywordMap.MoveTo(0, asCStringPointer(source, tokenLength)) )
+		if( IsKeyWord(source, tokenLength, tokenLength, tokenType) )
 			return false;
 
 		return true;
@@ -394,75 +426,41 @@ bool asCTokenizer::IsIdentifier(const char *source, size_t sourceLength, size_t
 
 bool asCTokenizer::IsKeyWord(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
 {
-	// TODO: optimize: This can probably be optimized further with a specialized algorithm
-	//                 As most keywords are shorter, then we should start from the shortest
-	//                 to the longest. Only for some of the keywords is it necessary to look
-	//                 for a longer part, e.g. ! and !is.
-	//
-	//                 We can use a map that separates the tokens based on the first character.
-	//                 The highest number of possible tokens would then be 11 for the letter 'i'.
-
-	// Choose the best map
-	const asCMap<asCStringPointer,eTokenType> *map;
-	int maxLength;
-
-	// Optimization for large array init-lists
-	// This makes a significant improvement when parsing
-	// very long initialization lists, yet doesn't cause
-	// a noticeable impact in other situations.
-	if (source[0] == ',')
-	{
-		tokenType = ttListSeparator;
-		tokenLength = 1;
-		return true;
-	}
+	unsigned char start = source[0];
+	const sTokenWord **ptr = keywordTable[start];
 
-	if( (source[0] >= 'a' && source[0] <= 'z') ||
-		(source[0] >= 'A' && source[0] <= 'Z') )
-	{
-		map = &alphaKeywordMap;
-		// 'interface' is the longest alpha keyword
-		maxLength = sourceLength > 9 ? 9 : int(sourceLength);
-	}
-	else
-	{
-		map = &nonAlphaKeywordMap;
-		// '>>>=' is the longest non-alpha keyword
-		maxLength = sourceLength > 4 ? 4 : int(sourceLength);
-	}
+	if( !ptr )
+		return false;
 
-	// Find the longest keyword that matches the start of the source string
-	while( maxLength > 0 )
+	for( ; *ptr; ++ptr )
 	{
-		asSMapNode<asCStringPointer, eTokenType> *cursor;
-		if( map->MoveTo(&cursor, asCStringPointer(source, maxLength)) )
+		size_t wlen = (*ptr)->wordLength;
+		if( sourceLength >= wlen && strncmp(source, (*ptr)->word, wlen) == 0 )
 		{
 			// Tokens that end with a character that can be part of an 
 			// identifier require an extra verification to guarantee that 
 			// we don't split an identifier token, e.g. the "!is" token 
 			// and the tokens "!" and "isTrue" in the "!isTrue" expression.
-			if( maxLength < int(sourceLength) &&
-				((source[maxLength-1] >= 'a' && source[maxLength-1] <= 'z') ||
-				 (source[maxLength-1] >= 'A' && source[maxLength-1] <= 'Z')) &&
-				((source[maxLength] >= 'a' && source[maxLength] <= 'z') ||
-				 (source[maxLength] >= 'A' && source[maxLength] <= 'Z') ||
-				 (source[maxLength] >= '0' && source[maxLength] <= '9') ||
-				 (source[maxLength] == '_')) )
+			if( wlen < sourceLength &&
+				((source[wlen-1] >= 'a' && source[wlen-1] <= 'z') ||
+				 (source[wlen-1] >= 'A' && source[wlen-1] <= 'Z')) &&
+				((source[wlen] >= 'a' && source[wlen] <= 'z') ||
+				 (source[wlen] >= 'A' && source[wlen] <= 'Z') ||
+				 (source[wlen] >= '0' && source[wlen] <= '9') ||
+				 (source[wlen] == '_')) )
 			{
 				// The token doesn't really match, even though 
 				// the start of the source matches the token
-				maxLength--;
 				continue;
 			}
 
-			tokenType   = cursor->value;
-			tokenLength = maxLength;
+			tokenType = (*ptr)->tokenType;
+			tokenLength = wlen;
 			return true;
 		}
-		maxLength--;
 	}
 
-	return false;	
+	return false;
 }
 
 END_AS_NAMESPACE

+ 1 - 2
Source/ThirdParty/AngelScript/source/as_tokenizer.h

@@ -70,8 +70,7 @@ protected:
 
 	const asCScriptEngine *engine;
 
-	asCMap<asCStringPointer, eTokenType> alphaKeywordMap;
-	asCMap<asCStringPointer, eTokenType> nonAlphaKeywordMap;
+	const sTokenWord **keywordTable[256];
 };
 
 END_AS_NAMESPACE

+ 40 - 7
Source/ThirdParty/AngelScript/source/as_typeinfo.cpp

@@ -40,6 +40,7 @@
 #ifndef AS_NO_COMPILER
 
 #include "as_typeinfo.h"
+#include "as_scriptengine.h"
 
 BEGIN_AS_NAMESPACE
 
@@ -52,6 +53,7 @@ asCTypeInfo::asCTypeInfo()
 	isExplicitHandle      = false;
 	qwordValue            = 0;
 	isLValue              = false;
+	isVoidExpression      = false;
 }
 
 void asCTypeInfo::Set(const asCDataType &dt)
@@ -65,6 +67,7 @@ void asCTypeInfo::Set(const asCDataType &dt)
 	isExplicitHandle = false;
 	qwordValue       = 0;
 	isLValue         = false;
+	isVoidExpression = false;
 }
 
 void asCTypeInfo::SetVariable(const asCDataType &dt, int stackOffset, bool isTemporary)
@@ -116,27 +119,57 @@ void asCTypeInfo::SetConstantD(const asCDataType &dt, double value)
 	doubleValue = value;
 }
 
+void asCTypeInfo::SetUndefinedFuncHandle(asCScriptEngine *engine)
+{
+	// This is used for when the expression evaluates to a 
+	// function, but it is not yet known exactly which. The
+	// owner expression will hold the name of the function
+	// to determine the exact function when the signature is
+	// known.
+	Set(asCDataType::CreateObjectHandle(&engine->functionBehaviours, true));
+	isConstant       = true;
+	isExplicitHandle = false;
+	qwordValue       = 1; // Set to a different value than 0 to differentiate from null constant
+	isLValue         = false;
+}
+
 void asCTypeInfo::SetNullConstant()
 {
 	Set(asCDataType::CreateNullHandle());
 	isConstant       = true;
-	isExplicitHandle = true;
+	isExplicitHandle = false;
 	qwordValue       = 0;
+	isLValue         = false;
 }
 
-void asCTypeInfo::SetDummy()
+bool asCTypeInfo::IsNullConstant() const
 {
-	SetConstantQW(asCDataType::CreatePrimitive(ttInt, true), 0);
+	// We can't check the actual object type, because the null constant may have been cast to another type
+	if( isConstant && dataType.IsObjectHandle() && qwordValue == 0 )
+		return true;
+
+	return false;
 }
 
-bool asCTypeInfo::IsNullConstant()
+void asCTypeInfo::SetVoidExpression()
 {
-	if( isConstant && dataType.IsObjectHandle() )
-		return true;
+	Set(asCDataType::CreatePrimitive(ttVoid, false));
+	isLValue = false;
+	isConstant = false;
+	isVoidExpression = true;
+}
 
-	return false;
+bool asCTypeInfo::IsVoidExpression() const
+{
+	return isVoidExpression;
 }
 
+void asCTypeInfo::SetDummy()
+{
+	SetConstantQW(asCDataType::CreatePrimitive(ttInt, true), 0);
+}
+
+
 END_AS_NAMESPACE
 
 #endif // AS_NO_COMPILER

+ 6 - 2
Source/ThirdParty/AngelScript/source/as_typeinfo.h

@@ -60,9 +60,12 @@ struct asCTypeInfo
 	void SetConstantF(const asCDataType &dataType, float value);
 	void SetConstantD(const asCDataType &dataType, double value);
 	void SetNullConstant();
+	void SetUndefinedFuncHandle(asCScriptEngine *engine);
+	void SetVoidExpression();
 	void SetDummy();
 
-	bool IsNullConstant();
+	bool IsNullConstant() const;
+	bool IsVoidExpression() const;
 
 	asCDataType dataType;
 	bool  isLValue         :  1; // Can this value be updated in assignment, or increment operators, etc
@@ -70,7 +73,8 @@ struct asCTypeInfo
 	bool  isConstant       :  1;
 	bool  isVariable       :  1;
 	bool  isExplicitHandle :  1;
-	short dummy            : 11;
+	bool  isVoidExpression :  1;
+	short dummy            : 10;
 	short stackOffset;
 	union
 	{

Some files were not shown because too many files changed in this diff