Browse Source

Migrated to AngelScript 2.22.1 WIP.

Lasse Öörni 14 years ago
parent
commit
c5f6516aee
33 changed files with 2132 additions and 1176 deletions
  1. 1 1
      Docs/Urho3D.dox
  2. 1 1
      Readme.txt
  3. 22 20
      ThirdParty/AngelScript/include/angelscript.h
  4. 552 61
      ThirdParty/AngelScript/source/as_builder.cpp
  5. 18 3
      ThirdParty/AngelScript/source/as_builder.h
  6. 235 235
      ThirdParty/AngelScript/source/as_callfunc_arm_gcc.S
  7. 242 242
      ThirdParty/AngelScript/source/as_callfunc_arm_msvc.asm
  8. 303 196
      ThirdParty/AngelScript/source/as_compiler.cpp
  9. 14 15
      ThirdParty/AngelScript/source/as_compiler.h
  10. 0 1
      ThirdParty/AngelScript/source/as_config.h
  11. 1 1
      ThirdParty/AngelScript/source/as_datatype.cpp
  12. 15 15
      ThirdParty/AngelScript/source/as_map.h
  13. 7 1
      ThirdParty/AngelScript/source/as_module.cpp
  14. 1 1
      ThirdParty/AngelScript/source/as_module.h
  15. 318 37
      ThirdParty/AngelScript/source/as_parser.cpp
  16. 7 1
      ThirdParty/AngelScript/source/as_parser.h
  17. 63 102
      ThirdParty/AngelScript/source/as_restore.cpp
  18. 2 0
      ThirdParty/AngelScript/source/as_restore.h
  19. 8 0
      ThirdParty/AngelScript/source/as_scriptcode.cpp
  20. 9 7
      ThirdParty/AngelScript/source/as_scriptcode.h
  21. 24 22
      ThirdParty/AngelScript/source/as_scriptengine.cpp
  22. 7 1
      ThirdParty/AngelScript/source/as_scriptengine.h
  23. 14 0
      ThirdParty/AngelScript/source/as_scriptfunction.cpp
  24. 5 0
      ThirdParty/AngelScript/source/as_scriptfunction.h
  25. 2 1
      ThirdParty/AngelScript/source/as_scriptnode.h
  26. 41 30
      ThirdParty/AngelScript/source/as_string.cpp
  27. 22 1
      ThirdParty/AngelScript/source/as_string.h
  28. 32 1
      ThirdParty/AngelScript/source/as_string_util.cpp
  29. 3 1
      ThirdParty/AngelScript/source/as_string_util.h
  30. 7 1
      ThirdParty/AngelScript/source/as_texts.h
  31. 43 37
      ThirdParty/AngelScript/source/as_tokendef.h
  32. 95 122
      ThirdParty/AngelScript/source/as_tokenizer.cpp
  33. 18 19
      ThirdParty/AngelScript/source/as_tokenizer.h

+ 1 - 1
Docs/Urho3D.dox

@@ -59,7 +59,7 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org/) and Horde3D (http://
 
 Urho3D uses the following third-party libraries:
 
-- AngelScript 2.22.0 (http://www.angelcode.com/angelscript/)
+- AngelScript 2.22.1 WIP (http://www.angelcode.com/angelscript/)
 - FreeType 2.3.12 (http://www.freetype.org/)
 - GLee 5.4 (http://elf-stone.com/)
 - GLFW 3.0 WIP (http://www.glfw.org/)

+ 1 - 1
Readme.txt

@@ -34,7 +34,7 @@ Urho3D is greatly inspired by OGRE (http://www.ogre3d.org) and Horde3D
   http://warp.povusers.org/SortComparison/
 
 Urho3D uses the following third-party libraries:
-- AngelScript 2.22.0 (http://www.angelcode.com/angelscript/)
+- AngelScript 2.22.1 WIP (http://www.angelcode.com/angelscript/)
 - FreeType 2.3.12 (http://www.freetype.org/)
 - GLee 5.4 (http://elf-stone.com/)
 - GLFW 3.0 WIP (http://www.glfw.org/)

+ 22 - 20
ThirdParty/AngelScript/include/angelscript.h

@@ -56,8 +56,8 @@ BEGIN_AS_NAMESPACE
 
 // AngelScript version
 
-#define ANGELSCRIPT_VERSION        22200
-#define ANGELSCRIPT_VERSION_STRING "2.22.0"
+#define ANGELSCRIPT_VERSION        22201
+#define ANGELSCRIPT_VERSION_STRING "2.22.1 WIP"
 
 // Data types
 
@@ -76,23 +76,24 @@ class asIJITCompiler;
 // Engine properties
 enum asEEngineProp
 {
-	asEP_ALLOW_UNSAFE_REFERENCES      = 1,
-	asEP_OPTIMIZE_BYTECODE            = 2,
-	asEP_COPY_SCRIPT_SECTIONS         = 3,
-	asEP_MAX_STACK_SIZE               = 4,
-	asEP_USE_CHARACTER_LITERALS       = 5,
-	asEP_ALLOW_MULTILINE_STRINGS      = 6,
-	asEP_ALLOW_IMPLICIT_HANDLE_TYPES  = 7,
-	asEP_BUILD_WITHOUT_LINE_CUES      = 8,
-	asEP_INIT_GLOBAL_VARS_AFTER_BUILD = 9,
-	asEP_REQUIRE_ENUM_SCOPE           = 10,
-	asEP_SCRIPT_SCANNER               = 11,
-	asEP_INCLUDE_JIT_INSTRUCTIONS     = 12,
-	asEP_STRING_ENCODING              = 13,
-	asEP_PROPERTY_ACCESSOR_MODE       = 14,
-	asEP_EXPAND_DEF_ARRAY_TO_TMPL     = 15,
-	asEP_AUTO_GARBAGE_COLLECT         = 16,
-	asEP_DISALLOW_GLOBAL_VARS         = 17
+	asEP_ALLOW_UNSAFE_REFERENCES       = 1,
+	asEP_OPTIMIZE_BYTECODE             = 2,
+	asEP_COPY_SCRIPT_SECTIONS          = 3,
+	asEP_MAX_STACK_SIZE                = 4,
+	asEP_USE_CHARACTER_LITERALS        = 5,
+	asEP_ALLOW_MULTILINE_STRINGS       = 6,
+	asEP_ALLOW_IMPLICIT_HANDLE_TYPES   = 7,
+	asEP_BUILD_WITHOUT_LINE_CUES       = 8,
+	asEP_INIT_GLOBAL_VARS_AFTER_BUILD  = 9,
+	asEP_REQUIRE_ENUM_SCOPE            = 10,
+	asEP_SCRIPT_SCANNER                = 11,
+	asEP_INCLUDE_JIT_INSTRUCTIONS      = 12,
+	asEP_STRING_ENCODING               = 13,
+	asEP_PROPERTY_ACCESSOR_MODE        = 14,
+	asEP_EXPAND_DEF_ARRAY_TO_TMPL      = 15,
+	asEP_AUTO_GARBAGE_COLLECT          = 16,
+	asEP_DISALLOW_GLOBAL_VARS          = 17,
+	asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT = 18
 };
 
 // Calling conventions
@@ -143,7 +144,8 @@ enum asEObjTypeFlags
 	asOBJ_APP_CLASS_ALLFLOATS        = 0x10000,
 	asOBJ_MASK_VALID_FLAGS           = 0x1FFFF,
 	asOBJ_SCRIPT_OBJECT              = 0x80000,
-	asOBJ_SHARED                     = 0x100000
+	asOBJ_SHARED                     = 0x100000,
+	asOBJ_NOINHERIT                  = 0x200000
 };
 
 // Behaviours

+ 552 - 61
ThirdParty/AngelScript/source/as_builder.cpp

@@ -69,6 +69,11 @@ asCBuilder::~asCBuilder()
 				functions[n]->node->Destroy(engine);
 			}
 
+			if( functions[n]->explicitSignature )
+			{
+				asDELETE(functions[n]->explicitSignature,sExplicitSignature);
+			}
+
 			asDELETE(functions[n],sFunctionDescription);
 		}
 
@@ -293,9 +298,9 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
 	node = node->firstChild;
 
 	// Create the function
-	bool isConstructor, isDestructor, isPrivate;
+	bool isConstructor, isDestructor, isPrivate, isFinal, isOverride;
 	asCScriptFunction *func = asNEW(asCScriptFunction)(engine,module,asFUNC_SCRIPT);
-	GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate);
+	GetParsedFunctionDetails(node, scripts[0], 0, func->name, func->returnType, func->parameterTypes, func->inOutFlags, func->defaultArgs, func->isReadOnly, isConstructor, isDestructor, isPrivate, isFinal, isOverride);
 	func->id               = engine->GetNextScriptFunctionId();
 	func->scriptSectionIdx = engine->GetScriptSectionNameIndex(sectionName ? sectionName : "");
 
@@ -328,13 +333,14 @@ int asCBuilder::CompileFunction(const char *sectionName, const char *code, int l
 	node->DisconnectParent();
 	sFunctionDescription *funcDesc = asNEW(sFunctionDescription);
 	functions.PushLast(funcDesc);
-	funcDesc->script = scripts[0];
-	funcDesc->node   = node;
-	funcDesc->name   = func->name;
-	funcDesc->funcId = func->id;
+	funcDesc->script            = scripts[0];
+	funcDesc->node              = node;
+	funcDesc->name              = func->name;
+	funcDesc->funcId            = func->id;
+	funcDesc->explicitSignature = 0;
 
 	asCCompiler compiler(engine);
-	if( compiler.CompileFunction(this, functions[0]->script, functions[0]->node, func) >= 0 )
+	if( compiler.CompileFunction(this, functions[0]->script, 0, functions[0]->node, func) >= 0 )
 	{
 		// Return the function
 		*outFunc = func;
@@ -438,6 +444,11 @@ void asCBuilder::ParseScripts()
 					node->DisconnectParent();
 					RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, decl->script, decl->objType, true);
 				}
+				else if( node->nodeType == snVirtualProperty )
+				{
+					node->DisconnectParent();
+					RegisterVirtualProperty(node, decl->script, decl->objType, true, false);
+				}
 
 				node = next;
 			}
@@ -467,6 +478,11 @@ void asCBuilder::ParseScripts()
 					node->DisconnectParent();
 					RegisterScriptFunction(engine->GetNextScriptFunctionId(), node, decl->script, decl->objType);
 				}
+				else if( node->nodeType == snVirtualProperty )
+				{
+					node->DisconnectParent();
+					RegisterVirtualProperty(node, decl->script, decl->objType, false, false);
+				}
 
 				node = next;
 			}
@@ -474,7 +490,31 @@ void asCBuilder::ParseScripts()
 			// Make sure the default factory & constructor exists for classes
 			if( decl->objType->beh.construct == engine->scriptTypeBehaviours.beh.construct )
 			{
-				AddDefaultConstructor(decl->objType, decl->script);
+				if( decl->objType->beh.constructors.GetLength() == 1 || engine->ep.alwaysImplDefaultConstruct )
+				{
+					AddDefaultConstructor(decl->objType, decl->script);
+				}
+				else
+				{
+					// As the class has another constructor we shouldn't provide the default constructor
+					if( decl->objType->beh.construct )
+					{
+						engine->scriptFunctions[decl->objType->beh.construct]->Release();
+						decl->objType->beh.construct = 0;
+						decl->objType->beh.constructors.RemoveIndex(0);
+					}
+					if( decl->objType->beh.factory )
+					{
+						engine->scriptFunctions[decl->objType->beh.factory]->Release();
+						decl->objType->beh.factory = 0;
+						decl->objType->beh.factories.RemoveIndex(0);
+					}
+					if( decl->objType->beh.copy )
+					{
+						engine->scriptFunctions[decl->objType->beh.copy]->Release();
+						decl->objType->beh.copy = 0;
+					}
+				}
 			}
 		}
 
@@ -497,6 +537,10 @@ void asCBuilder::ParseScripts()
 				{
 					RegisterGlobalVar(node, scripts[n]);
 				}
+				else if( node->nodeType == snVirtualProperty )
+				{
+					RegisterVirtualProperty(node, scripts[n], 0, false, true);
+				}
 				else if( node->nodeType == snImport )
 				{
 					RegisterImportedFunction(module->GetNextImportedFunctionId(), node, scripts[n]);
@@ -528,30 +572,35 @@ void asCBuilder::CompileFunctions()
 	// Compile each function
 	for( asUINT n = 0; n < functions.GetLength(); n++ )
 	{
-		if( functions[n] == 0 ) continue;
+		sFunctionDescription *current = functions[n];
+		if( current == 0 ) continue;
 
 		asCCompiler compiler(engine);
-		asCScriptFunction *func = engine->scriptFunctions[functions[n]->funcId];
+		asCScriptFunction *func = engine->scriptFunctions[current->funcId];
 
-		if( functions[n]->node )
+		if( current->node )
 		{
 			int r, c;
-			functions[n]->script->ConvertPosToRowCol(functions[n]->node->tokenPos, &r, &c);
+			current->script->ConvertPosToRowCol(current->node->tokenPos, &r, &c);
 
 			asCString str = func->GetDeclarationStr();
 			str.Format(TXT_COMPILING_s, str.AddressOf());
-			WriteInfo(functions[n]->script->name.AddressOf(), str.AddressOf(), r, c, true);
+			WriteInfo(current->script->name.AddressOf(), str.AddressOf(), r, c, true);
 
-			compiler.CompileFunction(this, functions[n]->script, functions[n]->node, func);
+			compiler.CompileFunction(this, current->script, current->explicitSignature, current->node, func);
 
 			preMessage.isSet = false;
 		}
-		else
+		else if( current->name == current->objType->name )
 		{
 			// This is the default constructor, that is generated
 			// automatically if not implemented by the user.
-			asASSERT( functions[n]->name == functions[n]->objType->name );
-			compiler.CompileDefaultConstructor(this, functions[n]->script, func);
+			compiler.CompileDefaultConstructor(this, current->script, func);
+		}
+		else
+		{
+			// This is a property accessor, but no implementation was provided for it
+			asASSERT( current->explicitSignature );
 		}
 	}
 }
@@ -1115,8 +1164,10 @@ void asCBuilder::CompleteFuncDef(sFuncDef *funcDef)
 	bool                       isConstructor;
 	bool                       isDestructor;
 	bool                       isPrivate;
+	bool                       isOverride;
+	bool                       isFinal;
 
-	GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, returnType, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate);
+	GetParsedFunctionDetails(funcDef->node, funcDef->script, 0, funcDef->name, returnType, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal);
 
 	asCScriptFunction *func = module->funcDefs[funcDef->idx];
 	if( func )
@@ -1203,17 +1254,30 @@ int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file)
 int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file)
 {
 	asCScriptNode *n = node->firstChild;
-	asCString name(&file->code[n->tokenPos], n->tokenLength);
-
+	bool isFinal = false;
 	bool isShared = false;
-	if( name == SHARED_TOKEN )
+
+	if( n->tokenType == ttIdentifier && file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) )
 	{
-		isShared = true;
+		isFinal = true;
+		n = n->next;
+	}
 
+	if( n->tokenType == ttIdentifier && file->TokenEquals(n->tokenPos, n->tokenLength, SHARED_TOKEN) )
+	{
+		isShared = true;
 		n = n->next;
-		name.Assign(&file->code[n->tokenPos], n->tokenLength);
+
+		// Check for final again
+		if( n->tokenType == ttIdentifier && file->TokenEquals(n->tokenPos, n->tokenLength, FINAL_TOKEN) )
+		{
+			isFinal = true;
+			n = n->next;
+		}
 	}
 
+	asCString name(&file->code[n->tokenPos], n->tokenLength);
+
 	int r, c;
 	file->ConvertPosToRowCol(n->tokenPos, &r, &c);
 
@@ -1255,6 +1319,9 @@ int asCBuilder::RegisterClass(asCScriptNode *node, asCScriptCode *file)
 	if( isShared )
 		st->flags |= asOBJ_SHARED;
 
+	if( isFinal )
+		st->flags |= asOBJ_NOINHERIT;
+
 	if( node->tokenType == ttHandle )
 		st->flags |= asOBJ_IMPLICIT_HANDLE;
 
@@ -1647,14 +1714,25 @@ void asCBuilder::CompileClasses()
 
 		// Find the base class that this class inherits from
 		bool multipleInheritance = false;
-		asCScriptNode *node = decl->node->firstChild->next;
+		asCScriptNode *node = decl->node->firstChild;
 
 		if( decl->objType->IsShared() )
 		{
 			// Skip the keyword 'shared'
+			asASSERT(node->tokenType == ttIdentifier);
+			node = node->next;
+		}
+		if( decl->objType->flags & asOBJ_NOINHERIT )
+		{
+			// skip the keyword 'final'
+			asASSERT(node->tokenType == ttIdentifier);
 			node = node->next;
 		}
 
+		// Skip the name of the class
+		asASSERT(node->tokenType == ttIdentifier);
+		node = node->next;
+
 		while( node && node->nodeType == snIdentifier )
 		{
 			// Get the interface name from the node
@@ -1671,12 +1749,15 @@ void asCBuilder::CompileClasses()
 				str.Format(TXT_IDENTIFIER_s_NOT_DATA_TYPE, name.AddressOf());
 				WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
 			}
-			else if( !(objType->flags & asOBJ_SCRIPT_OBJECT) )
+			else if( !(objType->flags & asOBJ_SCRIPT_OBJECT) || 
+					 objType->flags & asOBJ_NOINHERIT )
 			{
+				// Either the class is not a script class or interface
+				// or the class has been declared as 'final'
 				int r, c;
 				file->ConvertPosToRowCol(node->tokenPos, &r, &c);
 				asCString str;
-				str.Format(TXT_CANNOT_INHERIT_FROM_s, objType->name.AddressOf());
+				str.Format(TXT_CANNOT_INHERIT_FROM_s_FINAL, objType->name.AddressOf());
 				WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
 			}
 			else if( objType->size != 0 )
@@ -1874,6 +1955,15 @@ void asCBuilder::CompileClasses()
 					derivedFunc = GetFunctionDescription(decl->objType->methods[d]);
 					if( derivedFunc->IsSignatureEqual(baseFunc) )
 					{
+						if( baseFunc->IsFinal() )
+						{
+							int r, c;
+							decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
+							asCString msg;
+							msg.Format(TXT_METHOD_CANNOT_OVERRIDE_s, baseFunc->GetDeclaration());
+							WriteError(decl->script->name.AddressOf(), msg.AddressOf(), r, c);
+						}
+
 						// Move the function from the methods array to the virtualFunctionTable
 						decl->objType->methods.RemoveIndex(d);
 						decl->objType->virtualFunctionTable.PushLast(derivedFunc);
@@ -1913,6 +2003,10 @@ void asCBuilder::CompileClasses()
 
 		// Enumerate each of the declared properties
 		asCScriptNode *node = decl->node->firstChild->next;
+		if( decl->objType->IsShared() )
+			node = node->next;
+		if( decl->objType->flags & asOBJ_NOINHERIT )
+			node = node->next;
 
 		// Skip list of classes and interfaces
 		while( node && node->nodeType == snIdentifier )
@@ -1960,18 +2054,33 @@ void asCBuilder::CompileClasses()
 		toValidate.PushLast(decl);
 	}
 
+	// TODO: Warn if a method overrides a base method without marking it as 'override'. 
+	//       It must be possible to turn off this warning through engine property.
+
+	// TODO: A base class should be able to mark a method as 'abstract'. This will
+	//       allow a base class to provide a partial implementation, but still force
+	//       derived classes to implement specific methods.
+
 	// Verify that all interface methods are implemented in the classes
 	// We do this here so the base class' methods have already been inherited 
 	for( n = 0; n < classDeclarations.GetLength(); n++ )
 	{
 		sClassDeclaration *decl = classDeclarations[n];
 		if( decl->isExistingShared ) continue;
+
+		asCArray<bool> overrideValidations(decl->objType->GetMethodCount());
+		for( asUINT k = 0; k < decl->objType->methods.GetLength(); k++ )
+		{
+			overrideValidations.PushLast( !static_cast<asCScriptFunction*>(decl->objType->GetMethodByIndex(k, false))->IsOverride() );
+		}
+
 		for( asUINT m = 0; m < decl->objType->interfaces.GetLength(); m++ )
 		{
 			asCObjectType *objType = decl->objType->interfaces[m];
 			for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
 			{
-				if( !DoesMethodExist(decl->objType, objType->methods[i]) )
+				asUINT overrideIndex;
+				if( !DoesMethodExist(decl->objType, objType->methods[i], &overrideIndex) )
 				{
 					int r, c;
 					decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
@@ -1980,6 +2089,22 @@ void asCBuilder::CompileClasses()
 						engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
 					WriteError(decl->script->name.AddressOf(), str.AddressOf(), r, c);
 				}
+				else
+					overrideValidations[overrideIndex] = true;
+			}
+		}
+
+		bool hasBaseClass = decl->objType->derivedFrom != 0;
+
+		for( asUINT j = 0; j < overrideValidations.GetLength(); j++ )
+		{
+			if( !overrideValidations[j] && (!hasBaseClass || !DoesMethodExist(decl->objType->derivedFrom, decl->objType->methods[j])) )
+			{
+				int r, c;
+				decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
+				asCString msg;
+				msg.Format(TXT_METHOD_s_DOES_NOT_OVERRIDE, decl->objType->GetMethodByIndex(j, false)->GetDeclaration());
+				WriteError(decl->script->name.AddressOf(), msg.AddressOf(), r, c);
 			}
 		}
 	}
@@ -2117,19 +2242,22 @@ int asCBuilder::CreateVirtualFunction(asCScriptFunction *func, int idx)
 {
 	asCScriptFunction *vf =  asNEW(asCScriptFunction)(engine, module, asFUNC_VIRTUAL);
 
-	vf->funcType = asFUNC_VIRTUAL;
-	vf->name = func->name;
-	vf->returnType = func->returnType;
-	vf->parameterTypes = func->parameterTypes;
-	vf->inOutFlags = func->inOutFlags;
-	vf->id = engine->GetNextScriptFunctionId();
+	vf->funcType         = asFUNC_VIRTUAL;
+	vf->name             = func->name;
+	vf->returnType       = func->returnType;
+	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;
-	vf->isPrivate = func->isPrivate;
-	vf->vfTableIdx = idx;
-	vf->defaultArgs = func->defaultArgs;
+	vf->isReadOnly       = func->isReadOnly;
+	vf->objectType       = func->objectType;
+	vf->signatureId      = func->signatureId;
+	vf->isPrivate        = func->isPrivate;
+	vf->isFinal          = func->isFinal;
+	vf->isOverride       = func->isOverride;
+	vf->vfTableIdx       = idx;
+	vf->defaultArgs      = func->defaultArgs;
+
 	// Copy the default arg strings to avoid multiple deletes on the same object
 	for( asUINT n = 0; n < vf->defaultArgs.GetLength(); n++ )
 		if( vf->defaultArgs[n] )
@@ -2161,7 +2289,7 @@ asCObjectProperty *asCBuilder::AddPropertyToClass(sClassDeclaration *decl, const
 	return decl->objType->AddPropertyToClass(name, dt, isPrivate);
 }
 
-bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId)
+bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex)
 {
 	asCScriptFunction *method = GetFunctionDescription(methodId);
 
@@ -2175,6 +2303,9 @@ bool asCBuilder::DoesMethodExist(asCObjectType *objType, int methodId)
 		if( m->parameterTypes != method->parameterTypes ) continue;
 		if( m->inOutFlags     != method->inOutFlags     ) continue;
 
+		if( methodIndex )
+			*methodIndex = n;
+
 		return true;
 	}
 
