예제 #1
0
        /// <summary>
        /// Expand the results of a template with given name and scope.
        /// Throws errors if certain errors detected <see cref="TemplateErrors"/>.
        /// </summary>
        /// <param name="templateName">Given template name.</param>
        /// <param name="scope">Given scope.</param>
        /// <returns>All possiable results.</returns>
        public List <object> ExpandTemplate(string templateName, object scope)
        {
            var memory = scope is CustomizedMemory scopeMemory ? scopeMemory : new CustomizedMemory(scope);

            if (!TemplateMap.ContainsKey(templateName))
            {
                throw new ArgumentException(TemplateErrors.TemplateNotExist(templateName));
            }

            var templateTarget = new EvaluationTarget(templateName, memory);

            var currentEvaluateId = templateTarget.GetId();

            if (_evaluationTargetStack.Any(e => e.GetId() == currentEvaluateId))
            {
                throw new InvalidOperationException($"{TemplateErrors.LoopDetected} {string.Join(" => ", _evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}");
            }

            // Using a stack to track the evaluation trace
            _evaluationTargetStack.Push(templateTarget);
            var expanderResult = Visit(TemplateMap[templateName].TemplateBodyParseTree);

            _evaluationTargetStack.Pop();

            var result = new List <object>();

            expanderResult.ForEach(u =>
            {
                result.Add(u);
            });
            return(result);
        }
예제 #2
0
        /// <summary>
        /// Evaluate a template with given name and scope.
        /// </summary>
        /// <param name="inputTemplateName">Template name.</param>
        /// <param name="scope">Scope.</param>
        /// <returns>Evaluate result.</returns>
        public object EvaluateTemplate(string inputTemplateName, object scope)
        {
            if (!(scope is CustomizedMemory))
            {
                scope = new CustomizedMemory(scope);
            }

            (var reExecute, var templateName) = ParseTemplateName(inputTemplateName);

            if (!TemplateMap.ContainsKey(templateName))
            {
                throw new Exception(TemplateErrors.TemplateNotExist(templateName));
            }

            if (evaluationTargetStack.Any(e => e.TemplateName == templateName))
            {
                throw new Exception($"{TemplateErrors.LoopDetected} {string.Join(" => ", evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}");
            }

            var templateTarget = new EvaluationTarget(templateName, scope);

            var currentEvaluateId = templateTarget.GetId();

            EvaluationTarget previousEvaluateTarget = null;

            if (evaluationTargetStack.Count != 0)
            {
                previousEvaluateTarget = evaluationTargetStack.Peek();

                if (!reExecute && previousEvaluateTarget.EvaluatedChildren.ContainsKey(currentEvaluateId))
                {
                    return(previousEvaluateTarget.EvaluatedChildren[currentEvaluateId]);
                }
            }

            // Using a stack to track the evaluation trace
            evaluationTargetStack.Push(templateTarget);
            var result = Visit(TemplateMap[templateName].TemplateBodyParseTree);

            if (previousEvaluateTarget != null)
            {
                previousEvaluateTarget.EvaluatedChildren[currentEvaluateId] = result;
            }

            evaluationTargetStack.Pop();

            if (lgOptions.LineBreakStyle == LGLineBreakStyle.Markdown && result is string str)
            {
                result = NewLineRegex.Replace(str, "$1$1");
            }

            return(result);
        }
