private JinjaUserDefinedFunction ConvertMacroToUserDefinedFunction(MacroNode macro) { var usesCaller = macro.Contents.Transform(CallerFinderVisitor.Instance).Any(x => x); Func <UserDefinedArgumentData, object?> func = arguments => { using var checkout = StringBuilderPool.Instance.Checkout(); var stringBuilder = checkout.CheckedOutObject; Scopes.Push($"Macro: {macro.FunctionDeclaration.Name}"); foreach (var arg in arguments.AllArguments) { Scopes.Current.DefineAndSetVariable(arg.Name, arg.Value); } Scopes.Current.DefineAndSetVariable("varargs", arguments.AdditionalPositionalArguments.Select(arg => arg.Value)); Scopes.Current.DefineAndSetVariable("kwargs", arguments.AdditionalKeywordArguments); foreach (var output in macro.Contents.Transform(this)) { stringBuilder.Append(output); } Scopes.Pop($"Macro: {macro.FunctionDeclaration.Name}"); return(stringBuilder.ToString()); }; UserDefinedFunction.UserDefinedFunctionDelegate del = args => func(args); return(new JinjaUserDefinedFunction(macro.FunctionDeclaration, del, usesCaller)); }
public void Dispose() { Debug.Assert(Scopes.Count == 1); var rootScope = Scopes.Pop(); foreach (var line in rootScope) { Writer.WriteLine(line); } }
public void Dispose() { if (AutoCommit) { if (_hasException == null) { long exceptionCode = Marshal.GetExceptionCode(); _hasException = exceptionCode != 0 && exceptionCode != 0xCCCCCCCC; } if (_hasException.Value || !Item.Commit(ItemType)) { Item.Rollback(ItemType); } } Transaction.Dispose(); Scopes.Pop(); }
public IEnumerable <string> Transform(CallNode item) { _EncounteredOutputStyleBlock = true; if (!(ShouldRender && _EncounteredOutputStyleBlock)) { yield break; } Func <UserDefinedArgumentData, object?> func = arguments => { using var checkout = StringBuilderPool.Instance.Checkout(); var stringBuilder = checkout.CheckedOutObject; foreach (var output in item.Contents.Transform(this)) { stringBuilder.Append(output); } return(stringBuilder.ToString()); }; if (Environment.Evaluation.TryParseFunctionDeclaration(item.CallerDefinition.Expression, out var functionDeclaration) == false || functionDeclaration == null) { throw new NotImplementedException(); } Scopes.Push($"Call: {item.CallerDefinition.Expression}"); UserDefinedFunction.UserDefinedFunctionDelegate del = args => func(args); Scopes.Current.DefineAndSetVariable("caller", new JinjaUserDefinedFunction(functionDeclaration, del)); var evalObj = Environment.Evaluation.EvaluateDynamic(item.MacroCall.ExpressionParserNode, ExpressionParserTransformer); if (!(evalObj is ExpressionParser.Void)) { yield return(JinjaCustomStringProvider.Instance.ToString(evalObj)); } Scopes.Pop($"Call: {item.CallerDefinition.Expression}"); }
public IEnumerable <string> Transform(FilterNode item) { _EncounteredOutputStyleBlock = true; if (ShouldRender == false) { yield break; } var filterExpression = $"{item.Filter}(__item)"; foreach (var output in item.FilterContents.Transform(this)) { Scopes.Push("Filter"); Scopes.Current.DefineAndSetVariable("__item", output); var evaluated = Environment.Evaluation.EvaluateDynamic(filterExpression, Scopes); Scopes.Pop("Filter"); yield return(evaluated?.ToString() ?? string.Empty); } }
/// <summary>Starts a new scope</summary> /// <returns><see cref="IDisposable"/> to enable automatic restore of the scope in RAII style patterns</returns> /// <remarks> /// A new scope is pushed on the stack and remains active until the <see cref="IDisposable.Dispose"/> method /// of the return is called. Normally, code generation does this with a language provided means of ensuring the /// Dispose method is called even when an exception occurs. (i.e. C# 'using' or try/finally) /// </remarks> public IDisposable EnterScope( ) { Scopes.Push(new Dictionary <string, T>( )); return(new DisposableAction(() => Scopes.Pop( ))); }
public IEnumerable <string> Transform(ForNode item) { _EncounteredOutputStyleBlock = true; if (!(ShouldRender && _EncounteredOutputStyleBlock)) { yield break; } object?evalObj; if (item.Expression != null) { evalObj = Environment.Evaluation.EvaluateDynamic(item.Expression.Expression, Scopes); } else { evalObj = item.AlreadyEvaluatedObject; } Func <object?[], object?> loopFunction = args => { if (args?.Length != 1) { throw new NotImplementedException(); } return(new ForNode(item.PrimaryBlock, item.ElseBlock, item.VariableNames, args[0], item.Filter, item.Recursive, item.EndParsingNode, item.WhiteSpaceControl)); }; var arr = CollectionEx.ToArray(evalObj) ?? Array.Empty <object>(); if (item.Filter != null) { var filtered = new List <object?>(); foreach (var arrItem in arr) { var unpacked = ReflectionHelpers.Unpack(arrItem, item.VariableNames.Length); Scopes.Push($"ForNode | Filter: {item.Filter} Item: {arrItem}"); for (var i = 0; i < unpacked.Length; ++i) { Scopes.Current.DefineAndSetVariable(item.VariableNames[i], unpacked[i]); } var result = Environment.Evaluation.EvaluateDynamic(item.Filter.Expression, Scopes); Scopes.Pop($"ForNode | Filter: {item.Filter} Item: {arrItem}"); if (TypeCoercion.GetTruthy(result)) { filtered.Add(arrItem); } } arr = filtered.ToArray(); } if (arr.Length == 0 && item.ElseBlock != null) { foreach (var output in item.ElseBlock.Transform(this)) { yield return(output); } yield break; } var depth = 0; if (Scopes.Current.TryGetVariable <LoopInfo>("loop", out var previousLoopInfo) && previousLoopInfo != null) { depth = previousLoopInfo.depth0 + 1; } var loopInfo = new LoopInfo(arr, loopFunction, depth); for (var index = 0; index < arr.Length; ++index) { loopInfo.index0 = index; var arrItem = arr[index]; var unpacked = ReflectionHelpers.Unpack(arrItem, item.VariableNames.Length); Scopes.Push($"ForNode: {item.Expression} Item: {arrItem}"); for (var i = 0; i < unpacked.Length; ++i) { Scopes.Current.DefineAndSetVariable(item.VariableNames[i], unpacked[i]); } Scopes.Current.DefineAndSetVariable("loop", loopInfo); foreach (var output in item.PrimaryBlock.Transform(this)) { yield return(output); } Scopes.Pop($"ForNode: {item.Expression} Item: {arrItem}"); } yield break; }
internal static CacheEntry LeaveScope() { return(Scopes.Pop()); }
/// <summary> /// Do not override this method. Use Disposing instead. /// </summary> public void Dispose() { Disposing(); Scopes.Pop(); }
public void LeaveScope() => scopes.Pop();