Browse Source

Обновил AngelScript до 2.36.1 WIP

1vanK 3 years ago
parent
commit
724506fe48

+ 2 - 2
Source/ThirdParty/AngelScript/Urho3DNotes.txt

@@ -1,3 +1,3 @@
 URL: https://github.com/codecat/angelscript-mirror
-Date: 14.10.2021
-Latest commit: https://github.com/codecat/angelscript-mirror/commit/522a5fe8efbb8b4f964801e5515eafd8c018d46c
+Дата обновления: 28.11.2022
+Последний коммит: https://github.com/codecat/angelscript-mirror/commit/f3f6b6753b4f74f4567c1e8db0e2a6b3ac96bbdb

+ 34 - 12
Source/ThirdParty/AngelScript/include/angelscript.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -64,8 +64,8 @@ BEGIN_AS_NAMESPACE
 
 // AngelScript version
 
-#define ANGELSCRIPT_VERSION        23501
-#define ANGELSCRIPT_VERSION_STRING "2.35.1"
+#define ANGELSCRIPT_VERSION        23601
+#define ANGELSCRIPT_VERSION_STRING "2.36.1 WIP"
 
 // Data types
 
@@ -152,6 +152,8 @@ enum asEEngineProp
 	asEP_INIT_STACK_SIZE                    = 29,
 	asEP_INIT_CALL_STACK_SIZE               = 30,
 	asEP_MAX_CALL_STACK_SIZE                = 31,
+	asEP_IGNORE_DUPLICATE_SHARED_INTF       = 32,
+	asEP_NO_DEBUG_OUTPUT                    = 33,
 
 	asEP_LAST_PROPERTY
 };
@@ -257,14 +259,15 @@ enum asEBehaviours
 // Context states
 enum asEContextState
 {
-	asEXECUTION_FINISHED      = 0,
-	asEXECUTION_SUSPENDED     = 1,
-	asEXECUTION_ABORTED       = 2,
-	asEXECUTION_EXCEPTION     = 3,
-	asEXECUTION_PREPARED      = 4,
-	asEXECUTION_UNINITIALIZED = 5,
-	asEXECUTION_ACTIVE        = 6,
-	asEXECUTION_ERROR         = 7
+	asEXECUTION_FINISHED        = 0,
+	asEXECUTION_SUSPENDED       = 1,
+	asEXECUTION_ABORTED         = 2,
+	asEXECUTION_EXCEPTION       = 3,
+	asEXECUTION_PREPARED        = 4,
+	asEXECUTION_UNINITIALIZED   = 5,
+	asEXECUTION_ACTIVE          = 6,
+	asEXECUTION_ERROR           = 7,
+	asEXECUTION_DESERIALIZATION = 8
 };
 
 // Message types
@@ -365,6 +368,7 @@ enum asEFuncType
 //
 typedef signed char    asINT8;
 typedef signed short   asINT16;
+typedef signed int     asINT32;
 typedef unsigned char  asBYTE;
 typedef unsigned short asWORD;
 typedef unsigned int   asUINT;
@@ -955,10 +959,17 @@ public:
 	virtual asIScriptFunction *GetFunction(asUINT stackLevel = 0) = 0;
 	virtual int                GetLineNumber(asUINT stackLevel = 0, int *column = 0, const char **sectionName = 0) = 0;
 	virtual int                GetVarCount(asUINT stackLevel = 0) = 0;
+	virtual int                GetVar(asUINT varIndex, asUINT stackLevel, const char** name, int* typeId = 0, asETypeModifiers* typeModifiers = 0, bool* isVarOnHeap = 0, int* stackOffset = 0) = 0;
+#ifdef AS_DEPRECATED
+	// deprecated since 2022-05-04, 2.36.0
 	virtual const char        *GetVarName(asUINT varIndex, asUINT stackLevel = 0) = 0;
+#endif
 	virtual const char        *GetVarDeclaration(asUINT varIndex, asUINT stackLevel = 0, bool includeNamespace = false) = 0;
+#ifdef AS_DEPRECATED
+	// deprecated since 2022-05-04, 2.36.0
 	virtual int                GetVarTypeId(asUINT varIndex, asUINT stackLevel = 0) = 0;
-	virtual void              *GetAddressOfVar(asUINT varIndex, asUINT stackLevel = 0) = 0;
+#endif
+	virtual void              *GetAddressOfVar(asUINT varIndex, asUINT stackLevel = 0, bool dontDereference = false, bool returnAddressOfUnitializedObjects = false) = 0;
 	virtual bool               IsVarInScope(asUINT varIndex, asUINT stackLevel = 0) = 0;
 	virtual int                GetThisTypeId(asUINT stackLevel = 0) = 0;
 	virtual void              *GetThisPointer(asUINT stackLevel = 0) = 0;
@@ -968,6 +979,17 @@ public:
 	virtual void *SetUserData(void *data, asPWORD type = 0) = 0;
 	virtual void *GetUserData(asPWORD type = 0) const = 0;
 
+	// Serialization
+	virtual int StartDeserialization() = 0;
+	virtual int FinishDeserialization() = 0;
+	virtual int PushFunction(asIScriptFunction *func, void *object) = 0;
+	virtual int GetStateRegisters(asUINT stackLevel, asIScriptFunction **callingSystemFunction, asIScriptFunction **initialFunction, asDWORD *origStackPointer, asDWORD *argumentsSize, asQWORD *valueRegister, void **objectRegister, asITypeInfo **objectTypeRegister) = 0;
+	virtual int GetCallStateRegisters(asUINT stackLevel, asDWORD *stackFramePointer, asIScriptFunction **currentFunction, asDWORD *programPointer, asDWORD *stackPointer, asDWORD *stackIndex) = 0;
+	virtual int SetStateRegisters(asUINT stackLevel, asIScriptFunction *callingSystemFunction, asIScriptFunction *initialFunction, asDWORD origStackPointer, asDWORD argumentsSize, asQWORD valueRegister, void *objectRegister, asITypeInfo *objectTypeRegister) = 0;
+	virtual int SetCallStateRegisters(asUINT stackLevel, asDWORD stackFramePointer, asIScriptFunction *currentFunction, asDWORD programPointer, asDWORD stackPointer, asDWORD stackIndex) = 0;
+	virtual int GetArgsOnStackCount(asUINT stackLevel) = 0;
+	virtual int GetArgOnStack(asUINT stackLevel, asUINT arg, int* typeId, asUINT *flags, void** address) = 0;
+
 protected:
 	virtual ~asIScriptContext() {}
 };

+ 36 - 29
Source/ThirdParty/AngelScript/source/as_builder.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -572,7 +572,7 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
 	// Tell the engine that the function exists already so the compiler can access it
 	if( compileFlags & asCOMP_ADD_TO_MODULE )
 	{
-		r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->m_defaultNamespace, false, false);
+		r = CheckNameConflict(func->name.AddressOf(), node, scripts[0], module->m_defaultNamespace, false, false, false);
 		if( r < 0 )
 		{
 			func->ReleaseInternal();
@@ -1076,7 +1076,7 @@ int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &nam
 	}
 	else
 	{
-		if( CheckNameConflict(name.AddressOf(), nameNode, &source, ns, true, false) < 0 )
+		if( CheckNameConflict(name.AddressOf(), nameNode, &source, ns, true, false, false) < 0 )
 			return asNAME_TAKEN;
 	}
 
@@ -1507,14 +1507,14 @@ int asCBuilder::CheckNameConflictMember(asCTypeInfo *t, const char *name, asCScr
 	if (ns)
 	{
 		// Check as if not a function as it doesn't matter the function signature
-		return CheckNameConflict(name, node, code, ns, true, isVirtualProperty);
+		return CheckNameConflict(name, node, code, ns, true, isVirtualProperty, false);
 	}
 	
 	return 0;
 }
 
 // TODO: This should use SymbolLookup
-int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns, bool isProperty, bool isVirtualProperty)
+int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns, bool isProperty, bool isVirtualProperty, bool isSharedIntf)
 {
 	// Check against registered object types
 	if( engine->GetRegisteredType(name, ns) != 0 )
@@ -1610,18 +1610,22 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri
 		if (interfaceDeclarations[n]->name == name &&
 			interfaceDeclarations[n]->typeInfo->nameSpace == ns)
 		{
-			if (code)
+			// Don't report an error if the application wants to ignore duplicate declarations of shared interfaces
+			if (!(isSharedIntf && engine->ep.ignoreDuplicateSharedIntf))
 			{
-				asCString str;
-				if (ns->name != "")
-					str = ns->name + "::" + name;
-				else
-					str = name;
-				str.Format(TXT_NAME_CONFLICT_s_INTF, str.AddressOf());
-				WriteError(str, code, node);
-			}
+				if (code)
+				{
+					asCString str;
+					if (ns->name != "")
+						str = ns->name + "::" + name;
+					else
+						str = name;
+					str.Format(TXT_NAME_CONFLICT_s_INTF, str.AddressOf());
+					WriteError(str, code, node);
+				}
 
-			return -1;
+				return -1;
+			}
 		}
 	}
 
@@ -1759,6 +1763,8 @@ int asCBuilder::CheckNameConflict(const char *name, asCScriptNode *node, asCScri
 			}
 		}
 	}
+#else
+	UNUSED_VAR(isSharedIntf);
 #endif
 
 	return 0;
@@ -1852,7 +1858,7 @@ int asCBuilder::ValidateVirtualProperty(asCScriptFunction *func)
 	if( func->objectType )
 		r = CheckNameConflictMember(func->objectType, func->name.SubString(4).AddressOf(), 0, 0, true, true);
 	else
-		r = CheckNameConflict(func->name.SubString(4).AddressOf(), 0, 0, func->nameSpace, true, true);
+		r = CheckNameConflict(func->name.SubString(4).AddressOf(), 0, 0, func->nameSpace, true, true, false);
 	if( r < 0 )
 		return -5;
 	