@@ -2205,11 +2336,12 @@ void asCBuilder::AddDefaultConstructor(asCObjectType *objType, asCScriptCode *fi
 	sFunctionDescription *func = asNEW(sFunctionDescription);
 	functions.PushLast(func);
 
-	func->script  = file;
-	func->node    = 0;
-	func->name    = objType->name;
-	func->objType = objType;
-	func->funcId  = funcId;
+	func->script            = file;
+	func->node              = 0;
+	func->name              = objType->name;
+	func->objType           = objType;
+	func->funcId            = funcId;
+	func->explicitSignature = 0;
 
 	// Add a default factory as well
 	funcId = engine->GetNextScriptFunctionId();
@@ -2393,7 +2525,7 @@ int asCBuilder::RegisterTypedef(asCScriptNode *node, asCScriptCode *file)
 	return 0;
 }
 
-void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate)
+void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isOverride, bool &isFinal)
 {
 	node = node->firstChild;
 
@@ -2436,11 +2568,31 @@ void asCBuilder::GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *fi
 	else
 		returnType = asCDataType::CreatePrimitive(ttVoid, false);
 
-	// Is this a const method?
-	if( objType && n->next->next && n->next->next->tokenType == ttConst )
-		isConstMethod = true;
-	else
-		isConstMethod = false;
+	isConstMethod = false;
+	isFinal = false;
+	isOverride = false;
+
+	if( objType && n->next->next )
+	{
+		asCScriptNode *decorator = n->next->next;
+
+		// Is this a const method?
+		if( decorator->tokenType == ttConst )
+		{
+			isConstMethod = true;
+			decorator = decorator->next;
+		}
+
+		while( decorator )
+		{
+			if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, FINAL_TOKEN) )
+				isFinal = true;
+			else if( decorator->tokenType == ttIdentifier && file->TokenEquals(decorator->tokenPos, decorator->tokenLength, OVERRIDE_TOKEN) )
+				isOverride = true;
+
+			decorator = decorator->next;
+		}
+	}
 
 	// Count the number of parameters
 	int count = 0;
