Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Bykiev committed May 28, 2024
2 parents 1fa54c6 + e6c8c5f commit 53f44f0
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 136 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# 4.2
* [Improve Parlot error handling](https://github.com/ncalc/ncalc/pull/181) by [Andrey Bykiev](https://github.com/Bykiev)

## Breaking Changes
* [Do not convert external function name to lower case when ExpressionOptions.IgnoreCase option is used](https://github.com/ncalc/ncalc/pull/179) by [Andrey Bykiev](https://github.com/Bykiev)
* [Add support for using null with operators](https://github.com/ncalc/ncalc/pull/184) by [Andrey Bykiev](https://github.com/Bykiev)
* [Exceptions need to be handled as NCalcEvaluationException instead of ArgumentException and added TypeHelper](https://github.com/ncalc/ncalc/pull/182) by [Gustavo Barros](https://github.com/gumbarros)
* [Use IOptions instead of IOptionsSnapshot at LogicalExpressionMemoryCache] by [Gustavo Barros](https://github.com/gumbarros)

# 4.1
* [Remove excessive check for casing](https://github.com/ncalc/ncalc/pull/149) by [Andrey Bykiev](https://github.com/Bykiev)
Expand Down
13 changes: 1 addition & 12 deletions src/NCalc/Exceptions/NCalcEvaluationException.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
namespace NCalc.Exceptions;

public sealed class NCalcEvaluationException : NCalcException
{
public NCalcEvaluationException(string message)
: base(message)
{
}

public NCalcEvaluationException(string message, Exception innerException)
: base(message, innerException)
{
}
}
public class NCalcEvaluationException(string message) : NCalcException(message);
7 changes: 7 additions & 0 deletions src/NCalc/Exceptions/NCalcFunctionNotFoundException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace NCalc.Exceptions;

public sealed class NCalcFunctionNotFoundException(string message, string functionName)
: NCalcEvaluationException(message)
{
public string FunctionName { get;} = functionName;
}
7 changes: 7 additions & 0 deletions src/NCalc/Exceptions/NCalcParameterNotDefinedException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace NCalc.Exceptions;

public sealed class NCalcParameterNotDefinedException(string parameterName)
: NCalcEvaluationException($"Parameter {parameterName} not defined.")
{
public string ParameterName { get; } = parameterName;
}
2 changes: 1 addition & 1 deletion src/NCalc/Expression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public bool HasErrors()
}
else if (localsize != size)
{
throw new NCalcEvaluationException("When IterateParameters option is used, IEnumerable parameters must have the same number of items");
throw new NCalcException("When IterateParameters option is used, IEnumerable parameters must have the same number of items");
}
}
}
Expand Down
49 changes: 30 additions & 19 deletions src/NCalc/Helpers/MathHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ public static class MathHelper
return s is string or char ? decimal.Parse(s.ToString()!, cultureInfo) : s;
}

public static object Add(object? a, object? b)
public static object? Add(object? a, object? b)
{
return Add(a, b, CultureInfo.CurrentCulture);
}

public static object Add(object? a, object? b, CultureInfo cultureInfo)
public static object? Add(object? a, object? b, CultureInfo cultureInfo)
{
if (a == null || b == null)
return null;

a = ConvertIfString(a, cultureInfo);
b = ConvertIfString(b, cultureInfo);

switch (a)
{
case bool:
Expand Down Expand Up @@ -217,19 +220,22 @@ public static object Add(object? a, object? b, CultureInfo cultureInfo)
}
}

public static object Subtract(object? a, object? b)
public static object? Subtract(object? a, object? b)
{
return Subtract(a, b, CultureInfo.CurrentCulture);
}

public static object Subtract(object? a, object? b, CultureInfo cultureInfo)
public static object? Subtract(object? a, object? b, CultureInfo cultureInfo)
{
if (a == null || b == null)
return null;

a = ConvertIfString(a, cultureInfo);
b = ConvertIfString(b, cultureInfo);

switch (a)
{
case bool:
case bool:
throw new InvalidOperationException($"Operator '-' can't be applied to operands of types 'bool' and {b?.GetType()}");
case byte b1:
switch (b)
Expand Down Expand Up @@ -423,18 +429,19 @@ public static object Subtract(object? a, object? b, CultureInfo cultureInfo)
}
}

public static object Multiply(object? a, object? b)
public static object? Multiply(object? a, object? b)
{
return Multiply(a, b, CultureInfo.CurrentCulture);
}

public static object Multiply(object? a, object? b, CultureInfo cultureInfo)
public static object? Multiply(object? a, object? b, CultureInfo cultureInfo)
{
if (a == null || b == null)
return null;

a = ConvertIfString(a, cultureInfo);
b = ConvertIfString(b, cultureInfo);



switch (a)
{
case bool:
Expand Down Expand Up @@ -594,7 +601,7 @@ public static object Multiply(object? a, object? b, CultureInfo cultureInfo)
case decimal @decimal: return Convert.ToDecimal(a) * @decimal;
default: throw new InvalidOperationException($"Operator '*' not implemented for operands of types 'float' and {b?.GetType()}");
}

case double d:
switch (b)
{
Expand Down Expand Up @@ -632,14 +639,17 @@ public static object Multiply(object? a, object? b, CultureInfo cultureInfo)
default: throw new InvalidOperationException($"Operator '*' not implemented for operands of types {a} and {b?.GetType()}");
}
}
public static object Divide(object? a, object? b)

public static object? Divide(object? a, object? b)
{
return Divide(a, b, CultureInfo.CurrentCulture);
}

public static object Divide(object? a, object? b, CultureInfo cultureInfo)
public static object? Divide(object? a, object? b, CultureInfo cultureInfo)
{
if (a == null || b == null)
return null;

a = ConvertIfString(a, cultureInfo);
b = ConvertIfString(b, cultureInfo);

Expand Down Expand Up @@ -840,18 +850,19 @@ public static object Divide(object? a, object? b, CultureInfo cultureInfo)
}
}

public static object Modulo(object? a, object? b)
public static object? Modulo(object? a, object? b)
{
return Modulo(a, b, CultureInfo.CurrentCulture);
}

public static object Modulo(object? a, object? b, CultureInfo cultureInfo)
public static object? Modulo(object? a, object? b, CultureInfo cultureInfo)
{
if (a == null || b == null)
return null;

a = ConvertIfString(a, cultureInfo);
b = ConvertIfString(b, cultureInfo);



switch (a)
{
case bool:
Expand Down Expand Up @@ -1072,7 +1083,7 @@ public static object Modulo(object? a, object? b, CultureInfo cultureInfo)
{
return a;
}

switch (a)
{
case byte b1:
Expand Down
60 changes: 60 additions & 0 deletions src/NCalc/Helpers/TypeHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
namespace NCalc.Helpers;

public static class TypeHelper
{
private static readonly Type[] BuiltInTypes =
[
typeof(decimal),
typeof(double),
typeof(float),
typeof(long),
typeof(ulong),
typeof(int),
typeof(uint),
typeof(short),
typeof(ushort),
typeof(byte),
typeof(sbyte),
typeof(char),
typeof(bool),
typeof(string),
typeof(object)
];

/// <summary>
/// Gets the the most precise type.
/// </summary>
/// <param name="a">Type a.</param>
/// <param name="b">Type b.</param>
/// <returns></returns>
private static Type GetMostPreciseType(Type? a, Type? b)
{
foreach (var t in BuiltInTypes)
{
if (a == t || b == t)
{
return t;
}
}

return a ?? typeof(object);
}

public static bool IsReal(object? value) => value is decimal or double or float;

public record struct ComparasionOptions(CultureInfo CultureInfo, bool IsCaseSensitive);
public static int CompareUsingMostPreciseType(object? a, object? b, ComparasionOptions options)
{
var (cultureInfo, isCaseInsensitiveComparer) = options;

var mpt = GetMostPreciseType(a?.GetType(), b?.GetType());

var aValue = a != null ? Convert.ChangeType(a, mpt, cultureInfo) : null;
var bValue = b != null ? Convert.ChangeType(b, mpt, cultureInfo) : null;

if (isCaseInsensitiveComparer)
return CaseInsensitiveComparer.Default.Compare(aValue, bValue);

return Comparer.Default.Compare(aValue, bValue);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public interface ILogicalExpressionVisitor
public void Visit(UnaryExpression expression);
public void Visit(ValueExpression expression);
public void Visit(Function function);
public void Visit(Identifier function);
public void Visit(Identifier identifier);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ public abstract class LogicalExpressionVisitor : ILogicalExpressionVisitor
public abstract void Visit(UnaryExpression expression);
public abstract void Visit(ValueExpression expression);
public abstract void Visit(Function function);
public abstract void Visit(Identifier function);
public abstract void Visit(Identifier identifier);
}
Loading

0 comments on commit 53f44f0

Please sign in to comment.