diff --git a/NTypewriter.Runtime/Rendering/TemplateRenderer.cs b/NTypewriter.Runtime/Rendering/TemplateRenderer.cs index 65f240e..3abf8a5 100644 --- a/NTypewriter.Runtime/Rendering/TemplateRenderer.cs +++ b/NTypewriter.Runtime/Rendering/TemplateRenderer.cs @@ -5,7 +5,9 @@ using System.Threading.Tasks; using NTypewriter.CodeModel; using NTypewriter.Editor.Config; +using NTypewriter.Ports; using NTypewriter.Runtime.Rendering.Internals; +using NTypewriter.Runtime.Scripting; namespace NTypewriter.Runtime.Rendering { @@ -38,7 +40,7 @@ public async Task> RenderAsync(string templateFileP dataModels[VariableNames.Config] = configAdapter; dataModels[VariableNames.Env] = environmentVariables ?? new EnvironmentVariables(); - var result = await NTypeWriter.Render(template, dataModels, configuration, new ExternalOutputAdapter(output)); + var result = await NTypeWriter.Render(template, dataModels, configuration, new ExternalOutputAdapter(output), new ExpressionCompiler()); output.Info("Used configuration : " + editorConfig.ToString()); diff --git a/NTypewriter.Runtime/Scripting/ExpressionCompiler.cs b/NTypewriter.Runtime/Scripting/ExpressionCompiler.cs new file mode 100644 index 0000000..268213c --- /dev/null +++ b/NTypewriter.Runtime/Scripting/ExpressionCompiler.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using NTypewriter.Ports; + +namespace NTypewriter.Runtime.Scripting +{ + internal class ExpressionCompiler : IExpressionCompiler + { + public Func CompilePredicate(string predicate) + { + return x => true; + } + } +} diff --git a/NTypewriter/Internals/BuiltinFunctionsScriptObject.cs b/NTypewriter/Internals/BuiltinFunctionsScriptObject.cs index 2d0af5c..a273148 100644 --- a/NTypewriter/Internals/BuiltinFunctionsScriptObject.cs +++ b/NTypewriter/Internals/BuiltinFunctionsScriptObject.cs @@ -1,5 +1,6 @@ using System; using NTypewriter.Internals.Functions; +using Scriban; using Scriban.Functions; using Scriban.Runtime; @@ -30,7 +31,22 @@ private BuiltinFunctionsScriptObject() this["Symbols"] = CreateScriptObject(typeof(global::NTypewriter.CodeModel.Functions.SymbolsFunctions)); this["Debug"] = CreateScriptObject(typeof(global::NTypewriter.Internals.Functions.DebugFunctions)); this.Import(typeof(SaveFunction), renamer: MemberRenamer); - } + this.Import(typeof(LINQFunctions), renamer: MemberRenamer); + } + + public override bool TryGetValue(TemplateContext context, Scriban.Parsing.SourceSpan span, string member, out object value) + { + return base.TryGetValue(context, span, member, out value); + } + + public override bool TrySetValue(TemplateContext context, Scriban.Parsing.SourceSpan span, string member, object value, bool readOnly) + { + return base.TrySetValue(context, span, member, value, readOnly); + } + + + + private ScriptObject CreateScriptObject(params Type[] types) { diff --git a/NTypewriter/Internals/Functions/LINQFunctions.cs b/NTypewriter/Internals/Functions/LINQFunctions.cs new file mode 100644 index 0000000..8d82fca --- /dev/null +++ b/NTypewriter/Internals/Functions/LINQFunctions.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NTypewriter.Internals.Functions +{ + internal class LINQFunctions + { + public static IEnumerable Where(MainTemplateContext context, IEnumerable source, string predicate) + { + var func = context.CompileExpression(predicate); + return source.Where(func); + } + } +} \ No newline at end of file diff --git a/NTypewriter/Internals/MainTemplateContext.cs b/NTypewriter/Internals/MainTemplateContext.cs index 5090472..029ac9d 100644 --- a/NTypewriter/Internals/MainTemplateContext.cs +++ b/NTypewriter/Internals/MainTemplateContext.cs @@ -1,6 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; using NTypewriter.Ports; using Scriban; +using Scriban.Syntax; namespace NTypewriter.Internals { @@ -8,8 +12,10 @@ internal sealed class MainTemplateContext : TemplateContext { private readonly List renderedItems = new List(); private readonly IExternalOutput externalOutput; + private readonly IExpressionCompiler expressionCompiler; - public MainTemplateContext(DataScriptObject dataScriptObject, CustomFunctionsScriptObject customScriptObject, IExternalOutput externalOutput) : base(BuiltinFunctionsScriptObject.Singleton) + + public MainTemplateContext(DataScriptObject dataScriptObject, CustomFunctionsScriptObject customScriptObject, IExternalOutput externalOutput, IExpressionCompiler expressionCompiler) : base(BuiltinFunctionsScriptObject.Singleton) { LoopLimit = 66_666; MemberRenamer = member => member.Name; @@ -19,6 +25,21 @@ public MainTemplateContext(DataScriptObject dataScriptObject, CustomFunctionsScr PushGlobal(customScriptObject); PushGlobal(dataScriptObject); this.externalOutput = externalOutput; + this.expressionCompiler = expressionCompiler; + + TryGetMember = TryGetMemberImp; + } + + + private bool TryGetMemberImp(TemplateContext context, Scriban.Parsing.SourceSpan span, object target, string member, out object value) + { + if (target is IEnumerable symbold) + { + + } + + value = null; + return false; } @@ -30,10 +51,29 @@ public void WriteOnExternalOutput(string text) { externalOutput?.Write(text); } + public Func CompileExpression(string predicate) + { + if (expressionCompiler == null) + { + throw new Exception("Expression compiler is unavailable"); + } + return expressionCompiler.CompilePredicate(predicate); + } + public List GetRenderedItems() { return renderedItems; } + + + public override object Evaluate(ScriptNode scriptNode, bool aliasReturnedFunction) + { + return base.Evaluate(scriptNode, aliasReturnedFunction); + } + public override ValueTask EvaluateAsync(ScriptNode scriptNode, bool aliasReturnedFunction) + { + return base.EvaluateAsync(scriptNode, aliasReturnedFunction); + } } } \ No newline at end of file diff --git a/NTypewriter/NTypeWriter.cs b/NTypewriter/NTypeWriter.cs index 35b7368..70f53e2 100644 --- a/NTypewriter/NTypeWriter.cs +++ b/NTypewriter/NTypeWriter.cs @@ -9,13 +9,13 @@ namespace NTypewriter { public class NTypeWriter { - public static async Task Render(string template, object dataModel, Configuration configuration = null, IExternalOutput externalOutput = null) + public static async Task Render(string template, object dataModel, Configuration configuration = null, IExternalOutput externalOutput = null, IExpressionCompiler expressionCompiler = null) { - return await Render(template, new Dictionary() { [VariableNames.Data] = dataModel }, configuration, externalOutput); + return await Render(template, new Dictionary() { [VariableNames.Data] = dataModel }, configuration, externalOutput, expressionCompiler); } - public static async Task Render(string template, Dictionary dataModels, Configuration configuration = null, IExternalOutput externalOutput = null) + public static async Task Render(string template, Dictionary dataModels, Configuration configuration = null, IExternalOutput externalOutput = null, IExpressionCompiler expressionCompiler = null) { var result = new Result(); var scribanTemplate = Template.Parse(template); @@ -29,11 +29,11 @@ public static async Task Render(string template, Dictionary CompilePredicate(string predicate); + } +} diff --git a/Tests.Assets.WebApi2022/RenderTemplatesCommand_HappyPathTemplate.nt b/Tests.Assets.WebApi2022/RenderTemplatesCommand_HappyPathTemplate.nt index 8e2d487..2d21ade 100644 --- a/Tests.Assets.WebApi2022/RenderTemplatesCommand_HappyPathTemplate.nt +++ b/Tests.Assets.WebApi2022/RenderTemplatesCommand_HappyPathTemplate.nt @@ -1,5 +1,5 @@ {{ capture output - for class in data.Classes | Array.Sort "FullName" + for class in data.Classes | Where "x => true" | Array.Sort "FullName" class.FullName | String.Append "\r\n" end end