private ScriptExecutable m_ScriptExecutable; //函数执行命令

        #endregion Fields

        #region Constructors

        public ScorpioScriptFunction(Script script, List<String> listParameters, ScriptExecutable scriptExecutable, bool bParams)
        {
            this.m_Script = script;
            this.m_ListParameters = new List<string>(listParameters);
            this.m_ScriptExecutable = scriptExecutable;
            this.m_ParameterCount = listParameters.Count;
            this.m_Params = bParams;
            this.m_ParamsArray = bParams ? script.CreateArray() : null;
        }
Example #2
0
        private static object Round(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 1 || parameters.Count > 2)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for math.round. Expecting at least 1 parameter <precision>? <value>");
            }

            var value = ScriptValueConverter.ToDouble(callerContext.Span, parameters[parameters.Count - 1]);
            int precision = 0;
            if (parameters.Count == 2)
            {
                precision = ScriptValueConverter.ToInt(callerContext.Span, parameters[0]);
            }

            return Round(precision, value);
        }
 public bool ExpandParameters(object value, ScriptArray expandedParameters)
 {
     // Handle parameters expansion for a function call when the operator ~ is used
     if (Operator == ScriptUnaryOperator.FunctionParametersExpand)
     {
         var valueEnumerator = value as IEnumerable;
         if (valueEnumerator != null)
         {
             foreach (var subValue in valueEnumerator)
             {
                 expandedParameters.Add(subValue);
             }
             return true;
         }
     }
     return false;
 }
Example #4
0
        /// <summary>
        /// Returns no more than the specified number of items from the input list, starting from the first index position.
        /// </summary>
        /// <param name="list">The input list.</param>
        /// <param name="count">The number of elements to return from the input list. If this number is less than one, no item is returned.</param>
        /// <remarks>
        /// ```template-text
        /// {{ [4, 5, 6] | array.limit 2 }}
        /// ```
        /// ```html
        /// [4, 5]
        /// ```
        /// </remarks>
        public static ScriptArray Limit(IEnumerable list, int count)
        {
            if (list == null)
            {
                return(null);
            }

            ScriptArray result = new ScriptArray();

            foreach (var item in list)
            {
                count--;
                if (count < 0)
                {
                    break;
                }

                result.Add(item);
            }
            return(result);
        }
Example #5
0
        /// <summary>
        /// Removes an element at the specified `index` from the input `list`
        /// </summary>
        /// <param name="list">The input list</param>
        /// <param name="index">The index of a list to return elements</param>
        /// <returns>A new list with the element removed. If index is negative, remove at the end of the list.</returns>
        /// <remarks>
        /// ```scriban-html
        /// {{ [4, 5, 6, 7, 8] | array.remove_at 2 }}
        /// ```
        /// ```html
        /// [4, 5, 7, 8]
        /// ```
        /// If the `index` is negative, removes at the end of the list (notice that we need to put -1 in parenthesis to avoid confusing the parser with a binary `-` operation):
        /// ```scriban-html
        /// {{ [4, 5, 6, 7, 8] | array.remove_at (-1) }}
        /// ```
        /// ```html
        /// [4, 5, 6, 7]
        /// ```
        /// </remarks>
        public static IList RemoveAt(IList list, int index)
        {
            if (list == null)
            {
                return(new ScriptArray());
            }

            list = new ScriptArray(list);

            // If index is negative, start from the end
            if (index < 0)
            {
                index = list.Count + index;
            }

            if (index >= 0 && index < list.Count)
            {
                list.RemoveAt(index);
            }
            return(list);
        }
Example #6
0
        /// <summary>
        /// Returns the remaining of the list after the specified offset
        /// </summary>
        /// <param name="list">The input list</param>
        /// <param name="index">The index of a list to return elements</param>
        /// <remarks>
        /// ```scriban-html
        /// {{ [4, 5, 6, 7, 8] | array.offset 2 }}
        /// ```
        /// ```html
        /// [6, 7, 8]
        /// ```
        /// </remarks>
        public static ScriptArray Offset(IEnumerable list, int index)
        {
            if (list == null)
            {
                return(null);
            }

            var result = new ScriptArray();

            foreach (var item in list)
            {
                if (index <= 0)
                {
                    result.Add(item);
                }
                else
                {
                    index--;
                }
            }
            return(result);
        }
    private static ScriptArray ReadScriptArray(GameBoxReader r)
    {
        ScriptVariable indexVar;

        var indexType = r.ReadByte(); // index

        if ((ScriptType)indexType == ScriptType.Struct)
        {
            indexVar = ReadScriptStruct(out int _, r);
        }
        else
        {
            indexVar = new ScriptVariable((ScriptType)indexType);
        }

        var arrayType = r.ReadByte(); // value

        var valueVar = (ScriptType)arrayType switch
        {
            ScriptType.Array => ReadScriptArray(r),
            ScriptType.Struct => ReadScriptStruct(out int _, r),
            _ => new ScriptVariable((ScriptType)arrayType),
        };

        var array = new ScriptArray(new KeyValuePair <ScriptVariable, ScriptVariable>(indexVar, valueVar));

        int counterArray = 0;

        while (r.ReadByte() == 0)
        {
            counterArray++;
        }
        r.BaseStream.Position -= 1;

        array.Unknown = counterArray;

        return(array);
    }