@@ -1891,7 +1897,7 @@ int asCBuilder::RegisterFuncDef(asCScriptNode *node, asCScriptCode *file, asSNam
 	// Check for name conflict with other types
 	if (ns)
 	{
-		int r = CheckNameConflict(name.AddressOf(), node, file, ns, true, false);
+		int r = CheckNameConflict(name.AddressOf(), node, file, ns, true, false, false);
 		if (asSUCCESS != r)
 		{
 			node->Destroy(engine);
@@ -1990,6 +1996,7 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 
 			if( fdt2->name == fdt->name &&
 				fdt2->nameSpace == fdt->nameSpace &&
+				fdt2->parentClass == fdt->parentClass &&
 				fdt2->funcdef->IsSignatureExceptNameEqual(func) )
 			{
 				// Replace our funcdef for the existing one
@@ -2048,7 +2055,7 @@ int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file, asSN
 	{
 		// Verify that the name isn't taken
 		asCString name(&file->code[n->tokenPos], n->tokenLength);
-		CheckNameConflict(name.AddressOf(), n, file, ns, true, false);
+		CheckNameConflict(name.AddressOf(), n, file, ns, true, false, false);
 
 		// Register the global variable
 		sGlobalVariableDescription *gvar = asNEW(sGlobalVariableDescription);
@@ -2127,7 +2134,7 @@ int asCBuilder::RegisterMixinClass(asCScriptNode *node, asCScriptCode *file, asS
 	int r, c;
 	file->ConvertPosToRowCol(n->tokenPos, &r, &c);
 
-	CheckNameConflict(name.AddressOf(), n, file, ns, true, false);
+	CheckNameConflict(name.AddressOf(), n, file, ns, true, false, false);
 
 	sMixinClass *decl = asNEW(sMixinClass);
 	if( decl == 0 )
@@ -2237,7 +2244,7 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file, asSNameS
 	int r, c;
 	file->ConvertPosToRowCol(n->tokenPos, &r, &c);
 
-	CheckNameConflict(name.AddressOf(), n, file, ns, true, false);
+	CheckNameConflict(name.AddressOf(), n, file, ns, true, false, false);
 
 	sClassDeclaration *decl = asNEW(sClassDeclaration);
 	if( decl == 0 )
@@ -2408,7 +2415,7 @@ int asCBuilder::RegisterInterface(asCScriptNode *node, asCScriptCode *file, asSN
 
 	asCString name;
 	name.Assign(&file->code[n->tokenPos], n->tokenLength);
-	CheckNameConflict(name.AddressOf(), n, file, ns, true, false);
+	CheckNameConflict(name.AddressOf(), n, file, ns, true, false, isShared);
 
 	sClassDeclaration *decl = asNEW(sClassDeclaration);
 	if( decl == 0 )
@@ -3725,7 +3732,7 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 	//                         allow incremental builds, i.e. allow application to add or replace classes in an
 	//                         existing module. However, the applications that want to use that should use a special
 	//                         build flag to not finalize the module.
-    
+
     // Urho3D: disable garbage collection from script classes
     /*
 
@@ -3914,9 +3921,9 @@ void asCBuilder::CompileClasses(asUINT numTempl)
 		// Reset the counter
 		numReevaluations = 0;
 	}
-    
-    // Urho3D: end
-    */
+
+// Urho3D: end
+*/
 }
 
 void asCBuilder::IncludeMethodsFromMixins(sClassDeclaration *decl)
@@ -4354,7 +4361,7 @@ int asCBuilder::RegisterEnum(asCScriptNode *node, asCScriptCode *file, asSNameSp
 		module->m_externalTypes.PushLast(existingSharedType);
 
 	// Check the name and add the enum
-	int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns, true, false);
+	int r = CheckNameConflict(name.AddressOf(), tmp->firstChild, file, ns, true, false, false);
 	if( asSUCCESS == r )
 	{
 		asCEnumType *st;
@@ -4524,7 +4531,7 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file, asSNam
 	name.Assign(&file->code[tmp->tokenPos], tmp->tokenLength);
 
 	// If the name is not already in use add it
- 	int r = CheckNameConflict(name.AddressOf(), tmp, file, ns, true, false);
+ 	int r = CheckNameConflict(name.AddressOf(), tmp, file, ns, true, false, false);
 
 	asCTypedefType *st = 0;
 	if( asSUCCESS == r )
@@ -4892,7 +4899,7 @@ int asCBuilder::RegisterScriptFunction(asCScriptNode *node, asCScriptCode *file,
 				WriteError(TXT_METHOD_CANT_HAVE_NAME_OF_CLASS, file, node);
 		}
 		else
-			CheckNameConflict(name.AddressOf(), node, file, ns, false, false);
+			CheckNameConflict(name.AddressOf(), node, file, ns, false, false, false);
 	}
 	else
 	{
@@ -5414,7 +5421,7 @@ int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCS
 		ns = engine->nameSpaces[0];
 
 	GetParsedFunctionDetails(node->firstChild, file, 0, name, returnType, parameterNames, parameterTypes, inOutFlags, defaultArgs, funcTraits, ns);
-	CheckNameConflict(name.AddressOf(), node, file, ns, false, false);
+	CheckNameConflict(name.AddressOf(), node, file, ns, false, false, false);
 
 	// Check that the same function hasn't been registered already in the namespace
 	asCArray<int> funcs;

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

@@ -142,7 +142,7 @@ public:
 	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, asCScriptNode **outListPattern = 0, asCObjectType **outParentClass = 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, bool isProperty, bool isVirtualProperty);
+	int CheckNameConflict(const char *name, asCScriptNode *node, asCScriptCode *code, asSNameSpace *ns, bool isProperty, bool isVirtualProperty, bool isSharedIntf);
 	int CheckNameConflictMember(asCTypeInfo *type, const char *name, asCScriptNode *node, asCScriptCode *code, bool isProperty, bool isVirtualProperty);
 	int ValidateVirtualProperty(asCScriptFunction *func);
 

+ 5 - 49
Source/ThirdParty/AngelScript/source/as_bytecode.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2019 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -2136,6 +2136,9 @@ void asCByteCode::PostProcess()
 #ifdef AS_DEBUG
 void asCByteCode::DebugOutput(const char *name, asCScriptFunction *func)
 {
+	if (engine->ep.noDebugOutput)
+		return;
+
 #ifndef __MINGW32__
 	// _mkdir is broken on mingw
 	_mkdir("AS_DEBUG");
@@ -2181,59 +2184,12 @@ void asCByteCode::DebugOutput(const char *name, asCScriptFunction *func)
 	fprintf(file, "Variables: \n");
 	for( n = 0; n < func->scriptData->variables.GetLength(); n++ )
 	{
-		int idx = func->scriptData->objVariablePos.IndexOf(func->scriptData->variables[n]->stackOffset);
-		bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
+		bool isOnHeap = func->scriptData->variables[n]->onHeap;
 		fprintf(file, " %.3d: %s%s %s\n", func->scriptData->variables[n]->stackOffset, isOnHeap ? "(heap) " : "", func->scriptData->variables[n]->type.Format(func->nameSpace, true).AddressOf(), func->scriptData->variables[n]->name.AddressOf());
 	}
-	asUINT offset = 0;
 	if( func->objectType )
-	{
 		fprintf(file, " %.3d: %s this\n", 0, func->objectType->name.AddressOf());
-		offset -= AS_PTR_SIZE;
-	}
-	for( n = 0; n < func->parameterTypes.GetLength(); n++ )
-	{
-		bool found = false;
-		for( asUINT v = 0; v < func->scriptData->variables.GetLength(); v++ )
-		{
-			if( func->scriptData->variables[v]->stackOffset == (int)offset )
-			{
-				found = true;
-				break;
-			}
-		}
-		if( !found )
-		{
-			int idx = func->scriptData->objVariablePos.IndexOf(offset);
-			bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
-			fprintf(file, " %.3d: %s%s {noname param}\n", offset, isOnHeap ? "(heap) " : "", func->parameterTypes[n].Format(func->nameSpace, true).AddressOf());
-		}
 
-		offset -= func->parameterTypes[n].GetSizeOnStackDWords();
-	}
-	for( n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ )
-	{
-		bool found = false;
-		for( asUINT v = 0; v < func->scriptData->variables.GetLength(); v++ )
-		{
-			if( func->scriptData->variables[v]->stackOffset == func->scriptData->objVariablePos[n] )
-			{
-				found = true;
-				break;
-			}
-		}
-		if( !found )
-		{
-			if( func->scriptData->objVariableTypes[n] )
-			{
-				int idx = func->scriptData->objVariablePos.IndexOf(func->scriptData->objVariablePos[n]);
-				bool isOnHeap = asUINT(idx) < func->scriptData->objVariablesOnHeap ? true : false;
-				fprintf(file, " %.3d: %s%s {noname}\n", func->scriptData->objVariablePos[n], isOnHeap ? "(heap) " : "", func->scriptData->objVariableTypes[n]->name.AddressOf());
-			}
-			else
-				fprintf(file, " %.3d: null handle {noname}\n", func->scriptData->objVariablePos[n]);
-		}
-	}
 	fprintf(file, "\n\n");
 
 	bool invalidStackSize = false;

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

@@ -108,7 +108,7 @@ static inline bool IsRegisterHFA(const asCDataType &type)
 {
 	const asCTypeInfo *const typeInfo = type.GetTypeInfo();
 
-	if( typeInfo == nullptr ||
+	if( typeInfo == 0 ||
 		(typeInfo->flags & asOBJ_APP_CLASS_ALLFLOATS) == 0 ||
 		type.IsObjectHandle() || type.IsReference() )
 		return false;

+ 3 - 1
Source/ThirdParty/AngelScript/source/as_callfunc_arm64_gcc.S

@@ -1,6 +1,6 @@
 //
 //  AngelCode Scripting Library
-//  Copyright (c) 2020-2021 Andreas Jonsson
+//  Copyright (c) 2020-2022 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
@@ -50,6 +50,7 @@
 .global CallARM64Float
 .global CallARM64
 
+#if !defined(__MACH__)
 .type GetHFAReturnDouble, %function
 .type GetHFAReturnFloat, %function
 .type CallARM64Ret128, %function
@@ -57,6 +58,7 @@
 .type CallARM64Double, %function
 .type CallARM64Float, %function
 .type CallARM64, %function
+#endif /* __MACH__ */
 
 .align  2
 GetHFAReturnDouble:

+ 215 - 0
Source/ThirdParty/AngelScript/source/as_callfunc_arm64_xcode.S

@@ -0,0 +1,215 @@
+//
+//  AngelCode Scripting Library
+//  Copyright (c) 2020-2022 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 ARM64/AArch64 call convention used for Linux
+// Written by Max Waine in July 2020, based on as_callfunc_arm_msvc.asm,
+// with assistance & guidance provided by Sir Kane
+
+// Compile with GCC/GAS
+
+#if !defined(AS_MAX_PORTABILITY)
+
+#if defined(__aarch64__)
+
+.align 2
+.global _GetHFAReturnDouble
+.global _GetHFAReturnFloat
+.global _CallARM64Ret128
+.global _CallARM64RetInMemory
+.global _CallARM64Double
+.global _CallARM64Float
+.global _CallARM64
+
+_GetHFAReturnDouble:
+    adr     x9, populateDoubles
+    sub     x9, x9, x1, lsr 1 // x9 -= returnSize >> 1; (/2 because double is 2x instruction size)
+    br      x9
+
+    str     d3, [x0, #0x18]
+    str     d2, [x0, #0x10]
+    str     d1, [x1]
+    str     d0, [x0]
+populateDoubles:
+
+    ret
+
+_GetHFAReturnFloat:
+    adr     x9, populateFloats
+    sub     x9, x9, x2 // x9 -= returnSize; (already 4 bytes per return)
+    br      x9
+
+    str     s3, [x1, #0x4]
+    str     s2, [x1]
+    str     s1, [x0, #0x4]
+    str     s0, [x0]
+populateFloats:
+
+    ret
+
+
+//[returnType] _CallARM64[type](
+//    const asQWORD *gpRegArgs,    asQWORD numGPRegArgs,
+//    const asQWORD *floatRegArgs, asQWORD numFloatRegArgs,
+//    const asQWORD *stackArgs,    asQWORD numStackArgs,
+//    asFUNCTION_t func
+//)
+_CallARM64Double:
+_CallARM64Float:
+_CallARM64:
+    .cfi_startproc
+    stp     fp, lr, [sp,#-0x20]!
+    str     x20, [sp,#0x10]
+    .cfi_def_cfa_offset 0x20
+    .cfi_offset 20,  0x10
+    .cfi_offset fp, -0x20
+    .cfi_offset lr, -0x18
+    mov     fp, sp
+
+    mov     x20, #0
+
+    cbz     x5, stackArgsLoopEnd
+
+    // Align count to 2, then multiply by 8, resulting in a size aligned to 16
+    add x20, x5,  #1
+    lsl x20, x20, #3
+    and x20, x20, #-0x10
+    // Multiply count by 8
+    lsl x10, x5, #3
+    sub sp, sp, x20
+stackArgsLoopStart:
+    ldp     x9,x11, [x4],#16
+    stp     x9,x11, [sp],#16
+    subs    x10, x10, #16
+    bgt     stackArgsLoopStart
+stackArgsLoopEnd:
+
+    // Calculate amount to jump forward, avoiding pointless instructions
+    adr     x9, populateFloatRegisterArgsEnd
+    sub     x9, x9, x3, lsl 2 // x9 -= numFloatRegArgs * 4
+    br      x9
+
+    ldr     d7, [x2, #0x38]
+    ldr     d6, [x2, #0x30]
+    ldr     d5, [x2, #0x28]
+    ldr     d4, [x2, #0x20]
+    ldr     d3, [x2, #0x18]
+    ldr     d2, [x2, #0x10]
+    ldr     d1, [x2, #0x08]
+    ldr     d0, [x2]
+populateFloatRegisterArgsEnd:
+
+    mov     x15, x6
+    // Calculate amount to jump forward, avoiding pointless instructions
+    adr     x9, populateGPRegisterArgsEnd
+    sub     x9, x9, x1, lsl 2 // x9 -= numGPRegArgs * 4
+    br      x9
+
+    ldr     x7, [x0, #0x38]
+    ldr     x6, [x0, #0x30]
+    ldr     x5, [x0, #0x28]
+    ldr     x4, [x0, #0x20]
+    ldr     x3, [x0, #0x18]
+    ldr     x2, [x0, #0x10]
+    ldr     x1, [x0, #0x08]
+    ldr     x0, [x0]
+populateGPRegisterArgsEnd:
+
+    // Actually call function
+    sub     sp, sp, x20
+    blr     x15
+    add     sp, sp, x20
+
+    ldr     x20, [sp,#0x10]
+    ldp     fp, lr, [sp],#0x20
+
+    .cfi_restore lr
+	.cfi_restore fp
+    .cfi_restore 20
+	.cfi_def_cfa_offset 0
+    ret
+    .cfi_endproc
+
+.align  2
+_CallARM64Ret128:
+    .cfi_startproc
+    stp     fp, lr, [sp,#-0x20]!
+    str     x20, [sp,#0x10]
+    .cfi_def_cfa_offset 0x20
+    .cfi_offset 20,  0x10
+    .cfi_offset fp, -0x20
+    .cfi_offset lr, -0x18
+    mov     fp, sp
+
+    mov     x20, x6
+    mov     x6, x7
+    mov     x7, #0
+    bl      _CallARM64
+
+    str     x1, [x20]
+
+    ldr     x20, [sp,#0x10]
+    ldp     fp, lr, [sp],#0x20
+
+    .cfi_restore lr
+	.cfi_restore fp
+    .cfi_restore 20
+	.cfi_def_cfa_offset 0
+    ret
+    .cfi_endproc
+
+.align  2
+_CallARM64RetInMemory:
+    .cfi_startproc
+    stp     fp, lr, [sp,#-0x10]!
+    mov     fp, sp
+    .cfi_def_cfa_offset 0x10
+    .cfi_offset fp, -0x10
+    .cfi_offset lr, -0x08
+
+    mov     x8, x6
+    mov     x6, x7
+    mov     x7, #0
+    bl      _CallARM64
+
+    mov     x0, x8
+
+    ldp     fp, lr, [sp],#0x10
+
+    .cfi_restore lr
+	.cfi_restore fp
+	.cfi_def_cfa_offset 0
+    ret
+    .cfi_endproc
+
+#endif /* __aarch64__ */
+
+#endif /* !AS_MAX_PORTABILITY */
+

File diff suppressed because it is too large
+ 223 - 163
Source/ThirdParty/AngelScript/source/as_compiler.cpp


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

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2020 Andreas Jonsson
+   Copyright (c) 2003-2022 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 
@@ -102,7 +102,7 @@ struct asCExprValue
 	bool  isRefToLocal : 1; // The reference may be to a local variable
 	bool  isRefSafe : 1; // the life-time of the ref is guaranteed for the duration of the access
 	short dummy : 9;
-	short stackOffset;
+	int   stackOffset; // used both for stack offset and indexing global variables
 
 private:
 	// These values must not be accessed directly in order to avoid problems with endianess. 
@@ -198,17 +198,20 @@ enum EImplicitConv
 
 enum EConvCost
 {
-	asCC_NO_CONV               = 0,
-	asCC_CONST_CONV            = 1,
-	asCC_ENUM_SAME_SIZE_CONV   = 2,
-	asCC_ENUM_DIFF_SIZE_CONV   = 3,
-	asCC_PRIMITIVE_SIZE_CONV   = 4,
-	asCC_SIGNED_CONV           = 5,
-	asCC_INT_FLOAT_CONV        = 6,
-	asCC_REF_CONV              = 7,
-	asCC_OBJ_TO_PRIMITIVE_CONV = 8,
-	asCC_TO_OBJECT_CONV        = 9,
-	asCC_VARIABLE_CONV         = 10
+	asCC_NO_CONV                  = 0,
+	asCC_CONST_CONV               = 1,
+	asCC_ENUM_SAME_SIZE_CONV      = 2,
+	asCC_ENUM_DIFF_SIZE_CONV      = 3,
+	asCC_PRIMITIVE_SIZE_UP_CONV   = 4,
+	asCC_PRIMITIVE_SIZE_DOWN_CONV = 5,
+	asCC_SIGNED_TO_UNSIGNED_CONV  = 5,
+	asCC_UNSIGNED_TO_SIGNED_CONV  = 6,
+	asCC_INT_TO_FLOAT_CONV        = 7,
+	asCC_FLOAT_TO_INT_CONV        = 8,
+	asCC_REF_CONV                 = 9,
+	asCC_OBJ_TO_PRIMITIVE_CONV    = 10,
+	asCC_TO_OBJECT_CONV           = 11,
+	asCC_VARIABLE_CONV            = 12
 };
 
 class asCCompiler
@@ -233,7 +236,7 @@ protected:
 	void CompileStatement(asCScriptNode *statement, bool *hasReturn, asCByteCode *bc);
 	void CompileIfStatement(asCScriptNode *node, bool *hasReturn, asCByteCode *bc);
 	void CompileSwitchStatement(asCScriptNode *node, bool *hasReturn, asCByteCode *bc);
-	void CompileCase(asCScriptNode *node, asCByteCode *bc);
+	void CompileCase(asCScriptNode *node, asCByteCode *bc, bool *hasReturn, bool *hasBreak);
 	void CompileForStatement(asCScriptNode *node, asCByteCode *bc);
 	void CompileWhileStatement(asCScriptNode *node, asCByteCode *bc);
 	void CompileDoWhileStatement(asCScriptNode *node, asCByteCode *bc);
@@ -269,7 +272,7 @@ protected:
 	int  CompileAnonymousInitList(asCScriptNode *listNode, asCExprContext *ctx, const asCDataType &dt);
 
 	int  CallDefaultConstructor(const 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, asCExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false);
+	int  CallCopyConstructor(asCDataType &type, int offset, bool isObjectOnHeap, asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node, bool isGlobalVar = false, bool derefDestination = false);
 	void CallDestructor(asCDataType &type, int offset, bool isObjectOnHeap, asCByteCode *bc);
 	int  CompileArgumentList(asCScriptNode *node, asCArray<asCExprContext *> &args, asCArray<asSNamedArgument> &namedArgs);
 	int  CompileDefaultAndNamedArgs(asCScriptNode *node, asCArray<asCExprContext*> &args, int funcId, asCObjectType *type, asCArray<asSNamedArgument> *namedArgs = 0);
@@ -278,7 +281,7 @@ protected:
 	void CompileMemberInitialization(asCByteCode *bc, bool onlyDefaults);
 	bool CompileAutoType(asCDataType &autoType, asCExprContext &compiledCtx, asCScriptNode *exprNode, asCScriptNode *errNode);
 	bool CompileInitialization(asCScriptNode *node, asCByteCode *bc, const asCDataType &type, asCScriptNode *errNode, int offset, asQWORD *constantValue, int isVarGlobOrMem, asCExprContext *preCompiled = 0);
-	void CompileInitAsCopy(asCDataType &type, int offset, asCByteCode *bc, asCExprContext *arg, asCScriptNode *node, bool derefDestination);
+	void CompileInitAsCopy(asCDataType &type, int offset, asCExprContext *ctx, asCExprContext *arg, asCScriptNode *node, bool derefDestination);
 
 	// Helper functions
 	void ConvertToPostFix(asCScriptNode *expr, asCArray<asCScriptNode *> &postfix);

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

@@ -1334,7 +1334,6 @@
 	#define AS_NO_THREADS
 #endif
 
-
 // The assert macro
 
 // Urho3D: commented out original

File diff suppressed because it is too large
+ 528 - 161
Source/ThirdParty/AngelScript/source/as_context.cpp


+ 30 - 2
Source/ThirdParty/AngelScript/source/as_context.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2018 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -114,10 +114,15 @@ public:
 	asIScriptFunction *GetFunction(asUINT stackLevel);
 	int                GetLineNumber(asUINT stackLevel, int *column, const char **sectionName);
 	int                GetVarCount(asUINT stackLevel);
+	int                GetVar(asUINT varIndex, asUINT stackLevel, const char** name, int* typeId, asETypeModifiers* typeModifiers, bool* isVarOnHeap, int* stackOffset);
+#ifdef AS_DEPRECATED
 	const char        *GetVarName(asUINT varIndex, asUINT stackLevel);
+#endif
 	const char        *GetVarDeclaration(asUINT varIndex, asUINT stackLevel, bool includeNamespace);
+#ifdef AS_DEPRECATED
 	int                GetVarTypeId(asUINT varIndex, asUINT stackLevel);
-	void              *GetAddressOfVar(asUINT varIndex, asUINT stackLevel);
+#endif
+	void              *GetAddressOfVar(asUINT varIndex, asUINT stackLevel, bool dontDereference, bool returnAddressOfUnitializedObjects);
 	bool               IsVarInScope(asUINT varIndex, asUINT stackLevel);
 	int                GetThisTypeId(asUINT stackLevel);
     void              *GetThisPointer(asUINT stackLevel);
@@ -127,10 +132,23 @@ public:
 	void *SetUserData(void *data, asPWORD type);
 	void *GetUserData(asPWORD type) const;
 
+	// Serialization
+	int StartDeserialization();
+	int FinishDeserialization();
+	int PushFunction(asIScriptFunction *func, void *obj);
+	int GetStateRegisters(asUINT stackLevel, asIScriptFunction** callingSystemFunction, asIScriptFunction** initialFunction, asDWORD* origStackPointer, asDWORD* argumentsSize, asQWORD* valueRegister, void** objectRegister, asITypeInfo** objectTypeRegister);
+	int GetCallStateRegisters(asUINT stackLevel, asDWORD* stackFramePointer, asIScriptFunction** currentFunction, asDWORD* programPointer, asDWORD* stackPointer, asDWORD* stackIndex);
+	int SetStateRegisters(asUINT stackLevel, asIScriptFunction* callingSystemFunction, asIScriptFunction* initialFunction, asDWORD origStackPointer, asDWORD argumentsSize, asQWORD valueRegister, void* objectRegister, asITypeInfo* objectTypeRegister);
+	int SetCallStateRegisters(asUINT stackLevel, asDWORD stackFramePointer, asIScriptFunction* currentFunction, asDWORD programPointer, asDWORD stackPointer, asDWORD stackIndex);
+	int GetArgsOnStackCount(asUINT stackLevel);
+	int GetArgOnStack(asUINT stackLevel, asUINT arg, int* typeId, asUINT *flags, void** address);
+
 public:
 	// Internal public functions
 	asCContext(asCScriptEngine *engine, bool holdRef);
 	virtual ~asCContext();
+	asCScriptFunction *GetRealFunc(asCScriptFunction * m_currentFunction, void ** objType);
+	int DeserializeProgramPointer(int programPointer, asCScriptFunction * currentFunction, void * object, asDWORD *& p, asCScriptFunction *& realFunc);
 
 //protected:
 	friend class asCScriptEngine;
@@ -157,8 +175,13 @@ public:
 	void CallInterfaceMethod(asCScriptFunction *func);
 	void PrepareScriptFunction();
 
+	void SetProgramPointer();
+
 	bool ReserveStackSpace(asUINT size);
 
+	asDWORD *DeserializeStackPointer(asDWORD);
+	asDWORD  SerializeStackPointer(asDWORD *) const;
+
 	void SetInternalException(const char *descr, bool allowCatch = true);
 	bool FindExceptionTryCatch();
 
@@ -201,6 +224,11 @@ public:
 	int                m_returnValueSize;
 	int                m_argumentsSize;
 
+	// Cache for GetArgsOnStack
+	asCArray<int>      m_argsOnStackCache;
+	asUINT             m_argsOnStackCacheProgPos;
+	asCScriptFunction* m_argsOnStackCacheFunc;
+
 	// callbacks
 	bool                       m_lineCallback;
 	asSSystemFunctionInterface m_lineCallbackFunc;

+ 3 - 1
Source/ThirdParty/AngelScript/source/as_datatype.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2017 Andreas Jonsson
+   Copyright (c) 2003-2022 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 
@@ -650,6 +650,8 @@ int asCDataType::GetSizeOnStackDWords() const
 	int size = tokenType == ttQuestion ? 1 : 0;
 
 	if( isReference ) return AS_PTR_SIZE + size;
+
+	// TODO: bug: Registered value types are also stored on the stack. Before changing though, check how GetSizeOnStackDWords is used
 	if( typeInfo && !IsEnumType() ) return AS_PTR_SIZE + size;
 
 	return GetSizeInMemoryDWords() + size;

+ 57 - 55
Source/ThirdParty/AngelScript/source/as_parser.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -732,7 +732,7 @@ asCScriptNode *asCParser::ParseParameterList()
 
 	sToken t1;
 	GetToken(&t1);
-	if( t1.type != ttOpenParanthesis )
+	if( t1.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t1);
 		Error(InsteadFound(t1), &t1);
@@ -742,7 +742,7 @@ asCScriptNode *asCParser::ParseParameterList()
 	node->UpdateSourcePos(t1.pos, t1.length);
 
 	GetToken(&t1);
-	if( t1.type == ttCloseParanthesis )
+	if( t1.type == ttCloseParenthesis )
 	{
 		node->UpdateSourcePos(t1.pos, t1.length);
 
@@ -756,7 +756,7 @@ asCScriptNode *asCParser::ParseParameterList()
 		{
 			sToken t2;
 			GetToken(&t2);
-			if( t2.type == ttCloseParanthesis )
+			if( t2.type == ttCloseParenthesis)
 			{
 				node->UpdateSourcePos(t2.pos, t2.length);
 				return node;
@@ -798,7 +798,7 @@ asCScriptNode *asCParser::ParseParameterList()
 			}
 
 			// Check if list continues
-			if( t1.type == ttCloseParanthesis )
+			if( t1.type == ttCloseParenthesis)
 			{
 				node->UpdateSourcePos(t1.pos, t1.length);
 
@@ -835,9 +835,9 @@ asCScriptNode *asCParser::SuperficiallyParseExpression()
 	{
 		GetToken(&t);
 
-		if( t.type == ttOpenParanthesis )
+		if( t.type == ttOpenParenthesis)
 			stack += "(";
-		else if( t.type == ttCloseParanthesis )
+		else if( t.type == ttCloseParenthesis)
 		{
 			if( stack == "" )
 			{
@@ -919,6 +919,8 @@ asCScriptNode *asCParser::SuperficiallyParseExpression()
 	return node;
 }
 
+// BNF:18: COMMENT       ::= single token:  starts with // and ends with new line or starts with /* and ends with */
+// BNF:18: WHITESPACE    ::= single token:  spaces, tab, carriage return, line feed, and UTF8 byte-order-mark
 void asCParser::GetToken(sToken *token)
 {
 	// Check if the token has already been parsed
@@ -1462,7 +1464,7 @@ asCScriptNode *asCParser::ParseCast()
 	}
 
 	GetToken(&t1);
-	if( t1.type != ttOpenParanthesis )
+	if( t1.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t1);
 		Error(InsteadFound(t1), &t1);
@@ -1473,7 +1475,7 @@ asCScriptNode *asCParser::ParseCast()
 	if( isSyntaxError ) return node;
 
 	GetToken(&t1);
-	if( t1.type != ttCloseParanthesis )
+	if( t1.type != ttCloseParenthesis)
 	{
 		Error(ExpectedToken(")"), &t1);
 		Error(InsteadFound(t1), &t1);
@@ -1557,7 +1559,7 @@ asCScriptNode *asCParser::ParseExprValue()
 		node->AddChildLast(ParseCast());
 	else if( IsConstant(t1.type) )
 		node->AddChildLast(ParseConstant());
-	else if( t1.type == ttOpenParanthesis )
+	else if( t1.type == ttOpenParenthesis)
 	{
 		GetToken(&t1);
 		node->UpdateSourcePos(t1.pos, t1.length);
@@ -1566,7 +1568,7 @@ asCScriptNode *asCParser::ParseExprValue()
 		if( isSyntaxError ) return node;
 
 		GetToken(&t1);
-		if( t1.type != ttCloseParanthesis )
+		if( t1.type != ttCloseParenthesis)
 		{
 			Error(ExpectedToken(")"), &t1);
 			Error(InsteadFound(t1), &t1);
@@ -1584,7 +1586,7 @@ asCScriptNode *asCParser::ParseExprValue()
 }
 
 // BNF:12: LITERAL       ::= NUMBER | STRING | BITS | 'true' | 'false' | 'null'
-// BNF:17: NUMBER        ::= single token:  includes integers and real numbers, same as C++
+// BNF:17: NUMBER        ::= single token:  includes integers and real numbers, same as C++ 
 // BNF:17: STRING        ::= single token:  single quoted ', double quoted ", or heredoc multi-line string """
 // BNF:17: BITS          ::= single token:  binary 0b or 0B, octal 0o or 0O, decimal 0d or 0D, hexadecimal 0x or 0X
 asCScriptNode *asCParser::ParseConstant()
@@ -1628,10 +1630,10 @@ bool asCParser::IsLambda()
 	{
 		sToken t2;
 		GetToken(&t2);
-		if( t2.type == ttOpenParanthesis )
+		if( t2.type == ttOpenParenthesis)
 		{
 			// Skip until )
-			while( t2.type != ttCloseParanthesis && t2.type != ttEnd )
+			while( t2.type != ttCloseParenthesis && t2.type != ttEnd )
 				GetToken(&t2);
 
 			// The next token must be a {
@@ -1661,7 +1663,7 @@ asCScriptNode *asCParser::ParseLambda()
 	}
 
 	GetToken(&t);
-	if( t.type != ttOpenParanthesis )
+	if( t.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t);
 		return node;
@@ -1702,7 +1704,7 @@ asCScriptNode *asCParser::ParseLambda()
 		}
 	}
 
-	if( t.type != ttCloseParanthesis )
+	if( t.type != ttCloseParenthesis)
 	{
 		Error(ExpectedToken(")"), &t);
 		return node;
@@ -1792,7 +1794,7 @@ asCScriptNode *asCParser::ParseArgList(bool withParenthesis)
 	if( withParenthesis )
 	{
 		GetToken(&t1);
-		if( t1.type != ttOpenParanthesis )
+		if( t1.type != ttOpenParenthesis)
 		{
 			Error(ExpectedToken("("), &t1);
 			Error(InsteadFound(t1), &t1);
@@ -1803,11 +1805,11 @@ asCScriptNode *asCParser::ParseArgList(bool withParenthesis)
 	}
 
 	GetToken(&t1);
-	if( t1.type == ttCloseParanthesis || t1.type == ttCloseBracket )
+	if( t1.type == ttCloseParenthesis || t1.type == ttCloseBracket )
 	{
 		if( withParenthesis )
 		{
-			if( t1.type == ttCloseParanthesis )
+			if( t1.type == ttCloseParenthesis)
 				node->UpdateSourcePos(t1.pos, t1.length);
 			else
 			{
@@ -1867,7 +1869,7 @@ asCScriptNode *asCParser::ParseArgList(bool withParenthesis)
 			{
 				if( withParenthesis )
 				{
-					if( t1.type == ttCloseParanthesis )
+					if( t1.type == ttCloseParenthesis)
 						node->UpdateSourcePos(t1.pos, t1.length);
 					else
 					{
@@ -1914,7 +1916,7 @@ bool asCParser::IsFunctionCall()
 		return false;
 	}
 
-	if( t2.type == ttOpenParanthesis )
+	if( t2.type == ttOpenParenthesis)
 	{
 		RewindTo(&s);
 		return true;
@@ -2118,7 +2120,7 @@ asCScriptNode *asCParser::ParseExprPostOp()
 		GetToken(&t1);
 		GetToken(&t2);
 		RewindTo(&t1);
-		if( t2.type == ttOpenParanthesis )
+		if( t2.type == ttOpenParenthesis)
 			node->AddChildLast(ParseFunctionCall());
 		else
 			node->AddChildLast(ParseIdentifier());
@@ -2137,7 +2139,7 @@ asCScriptNode *asCParser::ParseExprPostOp()
 
 		node->UpdateSourcePos(t.pos, t.length);
 	}
-	else if( t.type == ttOpenParanthesis )
+	else if( t.type == ttOpenParenthesis)
 	{
 		RewindTo(&t);
 		node->AddChildLast(ParseArgList());
@@ -2147,7 +2149,7 @@ asCScriptNode *asCParser::ParseExprPostOp()
 }
 
 // BNF:15: EXPROP        ::= MATHOP | COMPOP | LOGICOP | BITOP
-// BNF:16: MATHOP        ::= '+' | '-' | '*' | '/' | '%' | '**'
+// BNF:16: MATHOP        ::= '+' | '-' | '*' | '/' | '\%' | '**'
 // BNF:16: COMPOP        ::= '==' | '!=' | '<' | '<=' | '>' | '>=' | 'is' | '!is'
 // BNF:16: LOGICOP       ::= '&&' | '||' | '^^' | 'and' | 'or' | 'xor'
 // BNF:16: BITOP         ::= '&' | '|' | '^' | '<<' | '>>' | '>>>'
@@ -2261,7 +2263,7 @@ bool asCParser::IsPostOperator(int tokenType)
 		tokenType == ttDec ||            // post decrement
 		tokenType == ttDot ||            // member access
 		tokenType == ttOpenBracket ||    // index operator
-		tokenType == ttOpenParanthesis ) // argument list for call on function pointer
+		tokenType == ttOpenParenthesis) // argument list for call on function pointer
 		return true;
 	return false;
 }
@@ -2758,7 +2760,7 @@ bool asCParser::IsVarDecl()
 		RewindTo(&t);
 		return true;
 	}
-	if( t1.type == ttOpenParanthesis )
+	if( t1.type == ttOpenParenthesis)
 	{
 		// If the closing parenthesis is followed by a statement block, 
 		// function decorator, or end-of-file, then treat it as a function. 
@@ -2767,9 +2769,9 @@ bool asCParser::IsVarDecl()
 		int nest = 0;
 		while( t1.type != ttEnd )
 		{
-			if( t1.type == ttOpenParanthesis )
+			if( t1.type == ttOpenParenthesis)
 				nest++;
-			else if( t1.type == ttCloseParanthesis )
+			else if( t1.type == ttCloseParenthesis)
 			{
 				nest--;
 				if( nest == 0 )
@@ -2864,7 +2866,7 @@ bool asCParser::IsFuncDecl(bool isMethod)
 		GetToken(&t1);
 		GetToken(&t2);
 		RewindTo(&t1);
-		if( (t1.type == ttIdentifier && t2.type == ttOpenParanthesis) || t1.type == ttBitNot )
+		if( (t1.type == ttIdentifier && t2.type == ttOpenParenthesis) || t1.type == ttBitNot )
 		{
 			RewindTo(&t);
 			return true;
@@ -2897,7 +2899,7 @@ bool asCParser::IsFuncDecl(bool isMethod)
 	}
 
 	GetToken(&t1);
-	if( t1.type == ttOpenParanthesis )
+	if( t1.type == ttOpenParenthesis)
 	{
 		// If the closing parenthesis is not followed by a
 		// statement block then it is not a function.
@@ -2905,11 +2907,11 @@ bool asCParser::IsFuncDecl(bool isMethod)
 		// arguments so this should be checked for.
 		int nest = 0;
 		GetToken(&t1);
-		while( (nest || t1.type != ttCloseParanthesis) && t1.type != ttEnd )
+		while( (nest || t1.type != ttCloseParenthesis) && t1.type != ttEnd )
 		{
-			if( t1.type == ttOpenParanthesis )
+			if( t1.type == ttOpenParenthesis)
 				nest++;
-			if( t1.type == ttCloseParanthesis )
+			if( t1.type == ttCloseParenthesis)
 				nest--;
 
 			GetToken(&t1);
@@ -3053,7 +3055,7 @@ asCScriptNode *asCParser::ParseFunction(bool isMethod)
 	sToken t2;
 	GetToken(&t2);
 	RewindTo(&t1);
-	if( !isMethod || (t1.type != ttBitNot && t2.type != ttOpenParanthesis) )
+	if( !isMethod || (t1.type != ttBitNot && t2.type != ttOpenParenthesis) )
 	{
 		node->AddChildLast(ParseType(true));
 		if( isSyntaxError ) return node;
@@ -3514,14 +3516,14 @@ int asCParser::ParseVarInit(asCScriptCode *in_script, asCScriptNode *in_init)
 		else
 			scriptNode = ParseAssignment();
 	}
-	else if( t.type == ttOpenParanthesis )
+	else if( t.type == ttOpenParenthesis)
 	{
 		RewindTo(&t);
 		scriptNode = ParseArgList();
 	}
 	else
 	{
-		int tokens[] = {ttAssignment, ttOpenParanthesis};
+		int tokens[] = {ttAssignment, ttOpenParenthesis };
 		Error(ExpectedOneOf(tokens, 2), &t);
 		Error(InsteadFound(t), &t);
 	}
@@ -3560,9 +3562,9 @@ asCScriptNode *asCParser::SuperficiallyParseVarInit()
 		int indentBrace = 0;
 		while( indentParan || indentBrace || (t.type != ttListSeparator && t.type != ttEndStatement && t.type != ttEndStatementBlock) )
 		{
-			if( t.type == ttOpenParanthesis )
+			if( t.type == ttOpenParenthesis)
 				indentParan++;
-			else if( t.type == ttCloseParanthesis )
+			else if( t.type == ttCloseParenthesis)
 				indentParan--;
 			else if( t.type == ttStartStatementBlock )
 				indentBrace++;
@@ -3585,7 +3587,7 @@ asCScriptNode *asCParser::SuperficiallyParseVarInit()
 		// Rewind so that the next token read is the list separator, end statement, or end statement block
 		RewindTo(&t);
 	}
-	else if( t.type == ttOpenParanthesis )
+	else if( t.type == ttOpenParenthesis)
 	{
 		sToken start = t;
 
@@ -3594,9 +3596,9 @@ asCScriptNode *asCParser::SuperficiallyParseVarInit()
 		while( indent )
 		{
 			GetToken(&t);
-			if( t.type == ttOpenParanthesis )
+			if( t.type == ttOpenParenthesis)
 				indent++;
-			else if( t.type == ttCloseParanthesis )
+			else if( t.type == ttCloseParenthesis)
 				indent--;
 			else if( t.type == ttNonTerminatedStringConstant )
 			{
@@ -3613,7 +3615,7 @@ asCScriptNode *asCParser::SuperficiallyParseVarInit()
 	}
 	else
 	{
-		int tokens[] = {ttAssignment, ttOpenParanthesis};
+		int tokens[] = {ttAssignment, ttOpenParenthesis };
 		Error(ExpectedOneOf(tokens, 2), &t);
 		Error(InsteadFound(t), &t);
 	}
@@ -3892,7 +3894,7 @@ asCScriptNode *asCParser::ParseDeclaration(bool isClassProp, bool isGlobalVar)
 			// Only superficially parse the initialization info for the class property
 			GetToken(&t);
 			RewindTo(&t);
-			if( t.type == ttAssignment || t.type == ttOpenParanthesis )
+			if( t.type == ttAssignment || t.type == ttOpenParenthesis)
 			{
 				node->AddChildLast(SuperficiallyParseVarInit());
 				if( isSyntaxError ) return node;
@@ -3902,7 +3904,7 @@ asCScriptNode *asCParser::ParseDeclaration(bool isClassProp, bool isGlobalVar)
 		{
 			// If next token is assignment, parse expression
 			GetToken(&t);
-			if( t.type == ttOpenParanthesis )
+			if( t.type == ttOpenParenthesis)
 			{
 				RewindTo(&t);
 				node->AddChildLast(ParseArgList());
@@ -4037,7 +4039,7 @@ asCScriptNode *asCParser::ParseSwitch()
 	node->UpdateSourcePos(t.pos, t.length);
 
 	GetToken(&t);
-	if( t.type != ttOpenParanthesis )
+	if( t.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t);
 		Error(InsteadFound(t), &t);
@@ -4048,7 +4050,7 @@ asCScriptNode *asCParser::ParseSwitch()
 	if( isSyntaxError ) return node;
 
 	GetToken(&t);
-	if( t.type != ttCloseParanthesis )
+	if( t.type != ttCloseParenthesis)
 	{
 		Error(ExpectedToken(")"), &t);
 		Error(InsteadFound(t), &t);
@@ -4168,7 +4170,7 @@ asCScriptNode *asCParser::ParseIf()
 	node->UpdateSourcePos(t.pos, t.length);
 
 	GetToken(&t);
-	if( t.type != ttOpenParanthesis )
+	if( t.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t);
 		Error(InsteadFound(t), &t);
@@ -4179,7 +4181,7 @@ asCScriptNode *asCParser::ParseIf()
 	if( isSyntaxError ) return node;
 
 	GetToken(&t);
-	if( t.type != ttCloseParanthesis )
+	if( t.type != ttCloseParenthesis)
 	{
 		Error(ExpectedToken(")"), &t);
 		Error(InsteadFound(t), &t);
@@ -4254,7 +4256,7 @@ asCScriptNode *asCParser::ParseFor()
 	node->UpdateSourcePos(t.pos, t.length);
 
 	GetToken(&t);
-	if( t.type != ttOpenParanthesis )
+	if( t.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t);
 		Error(InsteadFound(t), &t);
@@ -4271,7 +4273,7 @@ asCScriptNode *asCParser::ParseFor()
 	if( isSyntaxError ) return node;
 
 	GetToken(&t);
-	if( t.type != ttCloseParanthesis )
+	if( t.type != ttCloseParenthesis)
 	{
 		RewindTo(&t);
 
@@ -4287,7 +4289,7 @@ asCScriptNode *asCParser::ParseFor()
 			GetToken(&t);
 			if( t.type == ttListSeparator )
 				continue;
-			else if( t.type == ttCloseParanthesis )
+			else if( t.type == ttCloseParenthesis)
 				break;
 			else
 			{
@@ -4322,7 +4324,7 @@ asCScriptNode *asCParser::ParseWhile()
 	node->UpdateSourcePos(t.pos, t.length);
 
 	GetToken(&t);
-	if( t.type != ttOpenParanthesis )
+	if( t.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t);
 		Error(InsteadFound(t), &t);
@@ -4333,7 +4335,7 @@ asCScriptNode *asCParser::ParseWhile()
 	if( isSyntaxError ) return node;
 
 	GetToken(&t);
-	if( t.type != ttCloseParanthesis )
+	if( t.type != ttCloseParenthesis)
 	{
 		Error(ExpectedToken(")"), &t);
 		Error(InsteadFound(t), &t);
@@ -4374,7 +4376,7 @@ asCScriptNode *asCParser::ParseDoWhile()
 	}
 
 	GetToken(&t);
-	if( t.type != ttOpenParanthesis )
+	if( t.type != ttOpenParenthesis)
 	{
 		Error(ExpectedToken("("), &t);
 		Error(InsteadFound(t), &t);
@@ -4385,7 +4387,7 @@ asCScriptNode *asCParser::ParseDoWhile()
 	if( isSyntaxError ) return node;
 
 	GetToken(&t);
-	if( t.type != ttCloseParanthesis )
+	if( t.type != ttCloseParenthesis)
 	{
 		Error(ExpectedToken(")"), &t);
 		Error(InsteadFound(t), &t);

+ 84 - 169
Source/ThirdParty/AngelScript/source/as_restore.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -1178,9 +1178,8 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 	}
 	savedFunctions.PushLast(func);
 
-	int i, count;
+	int i;
 	asCDataType dt;
-	int num;
 
 	asCObjectType *parentClass = 0;
 	ReadFunctionSignature(func, &parentClass);
@@ -1249,28 +1248,8 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 
 				func->scriptData->variableSpace = SanityCheck(ReadEncodedUInt(), 1000000);
 
-				func->scriptData->objVariablesOnHeap = 0;
 				if (bits & 8)
 				{
-					count = SanityCheck(ReadEncodedUInt(), 1000000);
-					func->scriptData->objVariablePos.Allocate(count, false);
-					func->scriptData->objVariableTypes.Allocate(count, false);
-					for (i = 0; i < count; ++i)
-					{
-						func->scriptData->objVariableTypes.PushLast(ReadTypeInfo());
-						num = ReadEncodedUInt();
-						func->scriptData->objVariablePos.PushLast(num);
-
-						if (error)
-						{
-							// No need to continue (the error has already been reported before)
-							func->DestroyHalfCreated();
-							return 0;
-						}
-					}
-					if (count > 0)
-						func->scriptData->objVariablesOnHeap = SanityCheck(ReadEncodedUInt(), 10000);
-
 					int length = SanityCheck(ReadEncodedUInt(), 1000000);
 					func->scriptData->objVariableInfo.SetLength(length);
 					for (i = 0; i < length; ++i)
@@ -1343,33 +1322,38 @@ asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool a
 				}
 
 				// Read the variable information
-				if (!noDebugInfo)
+				int length = SanityCheck(ReadEncodedUInt(), 1000000);
+				func->scriptData->variables.Allocate(length, false);
+				for (i = 0; i < length; i++)
 				{
-					int length = SanityCheck(ReadEncodedUInt(), 1000000);
-					func->scriptData->variables.Allocate(length, false);
-					for (i = 0; i < length; i++)
+					asSScriptVariable *var = asNEW(asSScriptVariable);
+					if (var == 0)
 					{
-						asSScriptVariable *var = asNEW(asSScriptVariable);
-						if (var == 0)
-						{
-							// Out of memory
-							error = true;
-							func->DestroyHalfCreated();
-							return 0;
-						}
-						func->scriptData->variables.PushLast(var);
+						// Out of memory
+						error = true;
+						func->DestroyHalfCreated();
+						return 0;
+					}
+					func->scriptData->variables.PushLast(var);
 
+					if (!noDebugInfo)
+					{
 						var->declaredAtProgramPos = ReadEncodedUInt();
-						var->stackOffset = SanityCheck(ReadEncodedInt(),10000);
 						ReadString(&var->name);
-						ReadDataType(&var->type);
+					}
+					else
+						var->declaredAtProgramPos = 0;
 
-						if (error)
-						{
-							// No need to continue (the error has already been reported before)
-							func->DestroyHalfCreated();
-							return 0;
-						}
+					var->stackOffset = SanityCheck(ReadEncodedInt(),10000);
+					var->onHeap = var->stackOffset & 1;
+					var->stackOffset >>= 1;
+					ReadDataType(&var->type);
+
+					if (error)
+					{
+						// No need to continue (the error has already been reported before)
+						func->DestroyHalfCreated();
+						return 0;
 					}
 				}
 
@@ -2258,6 +2242,9 @@ void asCReader::ReadDataType(asCDataType *dt)
 	dt->MakeReadOnly(isReadOnly ? true : false);
 	dt->MakeReference(isReference ? true : false);
 
+	if (tokenType == ttUnrecognizedToken && isObjectHandle && ti == 0)
+		*dt = asCDataType::CreateNullHandle();
+
 	// Update the previously saved slot
 	savedDataTypes[saveSlot] = *dt;
 }
@@ -3182,10 +3169,6 @@ void asCReader::TranslateFunction(asCScriptFunction *func)
 		func->scriptData->variables[n]->stackOffset = AdjustStackPosition(func->scriptData->variables[n]->stackOffset);
 	}
 
-	// objVariablePos
-	for( n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ )
-		func->scriptData->objVariablePos[n] = AdjustStackPosition(func->scriptData->objVariablePos[n]);
-
 	// Adjust the get offsets. This must be done in the second iteration because
 	// it relies on the function ids and variable position already being correct in the
 	// bytecodes that come after the GET instructions.
@@ -3458,7 +3441,7 @@ void asCReader::CalculateStackNeeded(asCScriptFunction *func)
 				bc == asBC_CALLINTF ||
 				bc == asBC_CallPtr )
 			{
-				asCScriptFunction *called = GetCalledFunction(func, pos);
+				asCScriptFunction *called = func->GetCalledFunction(pos);
 				if( called )
 				{
 					stackInc = -called->GetSpaceNeededForArguments();
@@ -3615,31 +3598,29 @@ void asCReader::CalculateAdjustmentByPos(asCScriptFunction *func)
 	// It is necessary to adjust to the size according to the current platform.
 	adjustments.SetLength(0);
 	int highestPos = 0;
-	for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ )
+	for (n = 0; n < func->scriptData->variables.GetLength(); n++)
 	{
-		// Determine the size the variable currently occupies on the stack
-		int size = AS_PTR_SIZE;
+		// Skip function parameters as these are adjusted by adjustNegativeStackByPos
+		if (func->scriptData->variables[n]->stackOffset <= 0)
+			continue;
 
-		// objVariableTypes is null if the type is a null pointer, or just a reference to an object that is not owned by the function
-		if( func->scriptData->objVariableTypes[n] &&
-			(func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) &&
-			n >= func->scriptData->objVariablesOnHeap )
-		{
-			size = func->scriptData->objVariableTypes[n]->GetSize();
-			if( size < 4 )
-				size = 1;
-			else
-				size /= 4;
-		}
+		asCDataType t = func->scriptData->variables[n]->type;
+		if (!t.IsObject() && !t.IsObjectHandle())
+			continue;
+
+		// Determing the size of the variable currently occupies on the stack
+		int size = AS_PTR_SIZE;
+		if (t.GetTypeInfo() && (t.GetTypeInfo()->GetFlags() & asOBJ_VALUE) && !func->scriptData->variables[n]->onHeap)
+			size = t.GetSizeInMemoryDWords();
 
 		// Check if type has a different size than stored
-		if( size > 1 )
+		if (size > 1)
 		{
-			if( func->scriptData->objVariablePos[n] > highestPos )
-				highestPos = func->scriptData->objVariablePos[n];
+			if (func->scriptData->variables[n]->stackOffset > highestPos)
+				highestPos = func->scriptData->variables[n]->stackOffset;
 
-			adjustments.PushLast(func->scriptData->objVariablePos[n]);
-			adjustments.PushLast(size-1);
+			adjustments.PushLast(func->scriptData->variables[n]->stackOffset);
+			adjustments.PushLast(size - 1);
 		}
 	}
 
@@ -3676,69 +3657,6 @@ int asCReader::AdjustStackPosition(int pos)
 	return pos;
 }
 
-asCScriptFunction *asCReader::GetCalledFunction(asCScriptFunction *func, asDWORD programPos)
-{
-	asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[programPos];
-
-	if( bc == asBC_CALL ||
-		bc == asBC_CALLSYS ||
-		bc == asBC_Thiscall1 ||
-		bc == asBC_CALLINTF )
-	{
-		// Find the function from the function id in bytecode
-		int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos]);
-		return engine->scriptFunctions[funcId];
-	}
-	else if( bc == asBC_ALLOC )
-	{
-		// Find the function from the function id in the bytecode
-		int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos+AS_PTR_SIZE]);
-		return engine->scriptFunctions[funcId];
-	}
-	else if( bc == asBC_CALLBND )
-	{
-		// Find the function from the engine's bind array
-		int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos]);
-		return engine->importedFunctions[funcId & ~FUNC_IMPORTED]->importedFunctionSignature;
-	}
-	else if( bc == asBC_CallPtr )
-	{
-		asUINT v;
-		int var = asBC_SWORDARG0(&func->scriptData->byteCode[programPos]);
-
-		// Find the funcdef from the local variable
-		for( v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
-			if (func->scriptData->objVariablePos[v] == var)
-			{
-				asASSERT(func->scriptData->objVariableTypes[v]);
-				return CastToFuncdefType(func->scriptData->objVariableTypes[v])->funcdef;
-			}
-
-		// Look in parameters
-		int paramPos = 0;
-		if( func->objectType )
-			paramPos -= AS_PTR_SIZE;
-		if( func->DoesReturnOnStack() )
-			paramPos -= AS_PTR_SIZE;
-		for( v = 0; v < func->parameterTypes.GetLength(); v++ )
-		{
-			if (var == paramPos)
-			{
-				if (func->parameterTypes[v].IsFuncdef())
-					return CastToFuncdefType(func->parameterTypes[v].GetTypeInfo())->funcdef;
-				else
-				{
-					error = true;
-					return 0;
-				}
-			}
-			paramPos -= func->parameterTypes[v].GetSizeOnStackDWords();
-		}
-	}
-
-	return 0;
-}
-
 int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD programPos)
 {
 	// TODO: optimize: multiple instructions for the same function doesn't need to look for the function everytime
@@ -3750,6 +3668,7 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
 	bool bcAlloc = false;
 
 	// Find out which function that will be called
+	// TODO: Can the asCScriptFunction::FindNextFunctionCalled be adapted so it can be reused here (support for asBC_ALLOC, asBC_REFCPY and asBC_COPY)?
 	asCScriptFunction *calledFunc = 0;
 	int stackDelta = 0;
 	for( asUINT n = programPos; func->scriptData->byteCode.GetLength(); )
@@ -3768,7 +3687,7 @@ int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
 			if (bc == asBC_ALLOC)
 				bcAlloc = true;
 
-			calledFunc = GetCalledFunction(func, n);
+			calledFunc = func->GetCalledFunction(n);
 			break;
 		}
 		else if( bc == asBC_REFCPY ||
@@ -4284,7 +4203,7 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
 		bits += func->dontCleanUpOnException ? 2 : 0;
 		if (module->m_externalFunctions.IndexOf(func) >= 0)
 			bits += 4;
-		if (func->scriptData->objVariablePos.GetLength() || func->scriptData->objVariableInfo.GetLength())
+		if (func->scriptData->objVariableInfo.GetLength())
 			bits += 8;
 		if (func->scriptData->tryCatchInfo.GetLength())
 			bits += 16;
@@ -4305,16 +4224,6 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
 
 		if (bits & 8)
 		{
-			count = (asUINT)func->scriptData->objVariablePos.GetLength();
-			WriteEncodedInt64(count);
-			for (i = 0; i < count; ++i)
-			{
-				WriteTypeInfo(func->scriptData->objVariableTypes[i]);
-				WriteEncodedInt64(AdjustStackPosition(func->scriptData->objVariablePos[i]));
-			}
-			if (count > 0)
-				WriteEncodedInt64(func->scriptData->objVariablesOnHeap);
-
 			WriteEncodedInt64((asUINT)func->scriptData->objVariableInfo.GetLength());
 			for (i = 0; i < func->scriptData->objVariableInfo.GetLength(); ++i)
 			{
@@ -4372,18 +4281,26 @@ void asCWriter::WriteFunction(asCScriptFunction* func)
 		}
 
 		// Write the variable information
-		if( !stripDebugInfo )
-		{
-			WriteEncodedInt64((asUINT)func->scriptData->variables.GetLength());
-			for( i = 0; i < func->scriptData->variables.GetLength(); i++ )
+		// Even without the debug info the type and position of the variables
+		// must be stored, as this is used for serializing contexts
+		// TODO: Store the type info/position in an intelligent way to avoid duplicating info in objVariablePos & objVariableTypes.
+		// TODO: Perhaps objVariablePos & objVariableTypes should be retired now that all variable types must be stored anyway
+		WriteEncodedInt64((asUINT)func->scriptData->variables.GetLength());
+		for( i = 0; i < func->scriptData->variables.GetLength(); i++ )
+		{
+			if (!stripDebugInfo)
 			{
 				// The program position must be adjusted to be in number of instructions
 				WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->variables[i]->declaredAtProgramPos]);
-				// The stack position must be adjusted according to the pointer sizes
-				WriteEncodedInt64(AdjustStackPosition(func->scriptData->variables[i]->stackOffset));
 				WriteString(&func->scriptData->variables[i]->name);
-				WriteDataType(&func->scriptData->variables[i]->type);
 			}
+
+			// The stack position must be adjusted according to the pointer sizes
+			asUINT data = AdjustStackPosition(func->scriptData->variables[i]->stackOffset) << 1;
+			// Encode the onHeap flag in the stackOffset to avoid 1 byte increase
+			data |= func->scriptData->variables[i]->onHeap & 1;
+			WriteEncodedInt64(data);
+			WriteDataType(&func->scriptData->variables[i]->type);
 		}
 
 		// Store script section name
@@ -4833,28 +4750,26 @@ void asCWriter::CalculateAdjustmentByPos(asCScriptFunction *func)
 	// Adjust the offset of all positive variables so that all object types and handles have a size of 1 dword
 	// This is similar to how the adjustment is done in the asCReader::TranslateFunction, only the reverse
 	adjustments.SetLength(0);
-	for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ )
+	for (n = 0; n < func->scriptData->variables.GetLength(); n++)
 	{
-		// Determine the size the variable currently occupies on the stack
-		int size = AS_PTR_SIZE;
+		// Skip function parameters as these are adjusted by adjustNegativeStackByPos
+		if (func->scriptData->variables[n]->stackOffset <= 0)
+			continue;
 
-		// objVariableTypes is null if the variable type is a null pointer, or a reference to an object that is not owned by the function
-		if( func->scriptData->objVariableTypes[n] &&
-			(func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) &&
-			n >= func->scriptData->objVariablesOnHeap )
-		{
-			size = func->scriptData->objVariableTypes[n]->GetSize();
-			if( size < 4 )
-				size = 1;
-			else
-				size /= 4;
-		}
+		asCDataType t = func->scriptData->variables[n]->type;
+		if (!t.IsObject() && !t.IsObjectHandle())
+			continue;
+
+		// Determing the size of the variable currently occupies on the stack
+		int size = AS_PTR_SIZE;
+		if (t.GetTypeInfo() && (t.GetTypeInfo()->GetFlags() & asOBJ_VALUE) && !func->scriptData->variables[n]->onHeap)
+			size = t.GetSizeInMemoryDWords();
 
 		// If larger than 1 dword, adjust the offsets accordingly
 		if (size > 1)
 		{
 			// How much needs to be adjusted?
-			adjustments.PushLast(func->scriptData->objVariablePos[n]);
+			adjustments.PushLast(func->scriptData->variables[n]->stackOffset);
 			adjustments.PushLast(-(size - 1));
 		}
 	}
@@ -4959,12 +4874,12 @@ int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD prog
 			int var = asBC_SWORDARG0(&func->scriptData->byteCode[n]);
 			asUINT v;
 			// Find the funcdef from the local variable
-			for( v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
+			for (v = 0; v < func->scriptData->variables.GetLength(); v++)
 			{
-				if( func->scriptData->objVariablePos[v] == var )
+				if (func->scriptData->variables[v]->stackOffset == var)
 				{
-					asASSERT(func->scriptData->objVariableTypes[v]);
-					calledFunc = CastToFuncdefType(func->scriptData->objVariableTypes[v])->funcdef;
+					asASSERT(func->scriptData->variables[v]->type.GetTypeInfo());
+					calledFunc = CastToFuncdefType(func->scriptData->variables[v]->type.GetTypeInfo())->funcdef;
 					break;
 				}
 			}

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

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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 
@@ -98,7 +98,6 @@ protected:
 	int  AdjustStackPosition(int pos);
 	int  AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD programPos);
 	void CalculateStackNeeded(asCScriptFunction *func);
-	asCScriptFunction *GetCalledFunction(asCScriptFunction *func, asDWORD programPos);
 
 	// Temporary storage for persisting variable data
 	asCArray<int>                usedTypeIds;

+ 80 - 23
Source/ThirdParty/AngelScript/source/as_scriptengine.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -443,6 +443,14 @@ int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
 		ep.maxCallStackSize = (asUINT)value;
 		break;
 
+	case asEP_IGNORE_DUPLICATE_SHARED_INTF:
+		ep.ignoreDuplicateSharedIntf = value ? true : false;
+		break;
+
+	case asEP_NO_DEBUG_OUTPUT:
+		ep.noDebugOutput = value ? true : false;
+		break;
+
 	default:
 		return asINVALID_ARG;
 	}
@@ -548,6 +556,12 @@ asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
 	case asEP_MAX_CALL_STACK_SIZE:
 		return ep.maxCallStackSize;
 
+	case asEP_IGNORE_DUPLICATE_SHARED_INTF:
+		return ep.ignoreDuplicateSharedIntf;
+
+	case asEP_NO_DEBUG_OUTPUT:
+		return ep.noDebugOutput;
+
 	default:
 		return 0;
 	}
@@ -617,6 +631,8 @@ asCScriptEngine::asCScriptEngine()
 		ep.genericCallMode               = 1;         // 0 = old (pre 2.33.0) behavior where generic ignored auto handles, 1 = treat handles like in native call
 		ep.initCallStackSize             = 10;        // 10 levels of calls
 		ep.maxCallStackSize              = 0;         // 0 = no limit
+		ep.ignoreDuplicateSharedIntf     = false;
+		ep.noDebugOutput                 = false;
 	}
 
 	gc.engine = this;
@@ -1570,7 +1586,7 @@ int asCScriptEngine::RegisterInterface(const char *name)
 	if( token != ttIdentifier || strlen(name) != tokenLen )
 		return ConfigError(asINVALID_NAME, "RegisterInterface", name, 0);
 
-	r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false);
+	r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false, false);
 	if( r < 0 )
 		return ConfigError(asNAME_TAKEN, "RegisterInterface", name, 0);
 
@@ -1853,7 +1869,7 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD
 			if( token != ttIdentifier || typeName.GetLength() != tokenLen )
 				return ConfigError(asINVALID_NAME, "RegisterObjectType", name, 0);
 
-			r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false);
+			r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false, false);
 			if( r < 0 )
 				return ConfigError(asNAME_TAKEN, "RegisterObjectType", name, 0);
 
@@ -2959,7 +2975,7 @@ int asCScriptEngine::RegisterGlobalFunction(const char *declaration, const asSFu
 	func->nameSpace = defaultNamespace;
 
 	// Check name conflicts
-	r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace, false, false);
+	r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace, false, false, false);
 	if( r < 0 )
 	{
 		// Set as dummy function before deleting
@@ -3616,24 +3632,59 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
 		ot->beh.listFactory = func->id;
 	}
 
+	// Create new template functions for behaviours that may need to know the new object type id
+	int funcId = templateType->beh.destruct;
+	asCScriptFunction* func = scriptFunctions[funcId];
+	if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
+		ot->beh.destruct = func->id;
+	else
+	{
+		ot->beh.destruct = templateType->beh.destruct;
+		if (scriptFunctions[ot->beh.destruct]) scriptFunctions[ot->beh.destruct]->AddRefInternal();
+	}
+
+	funcId = templateType->beh.copy;
+	func = scriptFunctions[funcId];
+	if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
+		ot->beh.copy = func->id;
+	else
+	{
+		ot->beh.copy = templateType->beh.copy;
+		if (scriptFunctions[ot->beh.copy]) scriptFunctions[ot->beh.copy]->AddRefInternal();
+	}
+
+	funcId = templateType->beh.gcEnumReferences;
+	func = scriptFunctions[funcId];
+	if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
+		ot->beh.gcEnumReferences = func->id;
+	else
+	{
+		ot->beh.gcEnumReferences = templateType->beh.gcEnumReferences;
+		if (scriptFunctions[ot->beh.gcEnumReferences]) scriptFunctions[ot->beh.gcEnumReferences]->AddRefInternal();
+	}
+
+	funcId = templateType->beh.gcReleaseAllReferences;
+	func = scriptFunctions[funcId];
+	if (func && GenerateNewTemplateFunction(templateType, ot, func, &func))
+		ot->beh.gcReleaseAllReferences = func->id;
+	else
+	{
+		ot->beh.gcReleaseAllReferences = templateType->beh.gcReleaseAllReferences;
+		if (scriptFunctions[ot->beh.gcReleaseAllReferences]) scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRefInternal();
+	}
+
+	// For the last behaviours no unique copy is generated. It is not expected that
+	// anyone will need to see the correct objectType for these to implement them
 	ot->beh.addref = templateType->beh.addref;
 	if( scriptFunctions[ot->beh.addref] ) scriptFunctions[ot->beh.addref]->AddRefInternal();
 	ot->beh.release = templateType->beh.release;
 	if( scriptFunctions[ot->beh.release] ) scriptFunctions[ot->beh.release]->AddRefInternal();
-	ot->beh.destruct = templateType->beh.destruct;
-	if( scriptFunctions[ot->beh.destruct] ) scriptFunctions[ot->beh.destruct]->AddRefInternal();
-	ot->beh.copy = templateType->beh.copy;
-	if( scriptFunctions[ot->beh.copy] ) scriptFunctions[ot->beh.copy]->AddRefInternal();
 	ot->beh.gcGetRefCount = templateType->beh.gcGetRefCount;
 	if( scriptFunctions[ot->beh.gcGetRefCount] ) scriptFunctions[ot->beh.gcGetRefCount]->AddRefInternal();
 	ot->beh.gcSetFlag = templateType->beh.gcSetFlag;
 	if( scriptFunctions[ot->beh.gcSetFlag] ) scriptFunctions[ot->beh.gcSetFlag]->AddRefInternal();
 	ot->beh.gcGetFlag = templateType->beh.gcGetFlag;
 	if( scriptFunctions[ot->beh.gcGetFlag] ) scriptFunctions[ot->beh.gcGetFlag]->AddRefInternal();
-	ot->beh.gcEnumReferences = templateType->beh.gcEnumReferences;
-	if( scriptFunctions[ot->beh.gcEnumReferences] ) scriptFunctions[ot->beh.gcEnumReferences]->AddRefInternal();
-	ot->beh.gcReleaseAllReferences = templateType->beh.gcReleaseAllReferences;
-	if( scriptFunctions[ot->beh.gcReleaseAllReferences] ) scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRefInternal();
 	ot->beh.getWeakRefFlag = templateType->beh.getWeakRefFlag;
 	if( scriptFunctions[ot->beh.getWeakRefFlag] ) scriptFunctions[ot->beh.getWeakRefFlag]->AddRefInternal();
 
@@ -3641,8 +3692,8 @@ asCObjectType *asCScriptEngine::GetTemplateInstanceType(asCObjectType *templateT
 	// generate new functions to substitute the ones with the template subtype.
 	for( n = 0; n < ot->methods.GetLength(); n++ )
 	{
-		int funcId = ot->methods[n];
-		asCScriptFunction *func = scriptFunctions[funcId];
+		funcId = ot->methods[n];
+		func = scriptFunctions[funcId];
 
 		if( GenerateNewTemplateFunction(templateType, ot, func, &func) )
 		{
@@ -3867,7 +3918,6 @@ asCScriptFunction *asCScriptEngine::GenerateTemplateFactoryStub(asCObjectType *t
 		func->inOutFlags[p-1] = factory->inOutFlags[p];
 		func->defaultArgs[p-1] = factory->defaultArgs[p] ? asNEW(asCString)(*factory->defaultArgs[p]) : 0;
 	}
-	func->scriptData->objVariablesOnHeap = 0;
 
 	// Generate the bytecode for the factory stub
 	asUINT bcLength = asBCTypeSize[asBCInfo[asBC_OBJTYPE].type] +
@@ -5378,22 +5428,29 @@ int asCScriptEngine::AssignScriptObject(void *dstObj, void *srcObj, const asITyp
 	}
 
 	// Must not copy if the opAssign is not available and the object is not a POD object
-	if( objType->beh.copy )
+	if (objType->beh.copy)
 	{
-		asCScriptFunction *func = scriptFunctions[objType->beh.copy];
-		if( func->funcType == asFUNC_SYSTEM )
+		asCScriptFunction* func = scriptFunctions[objType->beh.copy];
+		if (func->funcType == asFUNC_SYSTEM)
 			CallObjectMethod(dstObj, srcObj, objType->beh.copy);
 		else
 		{
 			// Call the script class' opAssign method
-			asASSERT( objType->flags & asOBJ_SCRIPT_OBJECT );
+			asASSERT(objType->flags & asOBJ_SCRIPT_OBJECT);
 			reinterpret_cast<asCScriptObject*>(dstObj)->CopyFrom(reinterpret_cast<asCScriptObject*>(srcObj));
 		}
 	}
-	else if( objType->size && (objType->flags & asOBJ_POD) )
+	else if (objType->size && (objType->flags & asOBJ_POD))
 	{
 		memcpy(dstObj, srcObj, objType->size);
 	}
+	else
+	{
+		asIScriptContext* ctx = asGetActiveContext();
+		if (ctx)
+			ctx->SetException("Cannot do value assignment");
+		return asNOT_SUPPORTED;
+	}
 
 	return asSUCCESS;
 }
@@ -5730,7 +5787,7 @@ int asCScriptEngine::RegisterFuncdef(const char *decl)
 	}
 
 	// Check name conflicts
-	r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace, true, false);
+	r = bld.CheckNameConflict(func->name.AddressOf(), 0, 0, defaultNamespace, true, false, false);
 	if( r < 0 )
 	{
 		asDELETE(func,asCScriptFunction);
@@ -5901,7 +5958,7 @@ int asCScriptEngine::RegisterTypedef(const char *type, const char *decl)
 		return ConfigError(asINVALID_NAME, "RegisterTypedef", type, decl);
 
 	asCBuilder bld(this, 0);
-	int r = bld.CheckNameConflict(type, 0, 0, defaultNamespace, true, false);
+	int r = bld.CheckNameConflict(type, 0, 0, defaultNamespace, true, false, false);
 	if( r < 0 )
 		return ConfigError(asNAME_TAKEN, "RegisterTypedef", type, decl);
 
@@ -5973,7 +6030,7 @@ int asCScriptEngine::RegisterEnum(const char *name)
 	if( token != ttIdentifier || strlen(name) != tokenLen )
 		return ConfigError(asINVALID_NAME, "RegisterEnum", name, 0);
 
-	r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false);
+	r = bld.CheckNameConflict(name, 0, 0, defaultNamespace, true, false, false);
 	if( r < 0 )
 		return ConfigError(asNAME_TAKEN, "RegisterEnum", name, 0);
 

+ 3 - 1
Source/ThirdParty/AngelScript/source/as_scriptengine.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2019 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -504,6 +504,8 @@ public:
 		asUINT genericCallMode;
 		asUINT initCallStackSize;
 		asUINT maxCallStackSize;
+		bool   ignoreDuplicateSharedIntf;
+		bool   noDebugOutput;
 	} ep;
 
 	// Callbacks

+ 127 - 15
Source/ThirdParty/AngelScript/source/as_scriptfunction.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -969,7 +969,7 @@ const char *asCScriptFunction::GetVarDecl(asUINT index, bool includeNamespace) c
 }
 
 // internal
-void asCScriptFunction::AddVariable(asCString &in_name, asCDataType &in_type, int in_stackOffset)
+void asCScriptFunction::AddVariable(const asCString &in_name, asCDataType &in_type, int in_stackOffset, bool in_onHeap)
 {
 	asASSERT( scriptData );
 	asSScriptVariable *var = asNEW(asSScriptVariable);
@@ -981,6 +981,7 @@ void asCScriptFunction::AddVariable(asCString &in_name, asCDataType &in_type, in
 	var->name                 = in_name;
 	var->type                 = in_type;
 	var->stackOffset          = in_stackOffset;
+	var->onHeap               = in_onHeap;
 	var->declaredAtProgramPos = 0;
 	scriptData->variables.PushLast(var);
 }
@@ -990,10 +991,10 @@ asCTypeInfo *asCScriptFunction::GetTypeInfoOfLocalVar(short varOffset)
 {
 	asASSERT( scriptData );
 
-	for( asUINT n = 0; n < scriptData->objVariablePos.GetLength(); n++ )
+	for( asUINT n = 0; n < scriptData->variables.GetLength(); n++ )
 	{
-		if( scriptData->objVariablePos[n] == varOffset )
-			return scriptData->objVariableTypes[n];
+		if (scriptData->variables[n]->stackOffset == varOffset)
+			return scriptData->variables[n]->type.GetTypeInfo();
 	}
 
 	return 0;
@@ -1096,14 +1097,17 @@ void asCScriptFunction::AddReferences()
 				if( group != 0 ) group->AddRef();
 			}
 
-		for( asUINT v = 0; v < scriptData->objVariableTypes.GetLength(); v++ )
-			if( scriptData->objVariableTypes[v] ) // The null handle is also stored, but it doesn't have an object type
+		for (asUINT v = 0; v < scriptData->variables.GetLength(); v++)
+		{
+			asCTypeInfo* ti = reinterpret_cast<asCTypeInfo*>(scriptData->variables[v]->type.GetTypeInfo());
+			if (ti) // The null handle is also stored, but it doesn't have an object type
 			{
-				scriptData->objVariableTypes[v]->AddRefInternal();
+				ti->AddRefInternal();
 
-				asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(scriptData->objVariableTypes[v]);
-				if( group != 0 ) group->AddRef();
+				asCConfigGroup* group = engine->FindConfigGroupForTypeInfo(ti);
+				if (group != 0) group->AddRef();
 			}
+		}
 
 		// Go through the byte code and add references to all resources used by the function
 		asCArray<asDWORD> &bc = scriptData->byteCode;
@@ -1253,14 +1257,17 @@ void asCScriptFunction::ReleaseReferences()
 				if( group != 0 ) group->Release();
 			}
 
-		for( asUINT v = 0; v < scriptData->objVariableTypes.GetLength(); v++ )
-			if( scriptData->objVariableTypes[v] ) // The null handle is also stored, but it doesn't have an object type
+		for (asUINT v = 0; v < scriptData->variables.GetLength(); v++)
+		{
+			asCTypeInfo* ti = reinterpret_cast<asCTypeInfo*>(scriptData->variables[v]->type.GetTypeInfo());
+			if (ti) // The null handle is also stored, but it doesn't have an object type
 			{
-				scriptData->objVariableTypes[v]->ReleaseInternal();
+				ti->ReleaseInternal();
 
-				asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(scriptData->objVariableTypes[v]);
-				if( group != 0 ) group->Release();
+				asCConfigGroup* group = engine->FindConfigGroupForTypeInfo(ti);
+				if (group != 0) group->Release();
 			}
+		}
 
 		// Go through the byte code and release references to all resources used by the function
 		asCArray<asDWORD> &bc = scriptData->byteCode;
@@ -1739,5 +1746,110 @@ bool asCScriptFunction::IsFactory() const
 	return true;
 }
 
+// internal
+asCScriptFunction* asCScriptFunction::FindNextFunctionCalled(asUINT startSearchFromProgramPos, int *outStackDelta, asUINT *outProgramPos)
+{
+	if (scriptData == 0)
+		return 0;
+
+	if (outProgramPos)
+		*outProgramPos = startSearchFromProgramPos;
+
+	// Find out which function that will be called
+	asCScriptFunction* calledFunc = 0;
+	int stackDelta = 0;
+	for (asUINT n = startSearchFromProgramPos; scriptData->byteCode.GetLength(); )
+	{
+		asBYTE bc = *(asBYTE*)&scriptData->byteCode[n];
+		if (bc == asBC_CALL ||
+			bc == asBC_CALLSYS ||
+			bc == asBC_Thiscall1 ||
+			bc == asBC_CALLINTF ||
+			bc == asBC_ALLOC ||
+			bc == asBC_CALLBND ||
+			bc == asBC_CallPtr)
+		{
+			calledFunc = GetCalledFunction(n);
+
+			if (outProgramPos)
+				*outProgramPos = n + asBCTypeSize[asBCInfo[bc].type];
+
+			break;
+		}
+
+		// Keep track of the stack size between the
+		// instruction that needs to be adjusted and the call
+		stackDelta += asBCInfo[bc].stackInc;
+
+		n += asBCTypeSize[asBCInfo[bc].type];
+	}
+
+	if (outStackDelta)
+		*outStackDelta = stackDelta;
+
+	return calledFunc;
+}
+
+// internal
+asCScriptFunction* asCScriptFunction::GetCalledFunction(asDWORD programPos)
+{
+	if (scriptData == 0)
+		return 0;
+
+	asBYTE bc = *(asBYTE*)&scriptData->byteCode[programPos];
+
+	if (bc == asBC_CALL ||
+		bc == asBC_CALLSYS ||
+		bc == asBC_Thiscall1 ||
+		bc == asBC_CALLINTF)
+	{
+		// Find the function from the function id in bytecode
+		int funcId = asBC_INTARG(&scriptData->byteCode[programPos]);
+		return engine->scriptFunctions[funcId];
+	}
+	else if (bc == asBC_ALLOC)
+	{
+		// Find the function from the function id in the bytecode
+		int funcId = asBC_INTARG(&scriptData->byteCode[programPos + AS_PTR_SIZE]);
+		return engine->scriptFunctions[funcId];
+	}
+	else if (bc == asBC_CALLBND)
+	{
+		// Find the function from the engine's bind array
+		int funcId = asBC_INTARG(&scriptData->byteCode[programPos]);
+		return engine->importedFunctions[funcId & ~FUNC_IMPORTED]->importedFunctionSignature;
+	}
+	else if (bc == asBC_CallPtr)
+	{
+		asUINT v;
+		int var = asBC_SWORDARG0(&scriptData->byteCode[programPos]);
+
+		// Find the funcdef from the local variable
+		for (v = 0; v < scriptData->variables.GetLength(); v++)
+			if (scriptData->variables[v]->stackOffset == var)
+				return CastToFuncdefType(scriptData->variables[v]->type.GetTypeInfo())->funcdef;
+
+		// Look in parameters
+		int paramPos = 0;
+		if (objectType)
+			paramPos -= AS_PTR_SIZE;
+		if (DoesReturnOnStack())
+			paramPos -= AS_PTR_SIZE;
+		for (v = 0; v < parameterTypes.GetLength(); v++)
+		{
+			if (var == paramPos)
+			{
+				if (parameterTypes[v].IsFuncdef())
+					return CastToFuncdefType(parameterTypes[v].GetTypeInfo())->funcdef;
+				else
+					return 0;
+			}
+			paramPos -= parameterTypes[v].GetSizeOnStackDWords();
+		}
+	}
+
+	return 0;
+}
+
 END_AS_NAMESPACE
 

+ 10 - 13
Source/ThirdParty/AngelScript/source/as_scriptfunction.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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
@@ -61,7 +61,8 @@ struct asSScriptVariable
 	asCString   name;
 	asCDataType type;
 	int         stackOffset;
-	asUINT      declaredAtProgramPos;
+	asUINT      onHeap : 1;
+	asUINT      declaredAtProgramPos : 31;
 };
 
 enum asEListPatternNodeType
@@ -237,7 +238,7 @@ public:
 
 	void      DestroyInternal();
 
-	void      AddVariable(asCString &name, asCDataType &type, int stackOffset);
+	void      AddVariable(const asCString &name, asCDataType &type, int stackOffset, bool onHeap);
 
 	int       GetSpaceNeededForArguments();
 	int       GetSpaceNeededForReturnValue();
@@ -268,6 +269,9 @@ public:
 	void      AllocateScriptFunctionData();
 	void      DeallocateScriptFunctionData();
 
+	asCScriptFunction* FindNextFunctionCalled(asUINT startSearchFromProgramPos, int *stackDelta, asUINT *outProgramPos);
+	asCScriptFunction* GetCalledFunction(asDWORD programPos);
+
 	asCGlobalProperty *GetPropertyByGlobalVarPtr(void *gvarPtr);
 
 	// GC methods (for delegates)
@@ -328,15 +332,6 @@ public:
 		// The stack space needed for the local variables
 		asDWORD                         variableSpace;
 
-		// These hold information on objects and function pointers, including temporary
-		// variables used by exception handler and when saving bytecode
-		asCArray<asCTypeInfo*>          objVariableTypes;
-		asCArray<int>                   objVariablePos; // offset on stackframe
-
-		// 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;
 
@@ -349,8 +344,10 @@ public:
 		// JIT compiled code of this function
 		asJITFunction                   jitFunction;
 
-		// Holds debug information on explicitly declared variables
+		// Holds type information on both explicitly declared variables and temporary variables
+		// Used during exception handling, byte code serialization, debugging, and context serialization
 		asCArray<asSScriptVariable*>    variables;
+
 		// Store position, line number pairs for debug information
 		asCArray<int>                   lineNumbers;
 		// Store the script section where the code was declared

+ 2 - 2
Source/ThirdParty/AngelScript/source/as_texts.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2021 Andreas Jonsson
+   Copyright (c) 2003-2022 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 
@@ -107,7 +107,7 @@
 #define TXT_EXPECTED_PRE_OPERATOR             "Expected pre operator"
 #define TXT_EXPECTED_STRING                   "Expected string"
 #define TXT_EXPR_DOESNT_EVAL_TO_FUNC          "Expression doesn't evaluate to a function"
-#define TXT_EXPR_MUST_BE_BOOL                 "Expression must be of boolean type"
+#define TXT_EXPR_MUST_BE_BOOL_s               "Expression must be of boolean type, instead found '%s'"
 #define TXT_EXPR_s_IS_DATA_TYPE               "Expression '%s' is a data type"
 #define TXT_EXTERNAL_SHARED_s_NOT_FOUND       "External shared entity '%s' not found"
 #define TXT_EXTERNAL_SHARED_s_CANNOT_REDEF    "External shared entity '%s' cannot redefine the original entity"

+ 5 - 5
Source/ThirdParty/AngelScript/source/as_tokendef.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2019 Andreas Jonsson
+   Copyright (c) 2003-2021 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,8 +101,8 @@ enum eTokenType
 	ttListSeparator,       // ,
 	ttStartStatementBlock, // {
 	ttEndStatementBlock,   // }
-	ttOpenParanthesis,     // (
-	ttCloseParanthesis,    // )
+	ttOpenParenthesis,     // (
+	ttCloseParenthesis,    // )
 	ttOpenBracket,         // [
 	ttCloseBracket,        // ]
 	ttAmp,                 // &
@@ -231,8 +231,8 @@ sTokenWord const tokenWords[] =
 	asTokenDef(","         , ttListSeparator),
 	asTokenDef("{"         , ttStartStatementBlock),
 	asTokenDef("}"         , ttEndStatementBlock),
-	asTokenDef("("         , ttOpenParanthesis),
-	asTokenDef(")"         , ttCloseParanthesis),
+	asTokenDef("("         , ttOpenParenthesis),
+	asTokenDef(")"         , ttCloseParenthesis),
 	asTokenDef("["         , ttOpenBracket),
 	asTokenDef("]"         , ttCloseBracket),
 	asTokenDef("?"         , ttQuestion),

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