예제 #3
0
        /// <summary>
        /// Evaluate a template with given name and scope.
        /// </summary>
        /// <param name="inputTemplateName">template name.</param>
        /// <param name="scope">scope.</param>
        /// <returns>Evaluate result.</returns>
        public object EvaluateTemplate(string inputTemplateName, object scope)
        {
            if (!(scope is CustomizedMemory))
            {
                scope = new CustomizedMemory(SimpleObjectMemory.Wrap(scope));
            }

            (var reExecute, var templateName) = ParseTemplateName(inputTemplateName);

            if (!TemplateMap.ContainsKey(templateName))
            {
                throw new Exception(LGErrors.TemplateNotExist(templateName));
            }

            if (evaluationTargetStack.Any(e => e.TemplateName == templateName))
            {
                throw new Exception($"{LGErrors.LoopDetected} {string.Join(" => ", evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}");
            }

            var templateTarget = new EvaluationTarget(templateName, scope);

            var currentEvaluateId = templateTarget.GetId();

            EvaluationTarget previousEvaluateTarget = null;

            if (evaluationTargetStack.Count != 0)
            {
                previousEvaluateTarget = evaluationTargetStack.Peek();

                if (!reExecute && previousEvaluateTarget.EvaluatedChildren.ContainsKey(currentEvaluateId))
                {
                    return(previousEvaluateTarget.EvaluatedChildren[currentEvaluateId]);
                }
            }

            // Using a stack to track the evaluation trace
            evaluationTargetStack.Push(templateTarget);
            var result = Visit(TemplateMap[templateName].ParseTree);

            if (previousEvaluateTarget != null)
            {
                previousEvaluateTarget.EvaluatedChildren[currentEvaluateId] = result;
            }

            evaluationTargetStack.Pop();

            return(result);
        }
예제 #4
0
        /// <summary>
        /// Evaluate a template with given name and scope.
        /// Throws errors if certain errors detected <see cref="TemplateErrors"/>.
        /// </summary>
        /// <param name="inputTemplateName">Template name.</param>
        /// <param name="scope">Scope.</param>
        /// <returns>Evaluate result.</returns>
        public object EvaluateTemplate(string inputTemplateName, object scope)
        {
            var memory = scope is CustomizedMemory scopeMemory ? scopeMemory : new CustomizedMemory(scope);

            (var reExecute, var templateName) = ParseTemplateName(inputTemplateName);

            if (!TemplateMap.ContainsKey(templateName))
            {
                throw new Exception(TemplateErrors.TemplateNotExist(templateName));
            }

            var templateTarget = new EvaluationTarget(templateName, memory);

            var currentEvaluateId = templateTarget.GetId();

            if (_evaluationTargetStack.Any(e => e.GetId() == currentEvaluateId))
            {
                throw new Exception($"{TemplateErrors.LoopDetected} {string.Join(" => ", _evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}");
            }

            EvaluationTarget previousEvaluateTarget = null;

            if (_evaluationTargetStack.Count != 0)
            {
                previousEvaluateTarget = _evaluationTargetStack.Peek();

                if (!reExecute && previousEvaluateTarget.EvaluatedChildren.ContainsKey(currentEvaluateId))
                {
                    return(previousEvaluateTarget.EvaluatedChildren[currentEvaluateId]);
                }
            }

            // Using a stack to track the evaluation trace
            _evaluationTargetStack.Push(templateTarget);
            var result = Visit(TemplateMap[templateName].TemplateBodyParseTree);

            if (previousEvaluateTarget != null)
            {
                previousEvaluateTarget.EvaluatedChildren[currentEvaluateId] = result;
            }

            _evaluationTargetStack.Pop();

            return(result);
        }
예제 #5
0
        public object EvaluateTemplate(string templateName, object scope)
        {
            if (!TemplateMap.ContainsKey(templateName))
            {
                throw new Exception($"[{templateName}] not found");
            }

            if (evaluationTargetStack.Any(e => e.TemplateName == templateName))
            {
                throw new Exception($"Loop detected: {string.Join(" => ", evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}");
            }

            var templateTarget = new EvaluationTarget(templateName, scope);

            var currentEvaluateId = templateTarget.GetId();

            EvaluationTarget previousEvaluateTarget = null;

            if (evaluationTargetStack.Count != 0)
            {
                previousEvaluateTarget = evaluationTargetStack.Peek();

                if (previousEvaluateTarget.EvaluatedChildren.ContainsKey(currentEvaluateId))
                {
                    return(previousEvaluateTarget.EvaluatedChildren[currentEvaluateId]);
                }
            }

            // Using a stack to track the evalution trace
            evaluationTargetStack.Push(templateTarget);
            var result = Visit(TemplateMap[templateName].ParseTree);

            if (previousEvaluateTarget != null)
            {
                previousEvaluateTarget.EvaluatedChildren.Add(currentEvaluateId, result);
            }

            evaluationTargetStack.Pop();

            return(result);
        }