Example #8
0
        public static string Join(TemplateContext context, SourceSpan span, IEnumerable list, string delimiter, object function = null)
        {
            if (list == null)
            {
                return(string.Empty);
            }

            var scriptingFunction = function as IScriptCustomFunction;

            if (function != null && scriptingFunction == null)
            {
                throw new ArgumentException($"The parameter `{function}` is not a function. Maybe prefix it with @?", nameof(function));
            }

            var  text       = new StringBuilder();
            bool afterFirst = false;
            var  arg        = new ScriptArray(1);

            foreach (var obj in list)
            {
                if (afterFirst)
                {
                    text.Append(delimiter);
                }

                var item = context.ObjectToString(obj);
                if (scriptingFunction != null)
                {
                    arg[0] = item;
                    var result = ScriptFunctionCall.Call(context, context.CurrentNode, scriptingFunction, arg);
                    item = context.ObjectToString(result);
                }

                text.Append(item);
                afterFirst = true;
            }
            return(text.ToString());
        }
Example #9
0
        private static void Write(Script script, ScorpioWriter writer, ScriptTable table, string tableName)
        {
            ScriptArray layout = (ScriptArray)script.GetValue(tableName);
            int         sign   = 0;

            for (int i = 0; i < layout.Count(); ++i)
            {
                ScriptObject config = layout.GetValue(i);
                if (table != null && table.HasValue(config.GetValue(Name).ObjectValue))
                {
                    sign = ScorpioUtil.AddSign(sign, ScorpioUtil.ToInt32(config.GetValue(Index).ObjectValue));
                }
            }
            writer.WriteInt32(sign);
            for (int i = 0; i < layout.Count(); ++i)
            {
                ScriptObject config = layout.GetValue(i);
                string       name   = (string)config.GetValue(Name).ObjectValue;
                if (table != null && table.HasValue(name))
                {
                    string type  = (string)config.GetValue(Type).ObjectValue;
                    bool   array = (bool)config.GetValue(Array).ObjectValue;
                    if (array)
                    {
                        ScriptArray arr = table.GetValue(name) as ScriptArray;
                        writer.WriteInt32(arr.Count());
                        for (int j = 0; j < arr.Count(); ++j)
                        {
                            WriteObject(script, writer, type, arr.GetValue(j));
                        }
                    }
                    else
                    {
                        WriteObject(script, writer, type, table.GetValue(name));
                    }
                }
            }
        }
Example #10
0
            public object Call(ScriptObject[] args)
            {
                string str    = (args[0] as ScriptString).Value;
                int    length = str.Length;

                if (length == 0)
                {
                    return(null);
                }
                else if (length == 1)
                {
                    return(Convert.ToInt32(str[0]));
                }
                else
                {
                    ScriptArray array = m_script.CreateArray();
                    for (int i = 0; i < length; ++i)
                    {
                        array.Add(m_script.CreateObject(Convert.ToInt32(str[i])));
                    }
                    return(array);
                }
            }
Example #11
0
        /// <summary>
        /// Searches an input string for multiple substrings that matches a regular expression pattern and returns an array with the match occurences.
        /// </summary>
        /// <param name="context">The template context (to fetch the timeout configuration)</param>
        /// <param name="text">The string to search for a match.</param>
        /// <param name="pattern">The regular expression pattern to match.</param>
        /// <param name="options">A string with regex options, that can contain the following option characters (default is `null`):
        /// - `i`: Specifies case-insensitive matching.
        /// - `m`: Multiline mode. Changes the meaning of `^` and `$` so they match at the beginning and end, respectively, of any line, and not just the beginning and end of the entire string.
        /// - `s`: Specifies single-line mode. Changes the meaning of the dot `.` so it matches every character (instead of every character except `\n`).
        /// - `x`: Eliminates unescaped white space from the pattern and enables comments marked with `#`.
        /// </param>
        /// <returns>An array of matches that contains all the match groups. The first group contains the entire match. The other elements contain regex matched groups `(..)`. An empty array returned means no match.</returns>
        /// <remarks>
        /// ```scriban-html
        /// {{ "this is a text123" | regex.matches `(\w+)` }}
        /// ```
        /// ```html
        /// [["this", "this"], ["is", "is"], ["a", "a"], ["text123", "text123"]]
        /// ```
        /// Notice that the first element returned in the sub array is the entire regex match, followed by the regex group matches.
        /// </remarks>
        public static ScriptArray Matches(TemplateContext context, string text, string pattern, string options = null)
        {
            var matches    = Regex.Matches(text, pattern, GetOptions(options), context.RegexTimeOut);
            var allMatches = new ScriptArray();

            foreach (Match match in matches)
            {
                if (match.Success)
                {
                    var matchObject = new ScriptArray();
                    for (var i = 0; i < match.Groups.Count; i++)
                    {
                        Group @group = match.Groups[i];
                        matchObject.Add(@group.Value);
                    }

                    allMatches.Add(matchObject);
                }
            }

            // otherwise return an empty array
            return(allMatches);
        }
