public object this[int index] { get { if (_values is IList list) { return(list[index]); } return(_values.Cast <object>().ElementAtOrDefault(index)); } set { var list = _values as IList; if (list == null) { _values = list = new ScriptArray(_values); } list[index] = value; } }
public virtual ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return(new ValueTask <object>(Invoke(context, callerContext, arguments, blockStatement))); }
public abstract object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement);
public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return(_customFunction(context, callerContext, arguments)); }
public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { var expectedNumberOfParameters = Parameters.Length; if (_hasTemplateContext) { expectedNumberOfParameters--; if (_hasSpan) { expectedNumberOfParameters--; } } var minimumRequiredParameters = expectedNumberOfParameters - _optionalParameterCount; // Check parameters if ((_hasObjectParams && arguments.Count < minimumRequiredParameters - 1) || (!_hasObjectParams && arguments.Count < minimumRequiredParameters)) { if (minimumRequiredParameters != expectedNumberOfParameters) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting at least `{minimumRequiredParameters}` arguments"); } else { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting `{expectedNumberOfParameters}` arguments"); } } // Convert arguments object[] paramArguments = null; if (_hasObjectParams) { paramArguments = new object[arguments.Count - _lastParamsIndex]; _arguments[_lastParamsIndex] = paramArguments; } // Copy TemplateContext/SourceSpan parameters int argOffset = 0; var argMask = 0; if (_hasTemplateContext) { _arguments[0] = context; argOffset++; argMask |= 1; if (_hasSpan) { _arguments[1] = callerContext.Span; argOffset++; argMask |= 2; } } var argOrderedIndex = argOffset; // Setup any default parameters if (_optionalParameterCount > 0) { for (int i = Parameters.Length - 1; i >= Parameters.Length - _optionalParameterCount; i--) { _arguments[i] = Parameters[i].DefaultValue; argMask |= 1 << i; } } int paramsIndex = 0; for (int i = 0; i < arguments.Count; i++) { Type argType = null; try { int argIndex; var arg = arguments[i]; var namedArg = arg as ScriptNamedArgument; if (namedArg != null) { arg = GetNamedArgument(context, callerContext, namedArg, out argIndex, out argType); if (_hasObjectParams && argIndex == _lastParamsIndex) { argType = _paramsElementType; argIndex = argIndex + paramsIndex; paramsIndex++; } } else { argIndex = argOrderedIndex; if (_hasObjectParams && argIndex == _lastParamsIndex) { argType = _paramsElementType; argIndex = argIndex + paramsIndex; paramsIndex++; } else { argType = Parameters[argIndex].ParameterType; argOrderedIndex++; } } var argValue = context.ToObject(callerContext.Span, arg, argType); if (paramArguments != null && argIndex >= _lastParamsIndex) { paramArguments[argIndex - _lastParamsIndex] = argValue; argMask |= 1 << _lastParamsIndex; } else { _arguments[argIndex] = argValue; argMask |= 1 << argIndex; } } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unable to convert parameter #{i} of type `{arguments[i]?.GetType()}` to type `{argType}`", exception); } } // In case we have named arguments we need to verify that all arguments were set if (argMask != (1 << Parameters.Length) - 1) { if (minimumRequiredParameters != expectedNumberOfParameters) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting at least `{minimumRequiredParameters}` arguments"); } else { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments `{arguments.Count}` passed to `{callerContext}` while expecting `{expectedNumberOfParameters}` arguments"); } } // Call method try { var result = Method.Invoke(_target, _arguments); return(result); } catch (TargetInvocationException exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception when calling {callerContext}", exception.InnerException); } }
public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement) { var expectedNumberOfParameters = parametersInfo.Length; if (hasTemplateContext) { expectedNumberOfParameters--; if (hasSpan) { expectedNumberOfParameters--; } } // Check parameters if ((hasObjectParams && parameters.Count < expectedNumberOfParameters - 1) || (!hasObjectParams && parameters.Count != expectedNumberOfParameters)) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments passed [{parameters.Count}] while expecting [{expectedNumberOfParameters}] for [{callerContext}]"); } // Convert arguments var arguments = new object[parametersInfo.Length]; object[] paramArguments = null; if (hasObjectParams) { paramArguments = new object[parameters.Count - lastParamsIndex]; arguments[lastParamsIndex] = paramArguments; } // Copy TemplateContext/SourceSpan parameters int argIndex = 0; if (hasTemplateContext) { arguments[0] = context; argIndex++; if (hasSpan) { arguments[1] = callerContext.Span; argIndex++; } } for (int i = 0; i < parameters.Count; i++, argIndex++) { var destType = hasObjectParams && i >= lastParamsIndex ? typeof(object) : parametersInfo[i].ParameterType; try { var argValue = context.ToObject(callerContext.Span, parameters[i], destType); if (hasObjectParams && i >= lastParamsIndex) { paramArguments[argIndex - lastParamsIndex] = argValue; } else { arguments[argIndex] = argValue; } } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unable to convert parameter #{i} of type [{parameters[i]?.GetType()}] to type [{destType}]", exception); } } // Call method try { var result = method.Invoke(target, arguments); return(result); } catch (Exception exception) { throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception when calling {callerContext}", exception); } }
public static object Call(TemplateContext context, ScriptNode callerContext, object functionObject, List <ScriptExpression> arguments = null) { if (callerContext == null) { throw new ArgumentNullException(nameof(callerContext)); } if (functionObject == null) { throw new ScriptRuntimeException(callerContext.Span, $"The target function [{callerContext}] is null"); } var function = functionObject as ScriptFunction; var externFunction = functionObject as IScriptCustomFunction; if (function == null && externFunction == null) { throw new ScriptRuntimeException(callerContext.Span, $"Invalid object function [{functionObject?.GetType()}]"); } ScriptBlockStatement blockDelegate = null; if (context.BlockDelegates.Count > 0) { blockDelegate = context.BlockDelegates.Pop(); } var argumentValues = new ScriptArray(); if (arguments != null) { foreach (var argument in arguments) { var value = context.Evaluate(argument); // Handle parameters expansion for a function call when the operator ^ is used var unaryExpression = argument as ScriptUnaryExpression; if (unaryExpression != null && unaryExpression.ExpandParameters(value, argumentValues)) { continue; } argumentValues.Add(value); } } // Handle pipe arguments here if (context.PipeArguments.Count > 0) { var additionalArgument = context.PipeArguments.Pop(); var value = context.Evaluate(additionalArgument); // Handle parameters expansion for a function call when the operator ~ is used var unaryExpression = additionalArgument as ScriptUnaryExpression; if (unaryExpression == null || !unaryExpression.ExpandParameters(value, argumentValues)) { argumentValues.Add(value); } } object result = null; context.EnterFunction(callerContext); try { if (externFunction != null) { result = externFunction.Evaluate(context, callerContext, argumentValues, blockDelegate); } else { context.SetValue(ScriptVariable.Arguments, argumentValues, true); // Set the block delegate if (blockDelegate != null) { context.SetValue(ScriptVariable.BlockDelegate, blockDelegate, true); } result = context.Evaluate(function.Body); } } finally { context.ExitFunction(); } // Restore the flow state to none context.FlowState = ScriptFlowState.None; return(result); }
public override async ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray scriptArguments, ScriptBlockStatement blockStatement) { Array paramArguments = null; var arguments = PrepareArguments(context, callerContext, scriptArguments, ref paramArguments); try { // Call the method via reflection var result = InvokeImpl(context, callerContext.Span, arguments); return(IsAwaitable ? await ConfigureAwait(result) : result); } catch (TargetInvocationException exception) { if (exception.InnerException != null) { throw exception.InnerException; } throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception when calling {callerContext}"); } finally { context.ReleaseReflectionArguments(arguments); } }
private object[] PrepareArguments(TemplateContext context, ScriptNode callerContext, ScriptArray scriptArguments, ref Array paramsArguments) { // TODO: optimize arguments allocations var reflectArgs = context.GetOrCreateReflectionArguments(Parameters.Length); // Copy TemplateContext/SourceSpan parameters if (_hasTemplateContext) { reflectArgs[0] = context; if (_hasSpan) { reflectArgs[1] = callerContext.Span; } } // Convert arguments paramsArguments = null; if (_varParamKind == ScriptVarParamKind.LastParameter) { // 0 1 _firstIndexOfUserParameters _paramsIndex // [context, [span]], arg0, arg1..., ,argn, [varg0,varg1, ...] var varArgs = (ScriptArray)scriptArguments[scriptArguments.Count - 1]; // Copy all normal arguments var normalArgCount = scriptArguments.Count - 1; if (normalArgCount > 0) { scriptArguments.CopyTo(0, reflectArgs, _firstIndexOfUserParameters, normalArgCount); } paramsArguments = _paramsElementType == typeof(object) ? context.GetOrCreateReflectionArguments(varArgs.Count) : Array.CreateInstance(_paramsElementType, varArgs.Count); reflectArgs[_paramsIndex] = paramsArguments; // Convert each argument for (int i = 0; i < varArgs.Count; i++) { var destValue = context.ToObject(context.CurrentSpan, varArgs[i], _paramsElementType); paramsArguments.SetValue(destValue, i); } } else { scriptArguments.CopyTo(0, reflectArgs, _firstIndexOfUserParameters, scriptArguments.Count); } return(reflectArgs); }
public ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement) { return(new ValueTask <object>(_customFunction(context, callerContext, arguments))); }
public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement) { return(customFunction(context, callerContext, parameters)); }