Skip to content

Commit e0a45cf

Browse files
committed
WIP on repetition
1 parent 02f8409 commit e0a45cf

16 files changed

+248
-36
lines changed

serilog-expressions.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<s:Boolean x:Key="/Default/UserDictionary/Words/=Acerola/@EntryIndexedValue">True</s:Boolean>
33
<s:Boolean x:Key="/Default/UserDictionary/Words/=Comparand/@EntryIndexedValue">True</s:Boolean>
44
<s:Boolean x:Key="/Default/UserDictionary/Words/=Enricher/@EntryIndexedValue">True</s:Boolean>
5+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Evaluatable/@EntryIndexedValue">True</s:Boolean>
56
<s:Boolean x:Key="/Default/UserDictionary/Words/=Existentials/@EntryIndexedValue">True</s:Boolean>
67
<s:Boolean x:Key="/Default/UserDictionary/Words/=formattable/@EntryIndexedValue">True</s:Boolean>
78
<s:Boolean x:Key="/Default/UserDictionary/Words/=nblumhardt/@EntryIndexedValue">True</s:Boolean>

src/Serilog.Expressions/Expressions/Compilation/ExpressionCompiler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static Expression Translate(Expression expression)
2222
return actual;
2323
}
2424

25-
public static CompiledExpression Compile(Expression expression, NameResolver nameResolver)
25+
public static Evaluatable Compile(Expression expression, NameResolver nameResolver)
2626
{
2727
var actual = Translate(expression);
2828
return LinqExpressionCompiler.Compile(actual, nameResolver);

src/Serilog.Expressions/Expressions/Compilation/Linq/Intrinsics.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Linq;
66
using System.Text.RegularExpressions;
77
using Serilog.Events;
8+
using Serilog.Expressions.Runtime;
89
using Serilog.Formatting.Display;
910
using Serilog.Parsing;
1011

@@ -131,9 +132,10 @@ public static bool CoerceToScalarBoolean(LogEventPropertyValue value)
131132
return null;
132133
}
133134