Example #12
0
        /// <summary>
        /// Concatenates two lists.
        /// </summary>
        /// <param name="list1">The 1st input list</param>
        /// <param name="list2">The 2nd input list</param>
        /// <returns>The concatenation of the two input lists</returns>
        /// <remarks>
        /// ```scriban-html
        /// {{ [1, 2, 3] | array.concat [4, 5] }}
        /// ```
        /// ```html
        /// [1, 2, 3, 4, 5]
        /// ```
        /// </remarks>
        public static IEnumerable Concat(IEnumerable list1, IEnumerable list2)
        {
            if (list2 == null && list1 == null)
            {
                return(null);
            }
            if (list2 == null)
            {
                return(list1);
            }

            if (list1 == null)
            {
                return(list2);
            }

            var result = new ScriptArray(list1);

            foreach (var item in list2)
            {
                result.Add(item);
            }
            return(result);
        }
Example #13
0
 public virtual object?Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement)
 {
     // If we access 'ndate' without any parameter, it calls the 'parse' function by default
     // otherwise it is the 'date' object itself
     return(arguments.Count switch
     {
         0 => this,
         1 => Parse(context, context.ObjectToString(arguments[0])),
         _ => throw new ScriptRuntimeException(callerContext.Span,
                                               $"Invalid number of parameters `{arguments.Count}` for `{DateVariable.Name}` object/function.")
     });
Example #14
0
        private static object Map(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count != 2)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for map. Expecting at 2 parameters: <property> <array>");
            }

            var member = ScriptValueConverter.ToString(callerContext.Span, parameters[0]);
            var target = parameters[1];

            return Map(context, target, member);
        }
Example #15
0
        protected override object EvaluateImpl(TemplateContext context)
        {
            var loopIterator = context.Evaluate(Iterator);
            var list         = loopIterator as IList;

            if (list == null)
            {
                var iterator = loopIterator as IEnumerable;
                if (iterator != null)
                {
                    list = new ScriptArray(iterator);
                }
            }

            if (list != null)
            {
                object loopResult    = null;
                object previousValue = null;

                bool reversed   = false;
                int  startIndex = 0;
                int  limit      = list.Count;
                if (NamedArguments != null)
                {
                    foreach (var option in NamedArguments)
                    {
                        switch (option.Name)
                        {
                        case "offset":
                            startIndex = context.ToInt(option.Value.Span, context.Evaluate(option.Value));
                            break;

                        case "reversed":
                            reversed = true;
                            break;

                        case "limit":
                            limit = context.ToInt(option.Value.Span, context.Evaluate(option.Value));
                            break;

                        default:
                            ProcessArgument(context, option);
                            break;
                        }
                    }
                }
                var endIndex = Math.Min(limit + startIndex, list.Count) - 1;

                var  index   = reversed ? endIndex : startIndex;
                var  dir     = reversed ? -1 : 1;
                bool isFirst = true;
                int  i       = 0;
                BeforeLoop(context);

                var loopState = CreateLoopState();
                context.SetValue(GetLoopVariable(context), loopState);
                loopState.Length = list.Count;

                while (!reversed && index <= endIndex || reversed && index >= startIndex)
                {
                    if (!context.StepLoop(this))
                    {
                        return(null);
                    }

                    // We update on next run on previous value (in order to handle last)
                    var  value  = list[index];
                    bool isLast = reversed ? index == startIndex : index == endIndex;
                    loopState.Index        = index;
                    loopState.LocalIndex   = i;
                    loopState.IsLast       = isLast;
                    loopState.ValueChanged = isFirst || !Equals(previousValue, value);
                    context.SetValue(Variable, value);

                    loopResult = LoopItem(context, loopState);
                    if (!ContinueLoop(context))
                    {
                        break;
                    }

                    previousValue = value;
                    isFirst       = false;
                    index        += dir;
                    i++;
                }
                AfterLoop(context);

                context.SetValue(ScriptVariable.Continue, index);
                return(loopResult);
            }

            if (loopIterator != null)
            {
                throw new ScriptRuntimeException(Iterator.Span, $"Unexpected type `{loopIterator.GetType()}` for iterator");
            }

            return(null);
        }
Example #16
0
        public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement)
        {
            if (parameters.Count == 0)
            {
                throw new ScriptRuntimeException(callerContext.Span, "Expecting at least the name of the template to include for the <include> function");
            }

            string templateName = null;
            try
            {
                templateName = ScriptValueConverter.ToString(callerContext.Span, parameters[0]);
            }
            catch (Exception ex)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception while converting first parameter for <include> function. Expecting a string", ex);
            }

            // If template name is empty, throw an exception
            if (templateName == null || string.IsNullOrEmpty(templateName = templateName.Trim()))
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Include template name cannot be null or empty");
            }

            // Compute a new parameters for the include
            var newParameters = new ScriptArray(parameters.Count - 1);
            for (int i = 1; i < parameters.Count; i++)
            {
                newParameters[i] = parameters[i];
            }

            context.SetValue(ScriptVariable.Arguments, newParameters, true);

            Template template;

            if (!context.CachedTemplates.TryGetValue(templateName, out template))
            {
                if (context.TemplateLoader == null)
                {
                    throw new ScriptRuntimeException(callerContext.Span,
                        $"Unable to include <{templateName}>. No TemplateLoader registered in TemplateContext.Options.TemplateLoader");
                }

                string templateFilePath;

                var templateText = context.TemplateLoader.Load(context, callerContext.Span, templateName, out templateFilePath);

                if (templateText == null)
                {
                    throw new ScriptRuntimeException(callerContext.Span, $"The result of including <{templateName}> cannot be null");
                }

                // IF template file path is not defined, we use the template name instead
                templateFilePath = templateFilePath ?? templateName;

                // Clone parser options
                var parserOptions = context.TemplateLoaderParserOptions.Clone();

                // Parse include in default modes (while top page can be using front matter)
                parserOptions.Mode = parserOptions.Mode == ScriptMode.ScriptOnly
                    ? ScriptMode.ScriptOnly
                    : ScriptMode.Default;

                template = Template.Parse(templateText, templateFilePath, parserOptions);

                // If the template has any errors, throw an exception
                if (template.HasErrors)
                {
                    throw new ScriptParserRuntimeException(callerContext.Span, $"Error while parsing template <{templateName}> from [{templateFilePath}]", template.Messages);
                }

                context.CachedTemplates.Add(templateName, template);
            }

            // Query the pending includes stored in the context
            HashSet<string> pendingIncludes;
            object pendingIncludesObject;
            if (!context.Tags.TryGetValue(typeof(IncludeFunction), out pendingIncludesObject))
            {
                pendingIncludesObject = pendingIncludes = new HashSet<string>();
                context.Tags[typeof (IncludeFunction)] = pendingIncludesObject;
            }
            else
            {
                pendingIncludes = (HashSet<string>) pendingIncludesObject;
            }

            // Make sure that we cannot recursively include a template
            if (pendingIncludes.Contains(templateName))
            {
                throw new ScriptRuntimeException(callerContext.Span, $"The include [{templateName}] cannot be used recursively");
            }
            pendingIncludes.Add(templateName);

            context.PushOutput();
            object result = null;
            try
            {
                template.Render(context);
            }
            finally
            {
                result = context.PopOutput();
                pendingIncludes.Remove(templateName);
            }

            return result;
        }
