protected void ParseMethod()

in Iris/IrisCompiler/FrontEnd/Translator.cs [171:268]


        protected void ParseMethod(bool isFunction)
        {
            FilePosition namePosition = _lexer.TokenStartPosition;
            if (!Accept(Token.Identifier))
            {
                AddError(namePosition, "Expecting procedure or function name.");
                SkipToNextEnd();
                return;
            }

            string methodName = _lexeme;
            if (!ValidateName(namePosition, methodName, global: true))
                methodName = (_nextUniqueName++).ToString();

            List<Tuple<Variable, FilePosition>> parameterList = new List<Tuple<Variable, FilePosition>>();
            if (Accept(Token.ChrOpenParen) && !Accept(Token.ChrCloseParen))
            {
                ParseVariableList(parameterList, isArgumentList: true);
                Expect(Token.ChrCloseParen);
            }

            IrisType returnType = IrisType.Void;
            if (Accept(Token.ChrColon))
            {
                returnType = ParseType();
                if (!isFunction)
                    AddErrorAtTokenStart("Procedure cannot have return value.");
            }
            else if (isFunction)
            {
                AddErrorAtTokenStart("Expecting return type for function.");
                returnType = IrisType.Invalid;
            }

            Expect(Token.ChrSemicolon);

            // We've now parsed the method header.  We can now create the method symbol and parse
            // the body of the method.
            IrisType method;
            Variable[] parameters = parameterList.Select(p => p.Item1).ToArray();
            method = isFunction ?
                (IrisType)Function.Create(returnType, parameters) :
                Procedure.Create(parameterList.Select(p => p.Item1).ToArray());

            Symbol methodSymbol = _symbolTable.OpenMethod(methodName, method);

            // Add argument symbols for all of the parameters
            foreach (Tuple<Variable, FilePosition> param in parameterList)
            {
                if (ValidateName(param.Item2, param.Item1.Name, global: false))
                    _symbolTable.Add(param.Item1.Name, param.Item1.Type, StorageClass.Argument);
            }

            List<Variable> locals = new List<Variable>();
            if (isFunction)
            {
                // Create a local variable for the return value
                _symbolTable.Add(methodName, returnType, StorageClass.Local);
                locals.Add(new Variable(returnType, methodName));
            }

            if (Accept(Token.KwVar))
            {
                List<Tuple<Variable, FilePosition>> localsAndPositions = new List<Tuple<Variable, FilePosition>>();
                ParseVariableList(localsAndPositions, isArgumentList: false);
                Accept(Token.ChrSemicolon);

                foreach (Tuple<Variable, FilePosition> localDecl in localsAndPositions)
                {
                    Variable local = localDecl.Item1;
                    string localName = local.Name;
                    if (ValidateName(localDecl.Item2, localName, global: false))
                    {
                        _symbolTable.Add(localName, local.Type, StorageClass.Local);
                        locals.Add(local);
                    }
                }
            }

            FilePosition begin = _lexer.TokenStartPosition;
            MethodGenerator.BeginMethod(methodSymbol.Name, returnType, parameters, locals.ToArray(), false, _context.FilePath);
            MethodGenerator.EmitNonCodeLineInfo(begin.Expand(5 /* Length of "begin" */));

            // Initialize locals if needed
            foreach (Variable local in locals)
                InitializeVariableIfNeeded(begin, local);

            // Parse the body of the method
            Expect(Token.KwBegin);
            ParseStatements(Token.KwEnd);

            if (isFunction)
                MethodGenerator.PushLocal(0);

            MethodGenerator.EndMethod();

            _symbolTable.CloseMethod();
        }