예제 #6
0
        /// <summary>
        /// Evaluate a template with given name and scope.
        /// Throws errors if certain errors detected <see cref="TemplateErrors"/>.
        /// </summary>
        /// <param name="inputTemplateName">Template name.</param>
        /// <param name="scope">Scope.</param>
        /// <returns>Evaluate result.</returns>
        public object EvaluateTemplate(string inputTemplateName, object scope)
        {
            var memory = scope is CustomizedMemory scopeMemory ? scopeMemory : new CustomizedMemory(scope);

            (var reExecute, var templateName) = ParseTemplateName(inputTemplateName);

            if (!TemplateMap.ContainsKey(templateName))
            {
                throw new ArgumentException(TemplateErrors.TemplateNotExist(templateName));
            }

            var templateTarget    = new EvaluationTarget(templateName, memory);
            var currentEvaluateId = templateTarget.GetId();

            if (_evaluationTargetStack.Any(e => e.GetId() == currentEvaluateId))
            {
                throw new InvalidOperationException($"{TemplateErrors.LoopDetected} {string.Join(" => ", _evaluationTargetStack.Reverse().Select(e => e.TemplateName))} => {templateName}");
            }

            object result    = null;
            var    hasResult = false;

            if (!reExecute)
            {
                if (_lgOptions.CacheScope == LGCacheScope.Global)
                {
                    if (_cachedResult.ContainsKey(currentEvaluateId))
                    {
                        result    = _cachedResult[currentEvaluateId];
                        hasResult = true;
                    }
                }
                else if (_lgOptions.CacheScope == null || _lgOptions.CacheScope == LGCacheScope.Local)
                {
                    EvaluationTarget previousEvaluateTarget = null;
                    if (CurrentTemplate() != null)
                    {
                        previousEvaluateTarget = CurrentTarget();

                        if (previousEvaluateTarget.CachedEvaluatedChildren.ContainsKey(currentEvaluateId))
                        {
                            result    = previousEvaluateTarget.CachedEvaluatedChildren[currentEvaluateId];
                            hasResult = true;
                        }
                    }
                }
            }

            if (!hasResult)
            {
                _evaluationTargetStack.Push(templateTarget);

                var currentTemplate = CurrentTemplate();
                _lgOptions.OnEvent?.Invoke(currentTemplate, new BeginTemplateEvaluationArgs {
                    Source = currentTemplate.SourceRange.Source, TemplateName = templateName
                });

                result = Visit(TemplateMap[templateName].TemplateBodyParseTree);

                if (_lgOptions.OnEvent != null)
                {
                    var text = $"Evaluate template [{templateName}] get result: {result}";
                    _lgOptions.OnEvent(currentTemplate, new MessageArgs {
                        Source = currentTemplate.SourceRange.Source, Text = text
                    });
                }

                _evaluationTargetStack.Pop();

                if (!reExecute)
                {
                    if (_lgOptions.CacheScope == LGCacheScope.Global)
                    {
                        _cachedResult[currentEvaluateId] = result;
                    }
                    else if (_lgOptions.CacheScope == null || _lgOptions.CacheScope == LGCacheScope.Local)
                    {
                        if (_evaluationTargetStack.Count > 0)
                        {
                            _evaluationTargetStack.Peek().CachedEvaluatedChildren[currentEvaluateId] = result;
                        }
                    }
                }
            }

            return(result);
        }