Example #17
0
        private static object FromYaml(string yamlText, bool expectOnlyFrontMatter, out TextPosition position)
        {
            position = new TextPosition();
            if (yamlText == null)
            {
                return(null);
            }

            var parser = new Parser(new StringReader(yamlText));
            var reader = new EventReader(parser);

            if (!reader.Accept <StreamStart>())
            {
                return(null);
            }

            reader.Expect <StreamStart>();
            var docStart         = reader.Expect <DocumentStart>();
            var hasDocumentStart = true;

            object      result  = null;
            ScriptArray objects = null;

            // If we expect to read multiple documents, we will return an array of result
            if (expectOnlyFrontMatter && docStart.IsImplicit)
            {
                return(null);
            }

            Mark endPosition;

            while (true)
            {
                if (reader.Accept <StreamEnd>())
                {
                    var evt = reader.Expect <StreamEnd>();
                    endPosition = evt.End;
                    break;
                }

                if (hasDocumentStart && reader.Accept <DocumentEnd>())
                {
                    reader.Expect <DocumentEnd>();

                    hasDocumentStart = false;

                    if (expectOnlyFrontMatter)
                    {
                        reader.Accept <DocumentStart>();
                        var nextDocStart = reader.Expect <DocumentStart>();
                        endPosition = nextDocStart.End;
                        break;
                    }
                    continue;
                }

                if (reader.Accept <DocumentStart>())
                {
                    reader.Expect <DocumentStart>();
                    hasDocumentStart = true;
                }

                var obj = ReadEvent(reader);

                if (result == null)
                {
                    result = obj;
                }
                else
                {
                    if (objects == null)
                    {
                        objects = new ScriptArray {
                            result
                        };
                        result = objects;
                    }
                    objects.Add(obj);
                }
            }

            position = new TextPosition(endPosition.Index, endPosition.Line, endPosition.Column);
            return(result);
        }
Example #18
0
 public ArrayVPairs(ScriptArray obj)
 {
     m_Enumerator = obj.GetIterator();
 }
Example #19
0
 private ScriptArray ReadStrictArray(Stream src)
 {
     byte[] bs = new byte[4];
     src.Read(bs, 0, 4);
     offset += 4;
     ScriptArray array = new ScriptArray();
     uint count = ByteUtil.ByteToUInt(bs, 4);
     for (uint i = 0; i < count; i++) {
         array.Add(ReadElement(src));
     }
     return array;
 }
