Refactor of Default RateRules

This commit is contained in:
nicolas.dorier 2024-05-10 08:55:53 +09:00
parent adbe5977cd
commit 84df96429c
No known key found for this signature in database
GPG Key ID: 6618763EF09186FE
3 changed files with 45 additions and 44 deletions

View File

@ -1,7 +1,10 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@ -29,7 +32,7 @@ namespace BTCPayServer.Rating
public List<RateRulesErrors> Errors = new List<RateRulesErrors>();
bool IsInvocation;
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
public override SyntaxNode? VisitInvocationExpression(InvocationExpressionSyntax node)
{
if (IsInvocation)
{
@ -50,7 +53,7 @@ namespace BTCPayServer.Rating
return node;
}
}
public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
public override SyntaxNode? VisitIdentifierName(IdentifierNameSyntax node)
{
if (CurrencyPair.TryParse(node.Identifier.ValueText, out var currencyPair))
{
@ -122,11 +125,17 @@ namespace BTCPayServer.Rating
// Remove every irrelevant statements
this.root = ruleList.GetSyntaxNode();
}
public static bool TryParse(string str, out RateRules rules)
public static bool TryParse(string str, [MaybeNullWhen(false)] out RateRules rules)
{
return TryParse(str, out rules, out var unused);
}
public static bool TryParse(string str, out RateRules rules, out List<RateRulesErrors> errors)
public static RateRules Parse(string str)
{
if (TryParse(str, out var rules, out var err))
return rules;
throw new FormatException(String.Join(", ", err));
}
public static bool TryParse(string str, [MaybeNullWhen(false)] out RateRules rules, [MaybeNullWhen(true)] out List<RateRulesErrors> errors)
{
str = ImplicitSatsRule + str;
rules = null;
@ -194,6 +203,12 @@ namespace BTCPayServer.Rating
return (ExpressionSyntax)CSharpSyntaxTree.ParseText(str, new CSharpParseOptions(LanguageVersion.Default).WithKind(SourceCodeKind.Script)).GetRoot().ChildNodes().First().ChildNodes().First().ChildNodes().First();
}
public static RateRules Combine(RateRules[] rateRules)
{
var str = string.Join(Environment.NewLine, rateRules.Select(r => r.ToString()));
return Parse(str);
}
public override string ToString()
{
return root.NormalizeWhitespace("", "\n")
@ -209,8 +224,8 @@ namespace BTCPayServer.Rating
class ReplaceExchangeRateRewriter : CSharpSyntaxRewriter
{
public List<RateRulesErrors> Errors = new List<RateRulesErrors>();
public ExchangeRates Rates;
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
public ExchangeRates? Rates;
public override SyntaxNode? VisitInvocationExpression(InvocationExpressionSyntax node)
{
var exchangeName = node.Expression.ToString();
if (exchangeName.StartsWith("ERR_", StringComparison.OrdinalIgnoreCase))
@ -227,7 +242,7 @@ namespace BTCPayServer.Rating
}
else
{
var rate = Rates.GetRate(exchangeName, pair);
var rate = Rates?.GetRate(exchangeName, pair);
if (rate == null)
{
Errors.Add(RateRulesErrors.RateUnavailable);
@ -349,7 +364,7 @@ namespace BTCPayServer.Rating
}
}
Stack<decimal> _TupleValues = null;
Stack<decimal>? _TupleValues = null;
public override void VisitTupleExpression(TupleExpressionSyntax node)
{
_TupleValues = new Stack<decimal>();
@ -412,7 +427,7 @@ namespace BTCPayServer.Rating
public ExchangeRates ExchangeRates = new ExchangeRates();
bool IsInvocation;
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
public override SyntaxNode? VisitInvocationExpression(InvocationExpressionSyntax node)
{
if (IsInvocation)
{
@ -427,7 +442,7 @@ namespace BTCPayServer.Rating
}
bool IsArgumentList;
public override SyntaxNode VisitArgumentList(ArgumentListSyntax node)
public override SyntaxNode? VisitArgumentList(ArgumentListSyntax node)
{
IsArgumentList = true;
var result = base.VisitArgumentList(node);
@ -435,11 +450,11 @@ namespace BTCPayServer.Rating
return result;
}
string _ExchangeName = null;
string? _ExchangeName = null;
public List<RateRulesErrors> Errors = new List<RateRulesErrors>();
const int MaxNestedCount = 8;
public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
public override SyntaxNode? VisitIdentifierName(IdentifierNameSyntax node)
{
if (
(!IsInvocation || IsArgumentList) &&
@ -497,7 +512,7 @@ namespace BTCPayServer.Rating
public static RateRule CreateFromExpression(string expression, CurrencyPair currencyPair)
{
var ex = RateRules.CreateExpression(expression);
RateRules.TryParse("", out var rules);
var rules = RateRules.Parse("");
return new RateRule(rules, currencyPair, ex);
}
public RateRule(RateRules parent, CurrencyPair currencyPair, SyntaxNode candidate)
@ -528,7 +543,7 @@ namespace BTCPayServer.Rating
public bool Reevaluate()
{
_BidAsk = null;
BidAsk = null;
_EvaluatedNode = null;
_Evaluated = null;
Errors.Clear();
@ -554,7 +569,7 @@ namespace BTCPayServer.Rating
}
return false;
}
_BidAsk = calculate.Values.Pop();
BidAsk = calculate.Values.Pop();
_EvaluatedNode = result;
return true;
}
@ -569,8 +584,8 @@ namespace BTCPayServer.Rating
}
}
SyntaxNode _EvaluatedNode;
string _Evaluated;
SyntaxNode? _EvaluatedNode;
string? _Evaluated;
public bool HasError
{
get
@ -592,14 +607,6 @@ namespace BTCPayServer.Rating
{
return expression.NormalizeWhitespace("", "\n").ToString();
}
BidAsk _BidAsk;
public BidAsk BidAsk
{
get
{
return _BidAsk;
}
}
public BidAsk? BidAsk { get; private set; }
}
}

View File

@ -158,24 +158,9 @@ namespace BTCPayServer.Data
public RateRules GetDefaultRateRules(IEnumerable<DefaultRates> defaultRates)
{
var builder = new StringBuilder();
foreach (var rates in defaultRates)
{
if (rates.Rates is { Length: > 0 } r)
{
foreach (var line in r)
{
builder.AppendLine(line);
}
builder.AppendLine("////////");
builder.AppendLine();
}
}
var preferredExchange = string.IsNullOrEmpty(PreferredExchange) ? GetRecommendedExchange() : PreferredExchange;
builder.AppendLine(CultureInfo.InvariantCulture, $"X_X = {preferredExchange}(X_X);");
RateRules.TryParse(builder.ToString(), out var rules);
var preferredExchangeRule = RateRules.Parse($"X_X = {preferredExchange}(X_X);");
var rules = RateRules.Combine(defaultRates.Select(r => r.Rules).Concat([preferredExchangeRule]).ToArray());
rules.Spread = Spread;
return rules;
}

View File

@ -1,2 +1,11 @@
using System;
using System.Linq;
using BTCPayServer.Rating;
namespace BTCPayServer;
public record DefaultRates(string[] Rates);
public record DefaultRates(RateRules Rules)
{
public DefaultRates(string[] Rules) : this(RateRules.Combine(Rules.Select(r => RateRules.Parse(r)).ToArray()))
{
}
}