@@ -2521,11 +2673,13 @@ int asCBuilder::RegisterScriptFunction(int funcId, asCScriptNode *node, asCScrip
 	asCArray<asETypeModifiers> inOutFlags;
 	asCArray<asCString *>      defaultArgs;
 	bool                       isConstMethod;
+	bool                       isOverride;
+	bool                       isFinal;
 	bool                       isConstructor;
 	bool                       isDestructor;
 	bool                       isPrivate;
 
-	GetParsedFunctionDetails(node, file, objType, name, returnType, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate);
+	GetParsedFunctionDetails(node, file, objType, name, returnType, parameterTypes, inOutFlags, defaultArgs, isConstMethod, isConstructor, isDestructor, isPrivate, isOverride, isFinal);
 
 	// Check for name conflicts
 	if( !isConstructor && !isDestructor )
@@ -2563,11 +2717,12 @@ int asCBuilder::RegisterScriptFunction(int funcId, asCScriptNode *node, asCScrip
 		sFunctionDescription *func = asNEW(sFunctionDescription);
 		functions.PushLast(func);
 
-		func->script    = file;
-		func->node      = node;
-		func->name      = name;
-		func->objType   = objType;
-		func->funcId    = funcId;
+		func->script            = file;
+		func->node              = node;
+		func->name              = name;
+		func->objType           = objType;
+		func->funcId            = funcId;
+		func->explicitSignature = 0;
 	}
 
 	// Destructors may not have any parameters
@@ -2647,7 +2802,7 @@ int asCBuilder::RegisterScriptFunction(int funcId, asCScriptNode *node, asCScrip
 	}
 
 	// Register the function
-	module->AddScriptFunction(file->idx, funcId, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType, isConstMethod, isGlobalFunction, isPrivate);
+	module->AddScriptFunction(file->idx, funcId, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType, isConstMethod, isGlobalFunction, isPrivate, isFinal, isOverride);
 
 	// Make sure the default args are declared correctly
 	ValidateDefaultArgs(file, node, engine->scriptFunctions[funcId]);
@@ -2713,6 +2868,339 @@ int asCBuilder::RegisterScriptFunction(int funcId, asCScriptNode *node, asCScrip
 	return 0;
 }
 
+int asCBuilder::RegisterScriptFunctionWithSignature(int funcId, asCScriptNode *node, asCScriptCode *file, asCString &name, sExplicitSignature *signature, asCObjectType *objType, bool isInterface, bool isGlobalFunction, bool isPrivate, bool isConst, bool isFinal, bool isOverride, bool treatAsProperty)
+{
+	bool isConstructor = false;
+	bool isDestructor = false;
+	asCArray<asCDataType> &parameterTypes = signature->argTypes;
+	asCArray<asETypeModifiers> &inOutFlags = signature->argModifiers;
+	asCArray<asCString *> defaultArgs = signature->defaultArgs;
+
+	if( objType && asCDataType::CreatePrimitive(ttVoid, false) == signature->returnType )
+	{
+		if( 0 == name.Compare( objType->name ) )
+			isConstructor = true;
+		else if( 0 == name.Compare( "~" + objType->name ) )
+			isDestructor = true;
+	}
+
+	// Check for name conflicts
+	if( !isConstructor && !isDestructor )
+	{
+		if( objType )
+			CheckNameConflictMember(objType, name.AddressOf(), node, file, treatAsProperty);
+		else
+			CheckNameConflict(name.AddressOf(), node, file);
+	}
+
+	if( isInterface )
+	{
+		asASSERT(!isFinal);
+		asASSERT(!isOverride);
+	}
+	else
+	{
+		sFunctionDescription *func = asNEW(sFunctionDescription);
+		functions.PushLast(func);
+
+		func->script            = file;
+		func->node              = node;
+		func->name              = name;
+		func->objType           = objType;
+		func->funcId            = funcId;
+		func->explicitSignature = signature;
+	}
+
+	// Destructors may not have any parameters
+	if( isDestructor && parameterTypes.GetLength() > 0 )
+	{
+		int r, c;
+		file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+
+		WriteError(file->name.AddressOf(), TXT_DESTRUCTOR_MAY_NOT_HAVE_PARM, r, c);
+	}
+
+	// If class or interface is shared, then only shared types may be used in the method signature
+	if( objType && (objType->flags & asOBJ_SHARED) )
+	{
+		asCObjectType *ot = signature->returnType.GetObjectType();
+		if( ot && (ot->flags & asOBJ_SCRIPT_OBJECT) && !(ot->flags & asOBJ_SHARED) )
+		{
+			int r, c;
+			file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+			asCString msg;
+			msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
+			WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
+		}
+
+		for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
+		{
+			asCObjectType *ot = parameterTypes[p].GetObjectType();
+			if( ot && (ot->flags & asOBJ_SCRIPT_OBJECT) && !(ot->flags & asOBJ_SHARED) )
+			{
+				int r, c;
+				file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+				asCString msg;
+				msg.Format(TXT_SHARED_CANNOT_USE_NON_SHARED_TYPE_s, ot->name.AddressOf());
+				WriteError(file->name.AddressOf(), msg.AddressOf(), r, c);
+			}
+		}
+	}
+
+	// TODO: Much of this can probably be reduced by using the IsSignatureEqual method
+	// Check that the same function hasn't been registered already
+	asCArray<int> funcs;
+	GetFunctionDescriptions(name.AddressOf(), funcs);
+	if( funcs.GetLength() )
+	{
+		for( asUINT n = 0; n < funcs.GetLength(); ++n )
+		{
+			asCScriptFunction *func = GetFunctionDescription(funcs[n]);
+
+			if( parameterTypes.GetLength() == func->parameterTypes.GetLength() )
+			{
+				bool match = true;
+				if( func->objectType != objType )
+				{
+					match = false;
+					break;
+				}
+
+				for( asUINT p = 0; p < parameterTypes.GetLength(); ++p )
+				{
+					if( parameterTypes[p] != func->parameterTypes[p] )
+					{
+						match = false;
+						break;
+					}
+				}
+
+				if( match )
+				{
+					int r, c;
+					file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+
+					WriteError(file->name.AddressOf(), TXT_FUNCTION_ALREADY_EXIST, r, c);
+					break;
+				}
+			}
+		}
+	}
+
+	// Register the function
+	module->AddScriptFunction(file->idx, funcId, name.AddressOf(), signature->returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType, isConst, isGlobalFunction, isPrivate, isFinal, isOverride);
+
+	// Make sure the default args are declared correctly
+	ValidateDefaultArgs(file, node, engine->scriptFunctions[funcId]);
+
+	if( objType )
+	{
+		engine->scriptFunctions[funcId]->AddRef();
+		if( isConstructor )
+		{
+			int factoryId = engine->GetNextScriptFunctionId();
+			if( parameterTypes.GetLength() == 0 )
+			{
+				// Overload the default constructor
+				engine->scriptFunctions[objType->beh.construct]->Release();
+				objType->beh.construct = funcId;
+				objType->beh.constructors[0] = funcId;
+
+				// Register the default factory as well
+				engine->scriptFunctions[objType->beh.factory]->Release();
+				objType->beh.factory = factoryId;
+				objType->beh.factories[0] = factoryId;
+			}
+			else
+			{
+				objType->beh.constructors.PushLast(funcId);
+
+				// Register the factory as well
+				objType->beh.factories.PushLast(factoryId);
+			}
+
+			// We must copy the default arg strings to avoid deleting the same object multiple times
+			for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
+				if( defaultArgs[n] )
+					defaultArgs[n] = asNEW(asCString)(*defaultArgs[n]);
+
+			asCDataType dt = asCDataType::CreateObjectHandle(objType, false);
+			module->AddScriptFunction(file->idx, factoryId, name.AddressOf(), dt, parameterTypes.AddressOf(), inOutFlags.AddressOf(), defaultArgs.AddressOf(), (asUINT)parameterTypes.GetLength(), false);
+
+			// Add a dummy function to the builder so that it doesn't mix up the fund Ids
+			functions.PushLast(0);
+
+			// Compile the factory immediately
+			asCCompiler compiler(engine);
+			compiler.CompileFactory(this, file, engine->scriptFunctions[factoryId]);
+			engine->scriptFunctions[factoryId]->AddRef();
+		}
+		else if( isDestructor )
+			objType->beh.destruct = funcId;
+		else
+			objType->methods.PushLast(funcId);
+	}
+
+	// We need to delete the node already if this is an interface method
+	if( isInterface && node )
+	{
+		node->Destroy(engine);
+	}
+
+	return 0;
+}
+
+int asCBuilder::RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface, bool isGlobalFunction)
+{
+	if( engine->ep.propertyAccessorMode != 2 )
+	{
+		int r, c;
+		file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+		WriteError(file->name.AddressOf(), TXT_PROPERTY_ACCESSOR_DISABLED, r, c);
+		node->Destroy(engine);
+		return 0;
+	}
+
+	bool isPrivate = false;
+	asCString emulatedName;
+	asCDataType emulatedType;
+	
+	if( !isGlobalFunction && node->tokenType == ttPrivate )
+	{
+		isPrivate = true;
+		node = node->next;
+	}
+
+	asCScriptNode *mainNode = node;
+	node = node->firstChild;
+
+	emulatedType = CreateDataTypeFromNode(node, file);
+	emulatedType = ModifyDataTypeFromNode(emulatedType, node->next, file, 0, 0);
+	node = node->next->next;
+
+	emulatedName.Assign(&file->code[node->tokenPos], node->tokenLength);
+	node = node->next;
+
+	while( node )
+	{
+		asCScriptNode *next           = node->next;
+		asCScriptNode *funcNode       = 0;
+		sExplicitSignature *signature = 0;
+		bool success                  = false;
+		bool isConst                  = false;
+		bool isFinal                  = false;
+		bool isOverride               = false;
+
+		asCString name;
+
+		// TODO: getset: Allow private for individual property accessors
+		// TODO: getset: If the accessor uses its own name, then the property should be automatically declared
+
+		if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, GET_TOKEN) )
+		{
+			funcNode  = node->firstChild->next;
+
+			if( funcNode && funcNode->tokenType == ttConst )
+			{
+				isConst = true;
+				funcNode = funcNode->next;
+			}
+
+			while( funcNode && funcNode->nodeType != snStatementBlock )
+			{
+				if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
+					isFinal = true;
+				else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
+					isOverride = true;
+
+				funcNode = funcNode->next;
+			}
+
+			if( funcNode )
+				funcNode->DisconnectParent();
+
+			if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
+			{
+				// TODO: getset: If no implementation is supplied the builder should provide an automatically generated implementation
+				//               The compiler needs to be able to handle the different types, primitive, value type, and handle
+				//               The code is also different for global property accessors
+				int r, c;
+				file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+
+				WriteError(file->name.AddressOf(), TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, r, c);
+			}
+
+			signature = asNEW(sExplicitSignature);
+			
+			signature->returnType = emulatedType;
+
+			name    = "get_" + emulatedName;
+			success = true;
+		}
+		else if( node->firstChild->nodeType == snIdentifier && file->TokenEquals(node->firstChild->tokenPos, node->firstChild->tokenLength, SET_TOKEN) )
+		{
+			funcNode  = node->firstChild->next;
+
+			if( funcNode && funcNode->tokenType == ttConst )
+			{
+				isConst = true;
+				funcNode = funcNode->next;
+			}
+
+			while( funcNode && funcNode->nodeType != snStatementBlock )
+			{
+				if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, FINAL_TOKEN) )
+					isFinal = true;
+				else if( funcNode->tokenType == ttIdentifier && file->TokenEquals(funcNode->tokenPos, funcNode->tokenLength, OVERRIDE_TOKEN) )
+					isOverride = true;
+
+				funcNode = funcNode->next;
+			}
+
+			if( funcNode )
+				funcNode->DisconnectParent();
+
+			if( funcNode == 0 && (objType == 0 || !objType->IsInterface()) )
+			{
+				int r, c;
+				file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+
+				WriteError(file->name.AddressOf(), TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED, r, c);
+			}
+
+			signature = asNEW(sExplicitSignature)(1);
+
+			signature->returnType = asCDataType::CreatePrimitive(ttVoid, false);
+
+			signature->argModifiers.PushLast(asTM_NONE);
+			signature->argNames.PushLast("value");
+			signature->argTypes.PushLast(emulatedType);
+			signature->defaultArgs.PushLast(0);
+
+			name    = "set_" + emulatedName;
+			success = true;
+		}
+		else
+		{
+			int r, c;
+			file->ConvertPosToRowCol(node->tokenPos, &r, &c);
+
+			WriteError(file->name.AddressOf(), TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE, r, c);
+		}
+
+		if( success )
+		{
+			RegisterScriptFunctionWithSignature(engine->GetNextScriptFunctionId(), funcNode, file, name, signature, objType, isInterface, isGlobalFunction, isPrivate, isConst, isFinal, isOverride, true);
+		}
+
+		node = next;
+	};
+
+	mainNode->Destroy(engine);
+
+	return 0;
+}
+
 int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file)
 {
 	// Find name
@@ -2827,8 +3315,13 @@ asCScriptFunction *asCBuilder::GetFunctionDescription(int id)
 
 void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs)
 {
+	// TODO: optimize: Improve linear searches in GetFunctionDescriptions
+	//                 A large part of the compilation time seems to be spent in this function
+	//                 I need to have a map with all global functions so that it will be
+	//                 quicker to find them by name. The key should be the function name, and 
+	//                 the value a list with all the functions using that name
+
 	asUINT n;
-	// TODO: optimize: Improve linear search
 	for( n = 0; n < module->scriptFunctions.GetLength(); n++ )
 	{
 		if( module->scriptFunctions[n]->name == name &&
@@ -2836,14 +3329,12 @@ void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs)
 			funcs.PushLast(module->scriptFunctions[n]->id);
 	}
 
-	// TODO: optimize: Improve linear search
 	for( n = 0; n < module->bindInformations.GetLength(); n++ )
 	{
 		if( module->bindInformations[n]->importedFunctionSignature->name == name )
 			funcs.PushLast(module->bindInformations[n]->importedFunctionSignature->id);
 	}
 
-	// TODO: optimize: Improve linear search
 	// TODO: optimize: Use the registeredGlobalFunctions array instead
 	for( n = 0; n < engine->scriptFunctions.GetLength(); n++ )
 	{

+ 18 - 3
ThirdParty/AngelScript/source/as_builder.h

@@ -50,12 +50,24 @@
 
 BEGIN_AS_NAMESPACE
 
+struct sExplicitSignature
+{
+	sExplicitSignature(int argCount = 0) : argTypes(argCount), argModifiers(argCount), argNames(argCount), defaultArgs(argCount) {}
+
+	asCDataType returnType;
+	asCArray<asCDataType> argTypes;
+	asCArray<asETypeModifiers> argModifiers;
+	asCArray<asCString> argNames;
+	asCArray<asCString *> defaultArgs;
+};
+
 struct sFunctionDescription
 {
 	asCScriptCode *script;
 	asCScriptNode *node;
 	asCString name;
 	asCObjectType *objType;
+	sExplicitSignature *explicitSignature;
 	int funcId;
 };
 
@@ -76,7 +88,7 @@ struct sGlobalVariableDescription
 
 struct sClassDeclaration
 {
-	sClassDeclaration() {script = 0; node = 0; validState = 0; objType = 0; isExistingShared = false;}
+	sClassDeclaration() {script = 0; node = 0; validState = 0; objType = 0; isExistingShared = false; isFinal = false;}
 
 	asCScriptCode *script;
 	asCScriptNode *node;
@@ -84,6 +96,7 @@ struct sClassDeclaration
 	int validState;
 	asCObjectType *objType;
 	bool isExistingShared;
+	bool isFinal;
 };
 
 struct sFuncDef
@@ -136,6 +149,8 @@ protected:
 	void GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst, const asCString &scope = "");
 
 	int RegisterScriptFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false);
+	int RegisterScriptFunctionWithSignature(int funcID, asCScriptNode *node, asCScriptCode *file, asCString &name, sExplicitSignature *signature, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false, bool isPrivate = false, bool isConst = false, bool isFinal = false, bool isOverride = false, bool treatAsProperty = false);
+	int RegisterVirtualProperty(asCScriptNode *node, asCScriptCode *file, asCObjectType *object = 0, bool isInterface = false, bool isGlobalFunction = false);
 	int RegisterImportedFunction(int funcID, asCScriptNode *node, asCScriptCode *file);
 	int RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file);
 	int RegisterClass(asCScriptNode *node, asCScriptCode *file);
@@ -146,10 +161,10 @@ protected:
 	void CompleteFuncDef(sFuncDef *funcDef);
 	void CompileClasses();
 
-	void GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate);
+	void GetParsedFunctionDetails(asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, asCString &name, asCDataType &returnType, asCArray<asCDataType> &parameterTypes, asCArray<asETypeModifiers> &inOutFlags, asCArray<asCString *> &defaultArgs, bool &isConstMethod, bool &isConstructor, bool &isDestructor, bool &isPrivate, bool &isOverride, bool &isFinal);
 	int  ValidateDefaultArgs(asCScriptCode *script, asCScriptNode *node, asCScriptFunction *func);
 
-	bool DoesMethodExist(asCObjectType *objType, int methodId);
+	bool DoesMethodExist(asCObjectType *objType, int methodId, asUINT *methodIndex = 0);
 
 	void AddDefaultConstructor(asCObjectType *objType, asCScriptCode *file);
 	asCObjectProperty *AddPropertyToClass(sClassDeclaration *c, const asCString &name, const asCDataType &type, bool isPrivate, asCScriptCode *file = 0, asCScriptNode *node = 0);

+ 235 - 235
ThirdParty/AngelScript/source/as_callfunc_arm_gcc.S