Example #20
0
 public HtmlObject(ScriptObject parent) : base(parent)
 {
     HeadIncludes = new ScriptArray <string>();
     // Import html object
     SetValue("head_includes", HeadIncludes, true);
 }
            public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement)
            {
                // Check parameters
                if ((hasObjectParams && parameters.Count < parametersInfo.Length - 1) || (!hasObjectParams && parameters.Count != parametersInfo.Length))
                {
                    throw new ScriptRuntimeException(callerContext.Span, $"Invalid number of arguments passed [{parameters.Count}] while expecting [{parametersInfo.Length}] for [{callerContext}]");
                }

                // Convert arguments
                var arguments = new object[parametersInfo.Length];
                object[] paramArguments = null;
                if (hasObjectParams)
                {
                    paramArguments = new object[parameters.Count - lastParamsIndex];
                    arguments[lastParamsIndex] = paramArguments;
                }

                for (int i = 0; i < parameters.Count; i++)
                {
                    var destType = hasObjectParams && i >= lastParamsIndex ? typeof(object) : parametersInfo[i].ParameterType;
                    try
                    {
                        var argValue = ScriptValueConverter.ToObject(callerContext.Span, parameters[i], destType);
                        if (hasObjectParams && i >= lastParamsIndex)
                        {
                            paramArguments[i - lastParamsIndex] = argValue;
                        }
                        else
                        {
                            arguments[i] = 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);
                }
            }
Example #22
0
 public object Evaluate(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement)
 {
     return customFunction(context, callerContext, parameters);
 }
Example #23
0
 public ArrayPairs(Script script, ScriptArray obj)
 {
     m_Script     = script;
     m_Index      = 0;
     m_Enumerator = obj.GetIterator();
 }
Example #24
0
        /// <summary>
        /// Renders an state machine function
        /// </summary>
        /// <param name="context">Template context</param>
        /// <param name="callerContext">Caller context</param>
        /// <param name="arguments">Arguments to render the function with</param>
        /// <returns>Rendered state machine function</returns>
        private async ValueTask <object> RenderStateMachineFunction(TemplateContext context, ScriptNode callerContext, ScriptArray arguments)
        {
            if (arguments.Count != 1 || !(arguments[0] is ScribanExportStateFunction))
            {
                _errorCollection.AddInvalidParameter(ScribanErrorUtil.FormatScribanSpan(callerContext.Span));
                return("<<DID NOT PROVIDE VALID STATE MACHINE FUNCTION>>");
            }
            ScribanExportStateFunction exportFunction = (ScribanExportStateFunction)arguments[0];

            GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject();

            ExportTemplate eventFunctionTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectStateFunction);

            ExportObjectData objectData = new ExportObjectData();

            objectData.ExportData.Add(ExportConstants.ExportDataObject, exportFunction.ToStateFunction());

            ExportPlaceholderFillResult fillResult = await _templatePlaceholderResolver.FillPlaceholders(TemplateType.ObjectStateFunction, eventFunctionTemplate.Code, objectData, eventFunctionTemplate.RenderingEngine);

            _errorCollection.Merge(fillResult.Errors);

            return(ScribanOutputUtil.IndentMultilineCode(context, fillResult.Code));
        }
Example #25
0
 public ArrayKPairs(ScriptArray obj)
 {
     m_Index      = 0;
     m_Enumerator = obj.GetIterator();
 }
Example #26
0
 public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement)
 {
     return(JsonConvert.SerializeObject(arguments[0]));
 }
Example #27
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;
        }
Example #28
0
        public static object Evaluate(TemplateContext context, SourceSpan span, ScriptBinaryOperator op, object leftValue, object rightValue)
        {
            if (op == ScriptBinaryOperator.EmptyCoalescing)
            {
                return(leftValue ?? rightValue);
            }

            switch (op)
            {
            case ScriptBinaryOperator.ShiftLeft:
                var leftList = leftValue as IList;
                if (leftList != null)
                {
                    var newList = new ScriptArray(leftList)
                    {
                        rightValue
                    };
                    return(newList);
                }
                break;

            case ScriptBinaryOperator.ShiftRight:
                var rightList = rightValue as IList;
                if (rightList != null)
                {
                    var newList = new ScriptArray(rightList);
                    newList.Insert(0, leftValue);
                    return(newList);
                }
                break;

            case ScriptBinaryOperator.LiquidHasKey:
            {
                var leftDict = leftValue as IDictionary <string, object>;
                if (leftDict != null)
                {
                    return(ObjectFunctions.HasKey(leftDict, context.ToString(span, rightValue)));
                }
            }
            break;

            case ScriptBinaryOperator.LiquidHasValue:
            {
                var leftDict = leftValue as IDictionary <string, object>;
                if (leftDict != null)
                {
                    return(ObjectFunctions.HasValue(leftDict, context.ToString(span, rightValue)));
                }
            }
            break;

            case ScriptBinaryOperator.CompareEqual:
            case ScriptBinaryOperator.CompareNotEqual:
            case ScriptBinaryOperator.CompareGreater:
            case ScriptBinaryOperator.CompareLess:
            case ScriptBinaryOperator.CompareGreaterOrEqual:
            case ScriptBinaryOperator.CompareLessOrEqual:
            case ScriptBinaryOperator.Add:
            case ScriptBinaryOperator.Substract:
            case ScriptBinaryOperator.Multiply:
            case ScriptBinaryOperator.Divide:
            case ScriptBinaryOperator.DivideRound:
            case ScriptBinaryOperator.Modulus:
            case ScriptBinaryOperator.RangeInclude:
            case ScriptBinaryOperator.RangeExclude:
            case ScriptBinaryOperator.LiquidContains:
            case ScriptBinaryOperator.LiquidStartsWith:
            case ScriptBinaryOperator.LiquidEndsWith:
                if (leftValue is string || rightValue is string)
                {
                    return(CalculateToString(context, span, op, leftValue, rightValue));
                }
                else if (leftValue == EmptyScriptObject.Default || rightValue == EmptyScriptObject.Default)
                {
                    return(CalculateEmpty(context, span, op, leftValue, rightValue));
                }
                else
                {
                    return(CalculateOthers(context, span, op, leftValue, rightValue));
                }
            }
            throw new ScriptRuntimeException(span, $"Operator `{op.ToText()}` is not implemented for `{leftValue}` and `{rightValue}`");
        }
Example #29
0
        private static object Round(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 1 || parameters.Count > 2)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for math.round. Expecting at least 1 parameter <precision>? <value>");
            }

            var value     = ScriptValueConverter.ToDouble(callerContext.Span, parameters[parameters.Count - 1]);
            int precision = 0;

            if (parameters.Count == 2)
            {
                precision = ScriptValueConverter.ToInt(callerContext.Span, parameters[0]);
            }

            return(Round(precision, value));
        }
