249
249
return new PropertyValueReference (ctx, props[i], target, null, values);
252
bool IsCompilerGeneratedType (SoftEvaluationContext cx, TypeMirror tm)
254
return tm.Name.IndexOf (">c__AnonStorey") != -1 || tm.Name.IndexOf (">c__Iterator") != -1;
257
bool InCompilerGeneratedType (EvaluationContext ctx)
252
static bool InGeneratedClosureOrIteratorType (EvaluationContext ctx)
259
254
SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
260
255
if (cx.Frame.Method.IsStatic)
262
257
TypeMirror tm = cx.Frame.Method.DeclaringType;
263
return IsCompilerGeneratedType (cx, tm);
258
return IsGeneratedClosureOrIteratorType (tm);
261
static bool IsGeneratedClosureOrIteratorType (TypeMirror tm)
263
return IsGeneratedClosureType (tm) || IsGeneratedIteratorType (tm);
266
static bool IsGeneratedClosureType (TypeMirror tm)
268
return tm.Name.IndexOf (">c__") != -1;
271
static bool IsGeneratedIteratorType (TypeMirror tm)
275
tm.Name.IndexOf (">c__Iterator") != -1
276
//csc is of form <NAME>d__NUMBER
277
|| (tm.Name.StartsWith ("<") && tm.Name.IndexOf (">d__") > -1);
280
static bool IsHoistedThisReference (FieldInfoMirror field)
282
// mcs is "<>f__this"
283
// csc is "<>4__this"
284
return field.Name.StartsWith ("<>") && field.Name.EndsWith ("__this");
287
static bool IsClosureReferenceField (FieldInfoMirror field)
291
return field.Name.StartsWith ("CS$<>") || field.Name.StartsWith ("<>f__ref");
294
static bool IsClosureReferenceLocal (LocalVariable local)
296
if (local.Name == null)
301
local.Name.Length == 0 || local.Name.StartsWith ("<") || local.Name.StartsWith ("$locvar")
303
|| local.Name.StartsWith ("CS$<>");
306
static bool IsGeneratedTemporaryLocal (LocalVariable local)
308
return local.Name != null && local.Name.StartsWith ("CS$");
311
static string GetHoistedIteratorLocalName (FieldInfoMirror field)
313
//mcs captured args, of form <$>name
314
if (field.Name.StartsWith ("<$>")) {
315
return field.Name.Substring (3);
318
// csc, mcs locals of form <name>__0
319
if (field.Name.StartsWith ("<")) {
320
int i = field.Name.IndexOf ('>');
322
return field.Name.Substring (1, i - 1);
266
IEnumerable<ValueReference> GetCompilerGeneratedLocalVariables (SoftEvaluationContext cx, ValueReference vthis)
328
IEnumerable<ValueReference> GetHoistedLocalVariables (SoftEvaluationContext cx, ValueReference vthis)
268
330
if (vthis == null)
269
331
return new ValueReference [0];
273
335
return new ValueReference [0];
275
337
TypeMirror tm = (TypeMirror) vthis.Type;
276
bool isIterator = tm.Name.IndexOf (">c__Iterator") != -1;
338
bool isIterator = IsGeneratedIteratorType (tm);
278
340
var list = new List<ValueReference> ();
279
341
TypeMirror type = (TypeMirror) vthis.Type;
280
342
foreach (FieldInfoMirror field in type.GetFields ()) {
281
if (field.Name == "<>f__this")
343
if (IsHoistedThisReference (field))
283
if (field.Name.StartsWith ("<>f__ref")) {
284
list.AddRange (GetCompilerGeneratedLocalVariables (cx, new FieldValueReference (cx, field, val, type)));
345
if (IsClosureReferenceField (field)) {
346
list.AddRange (GetHoistedLocalVariables (cx, new FieldValueReference (cx, field, val, type)));
287
349
if (field.Name.StartsWith ("<")) {
288
350
if (isIterator) {
289
int i = field.Name.IndexOf ('>');
291
string vname = field.Name.Substring (1, i - 1);
292
list.Add (new FieldValueReference (cx, field, val, type, vname, ObjectValueFlags.Variable));
351
var name = GetHoistedIteratorLocalName (field);
352
if (!string.IsNullOrEmpty (name)) {
353
list.Add (new FieldValueReference (cx, field, val, type, name, ObjectValueFlags.Variable));
356
} else if (!field.Name.Contains ("$")) {
297
357
list.Add (new FieldValueReference (cx, field, val, type, field.Name, ObjectValueFlags.Variable));
302
ValueReference GetCompilerGeneratedThisReference (SoftEvaluationContext cx)
363
ValueReference GetHoistedThisReference (SoftEvaluationContext cx)
305
366
Value val = cx.Frame.GetThis ();
306
367
TypeMirror type = (TypeMirror) GetValueType (cx, val);
307
FieldInfoMirror field = type.GetField ("<>f__this");
368
return GetHoistedThisReference (cx, type, val);
369
} catch (AbsentInformationException) {
374
ValueReference GetHoistedThisReference (SoftEvaluationContext cx, TypeMirror type, object val)
376
foreach (FieldInfoMirror field in type.GetFields ()) {
377
if (IsHoistedThisReference (field)) {
309
378
return new FieldValueReference (cx, field, val, type, "this", ObjectValueFlags.Literal);
310
} catch (AbsentInformationException) {
379
} else if (IsClosureReferenceField (field)) {
380
var fieldRef = new FieldValueReference (cx, field, val, type);
381
var thisRef = GetHoistedThisReference (cx, field.FieldType, fieldRef.Value);
389
// if the local does not have a name, constructs one from the index
390
static string GetLocalName (SoftEvaluationContext cx, LocalVariable local)
392
var name = local.Name;
393
if (!string.IsNullOrEmpty (local.Name) || cx.SourceCodeAvailable)
395
return "loc" + local.Index;
315
398
protected override ValueReference OnGetLocalVariable (EvaluationContext ctx, string name)
317
400
SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
318
if (InCompilerGeneratedType (cx))
401
if (InGeneratedClosureOrIteratorType (cx))
319
402
return FindByName (OnGetLocalVariables (cx), v => v.Name, name, ctx.CaseSensitive);
326
409
if (int.TryParse (name.Substring (3), out idx))
327
410
local = cx.Frame.Method.GetLocals ().FirstOrDefault (loc => loc.Index == idx);
330
local = ctx.CaseSensitive ? cx.Frame.GetVisibleVariableByName (name) : FindByName (cx.Frame.GetVisibleVariables(), v => v.Name, name, false);
413
local = ctx.CaseSensitive
414
? cx.Frame.GetVisibleVariableByName (name)
415
: FindByName (cx.Frame.GetVisibleVariables(), v => v.Name, name, false);
332
417
if (local != null) {
333
string vname = !string.IsNullOrEmpty (local.Name) || cx.SourceCodeAvailable ? local.Name : "loc" + local.Index;
334
return new VariableValueReference (ctx, vname, local);
418
return new VariableValueReference (ctx, GetLocalName (cx, local), local);
336
420
return FindByName (OnGetLocalVariables (ctx), v => v.Name, name, ctx.CaseSensitive);;
337
421
} catch (AbsentInformationException) {
358
442
} catch (AbsentInformationException) {
361
foreach (LocalVariable var in locals) {
363
string name = !string.IsNullOrEmpty (var.Name) || cx.SourceCodeAvailable ? var.Name : "loc" + var.Index;
364
if (name.Length == 0 || name.StartsWith ("<")) {
365
if (IsCompilerGeneratedType (cx, var.Type)) {
366
foreach (var gv in GetCompilerGeneratedLocalVariables (cx, new VariableValueReference (cx, name, var)))
445
foreach (LocalVariable local in locals) {
448
if (IsClosureReferenceLocal (local) && IsGeneratedClosureType (local.Type)) {
449
foreach (var gv in GetHoistedLocalVariables (cx, new VariableValueReference (cx, local.Name, local))) {
371
yield return new VariableValueReference (cx, name, var);
452
} else if (!IsGeneratedTemporaryLocal (local)) {
453
yield return new VariableValueReference (cx, GetLocalName (cx, local), local);