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();
}