Example #30
0
        private static object Slice(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 2 || parameters.Count > 3)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for slice. Expecting at least 2 parameters <start> <length>? <text>");
            }

            var text = ScriptValueConverter.ToString(callerContext.Span, parameters[parameters.Count - 1]);
            var start = ScriptValueConverter.ToInt(callerContext.Span, parameters[0]);
            var length = -1;
            if (parameters.Count == 3)
            {
                length = ScriptValueConverter.ToInt(callerContext.Span, parameters[1]);
            }

            return Slice(text, start, length);
        }
        /// <summary>
        /// Renders an daily routine function list
        /// </summary>
        /// <param name="context">Template context</param>
        /// <param name="callerContext">Caller context</param>
        /// <param name="arguments">Arguments to render the list with</param>
        /// <returns>Rendered daily routine function list</returns>
        private async ValueTask <object> RenderDailyRoutineFunctionList(TemplateContext context, ScriptNode callerContext, ScriptArray arguments)
        {
            List <ScribanExportDailyRoutineFunction> functionList = ScribanParsingUtil.GetArrayFromScribanArgument <ScribanExportDailyRoutineFunction>(arguments, 0);

            if (functionList == null)
            {
                _errorCollection.AddInvalidParameter(ScribanErrorUtil.FormatScribanSpan(callerContext.Span));
                return("<<DID NOT PROVIDE VALID FUNCTION LIST>>");
            }

            GoNorthProject curProject = await _exportCachedDbAccess.GetUserProject();

            ExportTemplate functionListTemplate = await _defaultTemplateProvider.GetDefaultTemplateByType(curProject.Id, TemplateType.ObjectDailyRoutineFunctionList);

            ExportObjectData objectData = new ExportObjectData();

            objectData.ExportData.Add(ExportConstants.ExportDataObject, functionList.Select(f => f.ToDailyRoutineFunction()).ToList());

            ExportPlaceholderFillResult fillResult = await _templatePlaceholderResolver.FillPlaceholders(TemplateType.ObjectDailyRoutineFunctionList, functionListTemplate.Code, objectData, functionListTemplate.RenderingEngine);

            _errorCollection.Merge(fillResult.Errors);

            return(ScribanOutputUtil.IndentMultilineCode(context, fillResult.Code));
        }
Example #32
0
        public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement)
        {
            if (arguments.Count == 0)
            {
                throw new ScriptRuntimeException(callerContext.Span, "Expecting the name of the include for the 'markdown' function");
            }
            var md   = base.Invoke(context, callerContext, arguments, blockStatement) as string;
            var html = context.Markdown?.Render(md) ?? "";

            return(html);
        }
Example #33
0
 /// <summary>
 /// Invokes the state machine function generation async
 /// </summary>
 /// <param name="context">Template context</param>
 /// <param name="callerContext">Caller context</param>
 /// <param name="arguments">Arguments</param>
 /// <param name="blockStatement">Block Statement</param>
 /// <returns>State machine function</returns>
 public override async ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement)
 {
     return(await RenderStateMachineFunction(context, callerContext, arguments));
 }
 public ArrayPairs(Script script, ScriptArray obj)
 {
     m_Script = script;
     m_Index = 0;
     m_Enumerator = obj.GetIterator();
 }
Example #35
0
 /// <summary>
 /// Invokes the state machine function generation
 /// </summary>
 /// <param name="context">Template context</param>
 /// <param name="callerContext">Caller context</param>
 /// <param name="arguments">Arguments</param>
 /// <param name="blockStatement">Block Statement</param>
 /// <returns>State machine function</returns>
 public override object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement)
 {
     return(RenderStateMachineFunction(context, callerContext, arguments).Result);
 }
 public ArrayKPairs(ScriptArray obj)
 {
     m_Index = 0;
     m_Enumerator = obj.GetIterator();
 }
Example #37
0
        public ValueTask <object> InvokeAsync(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement)
        {
            var result = this.Invoke(context, callerContext, arguments, blockStatement);

            return(new ValueTask <object>(result));
        }
 public ArrayVPairs(ScriptArray obj)
 {
     m_Enumerator = obj.GetIterator();
 }
Example #39
0
 public static object AnyOf(Random random, ScriptArray array)
 {
     return(array[random.Next(array.Count)]);
 }
