MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Management.Automation.Internal;6using System.Management.Automation.Language;7using System.Runtime.CompilerServices;8 9namespace System.Management.Automation10{11 /// <summary>12 /// The parameter binder for shell functions.13 /// </summary>14 internal class ScriptParameterBinder : ParameterBinderBase15 {16 #region ctor17 18 /// <summary>19 /// Constructs a ScriptParameterBinder with the specified context.20 /// </summary>21 /// <param name="script">22 /// The script block representing the code being run23 /// </param>24 /// <param name="invocationInfo">25 /// The invocation information about the code that is being run.26 /// </param>27 /// <param name="context">28 /// The context under which the shell function is executing.29 /// </param>30 /// <param name="command">31 /// The command instance that represents the script in a pipeline. May be null.32 /// </param>33 /// <param name="localScope">34 /// If binding in a new local scope, the scope to set variables in. If dotting, the value is null.35 /// </param>36 internal ScriptParameterBinder(37 ScriptBlock script,38 InvocationInfo invocationInfo,39 ExecutionContext context,40 InternalCommand command,41 SessionStateScope localScope) : base(invocationInfo, context, command)42 {43 Diagnostics.Assert(script != null, "caller to verify script is not null.");44 45 this.Script = script;46 this.LocalScope = localScope;47 }48 49 private readonly CallSite<Func<CallSite, object, object>> _copyMutableValueSite =50 CallSite<Func<CallSite, object, object>>.Create(PSVariableAssignmentBinder.Get());51 52 internal object CopyMutableValues(object o)53 {54 // The variable assignment binder copies mutable values and returns other values as is.55 return _copyMutableValueSite.Target.Invoke(_copyMutableValueSite, o);56 }57 58 #endregion ctor59 60 #region internal members61 62 #region Parameter default values63 64 /// <summary>65 /// Gets the default value for the specified parameter.66 /// </summary>67 /// <param name="name">68 /// The name of the parameter to get the default value of.69 /// </param>70 /// <returns>71 /// The default value of the specified parameter.72 /// </returns>73 /// <exception cref="Exception">See SessionStateInternal.GetVariableValue.</exception>74 internal override object GetDefaultParameterValue(string name)75 {76 RuntimeDefinedParameter runtimeDefinedParameter;77 if (Script.RuntimeDefinedParameters.TryGetValue(name, out runtimeDefinedParameter))78 {79 return GetDefaultScriptParameterValue(runtimeDefinedParameter);80 }81 82 return null;83 }84 85 #endregion Parameter default values86 87 #region Parameter binding88 89 /// <summary>90 /// Binds the parameters to local variables in the function scope.91 /// </summary>92 /// <param name="name">93 /// The name of the parameter to bind the value to.94 /// </param>95 /// <param name="value">96 /// The value to bind to the parameter. It should be assumed by97 /// derived classes that the proper type coercion has already taken98 /// place and that any prerequisite metadata has been satisfied.99 /// </param>100 /// <param name="parameterMetadata"></param>101 internal override void BindParameter(string name, object value, CompiledCommandParameter parameterMetadata)102 {103 if (value == AutomationNull.Value || value == UnboundParameter.Value)104 {105 value = null;106 }107 108 Diagnostics.Assert(name != null, "The caller should verify that name is not null");109 110 var varPath = new VariablePath(name, VariablePathFlags.Variable);111 112 // If the parameter was allocated in the LocalsTuple, we can avoid creating a PSVariable,113 if (LocalScope != null114 && varPath.IsAnyLocal()115 && LocalScope.TrySetLocalParameterValue(varPath.UnqualifiedPath, CopyMutableValues(value)))116 {117 return;118 }119 120 // Otherwise we'll fall through and enter a new PSVariable in the current scope. This121 // is what normally happens when dotting (though the above may succeed if a parameter name122 // was an automatic variable like $PSBoundParameters.123 124 // First we need to make a variable instance and apply125 // any attributes from the script.126 127 PSVariable variable = new PSVariable(varPath.UnqualifiedPath, value,128 varPath.IsPrivate ? ScopedItemOptions.Private : ScopedItemOptions.None);129 Context.EngineSessionState.SetVariable(varPath, variable, false, CommandOrigin.Internal);130 RuntimeDefinedParameter runtimeDefinedParameter;131 if (Script.RuntimeDefinedParameters.TryGetValue(name, out runtimeDefinedParameter))132 {133 // The attributes have already been checked and conversions run, so it is wrong134 // to do so again.135 variable.AddParameterAttributesNoChecks(runtimeDefinedParameter.Attributes);136 }137 }138 139 /// <summary>140 /// Return the default value of a script parameter, evaluating the parse tree if necessary.141 /// </summary>142 internal object GetDefaultScriptParameterValue(RuntimeDefinedParameter parameter, IDictionary implicitUsingParameters = null)143 {144 object result = parameter.Value;145 146 var compiledDefault = result as Compiler.DefaultValueExpressionWrapper;147 if (compiledDefault != null)148 {149 result = compiledDefault.GetValue(Context, Script.SessionStateInternal, implicitUsingParameters);150 }151 152 return result;153 }154 155 #endregion Parameter binding156 157 #endregion internal members158 159 #region private members160 161 /// <summary>162 /// The script that is being bound to.163 /// </summary>164 internal ScriptBlock Script { get; }165 166 internal SessionStateScope LocalScope { get; set; }167 168 #endregion private members169 }170}171 