Skip to content

Commit c758595

Browse files
committed
#224 - Introduce simplification rules
1 parent e9b4a40 commit c758595

Some content is hidden

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

59 files changed

+1267
-8
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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+
public string Description => "This is a chain of rules.";
65+
}
66+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
Description = rule.Description;
9+
Before = before;
10+
After = after;
11+
}
12+
13+
public string Name { get; }
14+
15+
public string Description { get; }
16+
17+
public IExpression Before { get; }
18+
19+
public IExpression After { get; }
20+
}
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: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public interface IRule
4+
{
5+
Result Execute(IExpression expression, RuleContext context);
6+
7+
string Name { get; }
8+
9+
string Description { get; }
10+
}
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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace xFunc.Maths.Analyzers2;
2+
3+
public readonly struct Result
4+
{
5+
private readonly ResultKind kind;
6+
7+
private Result(ResultKind kind, IExpression? value)
8+
{
9+
this.kind = kind;
10+
Value = value;
11+
}
12+
13+
public static Result NotHandled()
14+
=> new Result(ResultKind.NotHandled, default);
15+
16+
public static Result Handled(IExpression value)
17+
=> new Result(ResultKind.Handled, value);
18+
19+
public static Result Continue(IExpression value)
20+
=> new Result(ResultKind.Continue, value);
21+
22+
public static Result ReAnalyze(IExpression value)
23+
=> new Result(ResultKind.ReAnalyze, value);
24+
25+
private bool IsKind(ResultKind kind)
26+
=> this.kind == kind;
27+
28+
public bool IsNotHandled()
29+
=> IsKind(ResultKind.NotHandled);
30+
31+
public bool IsHandled()
32+
=> IsKind(ResultKind.Handled);
33+
34+
public bool IsContinue()
35+
=> IsKind(ResultKind.Continue);
36+
37+
public bool IsReAnalyze()
38+
=> IsKind(ResultKind.ReAnalyze);
39+
40+
public IExpression? Value { get; }
41+
}
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: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
34+
public abstract string Description { get; }
35+
}

0 commit comments

Comments
 (0)