211 lines
6.5 KiB
C#
211 lines
6.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace System.Linq.Expressions
|
|
{
|
|
// Token: 0x02000019 RID: 25
|
|
internal class CompilationContext
|
|
{
|
|
// Token: 0x06000167 RID: 359 RVA: 0x000091AC File Offset: 0x000073AC
|
|
public int AddGlobal(object global)
|
|
{
|
|
return CompilationContext.AddItemToList<object>(global, this.globals);
|
|
}
|
|
|
|
// Token: 0x06000168 RID: 360 RVA: 0x000091BC File Offset: 0x000073BC
|
|
public object[] GetGlobals()
|
|
{
|
|
return this.globals.ToArray();
|
|
}
|
|
|
|
// Token: 0x06000169 RID: 361 RVA: 0x000091CC File Offset: 0x000073CC
|
|
private static int AddItemToList<T>(T item, IList<T> list)
|
|
{
|
|
list.Add(item);
|
|
return list.Count - 1;
|
|
}
|
|
|
|
// Token: 0x0600016A RID: 362 RVA: 0x000091E0 File Offset: 0x000073E0
|
|
public int AddCompilationUnit(LambdaExpression lambda)
|
|
{
|
|
this.DetectHoistedVariables(lambda);
|
|
return this.AddCompilationUnit(null, lambda);
|
|
}
|
|
|
|
// Token: 0x0600016B RID: 363 RVA: 0x000091F4 File Offset: 0x000073F4
|
|
public int AddCompilationUnit(EmitContext parent, LambdaExpression lambda)
|
|
{
|
|
EmitContext emitContext = new EmitContext(this, parent, lambda);
|
|
int num = CompilationContext.AddItemToList<EmitContext>(emitContext, this.units);
|
|
emitContext.Emit();
|
|
return num;
|
|
}
|
|
|
|
// Token: 0x0600016C RID: 364 RVA: 0x00009220 File Offset: 0x00007420
|
|
private void DetectHoistedVariables(LambdaExpression lambda)
|
|
{
|
|
this.hoisted_map = new CompilationContext.HoistedVariableDetector().Process(lambda);
|
|
}
|
|
|
|
// Token: 0x0600016D RID: 365 RVA: 0x00009234 File Offset: 0x00007434
|
|
public List<ParameterExpression> GetHoistedLocals(LambdaExpression lambda)
|
|
{
|
|
if (this.hoisted_map == null)
|
|
{
|
|
return null;
|
|
}
|
|
List<ParameterExpression> list;
|
|
this.hoisted_map.TryGetValue(lambda, out list);
|
|
return list;
|
|
}
|
|
|
|
// Token: 0x0600016E RID: 366 RVA: 0x00009260 File Offset: 0x00007460
|
|
public object[] CreateHoistedLocals(int unit)
|
|
{
|
|
List<ParameterExpression> hoistedLocals = this.GetHoistedLocals(this.units[unit].Lambda);
|
|
return new object[(hoistedLocals != null) ? hoistedLocals.Count : 0];
|
|
}
|
|
|
|
// Token: 0x0600016F RID: 367 RVA: 0x0000929C File Offset: 0x0000749C
|
|
public Expression IsolateExpression(ExecutionScope scope, object[] locals, Expression expression)
|
|
{
|
|
return new CompilationContext.ParameterReplacer(this, scope, locals).Transform(expression);
|
|
}
|
|
|
|
// Token: 0x06000170 RID: 368 RVA: 0x000092AC File Offset: 0x000074AC
|
|
public Delegate CreateDelegate()
|
|
{
|
|
return this.CreateDelegate(0, new ExecutionScope(this));
|
|
}
|
|
|
|
// Token: 0x06000171 RID: 369 RVA: 0x000092BC File Offset: 0x000074BC
|
|
public Delegate CreateDelegate(int unit, ExecutionScope scope)
|
|
{
|
|
return this.units[unit].CreateDelegate(scope);
|
|
}
|
|
|
|
// Token: 0x04000064 RID: 100
|
|
private List<object> globals = new List<object>();
|
|
|
|
// Token: 0x04000065 RID: 101
|
|
private List<EmitContext> units = new List<EmitContext>();
|
|
|
|
// Token: 0x04000066 RID: 102
|
|
private Dictionary<LambdaExpression, List<ParameterExpression>> hoisted_map;
|
|
|
|
// Token: 0x0200001A RID: 26
|
|
private class ParameterReplacer : ExpressionTransformer
|
|
{
|
|
// Token: 0x06000172 RID: 370 RVA: 0x000092D0 File Offset: 0x000074D0
|
|
public ParameterReplacer(CompilationContext context, ExecutionScope scope, object[] locals)
|
|
{
|
|
this.context = context;
|
|
this.scope = scope;
|
|
this.locals = locals;
|
|
}
|
|
|
|
// Token: 0x06000173 RID: 371 RVA: 0x000092F0 File Offset: 0x000074F0
|
|
protected override Expression VisitParameter(ParameterExpression parameter)
|
|
{
|
|
ExecutionScope parent = this.scope;
|
|
object[] array = this.locals;
|
|
while (parent != null)
|
|
{
|
|
int num = this.IndexOfHoistedLocal(parent, parameter);
|
|
if (num != -1)
|
|
{
|
|
return this.ReadHoistedLocalFromArray(array, num);
|
|
}
|
|
array = parent.Locals;
|
|
parent = parent.Parent;
|
|
}
|
|
return parameter;
|
|
}
|
|
|
|
// Token: 0x06000174 RID: 372 RVA: 0x00009340 File Offset: 0x00007540
|
|
private Expression ReadHoistedLocalFromArray(object[] locals, int position)
|
|
{
|
|
return Expression.Field(Expression.Convert(Expression.ArrayIndex(Expression.Constant(locals), Expression.Constant(position)), locals[position].GetType()), "Value");
|
|
}
|
|
|
|
// Token: 0x06000175 RID: 373 RVA: 0x0000937C File Offset: 0x0000757C
|
|
private int IndexOfHoistedLocal(ExecutionScope scope, ParameterExpression parameter)
|
|
{
|
|
return this.context.units[scope.compilation_unit].IndexOfHoistedLocal(parameter);
|
|
}
|
|
|
|
// Token: 0x04000067 RID: 103
|
|
private CompilationContext context;
|
|
|
|
// Token: 0x04000068 RID: 104
|
|
private ExecutionScope scope;
|
|
|
|
// Token: 0x04000069 RID: 105
|
|
private object[] locals;
|
|
}
|
|
|
|
// Token: 0x0200001B RID: 27
|
|
private class HoistedVariableDetector : ExpressionVisitor
|
|
{
|
|
// Token: 0x06000177 RID: 375 RVA: 0x000093B0 File Offset: 0x000075B0
|
|
public Dictionary<LambdaExpression, List<ParameterExpression>> Process(LambdaExpression lambda)
|
|
{
|
|
this.Visit(lambda);
|
|
return this.hoisted_map;
|
|
}
|
|
|
|
// Token: 0x06000178 RID: 376 RVA: 0x000093C0 File Offset: 0x000075C0
|
|
protected override void VisitLambda(LambdaExpression lambda)
|
|
{
|
|
this.lambda = lambda;
|
|
foreach (ParameterExpression parameterExpression in lambda.Parameters)
|
|
{
|
|
this.parameter_to_lambda[parameterExpression] = lambda;
|
|
}
|
|
base.VisitLambda(lambda);
|
|
}
|
|
|
|
// Token: 0x06000179 RID: 377 RVA: 0x00009438 File Offset: 0x00007638
|
|
protected override void VisitParameter(ParameterExpression parameter)
|
|
{
|
|
if (this.lambda.Parameters.Contains(parameter))
|
|
{
|
|
return;
|
|
}
|
|
this.Hoist(parameter);
|
|
}
|
|
|
|
// Token: 0x0600017A RID: 378 RVA: 0x00009458 File Offset: 0x00007658
|
|
private void Hoist(ParameterExpression parameter)
|
|
{
|
|
LambdaExpression lambdaExpression;
|
|
if (!this.parameter_to_lambda.TryGetValue(parameter, out lambdaExpression))
|
|
{
|
|
return;
|
|
}
|
|
if (this.hoisted_map == null)
|
|
{
|
|
this.hoisted_map = new Dictionary<LambdaExpression, List<ParameterExpression>>();
|
|
}
|
|
List<ParameterExpression> list;
|
|
if (!this.hoisted_map.TryGetValue(lambdaExpression, out list))
|
|
{
|
|
list = new List<ParameterExpression>();
|
|
this.hoisted_map[lambdaExpression] = list;
|
|
}
|
|
list.Add(parameter);
|
|
}
|
|
|
|
// Token: 0x0400006A RID: 106
|
|
private Dictionary<ParameterExpression, LambdaExpression> parameter_to_lambda = new Dictionary<ParameterExpression, LambdaExpression>();
|
|
|
|
// Token: 0x0400006B RID: 107
|
|
private Dictionary<LambdaExpression, List<ParameterExpression>> hoisted_map;
|
|
|
|
// Token: 0x0400006C RID: 108
|
|
private LambdaExpression lambda;
|
|
}
|
|
}
|
|
}
|