134-
public static LogEventPropertyValue? GetPropertyValue(LogEvent context, string propertyName)
135+
public static LogEventPropertyValue? GetPropertyValue(EvaluationContext ctx, string propertyName)
135136
{
136-
if (!context.Properties.TryGetValue(propertyName, out var value))
137+
if (!Locals.TryGetValue(ctx.Locals, propertyName, out var value) &&
138+
!ctx.LogEvent.Properties.TryGetValue(propertyName, out value))
137139
return null;
138140

139141
return value;

src/Serilog.Expressions/Expressions/Compilation/Linq/LinqExpressionCompiler.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,22 @@ class LinqExpressionCompiler : SerilogExpressionTransformer<ExpressionBody>
6868
static readonly MethodInfo TryGetStructurePropertyValueMethod = typeof(Intrinsics)
6969
.GetMethod(nameof(Intrinsics.TryGetStructurePropertyValue), BindingFlags.Static | BindingFlags.Public)!;
7070

71-
ParameterExpression Context { get; } = LX.Variable(typeof(LogEvent), "evt");
71+
ParameterExpression Context { get; } = LX.Variable(typeof(EvaluationContext), "ctx");
7272

7373
LinqExpressionCompiler(NameResolver nameResolver)
7474
{
7575
_nameResolver = nameResolver;
7676
}
7777

78-
public static CompiledExpression Compile(Expression expression, NameResolver nameResolver)
78+
public static Evaluatable Compile(Expression expression, NameResolver nameResolver)
7979
{
8080
if (expression == null) throw new ArgumentNullException(nameof(expression));
8181
var compiler = new LinqExpressionCompiler(nameResolver);
8282
var body = compiler.Transform(expression);
83-
return LX.Lambda<CompiledExpression>(body, compiler.Context).Compile();
83+
return LX.Lambda<Evaluatable>(body, compiler.Context).Compile();
8484
}
8585

86-
ExpressionBody Splice(Expression<CompiledExpression> lambda)
86+
ExpressionBody Splice(Expression<Evaluatable> lambda)
8787
{
8888
return ParameterReplacementVisitor.ReplaceParameters(lambda, Context);
8989
}
@@ -140,18 +140,18 @@ protected override ExpressionBody Transform(AmbientPropertyExpression px)
140140
{
141141
return px.PropertyName switch
142142
{
143-
BuiltInProperty.Level => Splice(context => new ScalarValue(context.Level)),
144-
BuiltInProperty.Message => Splice(context => new ScalarValue(Intrinsics.RenderMessage(context))),
143+
BuiltInProperty.Level => Splice(context => new ScalarValue(context.LogEvent.Level)),
144+
BuiltInProperty.Message => Splice(context => new ScalarValue(Intrinsics.RenderMessage(context.LogEvent))),
145145
BuiltInProperty.Exception => Splice(context =>
146-
context.Exception == null ? null : new ScalarValue(context.Exception)),
147-
BuiltInProperty.Timestamp => Splice(context => new ScalarValue(context.Timestamp)),
148-
BuiltInProperty.MessageTemplate => Splice(context => new ScalarValue(context.MessageTemplate.Text)),
146+
context.LogEvent.Exception == null ? null : new ScalarValue(context.LogEvent.Exception)),
147+
BuiltInProperty.Timestamp => Splice(context => new ScalarValue(context.LogEvent.Timestamp)),
148+
BuiltInProperty.MessageTemplate => Splice(context => new ScalarValue(context.LogEvent.MessageTemplate.Text)),
149149
BuiltInProperty.Properties => Splice(context =>
150-
new StructureValue(context.Properties.Select(kvp => new LogEventProperty(kvp.Key, kvp.Value)),
150+
new StructureValue(context.LogEvent.Properties.Select(kvp => new LogEventProperty(kvp.Key, kvp.Value)),
151151
null)),
152-
BuiltInProperty.Renderings => Splice(context => Intrinsics.GetRenderings(context)),
152+
BuiltInProperty.Renderings => Splice(context => Intrinsics.GetRenderings(context.LogEvent)),
153153
BuiltInProperty.EventId => Splice(context =>
154-
new ScalarValue(EventIdHash.Compute(context.MessageTemplate.Text))),
154+
new ScalarValue(EventIdHash.Compute(context.LogEvent.MessageTemplate.Text))),
155155
_ => LX.Constant(null, typeof(LogEventPropertyValue))
156156
};
157157
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using Serilog.Events;
2+
3+
namespace Serilog.Expressions
4+
{
5+
delegate LogEventPropertyValue? Evaluatable(EvaluationContext ctx);
6+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using Serilog.Events;
3+
using Serilog.Expressions.Runtime;
4+
5+
namespace Serilog.Expressions
6+
{
7+
readonly struct EvaluationContext
8+
{
9+
public LogEvent LogEvent { get; }
10+
public Locals? Locals { get; }
11+
12+
public EvaluationContext(LogEvent logEvent, Locals? locals = null)
13+
{
14+
LogEvent = logEvent ?? throw new ArgumentNullException(nameof(logEvent));
15+
Locals = locals;
16+
}
17+
}
18+
}

src/Serilog.Expressions/Expressions/ExpressionResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
namespace Serilog.Expressions
1919
{
2020
/// <summary>
21-
/// Helper functions for working with the results of <see cref="CompiledExpression"/>s.
21+
/// Helper functions for working with the results of <see cref="Evaluatable"/>s.
2222
/// </summary>
2323
public static class ExpressionResult
2424
{
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using Serilog.Events;
3+
4+
namespace Serilog.Expressions.Runtime
5+
{
6+
/// <summary>
7+
/// Named local variables. We just look them up by name. The structure is a
8+
/// linked list with a null terminator: most of the time expressions won't have any
9+
/// locals, and when they do, they'll only have one or two at a given point.
10+
/// </summary>
11+
class Locals
12+
{
13+
readonly Locals? _others;
14+
readonly string _name;
15+
readonly LogEventPropertyValue _value;
16+
17+
Locals(Locals? others, string name, LogEventPropertyValue value)
18+
{
19+
_others = others;
20+
_name = name;
21+
_value = value;
22+
}
23+
24+
public static Locals Set(Locals? others, string name, LogEventPropertyValue value)
25+
{
26+
return new Locals(others, name, value);
27+
}
28+
29+
public static bool TryGetValue(Locals? locals, string name, [MaybeNullWhen(false)] out LogEventPropertyValue value)
30+
{
31+
while (locals != null)
32+
{
33+
if (name == locals._name)
34+
{
35+
value = locals._value;
36+
return true;
37+
}
38+
39+
locals = locals._others;
40+
}
41+
42+
value = null;
43+
return false;
44+
}
45+
}
46+
}

src/Serilog.Expressions/Expressions/SerilogExpression.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ static bool TryCompileImpl(
9898
return false;
9999
}
100100

101-
result = ExpressionCompiler.Compile(root, DefaultFunctionNameResolver.Build(nameResolver));
101+
var evaluate = ExpressionCompiler.Compile(root, DefaultFunctionNameResolver.Build(nameResolver));
102+
result = evt => evaluate(new EvaluationContext(evt));
102103
error = null;
103104
return true;
104105
}

src/Serilog.Expressions/Templates/Compilation/CompiledConditional.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@ namespace Serilog.Templates.Compilation
77
{
88
class CompiledConditional : CompiledTemplate
99
{
10-
readonly CompiledExpression _condition;
10+
readonly Evaluatable _condition;
1111
readonly CompiledTemplate _consequent;
1212
readonly CompiledTemplate? _alternative;
1313

14-
public CompiledConditional(CompiledExpression condition, CompiledTemplate consequent, CompiledTemplate? alternative)
14+
public CompiledConditional(Evaluatable condition, CompiledTemplate consequent, CompiledTemplate? alternative)
1515
{
1616
_condition = condition ?? throw new ArgumentNullException(nameof(condition));
1717
_consequent = consequent ?? throw new ArgumentNullException(nameof(consequent));
1818
_alternative = alternative;
1919
}
2020

21-
public override void Evaluate(LogEvent logEvent, TextWriter output, IFormatProvider? formatProvider)
21+
public override void Evaluate(EvaluationContext ctx, TextWriter output, IFormatProvider? formatProvider)
2222
{
23-
if (ExpressionResult.IsTrue(_condition.Invoke(logEvent)))
24-
_consequent.Evaluate(logEvent, output, formatProvider);
23+
if (ExpressionResult.IsTrue(_condition.Invoke(ctx)))
24+
_consequent.Evaluate(ctx, output, formatProvider);
2525
else
26-
_alternative?.Evaluate(logEvent, output, formatProvider);
26+
_alternative?.Evaluate(ctx, output, formatProvider);
2727
}
2828
}
2929
}

0 commit comments

Comments
 (0)