示例#1
0
int asCBuilder::ParseVariableDeclaration(const char *decl, asCProperty *var)
{
	numErrors = 0;
	numWarnings = 0;
	preMessage.isSet = false;

	asCScriptCode source;
	source.SetCode(TXT_VARIABLE_DECL, decl, true);

	asCParser parser(this);

	int r = parser.ParsePropertyDeclaration(&source);
	if( r < 0 )
		return asINVALID_DECLARATION;

	asCScriptNode *node = parser.GetScriptNode();

	// Find name
	asCScriptNode *n = node->firstChild->next;
	var->name.Assign(&source.code[n->tokenPos], n->tokenLength);

	// Initialize a script variable object for registration
	var->type = CreateDataTypeFromNode(node->firstChild, &source);

	if( numErrors > 0 || numWarnings > 0 )
		return asINVALID_DECLARATION;

	return 0;
}
示例#2
0
int asCBuilder::VerifyProperty(asCDataType *dt, const char *decl, asCString &name, asCDataType &type)
{
	numErrors = 0;
	numWarnings = 0;
	preMessage.isSet = false;

	if( dt )
	{
		// Verify that the object type exist
		if( dt->GetObjectType() == 0 )
			return asINVALID_OBJECT;
	}

	// Check property declaration and type
	asCScriptCode source;
	source.SetCode(TXT_PROPERTY, decl, true);

	asCParser parser(this);
	int r = parser.ParsePropertyDeclaration(&source);
	if( r < 0 )
		return asINVALID_DECLARATION;

	// Get data type and property name
	asCScriptNode *dataType = parser.GetScriptNode()->firstChild;

	asCScriptNode *nameNode = dataType->next;

	type = CreateDataTypeFromNode(dataType, &source);
	name.Assign(&decl[nameNode->tokenPos], nameNode->tokenLength);

	// Verify property name
	if( dt )
		if( CheckNameConflictMember(*dt, name.AddressOf(), nameNode, &source) < 0 )
			return asINVALID_NAME;
	else
		if( CheckNameConflict(name.AddressOf(), nameNode, &source) < 0 )
			return asINVALID_NAME;

	if( numErrors > 0 )
		return asINVALID_DECLARATION;

	return asSUCCESS;
}
示例#3
0
int asCBuilder::ParseDataType(const char *datatype, asCDataType *result)
{
	numErrors = 0;
	numWarnings = 0;

	asCScriptCode source;
	source.SetCode("", datatype, true);

	asCParser parser(this);
	int r = parser.ParseDataType(&source);
	if( r < 0 )
		return asINVALID_TYPE;

	// Get data type and property name
	asCScriptNode *dataType = parser.GetScriptNode()->firstChild;

	*result = CreateDataTypeFromNode(dataType, &source);

	if( numErrors > 0 )
		return asINVALID_TYPE;

	return asSUCCESS;
}
示例#4
0
void asCBuilder::CompileClasses()
{
	asUINT n;
	asCArray<sClassDeclaration*> toValidate;

	// Go through each of the classes and register the object type descriptions
	for( n = 0; n < classDeclarations.GetLength(); n++ )
	{
		sClassDeclaration *decl = classDeclarations[n];

		// Enumerate each of the declared properties
		asCScriptNode *node = decl->node->firstChild->next;

		// Skip list of classes and interfaces
		while( node && node->nodeType == snIdentifier )
			node = node->next;

		while( node )
		{
			if( node->nodeType == snDeclaration )
			{
				asCScriptCode *file = decl->script;
				asCDataType dt = CreateDataTypeFromNode(node->firstChild, file);
				GETSTRING(name, &file->code[node->lastChild->tokenPos], node->lastChild->tokenLength);

				if( dt.IsReadOnly() )
				{
					int r, c;
					file->ConvertPosToRowCol(node->tokenPos, &r, &c);

					WriteError(file->name.AddressOf(), TXT_PROPERTY_CANT_BE_CONST, r, c);
				}

				asCDataType st;
				st.SetObjectType(decl->objType);
				CheckNameConflictMember(st, name.AddressOf(), node->lastChild, file);

				// Store the properties in the object type descriptor
				asCProperty *prop = new asCProperty;
				prop->name = name;
				prop->type = dt;

				int propSize;
				if( dt.IsObject() )
				{
					propSize = dt.GetSizeOnStackDWords()*4;
					if( !dt.IsObjectHandle() )
					{
						if( dt.GetSizeInMemoryBytes() == 0 )
						{
							int r, c;
							file->ConvertPosToRowCol(node->tokenPos, &r, &c);
							asCString str;
							str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format().AddressOf());
							WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
						}
						prop->type.MakeReference(true);
					}
				}
				else
				{
					propSize = dt.GetSizeInMemoryBytes();
					if( propSize == 0 )
					{
						int r, c;
						file->ConvertPosToRowCol(node->tokenPos, &r, &c);
						asCString str;
						str.Format(TXT_DATA_TYPE_CANT_BE_s, dt.Format());
						WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
					}
				}

				// Add extra bytes so that the property will be properly aligned
				if( propSize == 2 && (decl->objType->size & 1) ) decl->objType->size += 1;
				if( propSize > 2 && (decl->objType->size & 3) ) decl->objType->size += 3 - (decl->objType->size & 3);

				prop->byteOffset = decl->objType->size;
				decl->objType->size += propSize;

				decl->objType->properties.PushLast(prop);

				// Make sure the module holds a reference to the config group where the object is registered
				module->RefConfigGroupForObjectType(dt.GetObjectType());
			}
			else if( node->nodeType == snFunction )
			{
				// TODO: Register the method and add it to the list of functions to compile later 

			}
			else
				assert(false);

			node = node->next;
		}

		toValidate.PushLast(decl);
	}

	// Verify that the declared structures are valid, e.g. that the structure
	// doesn't contain a member of its own type directly or indirectly
	while( toValidate.GetLength() > 0 ) 
	{
		asUINT numClasses = (asUINT)toValidate.GetLength();

		asCArray<sClassDeclaration*> toValidateNext;
		while( toValidate.GetLength() > 0 )
		{
			sClassDeclaration *decl = toValidate[toValidate.GetLength()-1];
			int validState = 1;
			for( asUINT n = 0; n < decl->objType->properties.GetLength(); n++ )
			{
				// A valid structure is one that uses only primitives or other valid objects
				asCProperty *prop = decl->objType->properties[n];
				asCDataType dt = prop->type;

				if( dt.IsScriptArray() )
				{
					asCDataType sub = dt;
					while( sub.IsScriptArray() && !sub.IsObjectHandle() )
						sub = sub.GetSubType();

					dt = sub;
				}

				if( dt.IsObject() && !dt.IsObjectHandle() )
				{
					// Find the class declaration
					sClassDeclaration *pdecl = 0;
					for( asUINT p = 0; p < classDeclarations.GetLength(); p++ )
					{
						if( classDeclarations[p]->objType == dt.GetObjectType() )
						{
							pdecl = classDeclarations[p];
							break;
						}
					}

					if( pdecl )
					{
						if( pdecl->objType == decl->objType )
						{
							int r, c;
							decl->script->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
							WriteError(decl->script->name.AddressOf(), TXT_ILLEGAL_MEMBER_TYPE, r, c);
							validState = 2;
							break;
						}
						else if( pdecl->validState != 1 )
						{
							validState = pdecl->validState;
							break;
						}
					}
				}
			}

			if( validState == 1 )
			{
				decl->validState = 1;
				toValidate.PopLast();
			}
			else if( validState == 2 )
			{
				decl->validState = 2;
				toValidate.PopLast();
			}
			else
			{
				toValidateNext.PushLast(toValidate.PopLast());
			}
		}

		toValidate = toValidateNext;
		toValidateNext.SetLength(0);

		if( numClasses == toValidate.GetLength() )
		{
			int r, c;
			toValidate[0]->script->ConvertPosToRowCol(toValidate[0]->node->tokenPos, &r, &c);
			WriteError(toValidate[0]->script->name.AddressOf(), TXT_ILLEGAL_MEMBER_TYPE, r, c);
			break;
		}
	}

	if( numErrors > 0 ) return;

	// TODO: The declarations form a graph, all circles in   
	//       the graph must be flagged as potential circles

	// Verify potential circular references
	for( n = 0; n < classDeclarations.GetLength(); n++ )
	{
		sClassDeclaration *decl = classDeclarations[n];
		asCObjectType *ot = decl->objType;

		// Is there some path in which this structure is involved in circular references?
		for( asUINT p = 0; p < ot->properties.GetLength(); p++ )
		{
			asCDataType dt = ot->properties[p]->type;
			if( dt.IsObject() )
			{
				// Any structure that contains an any type can generate circular references
				if( dt.GetObjectType()->flags & asOBJ_CONTAINS_ANY )
				{
					ot->flags |= asOBJ_POTENTIAL_CIRCLE | asOBJ_CONTAINS_ANY;
				}

				if( dt.IsObjectHandle() )
				{
					// TODO:
					// Can this handle really generate a circular reference

					ot->flags |= asOBJ_POTENTIAL_CIRCLE;
				}
				else if( dt.GetObjectType()->flags & asOBJ_POTENTIAL_CIRCLE )
				{
					// TODO:
					// Just because the member type is a potential circle doesn't mean that this one is

					ot->flags |= asOBJ_POTENTIAL_CIRCLE;
				}

				if( dt.IsArrayType() )
				{
					asCDataType sub = dt.GetSubType();
					while( sub.IsObject() )
					{
						if( sub.IsObjectHandle() || (sub.GetObjectType()->flags & asOBJ_POTENTIAL_CIRCLE) )
						{
							decl->objType->flags |= asOBJ_POTENTIAL_CIRCLE;

							// Make sure the array object is also marked as potential circle
							sub = dt;
							while( sub.IsScriptArray() )
							{
								sub.GetObjectType()->flags |= asOBJ_POTENTIAL_CIRCLE;
								sub = sub.GetSubType();
							}

							break;
						}

						if( sub.IsScriptArray() )
							sub = sub.GetSubType();
						else
							break;
					}
				}
			}
		}
	}

	// Verify that the class implements all the methods from the interfaces it implements
	for( n = 0; n < classDeclarations.GetLength(); n++ )
	{
		sClassDeclaration *decl = classDeclarations[n];
		asCScriptCode *file = decl->script;

		// Enumerate each of the implemented interfaces
		asCScriptNode *node = decl->node->firstChild->next;
		while( node && node->nodeType == snIdentifier )
		{
			// Get the interface name from the node
			GETSTRING(name, &file->code[node->tokenPos], node->tokenLength);

			// Find the object type for the interface
			asCObjectType *objType = GetObjectType(name.AddressOf());

			if( decl->objType->Implements(objType) )
			{
				int r, c;
				file->ConvertPosToRowCol(node->tokenPos, &r, &c);
				WriteWarning(file->name.AddressOf(), TXT_INTERFACE_ALREADY_IMPLEMENTED, r, c);
			}
			else
			{
				decl->objType->interfaces.PushLast(objType);

				// Make sure all the methods of the interface are implemented
				for( asUINT i = 0; i < objType->methods.GetLength(); i++ )
				{
					if( !DoesMethodExist(decl->objType, objType->methods[i]) )
					{
						int r, c;
						file->ConvertPosToRowCol(decl->node->tokenPos, &r, &c);
						asCString str;
						str.Format(TXT_MISSING_IMPLEMENTATION_OF_s, 
							engine->GetFunctionDeclaration(objType->methods[i]).AddressOf());
						WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
					}
				}
			}

			node = node->next;
		}
	}
}
示例#5
0
int asCBuilder::RegisterGlobalVar(asCScriptNode *node, asCScriptCode *file)
{
	// What data type is it?
	asCDataType type = CreateDataTypeFromNode(node->firstChild, file);

	if( type.GetSizeOnStackDWords() == 0 || 
		(type.IsObject() && !type.IsObjectHandle() && type.GetSizeInMemoryBytes() == 0) )
	{
		asCString str;
		// TODO: Change to "'type' cannot be declared as variable"
		str.Format(TXT_DATA_TYPE_CANT_BE_s, type.Format().AddressOf());
		
		int r, c;
		file->ConvertPosToRowCol(node->tokenPos, &r, &c);
		
		WriteError(file->name.AddressOf(), str.AddressOf(), r, c);
	}

	asCScriptNode *n = node->firstChild->next;

	while( n )
	{
		// Verify that the name isn't taken
		GETSTRING(name, &file->code[n->tokenPos], n->tokenLength);
		CheckNameConflict(name.AddressOf(), n, file);

		// Register the global variable
		sGlobalVariableDescription *gvar = new sGlobalVariableDescription;
		globVariables.PushLast(gvar);

		gvar->script     = file;
		gvar->name       = name;
		gvar->isCompiled = false;
		gvar->datatype   = type;

		// TODO: Give error message if wrong
		assert(!gvar->datatype.IsReference());

		// Allocate space on the global memory stack
		gvar->index = module->AllocGlobalMemory(gvar->datatype.GetSizeOnStackDWords());
		gvar->node = 0;
		if( n->next && 
			(n->next->nodeType == snAssignment ||
			 n->next->nodeType == snArgList    || 
			 n->next->nodeType == snInitList     ) )
		{
			gvar->node = n->next;
			n->next->DisconnectParent();
		}

		// Add script variable to engine
		asCProperty *prop = new asCProperty;
		prop->index      = gvar->index;
		prop->name       = name;
		prop->type       = gvar->datatype;
		module->scriptGlobals.PushLast(prop);

		gvar->property = prop;

		n = n->next;
	}

	delete node;

	return 0;
}
示例#6
0
int asCBuilder::ParseFunctionDeclaration(const char *decl, asCScriptFunction *func, asCArray<bool> *paramAutoHandles, bool *returnAutoHandle)
{
	numErrors = 0;
	numWarnings = 0;
	preMessage.isSet = false;

	asCScriptCode source;
	source.SetCode(TXT_SYSTEM_FUNCTION, decl, true);

	asCParser parser(this);

	int r = parser.ParseFunctionDefinition(&source);
	if( r < 0 )
		return asINVALID_DECLARATION;

	asCScriptNode *node = parser.GetScriptNode();

	// Find name
	asCScriptNode *n = node->firstChild->next->next;
	func->name.Assign(&source.code[n->tokenPos], n->tokenLength);

	// Initialize a script function object for registration
	bool autoHandle;
	func->returnType = CreateDataTypeFromNode(node->firstChild, &source);
	func->returnType = ModifyDataTypeFromNode(func->returnType, node->firstChild->next, &source, 0, &autoHandle);
	if( autoHandle && (!func->returnType.IsObjectHandle() || func->returnType.IsReference()) )
			return asINVALID_DECLARATION;			
	if( returnAutoHandle ) *returnAutoHandle = autoHandle;

	n = n->next->firstChild;
	while( n )
	{
		int inOutFlags;
		asCDataType type = CreateDataTypeFromNode(n, &source);
		type = ModifyDataTypeFromNode(type, n->next, &source, &inOutFlags, &autoHandle);
		
		// Store the parameter type
		func->parameterTypes.PushLast(type);
		func->inOutFlags.PushLast(inOutFlags);

		if( autoHandle && (!type.IsObjectHandle() || type.IsReference()) )
			return asINVALID_DECLARATION;			

		if( paramAutoHandles ) paramAutoHandles->PushLast(autoHandle);

		// Move to next parameter
		n = n->next->next;
		if( n && n->nodeType == snIdentifier )
			n = n->next;
	}

	// Set the read-only flag if const is declared after parameter list
	if( node->lastChild->nodeType == snUndefined && node->lastChild->tokenType == ttConst )
		func->isReadOnly = true;
	else 
		func->isReadOnly = false;

	if( numErrors > 0 || numWarnings > 0 )
		return asINVALID_DECLARATION;

	return 0;
}
示例#7
0
int asCBuilder::RegisterImportedFunction(int importID, asCScriptNode *node, asCScriptCode *file)
{
	// Find name 
	asCScriptNode *f = node->firstChild;
	asCScriptNode *n = f->firstChild->next->next;

	// Check for name conflicts
	GETSTRING(name, &file->code[n->tokenPos], n->tokenLength);
	CheckNameConflict(name.AddressOf(), n, file);

	// Initialize a script function object for registration
	asCDataType returnType;
	returnType = CreateDataTypeFromNode(f->firstChild, file);
	returnType = ModifyDataTypeFromNode(returnType, f->firstChild->next, file, 0, 0);
		
	asCArray<asCDataType> parameterTypes;
	asCArray<int> inOutFlags;
	n = n->next->firstChild;
	while( n )
	{
		int inOutFlag;
		asCDataType type = CreateDataTypeFromNode(n, file);
		type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);

		// Store the parameter type
		n = n->next->next;
		parameterTypes.PushLast(type);
		inOutFlags.PushLast(inOutFlag);

		// Move to next parameter
		if( n && n->nodeType == snIdentifier )
			n = n->next;
	}

	// 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]);

			// TODO: Isn't the name guaranteed to be equal, because of GetFunctionDescriptions()?
			if( name == func->name && 
				parameterTypes.GetLength() == func->parameterTypes.GetLength() )
			{
				bool match = true;
				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;
				}
			}
		}
		
	}

	// Read the module name as well
	n = node->firstChild->next;
	int moduleNameString = module->AddConstantString(&file->code[n->tokenPos+1], n->tokenLength-2);

	delete node;

	// Register the function
	module->AddImportedFunction(importID, name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), moduleNameString);

	return 0;
}
示例#8
0
int asCBuilder::RegisterScriptFunction(int funcID, asCScriptNode *node, asCScriptCode *file, asCObjectType *objType, bool isInterface)
{
	// Find name 
	bool isConstructor = false;
	asCScriptNode *n = 0;
	if( node->firstChild->nodeType == snDataType )
		n = node->firstChild->next->next;
	else
	{
		n = node->firstChild;
		isConstructor = true;
	}

	// Check for name conflicts
	GETSTRING(name, &file->code[n->tokenPos], n->tokenLength);
	if( !isConstructor )
		CheckNameConflict(name.AddressOf(), n, file);
	else
	{
		// Verify that the name of the function is the same as the class
		if( name != objType->name )
		{
			int r, c;
			file->ConvertPosToRowCol(n->tokenPos, &r, &c);
			WriteError(file->name.AddressOf(), TXT_CONSTRUCTOR_NAME_ERROR, r, c);
		}
	}

	if( !isInterface )
	{
		sFunctionDescription *func = new sFunctionDescription;
		functions.PushLast(func);

		func->script  = file;
		func->node    = node;
		func->name    = name;
		func->objType = objType;
		func->funcId  = funcID;
	}

	// Initialize a script function object for registration
	asCDataType returnType = asCDataType::CreatePrimitive(ttVoid, false);
	if( !isConstructor )
	{
		returnType = CreateDataTypeFromNode(node->firstChild, file);
		returnType = ModifyDataTypeFromNode(returnType, node->firstChild->next, file, 0, 0);

		module->RefConfigGroupForObjectType(returnType.GetObjectType());
	}

	asCArray<asCDataType> parameterTypes;
	asCArray<int> inOutFlags;
	n = n->next->firstChild;
	while( n )
	{
		int inOutFlag;
		asCDataType type = CreateDataTypeFromNode(n, file);
		type = ModifyDataTypeFromNode(type, n->next, file, &inOutFlag, 0);

		module->RefConfigGroupForObjectType(type.GetObjectType());

		// Store the parameter type
		parameterTypes.PushLast(type);
		inOutFlags.PushLast(inOutFlag);

		// Move to next parameter
		n = n->next->next;
		if( n && n->nodeType == snIdentifier )
			n = n->next;
	}

	// 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;
				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(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), (asUINT)parameterTypes.GetLength(), isInterface, objType);

	if( objType )
	{
		if( isConstructor )
		{
			if( parameterTypes.GetLength() == 0 )
			{
				// Overload the default constructor
				objType->beh.construct = funcID;
				objType->beh.constructors[0] = funcID;
			}
			else
				objType->beh.constructors.PushLast(funcID);
		}
		else
			objType->methods.PushLast(funcID);
	}

	// We need to delete the node already if this is an interface method
	if( isInterface && node )
		delete node;

	return 0;
}
示例#9
0
int asCBuilder::RegisterScriptFunction(int funcID, asCScriptNode *node, asCScriptCode *file)
{
	// Find name 
	asCScriptNode *n = node->firstChild->next->next;

	// Check for name conflicts
	GETSTRING(name, &file->code[n->tokenPos], n->tokenLength);
	CheckNameConflict(name.AddressOf(), n, file);

	sFunctionDescription *func = new sFunctionDescription;
	functions.PushLast(func);

	func->script = file;
	func->node   = node;
	func->name   = name;

	// Initialize a script function object for registration
	asCDataType returnType;
	returnType = CreateDataTypeFromNode(node->firstChild, file);
	returnType = ModifyDataTypeFromNode(returnType, node->firstChild->next, 0, 0);
		
	module->RefConfigGroupForObjectType(returnType.GetObjectType());

	asCArray<asCDataType> parameterTypes;
	asCArray<int> inOutFlags;
	n = n->next->firstChild;
	while( n )
	{
		int inOutFlag;
		asCDataType type = CreateDataTypeFromNode(n, file);
		type = ModifyDataTypeFromNode(type, n->next, &inOutFlag, 0);

		module->RefConfigGroupForObjectType(type.GetObjectType());

		// Store the parameter type
		parameterTypes.PushLast(type);
		inOutFlags.PushLast(inOutFlag);

		// Move to next parameter
		n = n->next->next;
		if( n && n->nodeType == snIdentifier )
			n = n->next;
	}

	// 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;
				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, func->name.AddressOf(), returnType, parameterTypes.AddressOf(), inOutFlags.AddressOf(), parameterTypes.GetLength());

	return 0;
}