Example #40
0
        public override object Evaluate(TemplateContext context)
        {
            var    leftValueOriginal  = context.Evaluate(Left);
            var    leftValue          = leftValueOriginal;
            var    rightValueOriginal = context.Evaluate(Right);
            object rightValue         = rightValueOriginal;

            if (Operator == ScriptBinaryOperator.EmptyCoalescing)
            {
                return(leftValue ?? rightValue);
            }
            else if (Operator == ScriptBinaryOperator.And || Operator == ScriptBinaryOperator.Or)
            {
                var leftBoolValue  = context.ToBool(leftValue);
                var rightBoolValue = context.ToBool(rightValue);
                if (Operator == ScriptBinaryOperator.And)
                {
                    return(leftBoolValue && rightBoolValue);
                }
                else
                {
                    return(leftBoolValue || rightBoolValue);
                }
            }
            else
            {
                switch (Operator)
                {
                case ScriptBinaryOperator.ShiftLeft:
                    var leftList = leftValue as IList;
                    if (leftList != null)
                    {
                        var newList = new ScriptArray(leftList)
                        {
                            rightValue
                        };
                        return(newList);
                    }
                    break;

                case ScriptBinaryOperator.ShiftRight:
                    var rightList = rightValue as IList;
                    if (rightList != null)
                    {
                        var newList = new ScriptArray(rightList);
                        newList.Insert(0, leftValue);
                        return(newList);
                    }
                    break;

                case ScriptBinaryOperator.CompareEqual:
                case ScriptBinaryOperator.CompareNotEqual:
                case ScriptBinaryOperator.CompareGreater:
                case ScriptBinaryOperator.CompareLess:
                case ScriptBinaryOperator.CompareGreaterOrEqual:
                case ScriptBinaryOperator.CompareLessOrEqual:
                case ScriptBinaryOperator.Add:
                case ScriptBinaryOperator.Substract:
                case ScriptBinaryOperator.Multiply:
                case ScriptBinaryOperator.Divide:
                case ScriptBinaryOperator.DivideRound:
                case ScriptBinaryOperator.Modulus:
                case ScriptBinaryOperator.RangeInclude:
                case ScriptBinaryOperator.RangeExclude:
                    var leftType  = leftValue?.GetType();
                    var rightType = rightValue?.GetType();

                    if (leftValue is string || rightValue is string)
                    {
                        return(CalculateToString(context, leftValue, rightValue));
                    }
                    else
                    {
                        return(Calculate(context, leftValue, leftType, rightValue, rightType));
                    }
                }
            }

            throw new ScriptRuntimeException(Span, $"Operator [{Operator.ToText()}] is not implemented for the left [{Left}] / right [{Right}]");
        }
