AspectedRouting/AspectedRouting/Language/Funcs.cs
2020-05-02 13:09:49 +02:00

133 lines
No EOL
4.2 KiB
C#

using System.Collections.Generic;
using System.Linq;
using AspectedRouting.Language.Expression;
using AspectedRouting.Language.Functions;
using AspectedRouting.Language.Typ;
using Type = AspectedRouting.Language.Typ.Type;
// ReSharper disable UnusedMember.Global
namespace AspectedRouting.Language
{
public static class Funcs
{
public static readonly Dictionary<string, Function> Builtins = new Dictionary<string, Function>();
public static IEnumerable<string> BuiltinNames = Builtins.Keys;
public static readonly Function Eq = new Eq();
public static readonly Function NotEq = new NotEq();
public static readonly Function Inv = new Inv();
public static readonly Function Default = new Default();
public static readonly Function Parse = new Parse();
public static readonly Function ToStringFunc = new ToString();
public static readonly Function Concat = new Concat();
public static readonly Function ContainedIn = new ContainedIn();
public static readonly Function Min = new Min();
public static readonly Function Max = new Max();
public static readonly Function Sum = new Sum();
public static readonly Function Multiply = new Multiply();
public static readonly Function FirstOf = new FirstMatchOf();
public static readonly Function MustMatch = new MustMatch();
public static readonly Function MemberOf = new MemberOf();
public static readonly Function If = new If();
public static readonly Function Id = new Id();
public static readonly Function Const = new Const();
public static readonly Function ConstRight = new ConstRight();
public static readonly Function Dot = new Dot();
public static readonly Function ListDot = new ListDot();
public static readonly Function EitherFunc = new EitherFunc();
public static readonly Function StringStringToTags = new StringStringToTagsFunction();
public static void AddBuiltin(Function f, string name = null)
{
Builtins.Add(name ?? f.Name, f);
}
public static IExpression Either(IExpression a, IExpression b, IExpression arg)
{
return new Apply(new Apply(new Apply(EitherFunc, a), b), arg);
}
public static Function BuiltinByName(string funcName)
{
if (funcName.StartsWith("$"))
{
funcName = funcName.Substring(1);
}
if (Builtins.TryGetValue(funcName, out var f)) return f;
return null;
}
public static IExpression Finalize(this IExpression e)
{
if (e == null)
{
return null;
}
e = e.SpecializeToSmallestType().Optimize();
e.SanityCheck();
return e;
}
public static IExpression SpecializeToSmallestType(this IExpression e)
{
Type smallest = null;
foreach (var t in e.Types)
{
if (smallest == null)
{
smallest = t;
continue;
}
var smallestIsSuperset = smallest.IsSuperSet(t);
if (!t.IsSuperSet(smallest) && !smallestIsSuperset)
{
return e;
}
if (smallestIsSuperset)
{
smallest = t;
}
}
return e.Specialize(new[] {smallest});
}
public static IExpression Apply(this IExpression function, IEnumerable<IExpression> args)
{
return function.Apply(args.ToList());
}
public static IExpression Apply(this IExpression function, List<IExpression> args)
{
if (args.Count == 0)
{
return function;
}
if (args.Count == 1)
{
return new Apply(function, args[0]);
}
var lastArg = args[args.Count - 1];
var firstArgs = args.GetRange(0, args.Count - 1);
return new Apply(Apply(function, firstArgs), lastArg);
}
}
}