private IrisType ProcessCall()

in Iris/IrisCompiler/FrontEnd/Translator.cs [885:974]


        private IrisType ProcessCall(FilePosition fp, Symbol symbol, bool skipArgList)
        {
            ParsedCallSyntax = true;

            IrisType symbolType = symbol.Type;
            if (!symbolType.IsMethod)
            {
                // Variables can have the same name as functions.  If the symbol is not a method,
                // try looking up the same name in the global scope.  If the global symbol is a
                // method, use it instead.
                Symbol globalSym = _symbolTable.LookupGlobal(symbol.Name);
                if (globalSym != null && globalSym.Type.IsMethod)
                {
                    symbol = globalSym;
                    symbolType = symbol.Type;
                }
            }

            IrisType resultType = IrisType.Invalid;
            bool semanticError = symbolType == IrisType.Invalid;
            if (!symbolType.IsMethod && !semanticError)
            {
                semanticError = true;
                AddError(fp, string.Format("Symbol '{0}' is not a procedure or function.", _lexeme));
            }

            string symbolTypeName = symbolType.IsFunction ? "function" : "procedure";
            Method method = symbolType as Method;
            Variable[] methodParams = method?.GetParameters();
            int count = 0;
            if (!skipArgList && !Accept(Token.ChrCloseParen))
            {
                do
                {
                    FilePosition argPosition = _lexer.TokenStartPosition;

                    if (methodParams != null && count < methodParams.Length)
                    {
                        Variable param = methodParams[count];
                        IrisType paramType = param.Type;
                        IrisType argType = ParseExpression(paramType.IsByRef ? SymbolLoadMode.Address : SymbolLoadMode.Dereference);

                        if (paramType != IrisType.Invalid && argType != IrisType.Invalid && paramType != argType)
                        {
                            if (paramType.IsByRef && !argType.IsByRef)
                            {
                                AddError(argPosition, "Cannot take address of constant, call, or expression.");
                            }
                            else
                            {
                                AddError(argPosition, string.Format(
                                    "Argument type doesn't match parameter '{0}' of {1} '{2}'",
                                    param.Name,
                                    symbolTypeName,
                                    symbol.Name));
                            }
                        }
                    }
                    else
                    {
                        // Undefined method or too many arguments.  Parse the argument without validation.
                        ParseExpression();
                    }

                    count++;
                }
                while (Accept(Token.ChrComma));

                Expect(Token.ChrCloseParen);
            }

            // Verify argument count
            if (methodParams != null && methodParams.Length != count)
            {
                AddError(fp, string.Format(
                    "Wrong number of arguments for {0} '{1}'.  {2} expected.  {3} provided.",
                    symbolTypeName,
                    symbol.Name,
                    methodParams.Length,
                    count));
            }

            if (!semanticError)
            {
                MethodGenerator.Call(symbol);
                resultType = symbolType.IsFunction ? ((Function)symbolType).ReturnType : IrisType.Void;
            }

            return resultType;
        }