Beispiel #1
0
        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);
Beispiel #4
0
 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);
                }
            }
Beispiel #6
0
            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);
                }
            }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
            }
        }
Beispiel #9
0
        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)));
 }
Beispiel #11
0
 public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement)
 {
     return(customFunction(context, callerContext, parameters));
 }