internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars) { if (this.NearestHoistedLocals != null) { List <long> list = new List <long>(vars.Count); foreach (ParameterExpression expression in vars) { ulong num = 0L; HoistedLocals nearestHoistedLocals = this.NearestHoistedLocals; while (!nearestHoistedLocals.Indexes.ContainsKey(expression)) { num += (ulong)1L; nearestHoistedLocals = nearestHoistedLocals.Parent; } ulong num2 = (num << 0x20) | ((ulong)nearestHoistedLocals.Indexes[expression]); list.Add((long)num2); } if (list.Count > 0) { this.EmitGet(this.NearestHoistedLocals.SelfVariable); lc.EmitConstantArray <long>(list.ToArray()); lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new Type[] { typeof(object[]), typeof(long[]) })); return; } } lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes)); }
private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals) { lc.EmitClosureArgument(); lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Locals")); AddLocal(lc, locals.SelfVariable); EmitSet(locals.SelfVariable); }
private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals) { lc.EmitClosureArgument(); lc.IL.Emit(OpCodes.Ldfld, Closure_Locals); AddLocal(lc, locals.SelfVariable); EmitSet(locals.SelfVariable); }
private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals) { if (locals != null) { this.EmitClosureToVariable(lc, locals); while ((locals = locals.Parent) != null) { ParameterExpression selfVariable = locals.SelfVariable; LocalStorage storage = new LocalStorage(lc, selfVariable); storage.EmitStore(this.ResolveVariable(selfVariable)); this._locals.Add(selfVariable, storage); } } }
internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection<ParameterExpression> vars) { if (parent != null) { vars = new TrueReadOnlyCollection<ParameterExpression>(vars.AddFirst<ParameterExpression>(parent.SelfVariable)); } Dictionary<Expression, int> dict = new Dictionary<Expression, int>(vars.Count); for (int i = 0; i < vars.Count; i++) { dict.Add(vars[i], i); } this.SelfVariable = Expression.Variable(typeof(object[]), null); this.Parent = parent; this.Variables = vars; this.Indexes = new ReadOnlyDictionary<Expression, int>(dict); }
internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection <ParameterExpression> vars) { if (parent != null) { vars = new TrueReadOnlyCollection <ParameterExpression>(vars.AddFirst <ParameterExpression>(parent.SelfVariable)); } Dictionary <Expression, int> dict = new Dictionary <Expression, int>(vars.Count); for (int i = 0; i < vars.Count; i++) { dict.Add(vars[i], i); } this.SelfVariable = Expression.Variable(typeof(object[]), null); this.Parent = parent; this.Variables = vars; this.Indexes = new ReadOnlyDictionary <Expression, int>(dict); }
private void SetParent(LambdaCompiler lc, CompilerScope parent) { this._parent = parent; if (this.NeedsClosure && (this._parent != null)) { this._closureHoistedLocals = this._parent.NearestHoistedLocals; } ReadOnlyCollection <ParameterExpression> vars = (from p in this.GetVariables() where ((VariableStorageKind)this.Definitions[p]) == VariableStorageKind.Hoisted select p).ToReadOnly <ParameterExpression>(); if (vars.Count > 0) { this._hoistedLocals = new HoistedLocals(this._closureHoistedLocals, vars); this.AddLocal(lc, this._hoistedLocals.SelfVariable); } }
internal CompilerScope Exit() { if (!this.IsMethod) { foreach (Storage storage in this._locals.Values) { storage.FreeLocal(); } } CompilerScope scope = this._parent; this._parent = null; this._hoistedLocals = null; this._closureHoistedLocals = null; this._locals.Clear(); return(scope); }
// Creates IL locals for accessing closures private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals) { if (locals == null) { return; } EmitClosureToVariable(lc, locals); while ((locals = locals.Parent) != null) { var v = locals.SelfVariable; var local = new LocalStorage(lc, v); local.EmitStore(ResolveVariable(v)); _locals.Add(v, local); } }
private void SetParent(LambdaCompiler lc, CompilerScope parent) { Debug.Assert(_parent == null && parent != this); _parent = parent; if (NeedsClosure && _parent != null) { _closureHoistedLocals = _parent.NearestHoistedLocals; } var hoistedVars = GetVariables().Where(p => Definitions[p] == VariableStorageKind.Hoisted).ToReadOnly(); if (hoistedVars.Count > 0) { _hoistedLocals = new HoistedLocals(_closureHoistedLocals, hoistedVars); AddLocal(lc, _hoistedLocals.SelfVariable); } }
internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection<ParameterExpression> vars) { if (parent != null) { // Add the parent locals array as the 0th element in the array vars = vars.AddFirst(parent.SelfVariable); } Dictionary<Expression, int> indexes = new Dictionary<Expression, int>(vars.Count); for (int i = 0; i < vars.Count; i++) { indexes.Add(vars[i], i); } SelfVariable = Expression.Variable(typeof(object[]), name: null); Parent = parent; Variables = vars; Indexes = new ReadOnlyDictionary<Expression, int>(indexes); }
internal HoistedLocals(HoistedLocals parent, ReadOnlyCollection <ParameterExpression> vars) { if (parent != null) { // Add the parent locals array as the 0th element in the array vars = new TrueReadOnlyCollection <ParameterExpression>(vars.AddFirst(parent.SelfVariable)); } Dictionary <Expression, int> indexes = new Dictionary <Expression, int>(vars.Count); for (int i = 0; i < vars.Count; i++) { indexes.Add(vars[i], i); } SelfVariable = Expression.Variable(typeof(object[]), null); Parent = parent; Variables = vars; Indexes = new ReadOnlyDictionary <Expression, int>(indexes); }
/// <summary> /// Resolve a local variable in this scope or a closed over scope /// Throws if the variable is defined /// </summary> private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) { // Search IL locals and arguments, but only in this lambda for (CompilerScope s = this; s != null; s = s._parent) { Storage storage; if (s._locals.TryGetValue(variable, out storage)) { return(storage); } // if this is a lambda, we're done if (s.IsMethod) { break; } } // search hoisted locals for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent) { int index; if (h.Indexes.TryGetValue(variable, out index)) { return(new ElementBoxStorage( ResolveVariable(h.SelfVariable, hoistedLocals), index, variable )); } } // // If this is an unbound variable in the lambda, the error will be // thrown from VariableBinder. So an error here is generally caused // by an internal error, e.g. a scope was created but it bypassed // VariableBinder. // throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName); }
/// <summary> /// Frees unnamed locals, clears state associated with this compiler /// </summary> internal CompilerScope Exit() { // free scope's variables if (!IsMethod) { foreach (var storage in _locals.Values) { storage.FreeLocal(); } } // Clear state that is associated with this parent // (because the scope can be reused in another context) var parent = _parent; _parent = null; _hoistedLocals = null; _closureHoistedLocals = null; _locals.Clear(); return(parent); }
internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars) { if (NearestHoistedLocals != null) { // Find what array each variable is on & its index var indexes = new List <long>(vars.Count); foreach (var variable in vars) { // For each variable, find what array it's defined on ulong parents = 0; HoistedLocals locals = NearestHoistedLocals; while (!locals.Indexes.ContainsKey(variable)) { parents++; locals = locals.Parent; Debug.Assert(locals != null); } // combine the number of parents we walked, with the // real index of variable to get the index to emit. ulong index = (parents << 32) | (uint)locals.Indexes[variable]; indexes.Add((long)index); } if (indexes.Count > 0) { EmitGet(NearestHoistedLocals.SelfVariable); lc.EmitConstantArray(indexes.ToArray()); lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", new[] { typeof(object[]), typeof(long[]) })); return; } } // No visible variables lc.IL.Emit(OpCodes.Call, typeof(RuntimeOps).GetMethod("CreateRuntimeVariables", Type.EmptyTypes)); return; }
private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) { // Search IL locals and arguments, but only in this lambda for (var s = this; s != null; s = s._parent) { if (s._locals.TryGetValue(variable, out var storage)) { return(storage); } // if this is a lambda, we're done if (s.IsMethod) { break; } } // search hoisted locals for (var h = hoistedLocals; h != null; h = h.Parent) { if (h.Indexes.TryGetValue(variable, out var index)) { return(new ElementBoxStorage ( ResolveVariable(h.SelfVariable, hoistedLocals), index, variable )); } } // // If this is an unbound variable in the lambda, the error will be // thrown from VariableBinder. So an error here is generally caused // by an internal error, e.g. a scope was created but it bypassed // VariableBinder. // throw new InvalidOperationException($"variable '{variable.Name}' of type '{variable.Type}' referenced from scope '{CurrentLambdaName}', but it is not defined"); }
private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) { for (CompilerScope scope = this; scope != null; scope = scope._parent) { Storage storage; if (scope._locals.TryGetValue(variable, out storage)) { return(storage); } if (scope.IsMethod) { break; } } for (HoistedLocals locals = hoistedLocals; locals != null; locals = locals.Parent) { int num; if (locals.Indexes.TryGetValue(variable, out num)) { return(new ElementBoxStorage(this.ResolveVariable(locals.SelfVariable, hoistedLocals), num, variable)); } } throw Error.UndefinedVariable(variable.Name, variable.Type, this.CurrentLambdaName); }
/// <summary> /// Resolve a local variable in this scope or a closed over scope /// Throws if the variable is defined /// </summary> private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) { // Search IL locals and arguments, but only in this lambda for (CompilerScope s = this; s != null; s = s._parent) { Storage storage; if (s._locals.TryGetValue(variable, out storage)) { return(storage); } // if this is a lambda, we're done if (s.IsLambda) { break; } } // search hoisted locals for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent) { int index; if (h.Indexes.TryGetValue(variable, out index)) { return(new ElementBoxStorage( ResolveVariable(h.SelfVariable, hoistedLocals), index, variable )); } } // If this is a genuine unbound variable, the error should be // thrown in VariableBinder. throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName); }
internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars) { if (NearestHoistedLocals != null && vars.Count > 0) { // Find what array each variable is on & its index var indexes = new ArrayBuilder <long>(vars.Count); foreach (var variable in vars) { // For each variable, find what array it's defined on ulong parents = 0; HoistedLocals locals = NearestHoistedLocals; while (!locals.Indexes.ContainsKey(variable)) { parents++; locals = locals.Parent; Debug.Assert(locals != null); } // combine the number of parents we walked, with the // real index of variable to get the index to emit. ulong index = (parents << 32) | (uint)locals.Indexes[variable]; indexes.UncheckedAdd((long)index); } EmitGet(NearestHoistedLocals.SelfVariable); lc.EmitConstantArray(indexes.ToArray()); lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables_ObjectArray_Int64Array); } else { // No visible variables lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables); } }
/// <summary> /// Resolve a local variable in this scope or a closed over scope /// Throws if the variable is defined /// </summary> private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) { // Search IL locals and arguments, but only in this lambda for (CompilerScope s = this; s != null; s = s._parent) { Storage storage; if (s._locals.TryGetValue(variable, out storage)) { return storage; } // if this is a lambda, we're done if (s.IsLambda) { break; } } // search hoisted locals for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent) { int index; if (h.Indexes.TryGetValue(variable, out index)) { return new ElementBoxStorage( ResolveVariable(h.SelfVariable, hoistedLocals), index, variable ); } } // If this is a genuine unbound variable, the error should be // thrown in VariableBinder. throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName); }
/// <summary> /// Frees unnamed locals, clears state associated with this compiler /// </summary> internal CompilerScope Exit() { // free scope's variables if (!IsMethod) { foreach (Storage storage in _locals.Values) { storage.FreeLocal(); } } // Clear state that is associated with this parent // (because the scope can be reused in another context) CompilerScope parent = _parent; _parent = null; _hoistedLocals = null; _closureHoistedLocals = null; _locals.Clear(); return parent; }
/// <summary> /// Resolve a local variable in this scope or a closed over scope /// Throws if the variable is not defined /// </summary> private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) { // Search IL locals and arguments, but only in this lambda for (CompilerScope s = this; s != null; s = s._parent) { Storage storage; if (s._locals.TryGetValue(variable, out storage)) { return storage; } // if this is a lambda, we're done if (s.IsMethod) { break; } } // search hoisted locals for (HoistedLocals h = hoistedLocals; h != null; h = h.Parent) { int index; if (h.Indexes.TryGetValue(variable, out index)) { return new ElementBoxStorage( ResolveVariable(h.SelfVariable, hoistedLocals), index, variable ); } } // // If this is an unbound variable in the lambda, the error will be // thrown from VariableBinder. So an error here is generally caused // by an internal error, e.g. a scope was created but it bypassed // VariableBinder. // throw Error.UndefinedVariable(variable.Name, variable.Type, CurrentLambdaName); }
private void SetParent(LambdaCompiler lc, CompilerScope parent) { Debug.Assert(_parent == null && parent != this); _parent = parent; if (NeedsClosure && _parent != null) { _closureHoistedLocals = _parent.NearestHoistedLocals; } ReadOnlyCollection<ParameterExpression> hoistedVars = GetVariables().Where(p => Definitions[p] == VariableStorageKind.Hoisted).ToReadOnly(); if (hoistedVars.Count > 0) { _hoistedLocals = new HoistedLocals(_closureHoistedLocals, hoistedVars); AddLocal(lc, _hoistedLocals.SelfVariable); } }
// Creates IL locals for accessing closures private void EmitClosureAccess(LambdaCompiler lc, HoistedLocals locals) { if (locals == null) { return; } EmitClosureToVariable(lc, locals); while ((locals = locals.Parent) != null) { ParameterExpression v = locals.SelfVariable; var local = new LocalStorage(lc, v); local.EmitStore(ResolveVariable(v)); _locals.Add(v, local); } }
private void EmitClosureToVariable(LambdaCompiler lc, HoistedLocals locals) { lc.EmitClosureArgument(); lc.IL.Emit(OpCodes.Ldfld, typeof(Closure).GetField("Locals")); this.AddLocal(lc, locals.SelfVariable); this.EmitSet(locals.SelfVariable); }
internal CompilerScope Exit() { if (!this.IsMethod) { foreach (Storage storage in this._locals.Values) { storage.FreeLocal(); } } CompilerScope scope = this._parent; this._parent = null; this._hoistedLocals = null; this._closureHoistedLocals = null; this._locals.Clear(); return scope; }
private void SetParent(LambdaCompiler lc, CompilerScope parent) { this._parent = parent; if (this.NeedsClosure && (this._parent != null)) { this._closureHoistedLocals = this._parent.NearestHoistedLocals; } ReadOnlyCollection<ParameterExpression> vars = (from p in this.GetVariables() where ((VariableStorageKind) this.Definitions[p]) == VariableStorageKind.Hoisted select p).ToReadOnly<ParameterExpression>(); if (vars.Count > 0) { this._hoistedLocals = new HoistedLocals(this._closureHoistedLocals, vars); this.AddLocal(lc, this._hoistedLocals.SelfVariable); } }
private Storage ResolveVariable(ParameterExpression variable, HoistedLocals hoistedLocals) { for (CompilerScope scope = this; scope != null; scope = scope._parent) { Storage storage; if (scope._locals.TryGetValue(variable, out storage)) { return storage; } if (scope.IsMethod) { break; } } for (HoistedLocals locals = hoistedLocals; locals != null; locals = locals.Parent) { int num; if (locals.Indexes.TryGetValue(variable, out num)) { return new ElementBoxStorage(this.ResolveVariable(locals.SelfVariable, hoistedLocals), num, variable); } } throw Error.UndefinedVariable(variable.Name, variable.Type, this.CurrentLambdaName); }