Example #41
0
        public object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray arguments, ScriptBlockStatement blockStatement)
        {
            if (arguments.Count == 0)
            {
                throw new ScriptRuntimeException(callerContext.Span, "Expecting at least the name of the template to include for the <include> function");
            }

            var templateName = context.ObjectToString(arguments[0]);

            // If template name is empty, throw an exception
            if (string.IsNullOrEmpty(templateName))
            {
                // In a liquid template context, we let an include to continue without failing
                if (context is LiquidTemplateContext)
                {
                    return(null);
                }
                throw new ScriptRuntimeException(callerContext.Span, $"Include template name cannot be null or empty");
            }

            var templateLoader = context.TemplateLoader;

            if (templateLoader == null)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unable to include <{templateName}>. No TemplateLoader registered in TemplateContext.TemplateLoader");
            }

            string templatePath;

            try
            {
                templatePath = templateLoader.GetPath(context, callerContext.Span, templateName);
            }
            catch (Exception ex) when(!(ex is ScriptRuntimeException))
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception while getting the path for the include name `{templateName}`", ex);
            }
            // If template path is empty (probably because template doesn't exist), throw an exception
            if (templatePath == null)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Include template path is null for `{templateName}");
            }

            string indent = null;

            // Handle indent
            if (context.IndentWithInclude)
            {
                // Find the statement for the include
                var current = callerContext.Parent;
                while (current != null && !(current is ScriptStatement))
                {
                    current = current.Parent;
                }

                // Find the RawStatement preceding this include
                ScriptNode childNode      = null;
                bool       shouldContinue = true;
                while (shouldContinue && current != null)
                {
                    if (current is ScriptList <ScriptStatement> statementList && childNode is ScriptStatement childStatement)
                    {
                        var indexOf = statementList.IndexOf(childStatement);

                        // Case for first indent, if it is not the first statement in the doc
                        // it's not a valid indent
                        if (indent != null && indexOf > 0)
                        {
                            indent = null;
                            break;
                        }

                        for (int i = indexOf - 1; i >= 0; i--)
                        {
                            var previousStatement = statementList[i];
                            if (previousStatement is ScriptEscapeStatement escapeStatement && escapeStatement.IsEntering)
                            {
                                if (i > 0 && statementList[i - 1] is ScriptRawStatement rawStatement)
                                {
                                    var text = rawStatement.Text;
                                    for (int j = text.Length - 1; j >= 0; j--)
                                    {
                                        var c = text[j];
                                        if (c == '\n')
                                        {
                                            shouldContinue = false;
                                            indent         = text.Substring(j + 1);
                                            break;
                                        }

                                        if (!char.IsWhiteSpace(c))
                                        {
                                            shouldContinue = false;
                                            break;
                                        }

                                        if (j == 0)
                                        {
                                            // We have a raw statement that has only white spaces
                                            // It could be the first raw statement of the document
                                            // so we continue but we handle it later
                                            indent = text.ToString();
                                        }
                                    }
                                }
                                else
                                {
                                    shouldContinue = false;
                                }

                                break;
                            }
                        }
                    }

                    childNode = current;
                    current   = childNode.Parent;
                }

                if (string.IsNullOrEmpty(indent))
                {
                    indent = null;
                }
            }

            Template template;

            if (!context.CachedTemplates.TryGetValue(templatePath, out template))
            {
                string templateText;
                try
                {
                    templateText = templateLoader.Load(context, callerContext.Span, templatePath);
                }
                catch (Exception ex) when(!(ex is ScriptRuntimeException))
                {
                    throw new ScriptRuntimeException(callerContext.Span, $"Unexpected exception while loading the include `{templateName}` from path `{templatePath}`", ex);
                }

                if (templateText == null)
                {
                    throw new ScriptRuntimeException(callerContext.Span, $"The result of including `{templateName}->{templatePath}` cannot be null");
                }

                // Clone parser options
                var parserOptions = context.TemplateLoaderParserOptions;
                var lexerOptions  = context.TemplateLoaderLexerOptions;
                template = Template.Parse(templateText, templatePath, parserOptions, lexerOptions);

                // If the template has any errors, throw an exception
                if (template.HasErrors)
                {
                    throw new ScriptParserRuntimeException(callerContext.Span, $"Error while parsing template `{templateName}` from `{templatePath}`", template.Messages);
                }

                context.CachedTemplates.Add(templatePath, template);
            }

            // Make sure that we cannot recursively include a template
            object result = null;

            context.EnterRecursive(callerContext);

            var previousIndent = context.CurrentIndent;

            context.CurrentIndent = indent;
            context.PushOutput();
            var previousArguments = context.GetValue(ScriptVariable.Arguments);

            try
            {
                context.SetValue(ScriptVariable.Arguments, arguments, true, true);

                if (indent != null)
                {
                    // We reset before and after the fact that we have a new line
                    context.ResetPreviousNewLine();
                }
                result = template.Render(context);
                if (indent != null)
                {
                    context.ResetPreviousNewLine();
                }
            }
            finally
            {
                context.PopOutput();
                context.CurrentIndent = previousIndent;
                context.ExitRecursive(callerContext);

                // Remove the arguments
                context.DeleteValue(ScriptVariable.Arguments);
                if (previousArguments != null)
                {
                    // Restore them if necessary
                    context.SetValue(ScriptVariable.Arguments, previousArguments, true);
                }
            }

            return(result);
        }
Example #42
0
        private static object Slice(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 2 || parameters.Count > 3)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for slice. Expecting at least 2 parameters <start> <length>? <text>");
            }

            var text   = ScriptValueConverter.ToString(callerContext.Span, parameters[parameters.Count - 1]);
            var start  = ScriptValueConverter.ToInt(callerContext.Span, parameters[0]);
            var length = -1;

            if (parameters.Count == 3)
            {
                length = ScriptValueConverter.ToInt(callerContext.Span, parameters[1]);
            }

            return(Slice(text, start, length));
        }
Example #43
0
        public static object Call(TemplateContext context, ScriptNode callerContext, object functionObject, bool processPipeArguments, 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 target function `{callerContext}`( as `{functionObject?.GetType()}`)");
            }

            ScriptBlockStatement blockDelegate = null;

            if (context.BlockDelegates.Count > 0)
            {
                blockDelegate = context.BlockDelegates.Pop();
            }

            // We can't cache this array because it might be collect by the function
            // So we absolutely need to generate a new array everytime we call a function
            ScriptArray argumentValues;

            // Handle pipe arguments here
            if (processPipeArguments && context.PipeArguments != null && context.PipeArguments.Count > 0)
            {
                var args = context.PipeArguments;
                argumentValues = new ScriptArray(args.Count);
                for (int i = 0; i < args.Count; i++)
                {
                    argumentValues.Add(args[i]);
                }
                args.Clear();
            }
            else
            {
                argumentValues = new ScriptArray(arguments?.Count ?? 0);
            }

            // Process direct arguments
            if (arguments != null)
            {
                foreach (var argument in arguments)
                {
                    object value;

                    // Handle named arguments
                    var namedArg = argument as ScriptNamedArgument;
                    if (namedArg != null)
                    {
                        // In case of a ScriptFunction, we write the named argument into the ScriptArray directly
                        if (externFunction == null)
                        {
                            // We can't add an argument that is "size" for array
                            if (argumentValues.CanWrite(namedArg.Name))
                            {
                                argumentValues.SetValue(context, callerContext.Span, namedArg.Name, context.Evaluate(namedArg), false);
                                continue;
                            }

                            // Otherwise pass as a regular argument
                            value = context.Evaluate(namedArg);
                        }
                        else
                        {
                            // Named argument are passed as is to the IScriptCustomFunction
                            value = argument;
                        }
                    }
                    else
                    {
                        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.Operator == ScriptUnaryOperator.FunctionParametersExpand)
                    {
                        var valueEnumerator = value as IEnumerable;
                        if (valueEnumerator != null)
                        {
                            foreach (var subValue in valueEnumerator)
                            {
                                argumentValues.Add(subValue);
                            }
                            continue;
                        }
                    }

                    argumentValues.Add(value);
                }
            }

            object result = null;

            context.EnterFunction(callerContext);
            try
            {
                if (externFunction != null)
                {
                    result = externFunction.Invoke(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);
        }
Example #44
0
        private static object Sort(TemplateContext context, ScriptNode callerContext, ScriptArray parameters)
        {
            if (parameters.Count < 1 || parameters.Count > 2)
            {
                throw new ScriptRuntimeException(callerContext.Span, $"Unexpected number of arguments [{parameters.Count}] for sort. Expecting at least 1 parameter <property>? <array>");
            }

            var target = parameters[parameters.Count - 1];
            string member = null;
            if (parameters.Count == 2)
            {
               member = ScriptValueConverter.ToString(callerContext.Span, parameters[0]);
            }

            return Sort(context, target, member);
        }