Skip to main content
GameDev.net gamedev.net
🔒 Locked

Improved Error Message

Started by droz Nov 19, 2009 at 11:44 AM 1 replies 1.1k views
Original Post
droz
droz
The error message for no matching signature currently doesn't give you a list of candidates that match the name, but not the arguments. So I modified the MatchFunctions to give a list of the candidates in the error message.

void asCCompiler::MatchFunctions(asCArray<int> &funcs, asCArray<asSExprContext*> &args, asCScriptNode *node, const char *name, asCObjectType *objectType, bool isConstMethod, bool silent, bool allowObjectConstruct, const asCString &scope)
{
	asUINT n;
	if( funcs.GetLength() > 0 )
	{
		// Check the number of parameters in the found functions
		for( n = 0; n < funcs.GetLength(); ++n )
		{
			asCScriptFunction *desc = builder->GetFunctionDescription(funcs[n]);

			if( desc->parameterTypes.GetLength() != args.GetLength() )
			{
				// remove it from the list
				if( n == funcs.GetLength()-1 )
					funcs.PopLast();
				else
					funcs[n] = funcs.PopLast();
				n--;
			}
		}

		// Match functions with the parameters, and discard those that do not match
		asCArray<int> matchingFuncs = funcs;

		for( n = 0; n < args.GetLength(); ++n )
		{
			asCArray<int> tempFuncs;
			MatchArgument(funcs, tempFuncs, &args[n]->type, n, allowObjectConstruct);

			// Intersect the found functions with the list of matching functions
			for( asUINT f = 0; f < matchingFuncs.GetLength(); f++ )
			{
				asUINT c;
				for( c = 0; c < tempFuncs.GetLength(); c++ )
				{
					if( matchingFuncs[f] == tempFuncs[c] )
						break;
				}

				// Was the function a match?
				if( c == tempFuncs.GetLength() )
				{
					// No, remove it from the list
					if( f == matchingFuncs.GetLength()-1 )
						matchingFuncs.PopLast();
					else
						matchingFuncs[f] = matchingFuncs.PopLast();
					f--;
				}
			}
		}

		funcs = matchingFuncs;
	}

	if( !isConstMethod )
		FilterConst(funcs);

	if( funcs.GetLength() != 1 && !silent )
	{
		// Build a readable string of the function with parameter types
		asCString str;
		if( scope != "" )
		{
			if( scope == "::" )
				str = scope;
			else
				str = scope + "::";
		}
		str += name;
		str += "(";
		if( args.GetLength() )
			str += args[0]->type.dataType.Format();
		for( n = 1; n < args.GetLength(); n++ )
			str += ", " + args[n]->type.dataType.Format();
		str += ")";

		if( isConstMethod )
			str += " const";

		if( objectType && scope == "" )
			str = objectType->name + "::" + str;

		if( funcs.GetLength() == 0 )
		{
			str.Format(TXT_NO_MATCHING_SIGNATURES_TO_s, str.AddressOf());
			Error(str.AddressOf(), node);

            str = "";
            if( objectType ) 
            {
                asCArray<int> Methods;

                builder->GetObjectMethodDescriptions(name, objectType, Methods, isConstMethod, scope);

                if( Methods.GetLength() > 0 ) 
                {
                    asUINT i = 0;
                    asCScriptFunction *Method = NULL;

                    str.Format(TXT_CANDIDATES_ARE_s, str.AddressOf());

                    for( i = 0; i < Methods.GetLength(); i++  ) 
                    {
                        Method = builder->GetFunctionDescription(Methods);
                        str += "\n\t\t\t\t";
                        str+= Method->GetDeclaration();
                    }
                        
                    Error(str.AddressOf(), node);
                }
            }
            else
            {
                asCArray<int> Functions;
                builder->GetFunctionDescriptions(name, Functions);

                if( Functions.GetLength() > 0 ) 
                {
                    asUINT i = 0;
                    asCScriptFunction *Function = NULL;

                    str.Format(TXT_CANDIDATES_ARE_s, str.AddressOf());
                    for( i = 0; i < Functions.GetLength(); i++  ) 
                    {
                        Function = builder->GetFunctionDescription(Functions);
                        str += "\n\t\t\t\t";
                        str+= Function->GetDeclaration();
                    }
                        
                    Error(str.AddressOf(), node);
                }
            }
		}
		else
		{
			str.Format(TXT_MULTIPLE_MATCHING_SIGNATURES_TO_s, str.AddressOf());
			Error(str.AddressOf(), node);
	
			PrintMatchingFuncs(funcs, node);
		}
	}
}

I also added the following text define:

#define TXT_CANDIDATES_ARE_s                "Candidates are: %s"

Now building the following source:

void test(int a) {

}

void test(float a) {

}

void test(bool c) {

}

class Test {
    void test(int a) {

    }

    void test(float a) {

    }

    void test(bool c) {

    }
}

void main() {
    test();

    Test test;
    test.test();
}

Will give you the following error messages:

Script (27, 1) : INFO : Compiling void main()
Script (28, 5) : ERR  : No matching signatures to 'test()'
Script (28, 5) : ERR  : Candidates are: 
				void test(int)
				void test(float)
				void test(bool)
Script (31, 10) : ERR  : No matching signatures to 'Test::test()'
Script (31, 10) : ERR  : Candidates are: 
				void Test::test(int)
				void Test::test(float)
				void Test::test(bool)

WitchLord
WitchLord
Thanks, I'll add this to the SVN as soon as possible.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - <a href="http://www.angelcode.com/tower" rel
droz
droz
You may want to think of a better solution for indenting, using "\n\t\t\t" seems like a bad idea because I'm forcing formatting of a error message. However it does fit your example message callback and looks much better indented (I made it look similar to GCC's output).

Now if I could only send you a patch that doesn't improve error messages :). I have worked on adding support for overloading the increment and decrement operators, but haven't gotten it working yet. Pre operators were very easy, having trouble with the post operators.

--Jeremy

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.