Skip to content

Commit

Permalink
#308 - Add Convert function
Browse files Browse the repository at this point in the history
  • Loading branch information
sys27 committed Oct 14, 2021
1 parent a7e5b7b commit 104d81e
Show file tree
Hide file tree
Showing 25 changed files with 741 additions and 15 deletions.
13 changes: 10 additions & 3 deletions xFunc.DotnetTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using xFunc.Maths.Analyzers.TypeAnalyzers;
using xFunc.Maths.Expressions;
using xFunc.Maths.Expressions.Collections;
using xFunc.Maths.Expressions.Units;

namespace xFunc.DotnetTool
{
Expand Down Expand Up @@ -138,6 +139,14 @@ private static void Run(DebugInfoOptions options, Action action)
{
PrintError(options, nse);
}
catch (ValueIsNotSupportedException vinse)
{
PrintError(options, vinse);
}
catch (UnitIsNotSupportedException uinse)
{
PrintError(options, uinse);
}
}

private static void PrintError(DebugInfoOptions options, Exception e)
Expand All @@ -149,12 +158,10 @@ private static void PrintError(DebugInfoOptions options, Exception e)
}

public static void Main(string[] args)
{
CommandLine.Parser.Default
=> CommandLine.Parser.Default
.ParseArguments<ParseOptions, SolveOptions, InteractiveOptions>(args)
.WithParsed<ParseOptions>(Parse)
.WithParsed<SolveOptions>(Solve)
.WithParsed<InteractiveOptions>(Interactive);
}
}
}
4 changes: 4 additions & 0 deletions xFunc.Maths/Analyzers/Analyzer{TResult,TContext}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ public virtual TResult Analyze(ToHex exp, TContext context)
public virtual TResult Analyze(StringExpression exp, TContext context)
=> Analyze(exp as IExpression, context);

/// <inheritdoc />
public virtual TResult Analyze(Expressions.Units.Convert exp, TContext context)
=> Analyze(exp as IExpression, context);

#endregion Standard

#region Matrix
Expand Down
4 changes: 4 additions & 0 deletions xFunc.Maths/Analyzers/Analyzer{TResult}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ public virtual TResult Analyze(ToHex exp)
public virtual TResult Analyze(StringExpression exp)
=> Analyze(exp as IExpression);

/// <inheritdoc />
public virtual TResult Analyze(Expressions.Units.Convert exp)
=> Analyze(exp as IExpression);

#endregion Standard

#region Matrix
Expand Down
9 changes: 9 additions & 0 deletions xFunc.Maths/Analyzers/Formatters/CommonFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,15 @@ public virtual string Analyze(ToHex exp)
public virtual string Analyze(StringExpression exp)
=> $"'{exp.Value}'";

/// <inheritdoc />
public virtual string Analyze(Convert exp)
{
var value = exp.Value.Analyze(this);
var unit = exp.Unit.Analyze(this);

return $"convert({value}, {unit})";
}

#endregion Standard

#region Matrix
Expand Down
8 changes: 8 additions & 0 deletions xFunc.Maths/Analyzers/IAnalyzer{TResult,TContext}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,14 @@ public interface IAnalyzer<out TResult, TContext>
/// <returns>The result of analysis.</returns>
TResult Analyze(StringExpression exp, TContext context);

/// <summary>
/// Analyzes the specified expression.
/// </summary>
/// <param name="exp">The expression.</param>
/// <param name="context">The context.</param>
/// <returns>The result of analysis.</returns>
TResult Analyze(Convert exp, TContext context);

#endregion Standard

#region Matrix
Expand Down
7 changes: 7 additions & 0 deletions xFunc.Maths/Analyzers/IAnalyzer{TResult}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,13 @@ public interface IAnalyzer<out TResult>
/// <returns>The result of analysis.</returns>
TResult Analyze(StringExpression exp);

/// <summary>
/// Analyzes the specified expression.
/// </summary>
/// <param name="exp">The expression.</param>
/// <returns>The result of analysis.</returns>
TResult Analyze(Convert exp);

