public Expr Parse(ParserContext pcon, object frm)
{
string source = (string)Compiler.SourceVar.deref();
IPersistentMap spanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); // Compiler.GetSourceSpanMap(form);
ISeq form = (ISeq)frm;
IPersistentVector loopLocals = (IPersistentVector)Compiler.LoopLocalsVar.deref();
if (pcon.Rhc != RHC.Return || loopLocals == null)
throw new ParseException("Can only recur from tail position");
if (Compiler.NoRecurVar.deref() != null)
throw new ParseException("Cannot recur across try");
IPersistentVector args = PersistentVector.EMPTY;
for (ISeq s = RT.seq(form.next()); s != null; s = s.next())
args = args.cons(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), s.first()));
if (args.count() != loopLocals.count())
throw new ParseException(string.Format("Mismatched argument count to recur, expected: {0} args, got {1}",
loopLocals.count(), args.count()));
for (int i = 0; i < loopLocals.count(); i++)
{
LocalBinding lb = (LocalBinding)loopLocals.nth(i);
Type primt = lb.PrimitiveType;
if (primt != null)
{
bool mismatch = false;
Type pt = Compiler.MaybePrimitiveType((Expr)args.nth(i));
if (primt == typeof(long))
{
if (!(pt == typeof(long) || pt == typeof(int) || pt == typeof(short) || pt == typeof(uint) || pt == typeof(ushort) || pt == typeof(ulong)
|| pt == typeof(char) || pt == typeof(byte) || pt == typeof(sbyte)))
mismatch = true;
}
else if (primt == typeof(double))
{
if (!(pt == typeof(double) || pt == typeof(float)))
mismatch = true;
}
if (mismatch)
{
lb.RecurMismatch = true;
if (RT.booleanCast(RT.WarnOnReflectionVar.deref()))
RT.errPrintWriter().WriteLine("{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}",
source, spanMap != null ? (int)spanMap.valAt(RT.StartLineKey, 0) : 0,
lb.Name, pt != null ? pt.Name : "Object", primt.Name);
}
}
}
return new RecurExpr(source, spanMap, loopLocals, args);
}