Skip to content

Commit 4bdac68

Browse files
committed
#224 - Introduce simplification rules
1 parent 7ec1344 commit 4bdac68

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1118
-8
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
internal class ChainRuleBuilder<TExpression> :
4+
IInitialChainRuleBuilder<TExpression>,
5+
IChainRuleBuilder<TExpression>
6+
where TExpression : IExpression
7+
{
8+
private ChainRule initialRule;
9+
private ChainRule currentRule;
10+
11+
public IChainRuleBuilder<TExpression> WithRule(IRule<TExpression> rule)
12+
{
13+
initialRule = currentRule = new ChainRule(rule);
14+
15+
return this;
16+
}
17+
18+
public IChainRuleBuilder<TExpression> WithNext(IRule<TExpression> next)
19+
{
20+
var chain = new ChainRule(next);
21+
currentRule.SetNext(chain);
22+
currentRule = chain;
23+
24+
return this;
25+
}
26+
27+
public IRule GetRule()
28+
=> initialRule.UnwrapIfEmpty();
29+
30+
private sealed class ChainRule : IRule<TExpression>
31+
{
32+
private readonly IRule<TExpression> current;
33+
private IRule<TExpression>? next;
34+
35+
public ChainRule(IRule<TExpression> rule)
36+
=> current = rule ?? throw new ArgumentNullException(nameof(rule));
37+
38+
public void SetNext(IRule<TExpression> rule)
39+
=> next = rule ?? throw new ArgumentNullException(nameof(rule));
40+
41+
public IRule UnwrapIfEmpty()
42+
=> next is null ? current : this;
43+
44+
public Result Execute(IExpression expression, RuleContext context)
45+
{
46+
var result = current.Execute(expression, context);
47+
if (result.IsHandled() || result.IsReAnalyze())
48+
return result;
49+
50+
if (result.IsContinue())
51+
expression = result.Value;
52+
53+
if (next is not null)
54+
return next.Execute(expression, context);
55+
56+
return Result.NotHandled();
57+
}
58+
59+
public Result Execute(TExpression expression, RuleContext context)
60+
=> Execute(expression as IExpression, context);
61+
62+
public string Name => "Chain Rule";
63+
}
64+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public readonly struct ExecutionStep
4+
{
5+
public ExecutionStep(IRule rule, IExpression before, IExpression after)
6+
{
7+
Name = rule.Name;
8+
Before = before;
9+
After = after;
10+
}
11+
12+
public string Name { get; }
13+
14+
public IExpression Before { get; }
15+
16+
public IExpression After { get; }
17+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public interface IAnalyzer2
4+
{
5+
IExpression Analyze(IExpression expression);
6+
7+
IExpression Analyze(IExpression expression, RuleContext context);
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
internal interface IChainRuleBuilder<out TExpression>
4+
where TExpression : IExpression
5+
{
6+
IChainRuleBuilder<TExpression> WithNext(IRule<TExpression> next);
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
internal interface IInitialChainRuleBuilder<out TExpression>
4+
where TExpression : IExpression
5+
{
6+
IChainRuleBuilder<TExpression> WithRule(IRule<TExpression> rule);
7+
}

xFunc.Maths/Analyzers2/IRule.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public interface IRule
4+
{
5+
Result Execute(IExpression expression, RuleContext context);
6+
7+
string Name { get; }
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public interface IRule<in TExpression> : IRule
4+
{
5+
Result Execute(TExpression expression, RuleContext context);
6+
}

xFunc.Maths/Analyzers2/Result.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
3+
namespace xFunc.Maths.Analyzers2;
4+
5+
public readonly struct Result
6+
{
7+
private readonly ResultKind kind;
8+
9+
private Result(ResultKind kind, IExpression? value)
10+
{
11+
this.kind = kind;
12+
Value = value;
13+
}
14+
15+
public static Result NotHandled()
16+
=> new Result(ResultKind.NotHandled, default);
17+
18+
public static Result Handled(IExpression value)
19+
=> new Result(ResultKind.Handled, value);
20+
21+
public static Result Continue(IExpression value)
22+
=> new Result(ResultKind.Continue, value);
23+
24+
public static Result ReAnalyze(IExpression value)
25+
=> new Result(ResultKind.ReAnalyze, value);
26+
27+
private bool IsKind(ResultKind kind)
28+
=> this.kind == kind;
29+
30+
[MemberNotNullWhen(false, nameof(Value))]
31+
public bool IsNotHandled()
32+
=> IsKind(ResultKind.NotHandled);
33+
34+
[MemberNotNullWhen(true, nameof(Value))]
35+
public bool IsHandled()
36+
=> IsKind(ResultKind.Handled);
37+
38+
[MemberNotNullWhen(true, nameof(Value))]
39+
public bool IsContinue()
40+
=> IsKind(ResultKind.Continue);
41+
42+
[MemberNotNullWhen(true, nameof(Value))]
43+
public bool IsReAnalyze()
44+
=> IsKind(ResultKind.ReAnalyze);
45+
46+
public IExpression? Value { get; }
47+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public enum ResultKind
4+
{
5+
NotHandled,
6+
Handled,
7+
Continue,
8+
ReAnalyze,
9+
}

xFunc.Maths/Analyzers2/Rule.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public abstract class Rule<TExpression> : IRule<TExpression>
4+
where TExpression : IExpression
5+
{
6+
Result IRule.Execute(IExpression expression, RuleContext context)
7+
=> Execute((TExpression)expression, context);
8+
9+
public Result Execute(TExpression expression, RuleContext context)
10+
{
11+
var result = ExecuteInternal(expression, context);
12+
if (result.IsHandled() || result.IsContinue() || result.IsReAnalyze())
13+
context.AddStep(this, expression, result.Value);
14+
15+
return result;
16+
}
17+
18+
protected abstract Result ExecuteInternal(TExpression expression, RuleContext context);
19+
20+
protected static Result Handled(IExpression value)
21+
=> Result.Handled(value);
22+
23+
protected static Result Continue(IExpression value)
24+
=> Result.Continue(value);
25+
26+
protected static Result ReAnalyze(IExpression value)
27+
=> Result.ReAnalyze(value);
28+
29+
protected static Result NotHandled()
30+
=> Result.NotHandled();
31+
32+
public virtual string Name => GetType().Name;
33+
}

0 commit comments

Comments
 (0)