@@ -1,235 +1,235 @@
-/*
-  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
-
-// Adapted to GNUC by darktemplar216 in September 2009
-
-#if defined(__arm__) || defined(__ARM__)
-
-.global armFunc
-.global armFuncR0
-.global armFuncR0R1
-.global armFuncObjLast
-.global armFuncR0ObjLast
-    
-armFunc:
-    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}
-
-armFuncObjLast:
-    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     nomoreargsarmFuncObjLast
-
-    // 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     nomoreargsarmFuncObjLast
-
-    // 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
-stackargslooparmFuncObjLast:
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     stackargslooparmFuncObjLast
-nomoreargsarmFuncObjLast:
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    add     sp, sp, #4
-    ldmia   sp!, {r4-r8, pc}
-
-armFuncR0ObjLast:
-    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     nomoreargsarmFuncR0ObjLast
-
-    // 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     nomoreargsarmFuncR0ObjLast
-
-    // 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
-stackargslooparmFuncR0ObjLast:
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     stackargslooparmFuncR0ObjLast
-nomoreargsarmFuncR0ObjLast:
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    add     sp, sp, #4
-    ldmia   sp!, {r4-r8, pc}
-
-
-armFuncR0:
-    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     nomoreargsarmFuncR0
-
-    // 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     nomoreargsarmFuncR0
-
-    // 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
-stackargslooparmFuncR0:
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     stackargslooparmFuncR0
-nomoreargsarmFuncR0:
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    ldmia   sp!, {r4-r8, pc}
-
-
-armFuncR0R1:
-    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     nomoreargsarmFuncR0R1
-
-    // 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     nomoreargsarmFuncR0R1
-
-    // 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
-stackargslooparmFuncR0R1:
-    ldr     r5, [r6], #4
-    str     r5, [sp], #4
-    subs    r7, r7, #4
-    bne     stackargslooparmFuncR0R1
-nomoreargsarmFuncR0R1:
-    sub     sp, sp, r8
-    blx     r4
-    add     sp, sp, r8
-    ldmia   sp!, {r4-r8, pc}
-
-#endif
+/*
+  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
+
+// Adapted to GNUC by darktemplar216 in September 2009
+
+#if defined(__arm__) || defined(__ARM__)
+
+.global armFunc
+.global armFuncR0
+.global armFuncR0R1
+.global armFuncObjLast
+.global armFuncR0ObjLast
+    
+armFunc:
+    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}
+
+armFuncObjLast:
+    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     nomoreargsarmFuncObjLast
+
+    // 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     nomoreargsarmFuncObjLast
+
+    // 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
+stackargslooparmFuncObjLast:
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     stackargslooparmFuncObjLast
+nomoreargsarmFuncObjLast:
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    add     sp, sp, #4
+    ldmia   sp!, {r4-r8, pc}
+
+armFuncR0ObjLast:
+    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     nomoreargsarmFuncR0ObjLast
+
+    // 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     nomoreargsarmFuncR0ObjLast
+
+    // 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
+stackargslooparmFuncR0ObjLast:
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     stackargslooparmFuncR0ObjLast
+nomoreargsarmFuncR0ObjLast:
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    add     sp, sp, #4
+    ldmia   sp!, {r4-r8, pc}
+
+
+armFuncR0:
+    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     nomoreargsarmFuncR0
+
+    // 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     nomoreargsarmFuncR0
+
+    // 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
+stackargslooparmFuncR0:
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     stackargslooparmFuncR0
+nomoreargsarmFuncR0:
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    ldmia   sp!, {r4-r8, pc}
+
+
+armFuncR0R1:
+    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     nomoreargsarmFuncR0R1
+
+    // 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     nomoreargsarmFuncR0R1
+
+    // 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
+stackargslooparmFuncR0R1:
+    ldr     r5, [r6], #4
+    str     r5, [sp], #4
+    subs    r7, r7, #4
+    bne     stackargslooparmFuncR0R1
+nomoreargsarmFuncR0R1:
+    sub     sp, sp, r8
+    blx     r4
+    add     sp, sp, r8
+    ldmia   sp!, {r4-r8, pc}
+
+#endif

+ 242 - 242
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

File diff suppressed because it is too large
+ 303 - 196
ThirdParty/AngelScript/source/as_compiler.cpp


+ 14 - 15
ThirdParty/AngelScript/source/as_compiler.h

@@ -78,7 +78,8 @@ struct asSExprContext
 	}
 	~asSExprContext() 
 	{
-		asASSERT(property_arg == 0);
+		if( property_arg )
+			asDELETE(property_arg, asSExprContext);
 	}
 
 	asCByteCode bc;
@@ -107,7 +108,7 @@ public:
 	asCCompiler(asCScriptEngine *engine);
 	~asCCompiler();
 
-	int CompileFunction(asCBuilder *builder, asCScriptCode *script, asCScriptNode *func, asCScriptFunction *outFunc);
+	int CompileFunction(asCBuilder *builder, asCScriptCode *script, sExplicitSignature *signature, asCScriptNode *func, asCScriptFunction *outFunc);
 	int CompileDefaultConstructor(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc);
 	int CompileFactory(asCBuilder *builder, asCScriptCode *script, asCScriptFunction *outFunc);
 	int CompileTemplateFactoryStub(asCBuilder *builder, int trueFactoryId, asCObjectType *objType, asCScriptFunction *outFunc);
@@ -170,10 +171,10 @@ protected:
 	int  FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asCScriptNode *node, bool isThisAccess = false);
 	int  FindPropertyAccessor(const asCString &name, asSExprContext *ctx, asSExprContext *arg, asCScriptNode *node, bool isThisAccess = false);
 	void SwapPostFixOperands(asCArray<asCScriptNode *> &postfix, asCArray<asCScriptNode *> &target);
-	void PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, asCArray<int> *reservedVars, bool forceOnHeap = false);
+	void PrepareTemporaryObject(asCScriptNode *node, asSExprContext *ctx, bool forceOnHeap = false);
 	void PrepareOperand(asSExprContext *ctx, asCScriptNode *node);
 	void PrepareForAssignment(asCDataType *lvalue, asSExprContext *rvalue, asCScriptNode *node, bool toTemporary, asSExprContext *lvalueExpr = 0);
-	void PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asCByteCode *bc, asCScriptNode *node);
+	int  PerformAssignment(asCTypeInfo *lvalue, asCTypeInfo *rvalue, asCByteCode *bc, asCScriptNode *node);
 	bool IsVariableInitialized(asCTypeInfo *type, asCScriptNode *node);
 	void Dereference(asSExprContext *ctx, bool generateCode);
 	bool CompileRefCast(asSExprContext *ctx, const asCDataType &to, bool isExplicit, asCScriptNode *node, bool generateCode = true);
@@ -184,8 +185,8 @@ protected:
 	void PrepareFunctionCall(int funcId, asCByteCode *bc, asCArray<asSExprContext *> &args);
 	void AfterFunctionCall(int funcId, asCArray<asSExprContext*> &args, asSExprContext *ctx, bool deferAll);
 	void ProcessDeferredParams(asSExprContext *ctx);
-	void PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction = false, int refType = 0, asCArray<int> *reservedVars = 0, bool forceOnHeap = false);
-	void PrepareArgument2(asSExprContext *ctx, asSExprContext *arg, asCDataType *paramType, bool isFunction = false, int refType = 0, asCArray<int> *reservedVars = 0);
+	void PrepareArgument(asCDataType *paramType, asSExprContext *ctx, asCScriptNode *node, bool isFunction = false, int refType = 0, bool isMakingCopy = false);
+	void PrepareArgument2(asSExprContext *ctx, asSExprContext *arg, asCDataType *paramType, bool isFunction = false, int refType = 0, bool isMakingCopy = false);
 	bool IsLValue(asCTypeInfo &type);
 	int  DoAssignment(asSExprContext *out, asSExprContext *lctx, asSExprContext *rctx, asCScriptNode *lexpr, asCScriptNode *rexpr, int op, asCScriptNode *opNode);
 	void MergeExprBytecode(asSExprContext *before, asSExprContext *after);
@@ -193,20 +194,18 @@ protected:
 	void FilterConst(asCArray<int> &funcs);
 	void ConvertToVariable(asSExprContext *ctx);
 	void ConvertToVariableNotIn(asSExprContext *ctx, asSExprContext *exclude);
-	void ConvertToVariableNotIn(asSExprContext *ctx, asCArray<int> *reservedVars);
 	void ConvertToTempVariable(asSExprContext *ctx);
 	void ConvertToTempVariableNotIn(asSExprContext *ctx, asSExprContext *exclude);
-	void ConvertToTempVariableNotIn(asSExprContext *ctx, asCArray<int> *reservedVars);
 	void ConvertToReference(asSExprContext *ctx);
 	void PushVariableOnStack(asSExprContext *ctx, bool asReference);
 	asCString GetScopeFromNode(asCScriptNode *node);
 	void DestroyVariables(asCByteCode *bc);
 
-	void ImplicitConversion(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, asCArray<int> *reservedVars = 0, bool allowObjectConstruct = true);
-	void ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, asCArray<int> *reservedVars = 0);
-	void ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, asCArray<int> *reservedVars = 0);
-	void ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, asCArray<int> *reservedVars = 0, bool allowObjectConstruct = true);
-	void ImplicitConvObjectToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, asCArray<int> *reservedVars = 0, bool allowObjectConstruct = true);
+	void ImplicitConversion(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true);
+	void ImplicitConvPrimitiveToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true);
+	void ImplicitConvObjectToPrimitive(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true);
+	void ImplicitConvPrimitiveToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true);
+	void ImplicitConvObjectToObject(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType, bool generateCode = true, bool allowObjectConstruct = true);
 	void ImplicitConversionConstant(asSExprContext *ctx, const asCDataType &to, asCScriptNode *node, EImplicitConv convType);
 
 	void LineInstr(asCByteCode *bc, size_t pos);
@@ -220,7 +219,6 @@ protected:
 	void Information(const char *msg, asCScriptNode *node);
 	void PrintMatchingFuncs(asCArray<int> &funcs, asCScriptNode *node);
 
-
 	void AddVariableScope(bool isBreakScope = false, bool isContinueScope = false);
 	void RemoveVariableScope();
 
@@ -245,7 +243,7 @@ protected:
 	asCArray<int> continueLabels;
 
 	int AllocateVariable(const asCDataType &type, bool isTemporary, bool forceOnHeap = false);
-	int AllocateVariableNotIn(const asCDataType &type, bool isTemporary, asCArray<int> *vars, bool forceOnHeap = false);
+	int AllocateVariableNotIn(const asCDataType &type, bool isTemporary, bool forceOnHeap, asSExprContext *ctx);
 	int GetVariableOffset(int varIndex);
 	int GetVariableSlot(int varOffset);
 	void DeallocateVariable(int pos);
@@ -258,6 +256,7 @@ protected:
 	asCArray<bool>        variableIsOnHeap;
 	asCArray<int>         freeVariables;
 	asCArray<int>         tempVariables;
+	asCArray<int>         reservedVariables;
 
 	bool isCompilingDefaultArg;
 	bool isProcessingDeferredParams;

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

@@ -911,7 +911,6 @@
 #endif
 
 // Urho3D: always use float type, use EMMS to clear FPU stack
-#define AS_OLD
 #define AS_USE_DOUBLE_AS_FLOAT
 #define CLEAR_FPU_STACK emms
 

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

@@ -152,7 +152,7 @@ asCString asCDataType::Format() const
 
 	if( tokenType != ttIdentifier )
 	{
-		str += asGetTokenDefinition(tokenType);
+		str += asCTokenizer::GetDefinition(tokenType);
 	}
 	else if( IsArrayType() && objectType && !objectType->engine->ep.expandDefaultArrayToTemplate )
 	{

+ 15 - 15
ThirdParty/AngelScript/source/as_map.h

@@ -48,7 +48,7 @@ public:
 	~asCMap();
 
 	int   Insert(const KEY &key, const VAL &value);
-	int   GetCount();
+	int   GetCount() const;
 	
 	const KEY &GetKey(const asSMapNode<KEY,VAL> *cursor) const;
 	const VAL &GetValue(const asSMapNode<KEY,VAL> *cursor) const;
@@ -59,15 +59,15 @@ public:
 
 	// Returns true as long as cursor is valid
 
-	bool MoveTo(asSMapNode<KEY,VAL> **out, const KEY &key);
-	bool MoveFirst(asSMapNode<KEY,VAL> **out);
-	bool MoveLast(asSMapNode<KEY,VAL> **out);
-	bool MoveNext(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor);
-	bool MovePrev(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor);
+	bool MoveTo(asSMapNode<KEY,VAL> **out, const KEY &key) const;
+	bool MoveFirst(asSMapNode<KEY,VAL> **out) const;
+	bool MoveLast(asSMapNode<KEY,VAL> **out) const;
+	bool MoveNext(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor) const;
+	bool MovePrev(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor) const;
 
 	// For debugging only
 
-	int CheckIntegrity(asSMapNode<KEY,VAL> *node);
+	int CheckIntegrity(asSMapNode<KEY,VAL> *node) const;
 
 protected:
 	void BalanceInsert(asSMapNode<KEY,VAL> *node);
@@ -146,7 +146,7 @@ int asCMap<KEY, VAL>::EraseAll(asSMapNode<KEY, VAL> *p)
 }
 
 template <class KEY, class VAL>
-int asCMap<KEY, VAL>::GetCount()
+int asCMap<KEY, VAL>::GetCount() const
 {
 	return count;
 }
@@ -286,7 +286,7 @@ void asCMap<KEY, VAL>::BalanceInsert(asSMapNode<KEY, VAL> *node)
 
 // For debugging purposes only
 template <class KEY, class VAL>
-int asCMap<KEY, VAL>::CheckIntegrity(asSMapNode<KEY, VAL> *node)
+int asCMap<KEY, VAL>::CheckIntegrity(asSMapNode<KEY, VAL> *node) const
 {
 	if( node == 0 ) 
 	{
@@ -315,7 +315,7 @@ int asCMap<KEY, VAL>::CheckIntegrity(asSMapNode<KEY, VAL> *node)
 
 // Returns true if successful
 template <class KEY, class VAL>
-bool asCMap<KEY, VAL>::MoveTo(asSMapNode<KEY,VAL> **out, const KEY &key)
+bool asCMap<KEY, VAL>::MoveTo(asSMapNode<KEY,VAL> **out, const KEY &key) const
 {
 	asSMapNode<KEY,VAL> *p = root;
 	while( p )
@@ -633,7 +633,7 @@ const VAL &asCMap<KEY, VAL>::GetValue(const asSMapNode<KEY,VAL> *cursor) const
 }
 
 template <class KEY, class VAL>
-VAL &asCMap<KEY, VAL>::GetValue(asSMapNode<KEY,VAL> *cursor)
+VAL &asCMap<KEY, VAL>::GetValue(asSMapNode<KEY,VAL> *cursor) 
 {
 	if( cursor == 0 ) 
 		return dummy.value;
@@ -651,7 +651,7 @@ const KEY &asCMap<KEY, VAL>::GetKey(const asSMapNode<KEY,VAL> *cursor) const
 }
 
 template <class KEY, class VAL>
-bool asCMap<KEY, VAL>::MoveFirst(asSMapNode<KEY,VAL> **out)
+bool asCMap<KEY, VAL>::MoveFirst(asSMapNode<KEY,VAL> **out) const
 {
 	*out = root;
 	if( root == 0 ) return false;
@@ -663,7 +663,7 @@ bool asCMap<KEY, VAL>::MoveFirst(asSMapNode<KEY,VAL> **out)
 }
 
 template <class KEY, class VAL>
-bool asCMap<KEY, VAL>::MoveLast(asSMapNode<KEY,VAL> **out)
+bool asCMap<KEY, VAL>::MoveLast(asSMapNode<KEY,VAL> **out) const
 {
 	*out = root;
 	if( root == 0 ) return false;
@@ -675,7 +675,7 @@ bool asCMap<KEY, VAL>::MoveLast(asSMapNode<KEY,VAL> **out)
 }
 
 template <class KEY, class VAL>
-bool asCMap<KEY, VAL>::MoveNext(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor)
+bool asCMap<KEY, VAL>::MoveNext(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor) const
 {
 	if( cursor == 0 )
 	{
@@ -706,7 +706,7 @@ bool asCMap<KEY, VAL>::MoveNext(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *
 }
 
 template <class KEY, class VAL>
-bool asCMap<KEY, VAL>::MovePrev(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor)
+bool asCMap<KEY, VAL>::MovePrev(asSMapNode<KEY,VAL> **out, asSMapNode<KEY,VAL> *cursor) const
 {
 	if( cursor == 0 ) 
 	{

+ 7 - 1
ThirdParty/AngelScript/source/as_module.cpp

@@ -763,7 +763,7 @@ int asCModule::GetNextImportedFunctionId()
 }
 
 // internal
-int asCModule::AddScriptFunction(int sectionIdx, int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, asCString **defaultArgs, int paramCount, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate)
+int asCModule::AddScriptFunction(int sectionIdx, int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, asCString **defaultArgs, int paramCount, bool isInterface, asCObjectType *objType, bool isConstMethod, bool isGlobalFunction, bool isPrivate, bool isFinal, bool isOverride)
 {
 	asASSERT(id >= 0);
 
@@ -782,6 +782,12 @@ int asCModule::AddScriptFunction(int sectionIdx, int id, const char *name, const
 	func->objectType = objType;
 	func->isReadOnly = isConstMethod;
 	func->isPrivate  = isPrivate;
+	func->isFinal    = isFinal;
+	func->isOverride = isOverride;
+
+	// Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
+	asASSERT( !(!objType && isFinal) );
+	asASSERT( !(!objType && isOverride) );
 
 	// The script function's refCount was initialized to 1
 	scriptFunctions.PushLast(func);

+ 1 - 1
ThirdParty/AngelScript/source/as_module.h

@@ -183,7 +183,7 @@ public:
 
 	void JITCompile();
 
-	int  AddScriptFunction(int sectionIdx, int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, asCString **defaultArgs, int paramCount, bool isInterface, asCObjectType *objType = 0, bool isConstMethod = false, bool isGlobalFunction = false, bool isPrivate = false);
+	int  AddScriptFunction(int sectionIdx, int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, asCString **defaultArgs, int paramCount, bool isInterface, asCObjectType *objType = 0, bool isConstMethod = false, bool isGlobalFunction = false, bool isPrivate = false, bool isFinal = false, bool isOverride = false);
 	int  AddScriptFunction(asCScriptFunction *func);
 	int  AddImportedFunction(int id, const char *name, const asCDataType &returnType, asCDataType *params, asETypeModifiers *inOutFlags, int paramCount, const asCString &moduleName);
 	int  AddFuncDef(const char *name);

+ 318 - 37
ThirdParty/AngelScript/source/as_parser.cpp

@@ -48,7 +48,7 @@
 
 BEGIN_AS_NAMESPACE
 
-asCParser::asCParser(asCBuilder *builder) : tokenizer(builder->engine)
+asCParser::asCParser(asCBuilder *builder)
 {
 	this->builder    = builder;
 	this->engine     = builder->engine;
@@ -120,7 +120,7 @@ int asCParser::ParseFunctionDefinition(asCScriptCode *script)
 		GetToken(&t);
 		if( t.type != ttEnd )
 		{
-			Error(ExpectedToken(asGetTokenDefinition(ttEnd)).AddressOf(), &t);
+			Error(ExpectedToken(asCTokenizer::GetDefinition(ttEnd)).AddressOf(), &t);
 			return -1;
 		}
 	}
@@ -160,7 +160,7 @@ int asCParser::ParseDataType(asCScriptCode *script)
 	GetToken(&t);
 	if( t.type != ttEnd )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttEnd)).AddressOf(), &t);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttEnd)).AddressOf(), &t);
 		return -1;
 	}
 
@@ -186,7 +186,7 @@ int asCParser::ParseTemplateDecl(asCScriptCode *script)
 	GetToken(&t);
 	if( t.type != ttLessThan )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttLessThan)).AddressOf(), &t);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttLessThan)).AddressOf(), &t);
 		return -1;
 	}
 
@@ -201,14 +201,14 @@ int asCParser::ParseTemplateDecl(asCScriptCode *script)
 	GetToken(&t);
 	if( t.type != ttGreaterThan )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttGreaterThan)).AddressOf(), &t);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttGreaterThan)).AddressOf(), &t);
 		return -1;
 	}
 
 	GetToken(&t);
 	if( t.type != ttEnd )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttEnd)).AddressOf(), &t);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttEnd)).AddressOf(), &t);
 		return -1;
 	}
 
@@ -237,7 +237,51 @@ int asCParser::ParsePropertyDeclaration(asCScriptCode *script)
 	GetToken(&t);
 	if( t.type != ttEnd )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttEnd)).AddressOf(), &t);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttEnd)).AddressOf(), &t);
+		return -1;
+	}
+
+	return 0;
+}
+
+int asCParser::ParseVirtualPropertyDeclaration(asCScriptCode *script, bool asMethod)
+{
+	Reset();
+
+	this->script = script;
+
+	scriptNode = new(engine->memoryMgr.AllocScriptNode()) asCScriptNode(snVirtualProperty);
+
+	sToken t;
+	
+
+	scriptNode->AddChildLast(ParseType(true));
+	if( isSyntaxError ) return -1;
+
+	scriptNode->AddChildLast(ParseTypeMod(false));
+	if( isSyntaxError ) return -1;
+
+	scriptNode->AddChildLast(ParseIdentifier());
+	if( isSyntaxError ) return -1;
+
+	if( asMethod )
+	{
+		GetToken(&t);
+		RewindTo(&t);
+
+		if( t.type == ttConst )
+		{
+			scriptNode->AddChildLast(ParseToken(ttConst));
+			if( isSyntaxError ) return -1;
+		}
+	}
+
+	GetToken(&t);
+
+	// The declaration should end after the identifier
+	if( t.type != ttEnd )
+	{
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttEnd)).AddressOf(), &t);
 		return -1;
 	}
 
@@ -252,7 +296,7 @@ asCScriptNode *asCParser::ParseImport()
 	GetToken(&t);
 	if( t.type != ttImport )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttImport)).AddressOf(), &t);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttImport)).AddressOf(), &t);
 		return node;
 	}
 
@@ -295,7 +339,7 @@ asCScriptNode *asCParser::ParseImport()
 	GetToken(&t);
 	if( t.type != ttEndStatement )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttEndStatement)).AddressOf(), &t);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttEndStatement)).AddressOf(), &t);
 		return node;
 	}
 
@@ -330,6 +374,14 @@ asCScriptNode *asCParser::ParseFunctionDefinition()
 	return node;
 }
 
+bool asCParser::IdentifierIs(const sToken &t, const char *str)
+{
+	if( t.type != ttIdentifier ) 
+		return false;
+
+	return script->TokenEquals(t.pos, t.length, str);
+}
+
 asCScriptNode *asCParser::ParseScript()
 {
 	asCScriptNode *node = new(engine->memoryMgr.AllocScriptNode()) asCScriptNode(snScript);
@@ -351,7 +403,9 @@ asCScriptNode *asCParser::ParseScript()
 				node->AddChildLast(ParseEnumeration());	//	Handle enumerations
 			else if( t1.type == ttTypedef )
 				node->AddChildLast(ParseTypedef());		//	Handle primitive typedefs
-			else if( t1.type == ttClass || (t1.type == ttIdentifier && t2.type == ttClass) )
+			else if( t1.type == ttClass || 
+					 ((IdentifierIs(t1, SHARED_TOKEN) || IdentifierIs(t1, FINAL_TOKEN)) && t2.type == ttClass) || 
+					 (IdentifierIs(t1, SHARED_TOKEN) && IdentifierIs(t2, FINAL_TOKEN)) )
 				node->AddChildLast(ParseClass());
 			else if( t1.type == ttInterface || (t1.type == ttIdentifier && t2.type == ttInterface) )
 				node->AddChildLast(ParseInterface());
@@ -359,7 +413,9 @@ asCScriptNode *asCParser::ParseScript()
 				node->AddChildLast(ParseFuncDef());
 			else if( t1.type == ttConst || IsDataType(t1) )
 			{
-				if( IsVarDecl() )
+				if( IsVirtualPropertyDecl() )
+					node->AddChildLast(ParseVirtualPropertyDecl(false, false));
+				else if( IsVarDecl() )
 					node->AddChildLast(ParseGlobalVar());
 				else
 					node->AddChildLast(ParseFunction());
@@ -374,7 +430,7 @@ asCScriptNode *asCParser::ParseScript()
 			else
 			{
 				asCString str;
-				const char *t = asGetTokenDefinition(t1.type);
+				const char *t = asCTokenizer::GetDefinition(t1.type);
 				if( t == 0 ) t = "<unknown token>";
 
 				str.Format(TXT_UNEXPECTED_TOKEN_s, t);
@@ -441,7 +497,7 @@ asCScriptNode *asCParser::ParseEnumeration()
 	GetToken(&token);
 	if( token.type != ttEnum )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttEnum)).AddressOf(), &token);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttEnum)).AddressOf(), &token);
 		return node;
 	}
 
@@ -469,7 +525,7 @@ asCScriptNode *asCParser::ParseEnumeration()
 	if( token.type != ttStartStatementBlock ) 
 	{
 		RewindTo(&token);
-		Error(ExpectedToken(asGetTokenDefinition(token.type)).AddressOf(), &token);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(token.type)).AddressOf(), &token);
 		return node;
 	}
 
@@ -522,7 +578,7 @@ asCScriptNode *asCParser::ParseEnumeration()
 	if( token.type != ttEndStatementBlock ) 
 	{
 		RewindTo(&token);
-		Error(ExpectedToken(asGetTokenDefinition(token.type)).AddressOf(), &token);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(token.type)).AddressOf(), &token);
 		return node;
 	}
 
@@ -671,6 +727,75 @@ bool asCParser::IsVarDecl()
 	return false;
 }
 
+bool asCParser::IsVirtualPropertyDecl()
+{
+	// Set start point so that we can rewind
+	sToken t;
+	GetToken(&t);
+	RewindTo(&t);
+
+	// A class property decl can be preceded by 'private' 
+	sToken t1;
+	GetToken(&t1);
+	if( t1.type != ttPrivate )
+		RewindTo(&t1);
+
+	// A variable decl can start with a const
+	GetToken(&t1);
+	if( t1.type == ttConst )
+		GetToken(&t1);
+
+	// We don't validate if the identifier is an actual declared type at this moment
+	// as it may wrongly identify the statement as a non-declaration if the user typed
+	// the name incorrectly. The real type is validated in ParseDeclaration where a
+	// proper error message can be given.
+	if( !IsRealType(t1.type) && t1.type != ttIdentifier )
+	{
+		RewindTo(&t);
+		return false;
+	}
+
+	if( !CheckTemplateType(t1) )
+	{
+		RewindTo(&t);
+		return false;
+	}
+
+	// Object handles can be interleaved with the array brackets
+	sToken t2;
+	GetToken(&t2);
+	while( t2.type == ttHandle || t2.type == ttOpenBracket )
+	{
+		if( t2.type == ttOpenBracket )
+		{
+			GetToken(&t2);
+			if( t2.type != ttCloseBracket )
+			{
+				RewindTo(&t);
+				return false;
+			}
+		}
+
+		GetToken(&t2);
+	}
+
+	if( t2.type != ttIdentifier )
+	{
+		RewindTo(&t);
+		return false;
+	}
+
+	GetToken(&t2);
+	if( t2.type == ttStartStatementBlock )
+	{
+		RewindTo(&t);
+		return true;
+	}
+
+	RewindTo(&t);
+	return false;
+}
+
 bool asCParser::IsFuncDecl(bool isMethod)
 {
 	// Set start point so that we can rewind
@@ -763,12 +888,23 @@ bool asCParser::IsFuncDecl(bool isMethod)
 			return false;
 		else
 		{
-			// A class method can have a 'const' token after the parameter list
 			if( isMethod )
 			{
+				// A class method can have a 'const' token after the parameter list
 				GetToken(&t1);
 				if( t1.type != ttConst )
 					RewindTo(&t1);
+				
+				// A class method may also have any number of additional inheritance behavior specifiers
+				for( ; ; )
+				{
+					GetToken(&t2);
+					if( !IdentifierIs(t2, FINAL_TOKEN) && !IdentifierIs(t2, OVERRIDE_TOKEN) )
+					{
+						RewindTo(&t2);
+						break;
+					}
+				}
 			}
 
 			GetToken(&t1);
@@ -793,7 +929,7 @@ asCScriptNode *asCParser::ParseFuncDef()
 	GetToken(&t1);
 	if( t1.type != ttFuncDef )
 	{
-		Error(asGetTokenDefinition(ttFuncDef), &t1);
+		Error(asCTokenizer::GetDefinition(ttFuncDef), &t1);
 		return node;
 	}
 
@@ -814,7 +950,7 @@ asCScriptNode *asCParser::ParseFuncDef()
 	GetToken(&t1);
 	if( t1.type != ttEndStatement )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(ttEndStatement)).AddressOf(), &t1);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(ttEndStatement)).AddressOf(), &t1);
 		return node;
 	}
 
@@ -864,11 +1000,15 @@ asCScriptNode *asCParser::ParseFunction(bool isMethod)
 
 	if( isMethod )
 	{
-		// Is the method a const?
 		GetToken(&t1);
 		RewindTo(&t1);
+
+		// Is the method a const?
 		if( t1.type == ttConst )
 			node->AddChildLast(ParseToken(ttConst));
+
+		ParseMethodOverrideBehaviors(node);
+		if( isSyntaxError ) return node;
 	}
 
 	// We should just find the end of the statement block here. The statements 
@@ -913,6 +1053,105 @@ asCScriptNode *asCParser::ParseInterfaceMethod()
 	return node;
 }
 
+asCScriptNode *asCParser::ParseVirtualPropertyDecl(bool isMethod, bool isInterface)
+{
+	asCScriptNode *node = new(engine->memoryMgr.AllocScriptNode()) asCScriptNode(snVirtualProperty);
+
+	sToken t1,t2;
+	GetToken(&t1);
+	GetToken(&t2);
+	RewindTo(&t1);
+
+	// A class method can start with private
+	if( isMethod && t1.type == ttPrivate )
+	{
+		node->AddChildLast(ParseToken(ttPrivate));
+		if( isSyntaxError ) return node;
+	}
+
+	node->AddChildLast(ParseType(true));
+	if( isSyntaxError ) return node;
+
+	node->AddChildLast(ParseTypeMod(false));
+	if( isSyntaxError ) return node;
+
+	node->AddChildLast(ParseIdentifier());
+	if( isSyntaxError ) return node;
+
+	GetToken(&t1);
+	if( t1.type != ttStartStatementBlock )
+	{
+		Error(ExpectedToken("{").AddressOf(), &t1);
+		return node;
+	}
+
+	for(;;)
+	{
+		GetToken(&t1);
+		asCScriptNode *accessorNode = 0;
+
+		if( IdentifierIs(t1, GET_TOKEN) || IdentifierIs(t1, SET_TOKEN) )
+		{
+			accessorNode = new(engine->memoryMgr.AllocScriptNode()) asCScriptNode(snVirtualProperty);
+			node->AddChildLast(accessorNode);
+
+			RewindTo(&t1);
+			accessorNode->AddChildLast(ParseIdentifier());
+			
+			if( isMethod )
+			{
+				GetToken(&t1);
+				RewindTo(&t1);
+				if( t1.type == ttConst )
+					accessorNode->AddChildLast(ParseToken(ttConst));
+
+				if( !isInterface )
+				{
+					ParseMethodOverrideBehaviors(accessorNode);
+					if( isSyntaxError ) return node;
+				}
+			}
+
+			if( !isInterface )
+			{
+				GetToken(&t1);
+				if( t1.type == ttStartStatementBlock )
+				{
+					RewindTo(&t1);
+					accessorNode->AddChildLast(SuperficiallyParseStatementBlock());
+					if( isSyntaxError ) return node;
+				}
+				else if( t1.type != ttEndStatement )
+				{
+					Error(ExpectedTokens(";", "{").AddressOf(), &t1);
+					return node;
+				}
+			}
+			else
+			{
+				GetToken(&t1);
+				if( t1.type != ttEndStatement )
+				{
+					Error(ExpectedToken(";").AddressOf(), &t1);
+					return node;
+				}
+			}
+		}
+		else if( t1.type == ttEndStatementBlock )
+		{
+			break;
+		}
+		else
+		{
+			const char *tokens[] = { GET_TOKEN, SET_TOKEN, asCTokenizer::GetDefinition(ttEndStatementBlock) };
+			Error(ExpectedOneOf(tokens, 3).AddressOf(), &t1);
+			return node;
+		}
+	}
+
+	return node;
+}
+
 asCScriptNode *asCParser::ParseInterface()
 {
 	asCScriptNode *node = new(engine->memoryMgr.AllocScriptNode()) asCScriptNode(snInterface);
@@ -958,8 +1197,16 @@ asCScriptNode *asCParser::ParseInterface()
 	RewindTo(&t);
 	while( t.type != ttEndStatementBlock && t.type != ttEnd )
 	{
-		// Parse the method signature
-		node->AddChildLast(ParseInterfaceMethod());
+		if( IsVirtualPropertyDecl() )
+		{
+			node->AddChildLast(ParseVirtualPropertyDecl(true, true));
+		}
+		else
+		{
+			// Parse the method signature
+			node->AddChildLast(ParseInterfaceMethod());
+		}
+
 		if( isSyntaxError ) return node;
 		
 		GetToken(&t);
@@ -986,16 +1233,15 @@ asCScriptNode *asCParser::ParseClass()
 	GetToken(&t);
 
 	// Allow the keyword 'shared' before 'class'
-	if( t.type == ttIdentifier )
+	if( IdentifierIs(t, SHARED_TOKEN) )
 	{
-		asCString str;
-		str.Assign(&script->code[t.pos], t.length);
-		if( str != SHARED_TOKEN )
-		{
-			Error(ExpectedToken(SHARED_TOKEN).AddressOf(), &t);
-			return node;
-		}
+		RewindTo(&t);
+		node->AddChildLast(ParseIdentifier());
+		GetToken(&t);
+	}
 
+	if( IdentifierIs(t, FINAL_TOKEN) )
+	{
 		RewindTo(&t);
 		node->AddChildLast(ParseIdentifier());
 		GetToken(&t);
@@ -1053,6 +1299,10 @@ asCScriptNode *asCParser::ParseClass()
 			// Parse the method
 			node->AddChildLast(ParseFunction(true));
 		}
+		else if( IsVirtualPropertyDecl() )
+		{
+			node->AddChildLast(ParseVirtualPropertyDecl(true, false));
+		}
 		else if( IsVarDecl() )
 		{
 			// Parse a property declaration
@@ -1326,7 +1576,7 @@ asCScriptNode *asCParser::ParseType(bool allowConst, bool allowVariableType)
 		GetToken(&t);
 		if( t.type != ttLessThan )
 		{
-			Error(ExpectedToken(asGetTokenDefinition(ttLessThan)).AddressOf(), &t);
+			Error(ExpectedToken(asCTokenizer::GetDefinition(ttLessThan)).AddressOf(), &t);
 			return node;
 		}
 
@@ -1338,7 +1588,7 @@ asCScriptNode *asCParser::ParseType(bool allowConst, bool allowVariableType)
 		GetToken(&t);
 		if( script->code[t.pos] != '>' )
 		{
-			Error(ExpectedToken(asGetTokenDefinition(ttGreaterThan)).AddressOf(), &t);
+			Error(ExpectedToken(asCTokenizer::GetDefinition(ttGreaterThan)).AddressOf(), &t);
 			return node;
 		}
 		else
@@ -1389,7 +1639,7 @@ asCScriptNode *asCParser::ParseToken(int token)
 	GetToken(&t1);
 	if( t1.type != token )
 	{
-		Error(ExpectedToken(asGetTokenDefinition(token)).AddressOf(), &t1);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(token)).AddressOf(), &t1);
 		return node;
 	}
 
@@ -2850,7 +3100,7 @@ void asCParser::GetToken(sToken *token)
 			token->length = 0;
 		}
 		else
-			token->type = tokenizer.GetToken(&script->code[sourcePos], sourceLength - sourcePos, &token->length);
+			token->type = engine->tok.GetToken(&script->code[sourcePos], sourceLength - sourcePos, &token->length);
 
 		token->pos = sourcePos;
 
@@ -3036,7 +3286,22 @@ asCString asCParser::ExpectedOneOf(int *tokens, int count)
 	str = TXT_EXPECTED_ONE_OF;
 	for( int n = 0; n < count; n++ )
 	{
-		str += asGetTokenDefinition(tokens[n]);
+		str += asCTokenizer::GetDefinition(tokens[n]);
+		if( n < count-1 )
+			str += ", ";
+	}
+
+	return str;
+}
+
+asCString asCParser::ExpectedOneOf(const char **tokens, int count)
+{
+	asCString str;
+
+	str = TXT_EXPECTED_ONE_OF;
+	for( int n = 0; n < count; n++ )
+	{
+		str += tokens[n];
 		if( n < count-1 )
 			str += ", ";
 	}
@@ -3055,7 +3320,7 @@ asCScriptNode *asCParser::ParseTypedef()
 	GetToken(&token);
 	if( token.type != ttTypedef)
 	{
-		Error(ExpectedToken(asGetTokenDefinition(token.type)).AddressOf(), &token);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(token.type)).AddressOf(), &token);
 		return node;
 	}
 	
@@ -3070,7 +3335,7 @@ asCScriptNode *asCParser::ParseTypedef()
 	if( !IsRealType(token.type) || token.type == ttVoid )
 	{
 		asCString str;
-		str.Format(TXT_UNEXPECTED_TOKEN_s, asGetTokenDefinition(token.type));
+		str.Format(TXT_UNEXPECTED_TOKEN_s, asCTokenizer::GetDefinition(token.type));
 		Error(str.AddressOf(), &token);
 		return node;
 	}
@@ -3083,11 +3348,27 @@ asCScriptNode *asCParser::ParseTypedef()
 	if( token.type != ttEndStatement ) 
 	{
 		RewindTo(&token);
-		Error(ExpectedToken(asGetTokenDefinition(token.type)).AddressOf(), &token);
+		Error(ExpectedToken(asCTokenizer::GetDefinition(token.type)).AddressOf(), &token);
 	}
 
 	return node;
 }
 
+void asCParser::ParseMethodOverrideBehaviors(asCScriptNode *funcNode)
+{
+	sToken t1;
+
+	for( ; ; )
+	{
+		GetToken(&t1);
+		RewindTo(&t1);
+
+		if( IdentifierIs(t1, FINAL_TOKEN) || IdentifierIs(t1, OVERRIDE_TOKEN) )
+			funcNode->AddChildLast(ParseIdentifier());
+		else
+			break;
+	}
+}
+
 END_AS_NAMESPACE
 

+ 7 - 1
ThirdParty/AngelScript/source/as_parser.h

@@ -104,6 +104,7 @@ public:
 	int ParseScript(asCScriptCode *script);
 	int ParseFunctionDefinition(asCScriptCode *script);
 	int ParsePropertyDeclaration(asCScriptCode *script);
+	int ParseVirtualPropertyDeclaration(asCScriptCode *script, bool asMethod);
 	int ParseDataType(asCScriptCode *script);
 	int ParseTemplateDecl(asCScriptCode *script);
 
@@ -169,11 +170,14 @@ protected:
 	asCScriptNode *ParseInitList();
 	asCScriptNode *ParseInterface();
 	asCScriptNode *ParseInterfaceMethod();
+	asCScriptNode *ParseVirtualPropertyDecl(bool isMethod, bool isInterface);
 	asCScriptNode *ParseCast();
 	asCScriptNode *ParseEnumeration();				//	Parse enumeration enum { X, Y }
 	asCScriptNode *ParseTypedef();					//	Parse named type declaration
+	void ParseMethodOverrideBehaviors(asCScriptNode *funcNode);
 
 	bool IsVarDecl();
+	bool IsVirtualPropertyDecl();
 	bool IsFuncDecl(bool isMethod);
 	bool IsRealType(int tokenType);
 	bool IsDataType(const sToken &token);
@@ -184,11 +188,14 @@ protected:
 	bool IsAssignOperator(int tokenType);
 	bool IsFunctionCall();
 
+	bool IdentifierIs(const sToken &t, const char *str);
+
 	bool CheckTemplateType(sToken &t);
 
 	asCString ExpectedToken(const char *token);
 	asCString ExpectedTokens(const char *token1, const char *token2);
 	asCString ExpectedOneOf(int *tokens, int count);
+	asCString ExpectedOneOf(const char **tokens, int count);
 
 	bool errorWhileParsing;
 	bool isSyntaxError;
@@ -200,7 +207,6 @@ protected:
 	asCScriptCode   *script;
 	asCScriptNode   *scriptNode;
 
-	asCTokenizer tokenizer;
 	size_t       sourcePos;
 };
 

+ 63 - 102
ThirdParty/AngelScript/source/as_restore.cpp

@@ -482,12 +482,14 @@ int asCRestore::Restore()
 
 int asCRestore::FindStringConstantIndex(int id)
 {
-	for( asUINT i = 0; i < usedStringConstants.GetLength(); i++ )
-		if( usedStringConstants[i] == id )
-			return i;
+	asSMapNode<int,int> *cursor = 0;
+	if (stringIdToIndexMap.MoveTo(&cursor, id))
+		return cursor->value;
 
 	usedStringConstants.PushLast(id);
-	return int(usedStringConstants.GetLength() - 1);
+	int index = int(usedStringConstants.GetLength() - 1);
+	stringIdToIndexMap.Insert(id, index);
+	return index;
 }
 
 void asCRestore::WriteUsedStringConstants()
@@ -901,12 +903,10 @@ void asCRestore::WriteObjectTypeDeclaration(asCObjectType *ot, int phase)
 			// behaviours
 			if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
 			{
-				WriteFunction(engine->scriptFunctions[ot->beh.construct]);
 				WriteFunction(engine->scriptFunctions[ot->beh.destruct]);
-				WriteFunction(engine->scriptFunctions[ot->beh.factory]);
-				size = (int)ot->beh.constructors.GetLength() - 1;
+				size = (int)ot->beh.constructors.GetLength();
 				WriteEncodedUInt(size);
-				for( n = 1; n < ot->beh.constructors.GetLength(); n++ )
+				for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
 				{
 					WriteFunction(engine->scriptFunctions[ot->beh.constructors[n]]);
 					WriteFunction(engine->scriptFunctions[ot->beh.factories[n]]);
@@ -958,6 +958,10 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 
 		// Use the default script class behaviours
 		ot->beh = engine->scriptTypeBehaviours.beh;
+		ot->beh.construct = 0;
+		ot->beh.factory = 0;
+		ot->beh.constructors.PopLast(); // These will be read from the file
+		ot->beh.factories.PopLast(); // These will be read from the file
 		engine->scriptFunctions[ot->beh.addref]->AddRef();
 		engine->scriptFunctions[ot->beh.release]->AddRef();
 		engine->scriptFunctions[ot->beh.gcEnumReferences]->AddRef();
@@ -966,8 +970,6 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 		engine->scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRef();
 		engine->scriptFunctions[ot->beh.gcSetFlag]->AddRef();
 		engine->scriptFunctions[ot->beh.copy]->AddRef();
-		engine->scriptFunctions[ot->beh.factory]->AddRef();
-		engine->scriptFunctions[ot->beh.construct]->AddRef();
 		for( asUINT i = 1; i < ot->beh.operators.GetLength(); i += 2 )
 			engine->scriptFunctions[ot->beh.operators[i]]->AddRef();
 	}
@@ -1039,61 +1041,25 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 			// behaviours
 			if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
 			{
-				// For existing types we don't want to make any updates
 				asCScriptFunction *func = ReadFunction(!sharedExists, !sharedExists, !sharedExists);
-				if( func )
+				if( sharedExists )
 				{
-					if( sharedExists )
+					// Find the real function in the object, and update the savedFunctions array
+					asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.destruct);
+					if( (realFunc == 0 && func == 0) || realFunc->IsSignatureEqual(func) )
 					{
-						// Find the real function in the object, and update the savedFunctions array
-						asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.construct);
-						if( realFunc->IsSignatureEqual(func) )
-						{
-							// If the function is not the last, then the substitution has already occurred before
-							if( savedFunctions[savedFunctions.GetLength()-1] == func )
-								savedFunctions[savedFunctions.GetLength()-1] = realFunc;
-						}
-						else
-						{
-							// TODO: Write message
-							error = true;
-						}
-						// Destroy the function without releasing any references
-						func->id = 0;
-						func->byteCode.SetLength(0);
-						func->Release();
-						module->scriptFunctions.PushLast(realFunc);
-						realFunc->AddRef();
-						dontTranslate.Insert(realFunc, true);
+						// If the function is not the last, then the substitution has already occurred before
+						if( func && savedFunctions[savedFunctions.GetLength()-1] == func )
+							savedFunctions[savedFunctions.GetLength()-1] = realFunc;
 					}
-					else 
+					else
 					{
-						engine->scriptFunctions[ot->beh.construct]->Release();
-						ot->beh.construct = func->id;
-						ot->beh.constructors[0] = func->id;
-						func->AddRef();
+						// TODO: Write message
+						error = true;
 					}
-				}
-
-				func = ReadFunction(!sharedExists, !sharedExists, !sharedExists);
-				if( func )
-				{
-					if( sharedExists )
+					// Destroy the function without releasing any references
+					if( func )
 					{
-						// Find the real function in the object, and update the savedFunctions array
-						asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.destruct);
-						if( realFunc->IsSignatureEqual(func) )
-						{
-							// If the function is not the last, then the substitution has already occurred before
-							if( savedFunctions[savedFunctions.GetLength()-1] == func )
-								savedFunctions[savedFunctions.GetLength()-1] = realFunc;
-						}
-						else
-						{
-							// TODO: Write message
-							error = true;
-						}
-						// Destroy the function without releasing any references
 						func->id = 0;
 						func->byteCode.SetLength(0);
 						func->Release();
@@ -1101,46 +1067,16 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 						realFunc->AddRef();
 						dontTranslate.Insert(realFunc, true);
 					}
-					else
-					{
-						ot->beh.destruct = func->id;
-						func->AddRef();
-					}
 				}
-
-				func = ReadFunction(!sharedExists, !sharedExists, !sharedExists);
-				if( func )
+				else
 				{
-					if( sharedExists )
-					{
-						// Find the real function in the object, and update the savedFunctions array
-						asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.factory);
-						if( realFunc->IsSignatureEqual(func) )
-						{
-							// If the function is not the last, then the substitution has already occurred before
-							if( savedFunctions[savedFunctions.GetLength()-1] == func )
-								savedFunctions[savedFunctions.GetLength()-1] = realFunc;
-						}
-						else
-						{
-							// TODO: Write message
-							error = true;
-						}
-						// Destroy the function without releasing any references
-						func->id = 0;
-						func->byteCode.SetLength(0);
-						func->Release();
-						module->scriptFunctions.PushLast(realFunc);
-						realFunc->AddRef();
-						dontTranslate.Insert(realFunc, true);
-					}
-					else
+					if( func )
 					{
-						engine->scriptFunctions[ot->beh.factory]->Release();
-						ot->beh.factory = func->id;
-						ot->beh.factories[0] = func->id;
+						ot->beh.destruct = func->id;
 						func->AddRef();
 					}
+					else
+						ot->beh.destruct = 0;
 				}
 
 				size = ReadEncodedUInt();
@@ -1182,8 +1118,16 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 						{
 							ot->beh.constructors.PushLast(func->id);
 							func->AddRef();
+
+							if( func->parameterTypes.GetLength() == 0 )
+								ot->beh.construct = func->id;
 						}
 					}
+					else
+					{
+						// TODO: Write message
+						error = true;
+					}
 
 					func = ReadFunction(!sharedExists, !sharedExists, !sharedExists);
 					if( func )
@@ -1221,8 +1165,16 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 						{
 							ot->beh.factories.PushLast(func->id);
 							func->AddRef();
+
+							if( func->parameterTypes.GetLength() == 0 )
+								ot->beh.factory = func->id;
 						}
 					}
+					else
+					{
+						// TODO: Write message
+						error = true;
+					}
 				}
 			}
 
@@ -1269,6 +1221,11 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 						func->AddRef();
 					}
 				}
+				else
+				{
+					// TODO: Write message
+					error = true;
+				}
 			}
 
 			// virtualFunctionTable[]
@@ -1313,6 +1270,11 @@ void asCRestore::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
 						func->AddRef();
 					}
 				}
+				else
+				{
+					// TODO: Write message
+					error = true;
+				}
 			}
 		}
 	}
@@ -1437,16 +1399,14 @@ void asCRestore::WriteString(asCString* str)
 	}
 
 	// First check if the string hasn't been saved already
-	for( asUINT n = 0; n < savedStrings.GetLength(); n++ )
+	asSMapNode<asCStringPointer, int> *cursor = 0;
+	if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str)))
 	{
-		if( *str == savedStrings[n] )
-		{
-			// Save a reference to the existing string
-			char b = 'r';
-			WRITE_NUM(b);
-			WriteEncodedUInt(n);
-			return;
-		}
+		// Save a reference to the existing string
+		char b = 'r';
+		WRITE_NUM(b);
+		WriteEncodedUInt(cursor->value);
+		return;
 	}
 
 	// Save a new string
@@ -1458,6 +1418,7 @@ void asCRestore::WriteString(asCString* str)
 	stream->Write(str->AddressOf(), (asUINT)len);
 
 	savedStrings.PushLast(*str);
+	stringToIdMap.Insert(asCStringPointer(str), savedStrings.GetLength() - 1);
 }
 
 void asCRestore::ReadString(asCString* str) 

+ 2 - 0
ThirdParty/AngelScript/source/as_restore.h

@@ -121,10 +121,12 @@ protected:
 	asCArray<asCScriptFunction*> usedFunctions;
 	asCArray<void*>              usedGlobalProperties;
 	asCArray<int>                usedStringConstants;
+	asCMap<int, int>             stringIdToIndexMap;
 
 	asCArray<asCScriptFunction*> savedFunctions;
 	asCArray<asCDataType>        savedDataTypes;
 	asCArray<asCString>          savedStrings;
+	asCMap<asCStringPointer, int> stringToIdMap;
 
 	struct SObjProp
 	{

+ 8 - 0
ThirdParty/AngelScript/source/as_scriptcode.cpp

@@ -139,4 +139,12 @@ void asCScriptCode::ConvertPosToRowCol(size_t pos, int *row, int *col)
 	if( col ) *col = (int)(pos - linePositions[i]) + 1;
 }
 
+bool asCScriptCode::TokenEquals(size_t pos, size_t len, const char *str)
+{
+	if( pos + len > codeLength ) return false;
+	if( strncmp(code + pos, str, len) == 0 && strlen(str) == len )
+		return true;
+	return false;
+}
+
 END_AS_NAMESPACE

+ 9 - 7
ThirdParty/AngelScript/source/as_scriptcode.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2007 Andreas Jonsson
+   Copyright (c) 2003-2011 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 
@@ -56,12 +56,14 @@ public:
 
 	void ConvertPosToRowCol(size_t pos, int *row, int *col);
 
-	asCString name;
-	char *code;
-	size_t   codeLength;
-	bool  sharedCode;
-	int idx;
-	int lineOffset;
+	bool TokenEquals(size_t pos, size_t len, const char *str);
+
+	asCString        name;
+	char            *code;
+	size_t           codeLength;
+	bool             sharedCode;
+	int              idx;
+	int              lineOffset;
 	asCArray<size_t> linePositions;
 };
 

+ 24 - 22
ThirdParty/AngelScript/source/as_scriptengine.cpp

@@ -296,6 +296,10 @@ int asCScriptEngine::SetEngineProperty(asEEngineProp property, asPWORD value)
 		ep.disallowGlobalVars = value ? true : false;
 		break;
 
+	case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
+		ep.alwaysImplDefaultConstruct = value ? true : false;
+		break;
+
 	default:
 		return asINVALID_ARG;
 	}
@@ -357,6 +361,9 @@ asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
 
 	case asEP_DISALLOW_GLOBAL_VARS:
 		return ep.disallowGlobalVars;
+
+	case asEP_ALWAYS_IMPL_DEFAULT_CONSTRUCT:
+		return ep.alwaysImplDefaultConstruct;
 	}
 
 	return 0;
@@ -368,7 +375,7 @@ asPWORD asCScriptEngine::GetEngineProperty(asEEngineProp property) const
 
 
 
-asCScriptEngine::asCScriptEngine()
+asCScriptEngine::asCScriptEngine() 
 {
 	// Instanciate the thread manager
 	ENTERCRITICALSECTION(engineCritical);
@@ -401,9 +408,11 @@ asCScriptEngine::asCScriptEngine()
 		ep.expandDefaultArrayToTemplate = false;
 		ep.autoGarbageCollect           = true;
 		ep.disallowGlobalVars           = false;
+		ep.alwaysImplDefaultConstruct   = false;
 	}
 
 	gc.engine = this;
+	tok.engine = this;
 
 	refCount.set(1);
 	stringFactory = 0;
@@ -628,6 +637,7 @@ asCScriptEngine::~asCScriptEngine()
 		asDELETE(stringConstants[n],asCString);
 	}
 	stringConstants.SetLength(0);
+	stringToIdMap.EraseAll();
 
 	// Free the script section names
 	for( n = 0; n < scriptSectionNames.GetLength(); n++ )
@@ -755,9 +765,8 @@ asETokenClass asCScriptEngine::ParseToken(const char *string, size_t stringLengt
 		stringLength = strlen(string);
 
 	size_t len;
-	asCTokenizer t(this);
 	asETokenClass tc;
-	t.GetToken(string, stringLength, &len, &tc);
+	tok.GetToken(string, stringLength, &len, &tc);
 
 	if( tokenLength )
 		*tokenLength = (int)len;
@@ -950,7 +959,7 @@ int asCScriptEngine::GetFactoryIdByDecl(const asCObjectType *ot, const char *dec
 
 	// Is this a script class?
 	if( ot->flags & asOBJ_SCRIPT_OBJECT && ot->size > 0 )
-		mod = scriptFunctions[ot->beh.factory]->module;
+		mod = scriptFunctions[ot->beh.factories[0]]->module;
 
 	asCBuilder bld(this, mod);
 
@@ -1109,9 +1118,8 @@ int asCScriptEngine::RegisterInterface(const char *name)
 	if( r >= 0 ) return ConfigError(asERROR);
 
 	// Make sure the name is not a reserved keyword
-	asCTokenizer t(this);
 	size_t tokenLen;
-	int token = t.GetToken(name, strlen(name), &tokenLen);
+	int token = tok.GetToken(name, strlen(name), &tokenLen);
 	if( token != ttIdentifier || strlen(name) != tokenLen )
 		return ConfigError(asINVALID_NAME);
 
@@ -1384,9 +1392,8 @@ int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD
 		if( r < 0 )
 		{
 			// Make sure the name is not a reserved keyword
-			asCTokenizer t(this);
 			size_t tokenLen;
-			int token = t.GetToken(name, typeName.GetLength(), &tokenLen);
+			int token = tok.GetToken(name, typeName.GetLength(), &tokenLen);
 			if( token != ttIdentifier || typeName.GetLength() != tokenLen )
 				return ConfigError(asINVALID_NAME);
 
@@ -3989,13 +3996,12 @@ int asCScriptEngine::RegisterTypedef(const char *type, const char *decl)
 	}
 
 	// Grab the data type
-	asCTokenizer t(this);
 	size_t tokenLen;
 	eTokenType token;
 	asCDataType dataType;
 
 	//	Create the data type
-	token = t.GetToken(decl, strlen(decl), &tokenLen);
+	token = tok.GetToken(decl, strlen(decl), &tokenLen);
 	switch(token)
 	{
 	case ttBool:
@@ -4022,7 +4028,7 @@ int asCScriptEngine::RegisterTypedef(const char *type, const char *decl)
 	dataType = asCDataType::CreatePrimitive(token, false);
 
 	// Make sure the name is not a reserved keyword
-	token = t.GetToken(type, strlen(type), &tokenLen);
+	token = tok.GetToken(type, strlen(type), &tokenLen);
 	if( token != ttIdentifier || strlen(type) != tokenLen )
 		return ConfigError(asINVALID_NAME);
 
@@ -4099,9 +4105,8 @@ int asCScriptEngine::RegisterEnum(const char *name)
 		return ConfigError(asERROR);
 
 	// Make sure the name is not a reserved keyword
-	asCTokenizer t(this);
 	size_t tokenLen;
-	int token = t.GetToken(name, strlen(name), &tokenLen);
+	int token = tok.GetToken(name, strlen(name), &tokenLen);
 	if( token != ttIdentifier || strlen(name) != tokenLen )
 		return ConfigError(asINVALID_NAME);
 
@@ -4288,24 +4293,21 @@ int asCScriptEngine::AddConstantString(const char *str, size_t len)
 {
 	// The str may contain null chars, so we cannot use strlen, or strcmp, or strcpy
 
-	// TODO: optimize: Improve linear search
 	// Has the string been registered before?
-	for( size_t n = 0; n < stringConstants.GetLength(); n++ )
-	{
-		if( stringConstants[n]->Compare(str, len) == 0 )
-		{
-			return (int)n;
-		}
-	}
+	asSMapNode<asCStringPointer, int> *cursor = 0;
+	if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str, len)))
+		return cursor->value;
 
 	// No match was found, add the string
 	asCString *cstr = asNEW(asCString)(str, len);
 	stringConstants.PushLast(cstr);
+	int index = (int)stringConstants.GetLength() - 1;
+	stringToIdMap.Insert(asCStringPointer(cstr), index);
 
 	// The VM currently doesn't handle string ids larger than 65535
 	asASSERT(stringConstants.GetLength() <= 65536);
 
-	return (int)stringConstants.GetLength() - 1;
+	return index;
 }
 
 // internal

+ 7 - 1
ThirdParty/AngelScript/source/as_scriptengine.h

@@ -52,6 +52,7 @@
 #include "as_configgroup.h"
 #include "as_memory.h"
 #include "as_gc.h"
+#include "as_tokenizer.h"
 
 BEGIN_AS_NAMESPACE
 
@@ -345,6 +346,9 @@ public:
 	asCModule             *lastModule;
 	bool                   isBuilding;
 
+	// Tokenizer is instanciated once to share resources
+	asCTokenizer tok;
+
 	// Stores script declared object types
 	asCArray<asCObjectType *> classTypes;
 	// This array stores the template instances types, that have been generated from template types
@@ -376,7 +380,8 @@ public:
     asIJITCompiler              *jitCompiler;
 
 	// String constants
-	asCArray<asCString*>        stringConstants;
+	asCArray<asCString*>          stringConstants;
+	asCMap<asCStringPointer, int> stringToIdMap;
 
 	// User data
 	void                   *userData;
@@ -409,6 +414,7 @@ public:
 		bool expandDefaultArrayToTemplate;
 		bool autoGarbageCollect;
 		bool disallowGlobalVars;
+		bool alwaysImplDefaultConstruct;
 	} ep;
 };
 

+ 14 - 0
ThirdParty/AngelScript/source/as_scriptfunction.cpp

@@ -133,6 +133,8 @@ asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, as
 	name                   = ""; 
 	isReadOnly             = false;
 	isPrivate              = false;
+	isFinal                = false;
+	isOverride             = false;
 	stackNeeded            = 0;
 	sysFuncIntf            = 0;
 	signatureId            = 0;
@@ -1062,5 +1064,17 @@ bool asCScriptFunction::IsShared() const
 	return isShared;
 }
 
+// internal
+bool asCScriptFunction::IsFinal() const
+{
+	return isFinal;
+}
+
+// internal
+bool asCScriptFunction::IsOverride() const
+{
+	return isOverride;
+}
+
 END_AS_NAMESPACE
 

+ 5 - 0
ThirdParty/AngelScript/source/as_scriptfunction.h

@@ -114,6 +114,7 @@ public:
 	const char          *GetConfigGroup() const;
 	bool                 IsReadOnly() const;
 	bool                 IsPrivate() const;
+	// TODO: interface: Add IsFinal() and IsOverride() as public methods
 	// TODO: access: Get/Set access mask for function
 
 	asUINT               GetParamCount() const;
@@ -158,6 +159,8 @@ public:
 	void      ReleaseReferences();
 
 	bool      IsShared() const;
+	bool      IsFinal() const;
+	bool      IsOverride() const;
 
 	asCGlobalProperty *GetPropertyByGlobalVarPtr(void *gvarPtr);
 
@@ -187,6 +190,8 @@ public:
 	asCArray<asCString *>        defaultArgs;
 	bool                         isReadOnly;
 	bool                         isPrivate;
+	bool                         isFinal;
+	bool                         isOverride;
 	asCObjectType               *objectType;
 	int                          signatureId;
 

+ 2 - 1
ThirdParty/AngelScript/source/as_scriptnode.h

@@ -85,7 +85,8 @@ enum eScriptNode
 	snTypedef,
 	snCast,
 	snVariableAccess,
-	snFuncDef
+	snFuncDef,
+	snVirtualProperty
 };
 
 struct sToken

+ 41 - 30
ThirdParty/AngelScript/source/as_string.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2009 Andreas Jonsson
+   Copyright (c) 2003-2011 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 @@
 #endif
 
 #include "as_string.h"
+#include "as_string_util.h"
 
 asCString::asCString()
 {
@@ -282,43 +283,17 @@ asCString asCString::SubString(size_t start, size_t length) const
 
 int asCString::Compare(const char *str) const
 {
-	return Compare(str, strlen(str));
+	return asCompareStrings(AddressOf(), length, str, strlen(str));
 }
 
 int asCString::Compare(const asCString &str) const
 {
-	return Compare(str.AddressOf(), str.GetLength());
+	return asCompareStrings(AddressOf(), length, str.AddressOf(), str.GetLength());
 }
 
 int asCString::Compare(const char *str, size_t len) const
 {
-	if( length == 0 ) 
-	{
-		if( str == 0 || len == 0 ) return 0; // Equal
-
-		return 1; // The other string is larger than this
-	}
-
-	if( str == 0 )
-	{
-		if( length == 0 ) 
-			return 0; // Equal
-
-		return -1; // The other string is smaller than this
-	}
-
-	if( len < length )
-	{
-		int result = memcmp(AddressOf(), str, len);
-		if( result == 0 ) return -1; // The other string is smaller than this
-
-		return result;
-	}
-
-	int result = memcmp(AddressOf(), str, length);
-	if( result == 0 && length < len ) return 1; // The other string is larger than this
-
-	return result;
+	return asCompareStrings(AddressOf(), length, str, len);
 }
 
 size_t asCString::RecalculateLength()
@@ -390,3 +365,39 @@ asCString operator +(const asCString &a, const char *b)
 	return res;
 }
 
+// wrapper class
+
+asCStringPointer::asCStringPointer()
+	: string(0), length(0), cstring(0)
+{
+}
+
+asCStringPointer::asCStringPointer(const char *str, size_t len)
+	: string(str), length(len), cstring(0)
+{
+}
+
+asCStringPointer::asCStringPointer(asCString *cstr)
+	: string(0), length(0), cstring(cstr)
+{
+}
+
+const char *asCStringPointer::AddressOf() const
+{
+	return string ? string : cstring->AddressOf();
+}
+
+size_t asCStringPointer::GetLength() const
+{
+	return string ? length : cstring->GetLength();
+}
+
+bool asCStringPointer::operator==(const asCStringPointer& other) const
+{
+	return asCompareStrings(AddressOf(), GetLength(), other.AddressOf(), other.GetLength()) == 0;
+}
+
+bool asCStringPointer::operator<(const asCStringPointer& other) const
+{
+	return asCompareStrings(AddressOf(), GetLength(), other.AddressOf(), other.GetLength()) < 0;
+}

+ 22 - 1
ThirdParty/AngelScript/source/as_string.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2009 Andreas Jonsson
+   Copyright (c) 2003-2011 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 
@@ -103,4 +103,25 @@ asCString operator +(const asCString &, const char *);
 asCString operator +(const char *, const asCString &);
 asCString operator +(const asCString &, const asCString &);
 
+// a wrapper for using the pointer of asCString in asCMap
+class asCStringPointer
+{
+public:
+	asCStringPointer();
+	asCStringPointer(const char *str, size_t len);
+	asCStringPointer(asCString *cstr);
+
+	const char *AddressOf() const;
+	size_t GetLength() const;
+
+	bool operator==(const asCStringPointer& other) const;
+	bool operator<(const asCStringPointer& other) const;
+
+private:
+	// Either string/length or cstring is stored
+	const char *string;
+	size_t      length;
+	asCString  *cstring;
+};
+
 #endif

+ 32 - 1
ThirdParty/AngelScript/source/as_string_util.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2009 Andreas Jonsson
+   Copyright (c) 2003-2011 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,37 @@
 
 BEGIN_AS_NAMESPACE
 
+int asCompareStrings(const char *str1, size_t len1, const char *str2, size_t len2)
+{
+	if( len1 == 0 ) 
+	{
+		if( str2 == 0 || len2 == 0 ) return 0; // Equal
+
+		return 1; // The other string is larger than this
+	}
+
+	if( str2 == 0 )
+	{
+		if( len1 == 0 ) 
+			return 0; // Equal
+
+		return -1; // The other string is smaller than this
+	}
+
+	if( len2 < len1 )
+	{
+		int result = memcmp(str1, str2, len2);
+		if( result == 0 ) return -1; // The other string is smaller than this
+
+		return result;
+	}
+
+	int result = memcmp(str1, str2, len1);
+	if( result == 0 && len1 < len2 ) return 1; // The other string is larger than this
+
+	return result;
+}
+
 double asStringScanDouble(const char *string, size_t *numScanned)
 {
 	char *end;

+ 3 - 1
ThirdParty/AngelScript/source/as_string_util.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2009 Andreas Jonsson
+   Copyright (c) 2003-2011 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 
@@ -36,6 +36,8 @@
 
 BEGIN_AS_NAMESPACE
 
+int     asCompareStrings(const char *str1, size_t len1, const char *str2, size_t len2);
+
 double  asStringScanDouble(const char *string, size_t *numScanned);
 asQWORD asStringScanUInt64(const char *string, int base, size_t *numScanned);
 

+ 7 - 1
ThirdParty/AngelScript/source/as_texts.h

@@ -51,7 +51,7 @@
 #define TXT_CANNOT_CALL_CONSTRUCTOR_IN_LOOPS     "Can't call a constructor in loops"
 #define TXT_CANNOT_CALL_CONSTRUCTOR_IN_SWITCH    "Can't call a constructor in switch"
 #define TXT_CANNOT_CALL_CONSTRUCTOR_TWICE        "Can't call a constructor multiple times"
-#define TXT_CANNOT_INHERIT_FROM_s                "Can't inherit from '%s'"
+#define TXT_CANNOT_INHERIT_FROM_s_FINAL          "Can't inherit from class '%s' marked as final"
 #define TXT_CANNOT_INHERIT_FROM_MULTIPLE_CLASSES "Can't inherit from multiple classes"
 #define TXT_CANNOT_INHERIT_FROM_SELF             "Can't inherit from itself, or another class that inherits from this class"
 #define TXT_CANNOT_INSTANCIATE_TEMPLATE_s_WITH_s "Can't instanciate template '%s' with subtype '%s'"
@@ -87,6 +87,7 @@
 #define TXT_EXPR_MUST_BE_BOOL             "Expression must be of boolean type"
 
 #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_s_NOT_FOUND          "Function '%s' not found"
@@ -118,7 +119,9 @@
 #define TXT_INVALID_UNICODE_VALUE               "Invalid unicode code point"
 #define TXT_INVALID_UNICODE_SEQUENCE_IN_SRC     "Invalid unicode sequence in source"
 
+#define TXT_METHOD_CANNOT_OVERRIDE_s      "Method '%s' declared as final and cannot be overridden"
 #define TXT_METHOD_CANT_HAVE_NAME_OF_CLASS          "The method cannot be named with the class name"
+#define TXT_METHOD_s_DOES_NOT_OVERRIDE    "Method '%s' marked as override but does not replace any base class or interface method"
 #define TXT_MISSING_IMPLEMENTATION_OF_s             "Missing implementation of '%s'"
 #define TXT_MORE_THAN_ONE_MATCHING_OP               "Found more than one matching operator"
 #define TXT_MULTIPLE_MATCHING_SIGNATURES_TO_s       "Multiple matching signatures to '%s'"
@@ -171,6 +174,8 @@
 #define TXT_POSSIBLE_LOSS_OF_PRECISION    "Conversion from double to float, possible loss of precision"
 #define TXT_PRIVATE_METHOD_CALL_s         "Illegal call to private method '%s'"
 #define TXT_PRIVATE_PROP_ACCESS_s         "Illegal access to private property '%s'"
+#define TXT_PROPERTY_ACCESSOR_DISABLED    "Property accessors have been disabled by the application"
+#define TXT_PROPERTY_ACCESSOR_MUST_BE_IMPLEMENTED "Property accessor must be implemented"
 #define TXT_PROPERTY_CANT_BE_CONST        "Class properties cannot be declared as const"
 #define TXT_PROPERTY_HAS_NO_GET_ACCESSOR  "The property has no get accessor"
 #define TXT_PROPERTY_HAS_NO_SET_ACCESSOR  "The property has no set accessor"
@@ -198,6 +203,7 @@
 #define TXT_UNEXPECTED_TOKEN_s            "Unexpected token '%s'"
 #define TXT_UNINITIALIZED_GLOBAL_VAR_s    "Use of uninitialized global variable '%s'."
 #define TXT_UNREACHABLE_CODE              "Unreachable code"
+#define TXT_UNRECOGNIZED_VIRTUAL_PROPERTY_NODE "Virtual property contains unrecognized aspect"
 #define TXT_UNUSED_SCRIPT_NODE            "Unused script node"
 
 #define TXT_VALUE_TOO_LARGE_FOR_TYPE      "Value is too large for data type"

+ 43 - 37
ThirdParty/AngelScript/source/as_tokendef.h

@@ -180,29 +180,40 @@ struct sTokenWord
 sTokenWord const tokenWords[] =
 {
 	{"+"         , ttPlus},
+	{"+="        , ttAddAssign},
+	{"++"        , ttInc},
 	{"-"         , ttMinus},
+	{"-="        , ttSubAssign},
+	{"--"        , ttDec},
 	{"*"         , ttStar},
+	{"*="        , ttMulAssign},
 	{"/"         , ttSlash},
+	{"/="        , ttDivAssign},
 	{"%"         , ttPercent},
+	{"%="        , ttModAssign},
 	{"="         , ttAssignment},
+	{"=="        , ttEqual},
 	{"."         , ttDot},
-	{"+="        , ttAddAssign},
-	{"-="        , ttSubAssign},
-	{"*="        , ttMulAssign},
-	{"/="        , ttDivAssign},
-	{"%="        , ttModAssign},
+	{"|"         , ttBitOr},
 	{"|="        , ttOrAssign},
+	{"||"        , ttOr},
+	{"&"         , ttAmp},
 	{"&="        , ttAndAssign},
+	{"&&"        , ttAnd},
+	{"^"         , ttBitXor},
 	{"^="        , ttXorAssign},
+	{"^^"        , ttXor},
+	{"<"         , ttLessThan},
+	{"<="        , ttLessThanOrEqual},
+	{"<<"        , ttBitShiftLeft},
 	{"<<="       , ttShiftLeftAssign},
+	{">"         , ttGreaterThan},
+	{">="        , ttGreaterThanOrEqual},
+	{">>"        , ttBitShiftRight},
 	{">>="       , ttShiftRightLAssign},
+	{">>>"       , ttBitShiftRightArith},
 	{">>>="      , ttShiftRightAAssign},
-	{"|"         , ttBitOr},
 	{"~"         , ttBitNot},
-	{"^"         , ttBitXor},
-	{"<<"        , ttBitShiftLeft},
-	{">>"        , ttBitShiftRight},
-	{">>>"       , ttBitShiftRightArith},
 	{";"         , ttEndStatement},
 	{","         , ttListSeparator},
 	{"{"         , ttStartStatementBlock},
@@ -214,26 +225,19 @@ sTokenWord const tokenWords[] =
 	{"?"         , ttQuestion},
 	{":"         , ttColon},
 	{"::"        , ttScope},
-	{"=="        , ttEqual},
-	{"!="        , ttNotEqual},
-	{"<"         , ttLessThan},
-	{">"         , ttGreaterThan},
-	{"<="        , ttLessThanOrEqual},
-	{">="        , ttGreaterThanOrEqual},
-	{"++"        , ttInc},
-	{"--"        , ttDec},
-	{"&"         , ttAmp},
 	{"!"         , ttNot},
-	{"||"        , ttOr},
-	{"&&"        , ttAnd},
-	{"^^"        , ttXor},
+	{"!="        , ttNotEqual},
+	{"!is"       , ttNotIs},
 	{"@"         , ttHandle},
 	{"and"       , ttAnd},
 	{"bool"      , ttBool},
 	{"break"     , ttBreak},
+	{"case"      , ttCase}, 
 	{"cast"      , ttCast},
+	{"class"     , ttClass},
 	{"const"     , ttConst},
 	{"continue"  , ttContinue},
+	{"default"   , ttDefault},
 	{"do"        , ttDo},
 #ifdef  AS_USE_DOUBLE_AS_FLOAT
 	{"double"    , ttFloat},
@@ -241,14 +245,15 @@ sTokenWord const tokenWords[] =
 	{"double"    , ttDouble},
 #endif
 	{"else"      , ttElse},
+	{"enum"      , ttEnum},
 	{"false"     , ttFalse},
 	{"float"     , ttFloat},
 	{"for"       , ttFor},
 	{"funcdef"   , ttFuncDef},
 	{"if"        , ttIf},
+	{"import"    , ttImport},
 	{"in"        , ttIn},
 	{"inout"     , ttInOut},
-	{"import"    , ttImport},
 	{"int"       , ttInt},
 	{"int8"      , ttInt8},
 	{"int16"     , ttInt16},
@@ -256,28 +261,23 @@ sTokenWord const tokenWords[] =
 	{"int64"     , ttInt64},
 	{"interface" , ttInterface},
 	{"is"        , ttIs},
-	{"!is"       , ttNotIs},
 	{"not"       , ttNot},
 	{"null"      , ttNull},
 	{"or"        , ttOr},
 	{"out"       , ttOut},
+	{"private"   , ttPrivate},
 	{"return"    , ttReturn},
+	{"switch"    , ttSwitch},
 	{"true"      , ttTrue},
-	{"void"      , ttVoid},
-	{"while"     , ttWhile},
+	{"typedef"   , ttTypedef},
 	{"uint"      , ttUInt},
 	{"uint8"     , ttUInt8},
 	{"uint16"    , ttUInt16},
 	{"uint32"    , ttUInt},
 	{"uint64"    , ttUInt64},
-	{"switch"    , ttSwitch},
-	{"class"     , ttClass},
-	{"case"      , ttCase}, 
-	{"default"   , ttDefault},
+	{"void"      , ttVoid},
+	{"while"     , ttWhile},
 	{"xor"       , ttXor},
-	{"typedef"   , ttTypedef},
-	{"enum"      , ttEnum},
-	{"private"   , ttPrivate}
 };
 
 const unsigned int numTokenWords = sizeof(tokenWords)/sizeof(sTokenWord);
@@ -285,10 +285,16 @@ const unsigned int numTokenWords = sizeof(tokenWords)/sizeof(sTokenWord);
 const char * const whiteSpace = " \t\r\n";
 
 // Some keywords that are not considered tokens by the parser
-const char * const THIS_TOKEN   = "this";
-const char * const FROM_TOKEN   = "from";
-const char * const SUPER_TOKEN  = "super";
-const char * const SHARED_TOKEN = "shared";
+// These only have meaning in specific situations. Outside these
+// situations they are treated as normal identifiers.
+const char * const THIS_TOKEN     = "this";
+const char * const FROM_TOKEN     = "from";
+const char * const SUPER_TOKEN    = "super";
+const char * const SHARED_TOKEN   = "shared";
+const char * const FINAL_TOKEN    = "final";
+const char * const OVERRIDE_TOKEN = "override";
+const char * const GET_TOKEN      = "get";
+const char * const SET_TOKEN      = "set";
 
 END_AS_NAMESPACE
 

+ 95 - 122
ThirdParty/AngelScript/source/as_tokenizer.cpp

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 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 
@@ -47,16 +47,27 @@
 
 BEGIN_AS_NAMESPACE
 
-asCTokenizer::asCTokenizer(const asCScriptEngine *e)
+asCTokenizer::asCTokenizer()
 {
-	engine = e;
+	engine = 0;
+
+	// Initialize the keyword map
+	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);
+	}
 }
 
 asCTokenizer::~asCTokenizer()
 {
 }
 
-const char *asGetTokenDefinition(int tokenType)
+// static
+const char *asCTokenizer::GetDefinition(int tokenType)
 {
 	if( tokenType == ttUnrecognizedToken			) return "<unrecognized token>";
 	if( tokenType == ttEnd							) return "<end of file>";
@@ -80,41 +91,38 @@ const char *asGetTokenDefinition(int tokenType)
 	return 0;
 }
 
-eTokenType asCTokenizer::GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc)
+eTokenType asCTokenizer::GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc) const
 {
 	asASSERT(source != 0);
 	asASSERT(tokenLength != 0);
 
-	this->source = source;
-	this->sourceLength = sourceLength;
-
-	asETokenClass t = ParseToken();
-	if( tc ) *tc = t;
-
-	// Copy the output to the token
-	*tokenLength = this->tokenLength;
+	eTokenType tokenType;
+	size_t     tlen;
+	asETokenClass t = ParseToken(source, sourceLength, tlen, tokenType);
+	if( tc          ) *tc          = t;
+	if( tokenLength ) *tokenLength = tlen;
 
 	return tokenType;
 }
 
-asETokenClass asCTokenizer::ParseToken()
+asETokenClass asCTokenizer::ParseToken(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
 {
-	if( IsWhiteSpace() ) return asTC_WHITESPACE;
-	if( IsComment()    ) return asTC_COMMENT;
-	if( IsConstant()   ) return asTC_VALUE;
-	if( IsIdentifier() ) return asTC_IDENTIFIER;
-	if( IsKeyWord()    ) return asTC_KEYWORD;
+	if( IsWhiteSpace(source, sourceLength, tokenLength, tokenType) ) return asTC_WHITESPACE;
+	if( IsComment(source, sourceLength, tokenLength, tokenType)    ) return asTC_COMMENT;
+	if( IsConstant(source, sourceLength, tokenLength, tokenType)   ) return asTC_VALUE;
+	if( IsIdentifier(source, sourceLength, tokenLength, tokenType) ) return asTC_IDENTIFIER;
+	if( IsKeyWord(source, sourceLength, tokenLength, tokenType)    ) return asTC_KEYWORD;
 
 	// If none of the above this is an unrecognized token
 	// We can find the length of the token by advancing
 	// one step and trying to identify a token there
-	tokenType = ttUnrecognizedToken;
+	tokenType   = ttUnrecognizedToken;
 	tokenLength = 1;
 
 	return asTC_UNKNOWN;
 }
 
-bool asCTokenizer::IsWhiteSpace()
+bool asCTokenizer::IsWhiteSpace(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
 {
 	// Treat UTF8 byte-order-mark (EF BB BF) as whitespace
 	if( sourceLength >= 3 && 
@@ -122,7 +130,7 @@ bool asCTokenizer::IsWhiteSpace()
 		asBYTE(source[1]) == 0xBBu &&
 		asBYTE(source[2]) == 0xBFu )
 	{
-		tokenType = ttWhiteSpace;
+		tokenType   = ttWhiteSpace;
 		tokenLength = 3;
 		return true;
 	}
@@ -146,7 +154,7 @@ bool asCTokenizer::IsWhiteSpace()
 
 	if( n > 0 )
 	{
-		tokenType = ttWhiteSpace;
+		tokenType   = ttWhiteSpace;
 		tokenLength = n;
 		return true;
 	}
@@ -154,7 +162,7 @@ bool asCTokenizer::IsWhiteSpace()
 	return false;
 }
 
-bool asCTokenizer::IsComment()
+bool asCTokenizer::IsComment(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
 {
 	if( sourceLength < 2 )
 		return false;
@@ -174,7 +182,7 @@ bool asCTokenizer::IsComment()
 				break;
 		}
 
-		tokenType = ttOnelineComment;
+		tokenType   = ttOnelineComment;
 		tokenLength = n+1;
 
 		return true;
@@ -192,7 +200,7 @@ bool asCTokenizer::IsComment()
 				break;
 		}
 
-		tokenType = ttMultilineComment;
+		tokenType   = ttMultilineComment;
 		tokenLength = n+1;
 
 		return true;
@@ -201,7 +209,7 @@ bool asCTokenizer::IsComment()
 	return false;
 }
 
-bool asCTokenizer::IsConstant()
+bool asCTokenizer::IsConstant(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
 {
 	// Starting with number
 	if( (source[0] >= '0' && source[0] <= '9') || (source[0] == '.' && sourceLength > 1 && source[1] >= '0' && source[1] <= '9') )
@@ -218,7 +226,7 @@ bool asCTokenizer::IsConstant()
 					break;
 			}
 
-			tokenType = ttBitsConstant;
+			tokenType   = ttBitsConstant;
 			tokenLength = n;
 			return true;
 		}
@@ -254,22 +262,22 @@ bool asCTokenizer::IsConstant()
 
 			if( n < sourceLength && (source[n] == 'f' || source[n] == 'F') )
 			{
-				tokenType = ttFloatConstant;
+				tokenType   = ttFloatConstant;
 				tokenLength = n + 1;
 			}
 			else
 			{
 #ifdef AS_USE_DOUBLE_AS_FLOAT
-				tokenType = ttFloatConstant;
+				tokenType   = ttFloatConstant;
 #else
-				tokenType = ttDoubleConstant;
+				tokenType   = ttDoubleConstant;
 #endif
 				tokenLength = n;
 			}
 			return true;
 		}
 
-		tokenType = ttIntConstant;
+		tokenType   = ttIntConstant;
 		tokenLength = n;
 		return true;
 	}
@@ -290,7 +298,7 @@ bool asCTokenizer::IsConstant()
 					break;
 			}
 
-			tokenType = ttHeredocStringConstant;
+			tokenType   = ttHeredocStringConstant;
 			tokenLength = n+3;
 		}
 		else
@@ -323,7 +331,7 @@ bool asCTokenizer::IsConstant()
 				if( source[n] == '\\' ) evenSlashes = !evenSlashes; else evenSlashes = true;
 			}
 
-			tokenType = ttNonTerminatedStringConstant;
+			tokenType   = ttNonTerminatedStringConstant;
 			tokenLength = n;
 		}
 
@@ -333,14 +341,14 @@ bool asCTokenizer::IsConstant()
 	return false;
 }
 
-bool asCTokenizer::IsIdentifier()
+bool asCTokenizer::IsIdentifier(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
 {
 	// Starting with letter or underscore
 	if( (source[0] >= 'a' && source[0] <= 'z') ||
 		(source[0] >= 'A' && source[0] <= 'Z') ||
 		source[0] == '_' )
 	{
-		tokenType = ttIdentifier;
+		tokenType   = ttIdentifier;
 		tokenLength = 1;
 
 		for( size_t n = 1; n < sourceLength; n++ )
@@ -355,17 +363,8 @@ bool asCTokenizer::IsIdentifier()
 		}
 
 		// Make sure the identifier isn't a reserved keyword
-		if( tokenLength > 50 ) return true;
-
-		char test[51];
-		memcpy(test, source, tokenLength);
-		test[tokenLength] = 0;
-
-		for( asUINT i = 0; i < numTokenWords; i++ )
-		{
-			if( strcmp(test, tokenWords[i].word) == 0 )
-				return false;
-		}
+		if( alphaKeywordMap.MoveTo(0, asCStringPointer(source, tokenLength)) )
+			return false;
 
 		return true;
 	}
@@ -373,92 +372,66 @@ bool asCTokenizer::IsIdentifier()
 	return false;
 }
 
-bool asCTokenizer::IsKeyWord()
+bool asCTokenizer::IsKeyWord(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const
 {
-	// Fill the list with all possible keywords
-	// Check each character against all the keywords in the list,
-	// remove keywords that don't match. When only one remains and
-	// it matches the source completely we have found a match.
-	int words[numTokenWords];
-	asUINT n;
-	for( n = 0; n < numTokenWords; n++ )
-		words[n] = n;
-
-	int numWords = numTokenWords;
-	int lastPossible = -1;
-
-	n = 0;
-	while( n < sourceLength && numWords >= 0 )
+	// 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;
+
+	if( (source[0] >= 'a' && source[0] <= 'z') ||
+		(source[0] >= 'A' && source[0] <= 'Z') )
 	{
-		for( int i = 0; i < numWords; i++ )
-		{
-			if( tokenWords[words[i]].word[n] == '\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 "!isTrue" expression.
-				if( ((tokenWords[words[i]].word[n-1] >= 'a' && tokenWords[words[i]].word[n-1] <= 'z') ||
-					 (tokenWords[words[i]].word[n-1] >= 'A' && tokenWords[words[i]].word[n-1] <= 'Z')) &&
-					((source[n] >= 'a' && source[n] <= 'z') ||
-					 (source[n] >= 'A' && source[n] <= 'Z') ||
-					 (source[n] >= '0' && source[n] <= '9') ||
-					 (source[n] == '_')) )
-				{
-					// The token doesn't really match, even though 
-					// the start of the source matches the token
-					words[i--] = words[--numWords];
-				}
-				else if( numWords > 1 )
-				{
-					// It's possible that a longer token matches, so let's 
-					// remember this match and continue searching
-					lastPossible = words[i];
-					words[i--] = words[--numWords];
-					continue;
-				}
-				else
-				{
-					// Only one token matches, so we return it
-					tokenType = tokenWords[words[i]].tokenType;
-					tokenLength = n;
-					return true;
-				}
-			}
-			else if( tokenWords[words[i]].word[n] != source[n] )
-			{
-				// The token doesn't match
-				words[i--] = words[--numWords];
-			}
-		}
-		n++;
+		map = &alphaKeywordMap;
+		// 'interface' is the longest alpha keyword
+		maxLength = sourceLength > 9 ? 9 : sourceLength;
+	}
+	else
+	{
+		map = &nonAlphaKeywordMap;
+		// '>>>=' is the longest non-alpha keyword
+		maxLength = sourceLength > 4 ? 4 : sourceLength;
 	}
 
-	// The source length ended or there where no more matchable words
-	if( numWords )
+	// Find the longest keyword that matches the start of the source string
+	while( maxLength > 0 )
 	{
-		// If any of the tokenWords also end at this
-		// position then we have found the matching token
-		for( int i = 0; i < numWords; i++ )
+		asSMapNode<asCStringPointer, eTokenType> *cursor;
+		if( map->MoveTo(&cursor, asCStringPointer(source, maxLength)) )
 		{
-			if( tokenWords[words[i]].word[n] == '\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] == '_')) )
 			{
-				tokenType = tokenWords[words[i]].tokenType;
-				tokenLength = n;
-				return true;
+				// The token doesn't really match, even though 
+				// the start of the source matches the token
+				maxLength--;
+				continue;
 			}
-		}
-	}
 
-	// It is still possible that a shorter token was found
-	if( lastPossible > -1 )
-	{
-		tokenType = tokenWords[lastPossible].tokenType;
-		tokenLength = strlen(tokenWords[lastPossible].word);
-		return true;
+			tokenType   = cursor->value;
+			tokenLength = maxLength;
+			return true;
+		}
+		maxLength--;
 	}
 
-	return false;
+	return false;	
 }
 
 END_AS_NAMESPACE

+ 18 - 19
ThirdParty/AngelScript/source/as_tokenizer.h

@@ -1,6 +1,6 @@
 /*
    AngelCode Scripting Library
-   Copyright (c) 2003-2010 Andreas Jonsson
+   Copyright (c) 2003-2011 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 
@@ -42,36 +42,35 @@
 
 #include "as_config.h"
 #include "as_tokendef.h"
+#include "as_map.h"
+#include "as_string.h"
 
 BEGIN_AS_NAMESPACE
 
-const char *asGetTokenDefinition(int tokenType);
-
-class asCScriptEngine;
-
 class asCTokenizer
 {
 public:
-	asCTokenizer(const asCScriptEngine *engine);
-	~asCTokenizer();
-
-	eTokenType GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc = 0);
+	eTokenType GetToken(const char *source, size_t sourceLength, size_t *tokenLength, asETokenClass *tc = 0) const;
+	
+	static const char *GetDefinition(int tokenType);
 
 protected:
-	asETokenClass ParseToken();
-	bool IsWhiteSpace();
-	bool IsComment();
-	bool IsConstant();
-	bool IsKeyWord();
-	bool IsIdentifier();
+	friend class asCScriptEngine;
 
-	const char *source;
-	size_t sourceLength;
+	asCTokenizer();
+	~asCTokenizer();
 
-	eTokenType tokenType;
-	size_t tokenLength;
+	asETokenClass ParseToken(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
+	bool IsWhiteSpace(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
+	bool IsComment(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
+	bool IsConstant(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
+	bool IsKeyWord(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
+	bool IsIdentifier(const char *source, size_t sourceLength, size_t &tokenLength, eTokenType &tokenType) const;
 
 	const asCScriptEngine *engine;
+
+	asCMap<asCStringPointer, eTokenType> alphaKeywordMap;
+	asCMap<asCStringPointer, eTokenType> nonAlphaKeywordMap;
 };
 
 END_AS_NAMESPACE

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