Beispiel #1
0
 /// <summary>
 /// Exit a parse tree produced by the <c>fnCallExp</c>
 /// labeled alternative in <see cref="ChessVCParser.postfixExpr"/>.
 /// <para>The default implementation does nothing.</para>
 /// </summary>
 /// <param name="context">The parse tree.</param>
 public virtual void ExitFnCallExp([NotNull] ChessVCParser.FnCallExpContext context)
 {
 }
Beispiel #2
0
 /// <summary>
 /// Visit a parse tree produced by the <c>fnCallExp</c>
 /// labeled alternative in <see cref="ChessVCParser.postfixExpr"/>.
 /// <para>
 /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
 /// on <paramref name="context"/>.
 /// </para>
 /// </summary>
 /// <param name="context">The parse tree.</param>
 /// <return>The visitor result.</return>
 public virtual Result VisitFnCallExp([NotNull] ChessVCParser.FnCallExpContext context)
 {
     return(VisitChildren(context));
 }
        public override object VisitFnCallExp([NotNull] ChessVCParser.FnCallExpContext context)
        {
            string s     = context.GetText();
            object fnobj = Visit(context.postfixExpr());

            if (fnobj is Reference)
            {
                Reference fnref = (Reference)fnobj;
                if (fnref.IsFunction)
                {
                    //	load all the function arguments
                    var      argListCtx = context.argumentList();
                    object[] arglist    = argListCtx == null ? new Reference[] { } : (object[])Visit(context.argumentList());

                    //	case of non-overloaded function
                    if (fnref.FunctionMember != null)
                    {
                        ParameterInfo[] pi = fnref.FunctionMember.GetParameters();
                        int             calledFunctionArgCount = fnref.FunctionMember.GetParameters().Length;
                        if (calledFunctionArgCount != arglist.Length)
                        {
                            //	we didn't supply all the arguments, but maybe the rest are optional
                            bool allRemainingArgsAreOptional = false;
                            if (arglist.Length < calledFunctionArgCount)
                            {
                                allRemainingArgsAreOptional = true;
                                for (int x = arglist.Length; x < calledFunctionArgCount; x++)
                                {
                                    if (!fnref.FunctionMember.GetParameters()[x].IsOptional)
                                    {
                                        allRemainingArgsAreOptional = false;
                                    }
                                }
                            }
                            if (!allRemainingArgsAreOptional)
                            {
                                throw new Exception("Incorrect number of arguments specified for function: " + context.postfixExpr().GetText());
                            }
                        }
                        if (!canMatchSignature(fnref.FunctionMember.GetParameters(), arglist))
                        {
                            //	before we decide we can't call this function, check to see if
                            //	there is only one argument, that argument is a type, that type
                            //	has a constructor taking no arguments, and if, after construction,
                            //	the object is of the required type.  If all this pans out,
                            //	we'll just construct a new object of this type.
                            if (arglist.Length == 1 && arglist[0].GetType() is Type &&
                                ((Type)arglist[0]).IsSubclassOf(fnref.FunctionMember.GetParameters()[0].ParameterType))
                            {
                                Type            t  = (Type)arglist[0];
                                ConstructorInfo ci = t.GetConstructor(new Type[] { });
                                if (ci != null)
                                {
                                    object[] arg = new object[1];
                                    arg[0] = ci.Invoke(null);
                                    return(fnref.GetValue(arg));
                                }
                            }
                            throw new Exception("Arguments of incorrect type provided for function: " + context.postfixExpr().GetText());
                        }
                        object[] args = new object[calledFunctionArgCount];
                        for (int x = 0; x < arglist.Length; x++)
                        {
                            args[x] = arglist[x];
                        }
                        for (int y = arglist.Length; y < calledFunctionArgCount; y++)
                        {
                            args[y] = Type.Missing;
                        }
                        return(fnref.GetValue(args));
                    }
                    else if (fnref.FunctionOverloads != null)
                    {
                        //	we have overloaded functions - search for one that works
                        foreach (MethodInfo mi in fnref.FunctionOverloads)
                        {
                            if (canMatchSignature(mi.GetParameters(), arglist))
                            {
                                ParameterInfo[] parameters = mi.GetParameters();
                                object[]        args       = new object[parameters.Length];
                                for (int x = 0; x < parameters.Length; x++)
                                {
                                    args[x] = x < arglist.Length ? arglist[x] : Type.Missing;
                                }
                                return(mi.Invoke(fnref.ReferencedObject, args));
                            }
                        }
                        throw new Exception("No overloaded found with compatible arguments for function: " + context.postfixExpr().GetText());
                    }
                }
                else if (fnref.ReferencedObject.GetType().IsSubclassOf(typeof(Type)))
                {
                    //	load the constructor arguments
                    var      argListCtx = context.argumentList();
                    object[] arglist    = argListCtx == null ? new Reference[] { } : (object[])Visit(context.argumentList());
                    //	our function call is really calling a constructor
                    Type tp = (Type)fnref.ReferencedObject;
                    foreach (ConstructorInfo ci in tp.GetConstructors())
                    {
                        if (canMatchSignature(ci.GetParameters(), arglist))
                        {
                            ParameterInfo[] parameters = ci.GetParameters();
                            object[]        args       = new object[parameters.Length];
                            for (int x = 0; x < parameters.Length; x++)
                            {
                                args[x] = x < arglist.Length ? arglist[x] : Type.Missing;
                            }
                            return(ci.Invoke(args));
                        }
                    }
                    throw new Exception("No constructor found with compatible arguments for type: " + context.postfixExpr().GetText());
                }
            }
            throw new Exception("Function call attempted with object that is not a function: " + context.postfixExpr().GetText());
        }