diff --git a/Convention/[Runtime]/EasySave/EasySaveReflection.cs b/Convention/[Runtime]/EasySave/EasySaveReflection.cs index 207bb26..bf4879e 100644 --- a/Convention/[Runtime]/EasySave/EasySaveReflection.cs +++ b/Convention/[Runtime]/EasySave/EasySaveReflection.cs @@ -52,7 +52,7 @@ namespace Convention.EasySave.Internal // This obviously won't work if exceptions are disabled. try { - //if (assemblyNames.Contains(assembly.GetName().Name)) + //if (assemblyNames.Contains(assembly.GetName().StructureName)) assemblyList.Add(assembly); } catch { } diff --git a/Convention/[Symbolization]/Internal/Functional.cs b/Convention/[Symbolization]/Internal/Functional.cs index c09917b..78582b8 100644 --- a/Convention/[Symbolization]/Internal/Functional.cs +++ b/Convention/[Symbolization]/Internal/Functional.cs @@ -1,21 +1,50 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Reflection; namespace Convention.Symbolization.Internal { - public abstract class Function : Variable + public abstract class Function : CloneableVariable { public readonly FunctionSymbol FunctionInfo; - public abstract Variable Invoke(Variable[] parameters); - public Function(string symbolName, Type returnType, Type[] parameterTypes, Modification[] modifiers) + + protected Function(string symbolName,string functionName, Type returnType, Type[] parameterTypes, Modification[] modifiers) : base(symbolName) { - FunctionInfo = new(symbolName, returnType, parameterTypes, modifiers); + FunctionInfo = new(functionName, returnType, parameterTypes, modifiers); + } + public abstract Variable Invoke(SymbolizationContext context, Variable[] parameters); + } + + public sealed class DelegationalFunction : Function + { + public readonly MethodInfo methodInfo; + + public DelegationalFunction(string symbolName, MethodInfo methodInfo) + : base(symbolName, methodInfo.Name, methodInfo.ReturnType, methodInfo.GetParameters().ToList().ConvertAll(x => x.ParameterType).ToArray(), Array.Empty()) + { + this.methodInfo = methodInfo!; + } + + public override DelegationalFunction CloneVariable(string targetSymbolName) + { + return new DelegationalFunction(targetSymbolName, methodInfo); + } + + public override bool Equals(Function other) + { + return other is DelegationalFunction df && df.methodInfo == this.methodInfo; + } + + public override Variable Invoke(SymbolizationContext context, Variable[] parameters) + { + Variable invoker = parameters.Length > 0 ? parameters[0] : null; + Variable[] invokerParameters = parameters.Length > 0 ? parameters.Skip(1).ToArray() : Array.Empty(); + object result = methodInfo.Invoke(invoker, invokerParameters); + return result as Variable; } } + public readonly struct FunctionSymbol { public readonly string FunctionName; diff --git a/Convention/[Symbolization]/Internal/Namespace.cs b/Convention/[Symbolization]/Internal/Namespace.cs index 8a6c68a..b5a66d5 100644 --- a/Convention/[Symbolization]/Internal/Namespace.cs +++ b/Convention/[Symbolization]/Internal/Namespace.cs @@ -4,18 +4,60 @@ using System.Linq; namespace Convention.Symbolization.Internal { - public sealed class Namespace : Variable + public sealed class Namespace : Variable, ICanFindVariable { - public Dictionary SubNamespaces = new(); - public Dictionary Functions = new(); - public Dictionary Structures = new(); + private int Updateable = 0; + + public void BeginUpdate() + { + Updateable++; + } + + private readonly Dictionary SubNamespaces = new(); + private readonly Dictionary Functions = new(); + private readonly Dictionary Structures = new(); + + public Namespace CreateOrGetSubNamespace(string subNamespace) + { + if (Updateable == 0) + throw new InvalidOperationException("Cannot create sub-namespace outside of an update block."); + if(!SubNamespaces.TryGetValue(subNamespace,out var result)) + { + result = new Namespace(subNamespace); + SubNamespaces[subNamespace] = result; + } + return result; + } + + public void AddFunction(Function function) + { + if (Updateable == 0) + throw new InvalidOperationException("Cannot add function outside of an update block."); + ArgumentNullException.ThrowIfNull(function); + Functions.Add(function.FunctionInfo, function); + } + + public void AddStructure(Structure structure) + { + if (Updateable == 0) + throw new InvalidOperationException("Cannot add structure outside of an update block."); + ArgumentNullException.ThrowIfNull(structure); + Structures.Add(structure.SymbolInfo.SymbolName, structure); + } + + public void EndAndApplyUpdate() + { + Updateable--; + if (Updateable == 0) + Refresh(); + } private readonly Dictionary SymbolCounter = new(); private readonly Dictionary> Symbol2Variable = new(); public void Refresh() { - // Refresh SymbolCounter + // Refresh Symbols SymbolCounter.Clear(); foreach (var ns in SubNamespaces) { @@ -27,30 +69,52 @@ namespace Convention.Symbolization.Internal else SymbolCounter[symbol.Key] = symbol.Value; } + foreach (var symbol in ns.Value.Symbol2Variable) + { + if (Symbol2Variable.TryGetValue(symbol.Key, out List value)) + value.AddRange(symbol.Value); + else + Symbol2Variable[symbol.Key] = new(symbol.Value); + } } foreach (var func in Functions) { - if (SymbolCounter.ContainsKey(func.Key.FunctionName)) - SymbolCounter[func.Key.FunctionName]++; - else - SymbolCounter[func.Key.FunctionName] = 1; + { + if (SymbolCounter.TryGetValue(func.Key.FunctionName, out var value)) + SymbolCounter[func.Key.FunctionName] = ++value; + else + SymbolCounter[func.Key.FunctionName] = 1; + } + { + if (Symbol2Variable.TryGetValue(func.Key.FunctionName, out var value)) + value.Add(func.Value); + else + Symbol2Variable[func.Key.FunctionName] = new() { func.Value }; + } + { + if (Symbol2Variable.TryGetValue(func.Key.FunctionName, out var value)) + value.Add(func.Value); + else + Symbol2Variable[func.Key.FunctionName] = new() { func.Value }; + } } foreach (var @struct in Structures) { - if (SymbolCounter.ContainsKey(@struct.Key)) - SymbolCounter[@struct.Key]++; - else - SymbolCounter[@struct.Key] = 1; + { + if (SymbolCounter.TryGetValue(@struct.Key, out int value)) + SymbolCounter[@struct.Key] = ++value; + else + SymbolCounter[@struct.Key] = 1; + } + { + if (Symbol2Variable.TryGetValue(@struct.Key, out List value)) + value.Add(@struct.Value); + else + Symbol2Variable[@struct.Key] = new() { @struct.Value }; + } } } - public static Namespace CreateOrGetSubNamespace(string namespaceName, Namespace parent) - { - if (parent.SubNamespaces.TryGetValue(namespaceName, out var sub)) - return sub; - parent.SubNamespaces[namespaceName] = new(namespaceName); - return parent.SubNamespaces[namespaceName]; - } public static Namespace CreateRootNamespace() { return new("global"); @@ -81,5 +145,40 @@ namespace Convention.Symbolization.Internal return Array.Empty(); return result.ToArray(); } + + public Namespace FindSubNamespace(string subNamespaceName) + { + if (!SubNamespaces.TryGetValue(subNamespaceName, out var result)) + return null; + return result; + } + + public Function[] FindFunction(string symbolName) + { + if (!Symbol2Variable.TryGetValue(symbolName, out var result)) + return Array.Empty(); + return result.OfType().ToArray(); + } + + public Function FindFunctionInNamespace(FunctionSymbol symbol) + { + if (!Functions.TryGetValue(symbol, out var result)) + return null; + return result; + } + + public Structure[] FindStructure(string symbolName) + { + if (!Symbol2Variable.TryGetValue(symbolName, out var result)) + return Array.Empty(); + return result.OfType().ToArray(); + } + + public Structure FindStructureInNamespace(string symbolName) + { + if (!Structures.TryGetValue(symbolName, out var result)) + return null; + return result; + } } } diff --git a/Convention/[Symbolization]/Internal/Structure.cs b/Convention/[Symbolization]/Internal/Structure.cs index 5885900..57b8b2d 100644 --- a/Convention/[Symbolization]/Internal/Structure.cs +++ b/Convention/[Symbolization]/Internal/Structure.cs @@ -6,39 +6,82 @@ using System.Threading.Tasks; namespace Convention.Symbolization.Internal { - public sealed class Structure : Variable + public sealed class Structure : Variable, ICanFindVariable { - public readonly string Name; - private Dictionary VariableSymbolAndDefaultValue; + private Dictionary MemberFields; + public readonly Namespace ParentNamespace; - private Structure(string name) + public Dictionary CloneMemberFields() { - this.Name = name; - } - public Structure(string name, Dictionary variableSymbolAndDefaultValue) - { - this.Name = name; - this.VariableSymbolAndDefaultValue = variableSymbolAndDefaultValue; + return new(from pair in MemberFields + select new KeyValuePair( + pair.Key, + pair.Value is ICloneable cloneable ? (cloneable.Clone() as Variable) : pair.Value) + ); } - public override object Clone() + private Structure(string symbolName, Namespace parentNamespace) : base(symbolName) { - Structure target = new(Name); - foreach (var pair in VariableSymbolAndDefaultValue) + this.ParentNamespace = parentNamespace; + } + + public static Structure Create(string structureName, Namespace parent) + { + Structure result = new(structureName, parent); + parent.AddStructure(result); + return result; + } + + public override bool Equals(Structure other) + { + return this == other; + } + + public Variable[] Find(string symbolName) + { + if (MemberFields.TryGetValue(symbolName, out var variable)) { - target.VariableSymbolAndDefaultValue[pair.Key] = pair.Value; + return new[] { variable }; } - return target; + return Array.Empty(); + } + } + + public sealed class StructureInstance : CloneableVariable,ICanFindVariable + { + public readonly Structure StructureType; + private readonly Dictionary MemberFields; + public StructureInstance(string symbolName, Structure structureType) + : base(symbolName) + { + this.StructureType = structureType; + this.MemberFields = structureType.CloneMemberFields(); + } + public override bool Equals(StructureInstance other) + { + return this == other; + } + public override StructureInstance CloneVariable(string targetSymbolName) + { + return new StructureInstance(targetSymbolName, this.StructureType); } - public bool Equals(Structure other) + public Variable GetField(string memberName) { - return Name.Equals(other.Name); + if (MemberFields.TryGetValue(memberName, out var result)) + return result; + else + throw new KeyNotFoundException($"Member '{memberName}' not found in structure '{StructureType.SymbolInfo.SymbolName}'."); } - public override int GetHashCode() + public Variable[] Find(string symbolName) { - return Name.GetHashCode(); + if (MemberFields.TryGetValue(symbolName, out var variable)) + { + return new[] { variable }; + } + return Array.Empty(); } } } + diff --git a/Convention/[Symbolization]/Internal/Variable.cs b/Convention/[Symbolization]/Internal/Variable.cs index 51b51fc..e6a797d 100644 --- a/Convention/[Symbolization]/Internal/Variable.cs +++ b/Convention/[Symbolization]/Internal/Variable.cs @@ -51,21 +51,38 @@ namespace Convention.Symbolization.Internal } } - public abstract class CloneableVariable : Variable, ICloneable + public interface ICanFindVariable { - protected CloneableVariable(string symbolName, Type variableType) : base(symbolName) - { - } - - protected CloneableVariable(string symbolName, CloneableVariable variable) : base(symbolName) - { - } - - public object Clone() => CloneVariable(); - - public abstract T CloneVariable(); + public Variable[] Find(string symbolName); } + public abstract class CloneableVariable : Variable, ICloneable + { + protected CloneableVariable(string symbolName) : base(symbolName) + { + } + + public object Clone() => CloneVariable(SymbolInfo.SymbolName); + + public abstract T CloneVariable(string targetSymbolName); + } + + public sealed class NullVariable : CloneableVariable + { + public NullVariable(string symbolName) : base(symbolName) + { + } + + public override NullVariable CloneVariable(string targetSymbolName) + { + return new(targetSymbolName); + } + + public override bool Equals(NullVariable other) + { + return true; + } + } public readonly struct VariableSymbol { diff --git a/Convention/[Symbolization]/Symbolization.cs b/Convention/[Symbolization]/Symbolization.cs index 7fb01d4..03b27f4 100644 --- a/Convention/[Symbolization]/Symbolization.cs +++ b/Convention/[Symbolization]/Symbolization.cs @@ -18,7 +18,7 @@ namespace Convention.Symbolization public SymbolizationRunner(SymbolizationContext context) { - GlobalNamespace = new(); + GlobalNamespace = Internal.Namespace.CreateRootNamespace(); Context = context; } public SymbolizationRunner() :this(new()){ }