namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using System; using System.Collections.Generic; using System.Linq; using HeuristicLab.Problems.ProgramSynthesis.Push.Attributes; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; public static class ExpressionTable { public static readonly IDictionary StatelessExpressionTable; public static readonly IDictionary> StatefullExpressionFactory; public static readonly IDictionary> StackTypeToNamesTable = new Dictionary>(); public static readonly IDictionary IndexToNameTable = new Dictionary(); public static readonly IDictionary TypeToNameTable = new Dictionary(); public static readonly string[] ExpressionNames; public static readonly int Count; static ExpressionTable() { StatelessExpressionTable = GetStatelessExpressionTable(); StatefullExpressionFactory = GetStatefullExpressionFactory(); ExpressionNames = StatelessExpressionTable.Keys.Concat(StatefullExpressionFactory.Keys).ToArray(); Count = StatelessExpressionTable.Count + StatefullExpressionFactory.Count; } public static int StatelessCount { get { return StatelessExpressionTable.Count; } } public static int StatefullCount { get { return StatefullExpressionFactory.Count; } } private static Dictionary GetStatelessExpressionTable() { var dictionary = new Dictionary(); var expressionTypes = GetExpressionTypes(typeof(StatelessExpression)); foreach (var type in expressionTypes) { var expression = Activator.CreateInstance(type) as Expression; var attribute = (PushExpressionAttribute)Attribute.GetCustomAttribute(type, typeof(PushExpressionAttribute)); dictionary.Add(attribute.ExpressionName, expression); IndexToNameTable.Add(IndexToNameTable.Keys.Count, attribute.ExpressionName); TypeToNameTable.Add(type, attribute.ExpressionName); if (!StackTypeToNamesTable.ContainsKey(attribute.StackType)) { StackTypeToNamesTable.Add(attribute.StackType, new List()); } StackTypeToNamesTable[attribute.StackType].Add(attribute.ExpressionName); } return dictionary; } private static Dictionary> GetStatefullExpressionFactory() { var dictionary = new Dictionary>(); var statefullExpressionType = typeof(StatefullExpression<>); var expressionTypes = GetExpressionTypes(statefullExpressionType); foreach (var type in expressionTypes) { // Make a NewExpression that calls the ctor var newExp = System.Linq.Expressions.Expression.New(type); // Create a lambda with the New expression as body var creator = System.Linq.Expressions.Expression.Lambda>(newExp).Compile(); var attribute = (PushExpressionAttribute)Attribute.GetCustomAttribute(type, typeof(PushExpressionAttribute)); dictionary.Add(attribute.ExpressionName, creator); IndexToNameTable.Add(IndexToNameTable.Keys.Count, attribute.ExpressionName); TypeToNameTable.Add(type, attribute.ExpressionName); if (!StackTypeToNamesTable.ContainsKey(attribute.StackType)) { StackTypeToNamesTable.Add(attribute.StackType, new List()); } StackTypeToNamesTable[attribute.StackType].Add(attribute.ExpressionName); } return dictionary; } private static bool IsSubclassOf(Type type, Type baseType) { if (type == null || baseType == null || type == baseType) return false; if (baseType.IsGenericType == false) { if (type.IsGenericType == false) return type.IsSubclassOf(baseType); } else { baseType = baseType.GetGenericTypeDefinition(); } type = type.BaseType; var objectType = typeof(object); while (type != objectType && type != null) { var curentType = type.IsGenericType ? type.GetGenericTypeDefinition() : type; if (curentType == baseType) return true; type = type.BaseType; } return false; } private static IEnumerable GetExpressionTypes(Type baseType) { return from domainAssembly in AppDomain.CurrentDomain.GetAssemblies() from assemblyType in domainAssembly.GetTypes() where !assemblyType.IsAbstract && IsSubclassOf(assemblyType, baseType) && assemblyType.GetConstructor(Type.EmptyTypes) != null select assemblyType; } public static ExecExpandExpression GetProgram(int[] index) { var expressions = new List(index.Length); for (var i = 0; i < index.Length; i++) { expressions.Add(GetExpression(index[i])); } return new ExecExpandExpression(expressions); } public static Expression GetExpression(int index) { return GetExpression(IndexToNameTable[index]); } public static Expression GetExpression(string name) { Expression expression; if (!TryGetStatelessExpression(name, out expression) && !TryGetStatefullExpression(name, out expression)) throw new InvalidOperationException(string.Format("Expression with name {0} not found", name)); return expression; } public static Expression GetStatelessExpression() where T : StatelessExpression { return GetStatelessExpression(TypeToNameTable[typeof(T)]); } public static Expression GetStatelessExpression(string name) { Expression expression; if (StatelessExpressionTable.TryGetValue(name, out expression)) return expression; throw new NotSupportedException("Expression not supported: " + name); } public static bool TryGetStatelessExpression(string name, out Expression expression) { return StatelessExpressionTable.TryGetValue(name, out expression); } public static Expression GetStatefullExpression() { return GetStatefullExpression(TypeToNameTable[typeof(T)]); } public static Expression GetStatefullExpression(string name) { Func creator; if (StatefullExpressionFactory.TryGetValue(name, out creator)) return creator(); throw new NotSupportedException("Expression not supported: " + name); } public static bool TryGetStatefullExpression(string name, out Expression expression) { Func creator; if (StatefullExpressionFactory.TryGetValue(name, out creator)) { expression = creator(); return true; } expression = default(Expression); return false; } } }