#endregion Standard

#region Matrix
Expand Down
5 changes: 5 additions & 0 deletions xFunc.Maths/Analyzers/TypeAnalyzers/ResultTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,10 @@ public enum ResultTypes
/// The expression returns a number or a vector or a matrix.
/// </summary>
NumberOrVectorOrMatrix = Number | Vector | Matrix,

/// <summary>
/// The expression returns any type of number.
/// </summary>
Numbers = Number | AngleNumber | PowerNumber,
}
}
18 changes: 18 additions & 0 deletions xFunc.Maths/Analyzers/TypeAnalyzers/TypeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,24 @@ public virtual ResultTypes Analyze(ToHex exp)
public virtual ResultTypes Analyze(StringExpression exp)
=> CheckArgument(exp, ResultTypes.String);

/// <inheritdoc />
public virtual ResultTypes Analyze(Convert exp)
{
if (exp is null)
ArgNull(ExceptionArgument.exp);

var valueResult = exp.Value.Analyze(this);

return valueResult switch
{
ResultTypes.Number => ResultTypes.Undefined,
ResultTypes.AngleNumber => ResultTypes.AngleNumber,
ResultTypes.PowerNumber => ResultTypes.PowerNumber,

_ => ResultTypes.Numbers.ThrowFor(valueResult),
};
}

#endregion Standard

#region Matrix
Expand Down
4 changes: 2 additions & 2 deletions xFunc.Maths/Expressions/BinaryExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ public override bool Equals(object? obj)
if (obj is null || GetType() != obj.GetType())
return false;

var exp = (BinaryExpression)obj;
var (left, right) = (BinaryExpression)obj;

return Left.Equals(exp.Left) && Right.Equals(exp.Right);
return Left.Equals(left) && Right.Equals(right);
}

/// <inheritdoc />
Expand Down
152 changes: 152 additions & 0 deletions xFunc.Maths/Expressions/Units/Convert.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Copyright 2012-2021 Dmytro Kyshchenko
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Immutable;
using xFunc.Maths.Analyzers;
using xFunc.Maths.Analyzers.Formatters;
using xFunc.Maths.Resources;

