Code/Core/Contexts/ExecutionContext/ExecutionContext.Impls.cs
namespace Nodebox;
public partial class ExecutionContext {
public HashSet<Type> GenericArguments { get; set; } = [];
protected virtual HashSet<Type> GenerateAvailableTypes() {
return [.. TypeLibrary.IntrinsicTypes.Where(x => !x.IsGenericType)];
}
public abstract class Implementation {
public abstract Type Target { get; }
public virtual bool IsValid => Node.GetAreValidGenerics(Target);
public abstract void Evaluate(ExecutionContext context, Node node);
}
public Dictionary<Type, Implementation> Implementations { get; set; } = [];
protected virtual Dictionary<Type, Implementation> GenerateImplementations() {
var implementations = new Dictionary<Type, Implementation>();
var availableTypes = GenericArguments.ToList();
foreach (var implementationType in TypeLibrary.GetTypes<Implementation>()) {
if (implementationType.TargetType == typeof(Implementation)) { continue; }
if (!implementationType.IsGenericType) {
var implementation = implementationType.Create<Implementation>([]);
implementations.Add(implementation.Target, implementation);
continue;
}
var genericArgumentsCount = implementationType.GenericArguments.Length;
var permuteSource = new List<Type>[genericArgumentsCount];
foreach (var i in Enumerable.Range(0, genericArgumentsCount)) {
permuteSource[i] = availableTypes;
}
foreach (var typeArgs in Permutations.Calculate(permuteSource)) {
try {
implementationType.MakeGenericType(typeArgs);
}
catch (Exception) {
continue;
}
var implementation = implementationType.CreateGeneric<Implementation>(typeArgs, []);
if (implementation == null || !implementation.IsValid) {
continue;
}
implementations.Add(implementation.Target, implementation);
}
}
return implementations;
}
public class MissingImplementationException(Node node) : Exception($"Missing evaluation implementation for {DisplayInfo.ForGenericType(node.GetType()).Name}") {
public Node Node { get; set; } = node;
}
}