MegaBites-AI/Windows-powershell
0372
1/* ****************************************************************************2 *3 * Copyright (c) Microsoft Corporation.4 *5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A6 * copy of the license can be found in the License.html file at the root of this distribution. If7 * you cannot locate the Apache License, Version 2.0, please send an email to8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound9 * by the terms of the Apache License, Version 2.0.10 *11 * You must not remove this notice, or any other, from this software.12 *13 *14 * ***************************************************************************/15 16#if !CLR217using System.Globalization;18using System.Linq.Expressions;19#else20using Microsoft.Scripting.Ast;21#endif22using System.Collections.Generic;23using System.Diagnostics;24using System.Runtime.CompilerServices;25 26namespace System.Management.Automation.Interpreter27{28 internal sealed class LocalVariable29 {30 private const int IsBoxedFlag = 1;31 private const int InClosureFlag = 2;32 33 public readonly int Index;34 private int _flags;35 36 public bool IsBoxed37 {38 get39 {40 return (_flags & IsBoxedFlag) != 0;41 }42 43 set44 {45 if (value)46 {47 _flags |= IsBoxedFlag;48 }49 else50 {51 _flags &= ~IsBoxedFlag;52 }53 }54 }55 56 public bool InClosure57 {58 get { return (_flags & InClosureFlag) != 0; }59 }60 61 public bool InClosureOrBoxed62 {63 get { return InClosure || IsBoxed; }64 }65 66 internal LocalVariable(int index, bool closure, bool boxed)67 {68 Index = index;69 _flags = (closure ? InClosureFlag : 0) | (boxed ? IsBoxedFlag : 0);70 }71 72 internal Expression LoadFromArray(Expression frameData, Expression closure)73 {74 Expression result = Expression.ArrayAccess(InClosure ? closure : frameData, Expression.Constant(Index));75 return IsBoxed ? Expression.Convert(result, typeof(StrongBox<object>)) : result;76 }77 78 public override string ToString()79 {80 return string.Format(CultureInfo.InvariantCulture, "{0}: {1} {2}", Index, IsBoxed ? "boxed" : null, InClosure ? "in closure" : null);81 }82 }83 84 internal readonly struct LocalDefinition85 {86 private readonly int _index;87 private readonly ParameterExpression _parameter;88 89 internal LocalDefinition(int localIndex, ParameterExpression parameter)90 {91 _index = localIndex;92 _parameter = parameter;93 }94 95 public int Index96 {97 get98 {99 return _index;100 }101 }102 103 public ParameterExpression Parameter104 {105 get106 {107 return _parameter;108 }109 }110 111 public override bool Equals(object obj)112 {113 if (obj is LocalDefinition)114 {115 LocalDefinition other = (LocalDefinition)obj;116 return other.Index == Index && other.Parameter == Parameter;117 }118 119 return false;120 }121 122 public override int GetHashCode()123 {124 if (_parameter == null)125 {126 return 0;127 }128 129 return _parameter.GetHashCode() ^ _index.GetHashCode();130 }131 132 public static bool operator ==(LocalDefinition self, LocalDefinition other)133 {134 return self.Index == other.Index && self.Parameter == other.Parameter;135 }136 137 public static bool operator !=(LocalDefinition self, LocalDefinition other)138 {139 return self.Index != other.Index || self.Parameter != other.Parameter;140 }141 }142 143 internal sealed class LocalVariables144 {145 private readonly HybridReferenceDictionary<ParameterExpression, VariableScope> _variables = new HybridReferenceDictionary<ParameterExpression, VariableScope>();146 private Dictionary<ParameterExpression, LocalVariable> _closureVariables;147 148 private int _localCount, _maxLocalCount;149 150 internal LocalVariables()151 {152 }153 154 public LocalDefinition DefineLocal(ParameterExpression variable, int start)155 {156 // ContractUtils.RequiresNotNull(variable, "variable");157 // ContractUtils.Requires(start >= 0, "start", "start must be positive");158 159 LocalVariable result = new LocalVariable(_localCount++, false, false);160 _maxLocalCount = System.Math.Max(_localCount, _maxLocalCount);161 162 VariableScope existing, newScope;163 if (_variables.TryGetValue(variable, out existing))164 {165 newScope = new VariableScope(result, start, existing);166 existing.ChildScopes ??= new List<VariableScope>();167 168 existing.ChildScopes.Add(newScope);169 }170 else171 {172 newScope = new VariableScope(result, start, null);173 }174 175 _variables[variable] = newScope;176 return new LocalDefinition(result.Index, variable);177 }178 179 public void UndefineLocal(LocalDefinition definition, int end)180 {181 var scope = _variables[definition.Parameter];182 scope.Stop = end;183 if (scope.Parent != null)184 {185 _variables[definition.Parameter] = scope.Parent;186 }187 else188 {189 _variables.Remove(definition.Parameter);190 }191 192 _localCount--;193 }194 195 internal void Box(ParameterExpression variable, InstructionList instructions)196 {197 var scope = _variables[variable];198 199 LocalVariable local = scope.Variable;200 Debug.Assert(!local.IsBoxed && !local.InClosure);201 _variables[variable].Variable.IsBoxed = true;202 203 int curChild = 0;204 for (int i = scope.Start; i < scope.Stop && i < instructions.Count; i++)205 {206 if (scope.ChildScopes != null && scope.ChildScopes[curChild].Start == i)207 {208 // skip boxing in the child scope209 var child = scope.ChildScopes[curChild];210 i = child.Stop;211 212 curChild++;213 continue;214 }215 216 instructions.SwitchToBoxed(local.Index, i);217 }218 }219 220 public int LocalCount221 {222 get { return _maxLocalCount; }223 }224 225 public int GetOrDefineLocal(ParameterExpression var)226 {227 int index = GetLocalIndex(var);228 if (index == -1)229 {230 return DefineLocal(var, 0).Index;231 }232 233 return index;234 }235 236 public int GetLocalIndex(ParameterExpression var)237 {238 VariableScope loc;239 return _variables.TryGetValue(var, out loc) ? loc.Variable.Index : -1;240 }241 242 public bool TryGetLocalOrClosure(ParameterExpression var, out LocalVariable local)243 {244 VariableScope scope;245 if (_variables.TryGetValue(var, out scope))246 {247 local = scope.Variable;248 return true;249 }250 251 if (_closureVariables != null && _closureVariables.TryGetValue(var, out local))252 {253 return true;254 }255 256 local = null;257 return false;258 }259 260 /// <summary>261 /// Gets a copy of the local variables which are defined in the current scope.262 /// </summary>263 /// <returns></returns>264 internal Dictionary<ParameterExpression, LocalVariable> CopyLocals()265 {266 var res = new Dictionary<ParameterExpression, LocalVariable>(_variables.Count);267 foreach (var keyValue in _variables)268 {269 res[keyValue.Key] = keyValue.Value.Variable;270 }271 272 return res;273 }274 275 /// <summary>276 /// Checks to see if the given variable is defined within the current local scope.277 /// </summary>278 internal bool ContainsVariable(ParameterExpression variable)279 {280 return _variables.ContainsKey(variable);281 }282 283 /// <summary>284 /// Gets the variables which are defined in an outer scope and available within the current scope.285 /// </summary>286 internal Dictionary<ParameterExpression, LocalVariable> ClosureVariables287 {288 get289 {290 return _closureVariables;291 }292 }293 294 internal LocalVariable AddClosureVariable(ParameterExpression variable)295 {296 _closureVariables ??= new Dictionary<ParameterExpression, LocalVariable>();297 298 LocalVariable result = new LocalVariable(_closureVariables.Count, true, false);299 _closureVariables.Add(variable, result);300 return result;301 }302 303 /// <summary>304 /// Tracks where a variable is defined and what range of instructions it's used in.305 /// </summary>306 private sealed class VariableScope307 {308 public readonly int Start;309 public int Stop = Int32.MaxValue;310 public readonly LocalVariable Variable;311 public readonly VariableScope Parent;312 public List<VariableScope> ChildScopes;313 314 public VariableScope(LocalVariable variable, int start, VariableScope parent)315 {316 Variable = variable;317 Start = start;318 Parent = parent;319 }320 }321 }322}323 