namespace xFunc.Maths.Expressions.Units
{
/// <summary>
/// Represents the convert function.
/// </summary>
public class Convert : IExpression
{
private readonly IConverter converter;

/// <summary>
/// Initializes a new instance of the <see cref="Convert"/> class.
/// </summary>
/// <param name="converter">The converter.</param>
/// <param name="value">The value to convert.</param>
/// <param name="unit">The target unit.</param>
public Convert(IConverter converter, IExpression value, StringExpression unit)
: this(converter, ImmutableArray.Create(value, unit))
{
}

/// <summary>
/// Initializes a new instance of the <see cref="Convert"/> class.
/// </summary>
/// <param name="converter">The converter.</param>
/// <param name="arguments">The list of arguments.</param>
internal Convert(IConverter converter, ImmutableArray<IExpression> arguments)
{
this.converter = converter ?? throw new ArgumentNullException(nameof(converter));

if (arguments == null)
throw new ArgumentNullException(nameof(arguments));

if (arguments.Length < 2)
throw new ParseException(Resource.LessParams);

if (arguments.Length > 2)
throw new ParseException(Resource.MoreParams);

Value = arguments[0];
Unit = (StringExpression)arguments[1];
}

/// <summary>
/// Deconstructs <see cref="Convert"/>.
/// </summary>
/// <param name="value">The value to convert.</param>
/// <param name="unit">The target unit.</param>
public void Deconstruct(out IExpression value, out StringExpression unit)
{
value = Value;
unit = Unit;
}

/// <inheritdoc />
public override bool Equals(object? obj)
{
if (ReferenceEquals(this, obj))
return true;

if (obj is null || GetType() != obj.GetType())
return false;

var (value, unit) = (Convert)obj;

return Value.Equals(value) && Unit.Equals(unit);
}

/// <inheritdoc />
public string ToString(IFormatter formatter) => Analyze(formatter);

/// <inheritdoc />
public override string ToString() => ToString(new CommonFormatter());

/// <inheritdoc />
public object Execute() => Execute(null);

/// <inheritdoc />
public object Execute(ExpressionParameters? parameters)
{
var valueResult = Value.Execute(parameters);
var unitResult = Unit.Execute(parameters);

return unitResult switch
{
string unit => converter.Convert(valueResult, unit),
_ => throw new ResultIsNotSupportedException(this, valueResult, unitResult),
};
}

/// <inheritdoc />
public TResult Analyze<TResult>(IAnalyzer<TResult> analyzer)
{
if (analyzer is null)
throw new ArgumentNullException(nameof(analyzer));

return analyzer.Analyze(this); // TODO:
}

/// <inheritdoc />
public TResult Analyze<TResult, TContext>(
IAnalyzer<TResult, TContext> analyzer,
TContext context)
{
if (analyzer is null)
throw new ArgumentNullException(nameof(analyzer));

return analyzer.Analyze(this, context); // TODO:
}

/// <summary>
/// Clones this instance of the <see cref="IExpression" />.
/// </summary>
/// <param name="left">The left argument of new expression.</param>
/// <param name="right">The right argument of new expression.</param>
/// <returns>
/// Returns the new instance of <see cref="IExpression" /> that is a clone of this instance.
/// </returns>
public IExpression Clone(IExpression? left = null, StringExpression? right = null)
=> new Convert(converter, left ?? Value, right ?? Unit);

/// <summary>
/// Gets the value.
/// </summary>
public IExpression Value { get; }

/// <summary>
/// Gets the target unit.
/// </summary>
public StringExpression Unit { get; }
}
}
80 changes: 80 additions & 0 deletions xFunc.Maths/Expressions/Units/Converter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2012-2021 Dmytro Kyshchenko
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using xFunc.Maths.Expressions.Units.AngleUnits;
using xFunc.Maths.Expressions.Units.PowerUnits;

namespace xFunc.Maths.Expressions.Units
{
/// <summary>
/// The unit converter.
/// </summary>
public class Converter : IConverter
{
/// <inheritdoc />
public object Convert(object value, string unit)
{
if (value is null)
throw new ArgumentNullException(nameof(value));
if (string.IsNullOrWhiteSpace(unit))
throw new ArgumentNullException(nameof(unit));

unit = unit.ToLower();

var result = value switch
{
NumberValue numberValue => Convert(numberValue, unit),
AngleValue angleValue => Convert(angleValue, unit),
PowerValue powerValue => Convert(powerValue, unit),
_ => throw new ValueIsNotSupportedException(value), // TODO: include in UI
};

return result;
}

private object Convert(NumberValue value, string unit)
=> unit switch
{
"rad" or "radian" or "radians" => AngleValue.Radian(value),
"deg" or "degree" or "degrees" => AngleValue.Degree(value),
"grad" or "gradian" or "gradians" => AngleValue.Gradian(value),

"w" => PowerValue.Watt(value),
"kw" => PowerValue.Kilowatt(value),
"hp" => PowerValue.Horsepower(value),

_ => throw new UnitIsNotSupportedException(unit), // TODO: include in UI
};

private AngleValue Convert(AngleValue value, string unit)
=> unit switch
{
"rad" or "radian" or "radians" => value.ToRadian(),
"deg" or "degree" or "degrees" => value.ToDegree(),
"grad" or "gradian" or "gradians" => value.ToGradian(),
_ => throw new UnitIsNotSupportedException(unit),
};

private PowerValue Convert(PowerValue value, string unit)
=> unit switch
{
"w" => value.ToWatt(),
"kw" => value.ToKilowatt(),
"hp" => value.ToHorsepower(),
_ => throw new UnitIsNotSupportedException(unit),
};
}
}

0 comments on commit 104d81e

Please sign in to comment.