public string GetMethod(MidMethodDecl method)
{
string result;
if (_methods.TryGetValue(method, out result))
return result;
var name = _shared.GenerateName(method.Name.ToString());
result = name;
_methods[method] = result;
Span span = new Span();
span.WriteLine("void {0}(",
name);
bool firstParam = true;
var resultType = EmitType(method.ResultType);
var resultVar = DeclareOutParam(
"__result",
resultType,
span,
ref firstParam);
foreach (var p in method.Parameters)
{
var pName = _shared.GenerateName(p.Name.ToString());
var pType = EmitType(p.Type);
var pVal = DeclareParam(
pName,
pType,
span,
ref firstParam);
_varVals[p] = pVal;
}
span.WriteLine(")");
span.WriteLine("{");
var bodySpan = span.IndentSpan();
// Scan for a label expression
// along the 'spine' of the method
var bodyExp = method.Body;
while (bodyExp is MidLetExp)
{
bodyExp = ((MidLetExp)bodyExp).Body;
}
if (bodyExp is MidLabelExp)
{
var labelExp = (MidLabelExp)bodyExp;
// a 'break' to this label should be
// emitted as a 'return':
_labels[labelExp.Label] = new ReturnLabel(this, resultVar);
EmitExp(method.Body, bodySpan);
}
else
{
// Otherwise, the body is an expression,
// and we should return it if it is non-null...
var resultExp = EmitExp(method.Body, bodySpan);
if (method.ResultType != null
&& !(method.ResultType is MidVoidType))
{
Assign(resultVar, resultExp, span);
}
}
span.WriteLine("}");
_subroutineHeaderSpan.Add(span);
return result;
}