mirror of
https://github.com/PetroProtsyk/SSharp
synced 2026-06-08 12:11:10 +00:00
209 lines
7.0 KiB
C#
209 lines
7.0 KiB
C#
/*
|
|
* Copyright © 2011, Petro Protsyk, Denys Vuika
|
|
*
|
|
* 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.Generic;
|
|
|
|
namespace Scripting.SSharp
|
|
{
|
|
public static class DynamicMath
|
|
{
|
|
static Dictionary<Type, Dictionary<Type, Func<dynamic, dynamic, Tuple<dynamic, dynamic>>>> converters = new Dictionary<Type, Dictionary<Type, Func<dynamic, dynamic, Tuple<dynamic, dynamic>>>>();
|
|
|
|
public static void AddConverter<TLeft, TRight>(Func<dynamic, dynamic, Tuple<dynamic, dynamic>> function)
|
|
{
|
|
Type leftType = typeof(TLeft);
|
|
Dictionary<Type, Func<dynamic, dynamic, Tuple<dynamic, dynamic>>> funcs = null;
|
|
if (!converters.TryGetValue(leftType, out funcs))
|
|
{
|
|
funcs = new Dictionary<Type, Func<dynamic, dynamic, Tuple<dynamic, dynamic>>>();
|
|
converters[leftType] = funcs;
|
|
}
|
|
|
|
funcs[typeof(TRight)] = function;
|
|
}
|
|
|
|
public static Tuple<dynamic, dynamic> TryConvert(dynamic left, dynamic right)
|
|
{
|
|
// Denys Vuika: the code below crash for mono 2.8 though should work fine,
|
|
// slightly rewriting to make the code mono-compatible
|
|
/*
|
|
Dictionary<Type, Func<dynamic, dynamic, Tuple<dynamic, dynamic>>> funcs = null;
|
|
if (converters.TryGetValue(left.GetType(), out funcs))
|
|
{
|
|
Func<dynamic, dynamic, Tuple<dynamic, dynamic>> function = null;
|
|
if (funcs.TryGetValue(right.GetType(), out function))
|
|
return function(left, right);
|
|
}
|
|
*/
|
|
|
|
Type leftType = left.GetType();
|
|
if (converters.ContainsKey(leftType))
|
|
{
|
|
var funcs = converters[leftType];
|
|
Type rightType = right.GetType();
|
|
|
|
if (funcs.ContainsKey(rightType))
|
|
return funcs[rightType](left, right);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static DynamicMath()
|
|
{
|
|
AddConverter<decimal, double>((left, right) => new Tuple<dynamic, dynamic>((double)left, right));
|
|
AddConverter<double, decimal>((left, right) => new Tuple<dynamic, dynamic>(left, (double)right));
|
|
|
|
AddConverter<decimal, float>((left, right) => new Tuple<dynamic, dynamic>((float)left, right));
|
|
AddConverter<float, decimal>((left, right) => new Tuple<dynamic, dynamic>(left, (float)right));
|
|
|
|
Func<dynamic, dynamic, Tuple<dynamic, dynamic>> rightToString = (left, right) => new Tuple<dynamic, dynamic>(left, right.ToString());
|
|
Func<dynamic, dynamic, Tuple<dynamic, dynamic>> leftToString = (left, right) => new Tuple<dynamic, dynamic>(left.ToString(), right);
|
|
|
|
AddConverter<string, Int16>(rightToString);
|
|
AddConverter<string, Int32>(rightToString);
|
|
AddConverter<string, Int64>(rightToString);
|
|
AddConverter<string, float>(rightToString);
|
|
AddConverter<string, decimal>(rightToString);
|
|
AddConverter<string, double>(rightToString);
|
|
|
|
AddConverter<Int16, string>(leftToString);
|
|
AddConverter<Int32, string>(leftToString);
|
|
AddConverter<Int64, string>(leftToString);
|
|
AddConverter<float, string>(leftToString);
|
|
AddConverter<decimal, string>(leftToString);
|
|
AddConverter<double, string>(leftToString);
|
|
|
|
AddConverter<string, char>(rightToString);
|
|
AddConverter<char, string>(leftToString);
|
|
}
|
|
|
|
public static bool Eq(dynamic left, dynamic right)
|
|
{
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null)
|
|
return ((converted.Item1 == converted.Item2) || (((converted.Item1 != null) && (converted.Item2 != null)) && converted.Item1.Equals(converted.Item2)));
|
|
|
|
return ((left == right) || (((left != null) && (right != null)) && left.Equals(right)));
|
|
}
|
|
|
|
public static dynamic Add(dynamic left, dynamic right)
|
|
{
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 + converted.Item2;
|
|
|
|
return (left + right);
|
|
}
|
|
|
|
public static dynamic Subtract(dynamic left, dynamic right)
|
|
{
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 - converted.Item2;
|
|
|
|
return (left - right);
|
|
}
|
|
|
|
public static dynamic Multiply(dynamic left, dynamic right)
|
|
{
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 * converted.Item2;
|
|
|
|
return left * right;
|
|
}
|
|
|
|
public static bool Less(dynamic left, dynamic right)
|
|
{
|
|
if (left is string && right is string)
|
|
return string.Compare(left, right) < 0;
|
|
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 < converted.Item2;
|
|
|
|
return left < right;
|
|
}
|
|
|
|
public static bool LessOrEquals(dynamic left, dynamic right)
|
|
{
|
|
if (left is string && right is string)
|
|
return string.Compare(left, right) <= 0;
|
|
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 <= converted.Item2;
|
|
|
|
return left <= right;
|
|
}
|
|
|
|
public static bool Greater(dynamic left, dynamic right)
|
|
{
|
|
if (left is string && right is string)
|
|
return string.Compare(left, right) > 0;
|
|
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 > converted.Item2;
|
|
|
|
return left > right;
|
|
}
|
|
|
|
public static bool GreaterOrEquals(dynamic left, dynamic right)
|
|
{
|
|
if (left is string && right is string)
|
|
return string.Compare(left, right) >= 0;
|
|
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 >= converted.Item2;
|
|
|
|
return left >= right;
|
|
}
|
|
|
|
public static dynamic Mod(dynamic left, dynamic right)
|
|
{
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 % converted.Item2;
|
|
|
|
return left % right;
|
|
}
|
|
|
|
public static dynamic Div(dynamic left, dynamic right)
|
|
{
|
|
Tuple<dynamic, dynamic> converted = TryConvert(left, right);
|
|
if (converted != null) return converted.Item1 / converted.Item2;
|
|
|
|
return left / right;
|
|
}
|
|
|
|
public static bool And(dynamic left, dynamic right)
|
|
{
|
|
return left & right;
|
|
}
|
|
|
|
public static bool ConditionalAnd(dynamic left, dynamic right)
|
|
{
|
|
return left && right;
|
|
}
|
|
|
|
public static bool Or(dynamic left, dynamic right)
|
|
{
|
|
return left | right;
|
|
}
|
|
|
|
public static bool ConditionalOr(dynamic left, dynamic right)
|
|
{
|
|
return left || right;
|
|
}
|
|
}
|
|
}
|