This commit is contained in:
ninemine
2025-07-02 13:11:26 +08:00
parent 4d49ab1990
commit d0dfe39fe9
6 changed files with 248 additions and 60 deletions

View File

@@ -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 { }

View File

@@ -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<Function>
{
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<Modification>())
{
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<Variable>();
object result = methodInfo.Invoke(invoker, invokerParameters);
return result as Variable;
}
}
public readonly struct FunctionSymbol
{
public readonly string FunctionName;

View File

@@ -4,18 +4,60 @@ using System.Linq;
namespace Convention.Symbolization.Internal
{
public sealed class Namespace : Variable<Namespace>
public sealed class Namespace : Variable<Namespace>, ICanFindVariable
{
public Dictionary<string, Namespace> SubNamespaces = new();
public Dictionary<FunctionSymbol, Function> Functions = new();
public Dictionary<string, Structure> Structures = new();
private int Updateable = 0;
public void BeginUpdate()
{
Updateable++;
}
private readonly Dictionary<string, Namespace> SubNamespaces = new();
private readonly Dictionary<FunctionSymbol, Function> Functions = new();
private readonly Dictionary<string, Structure> 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<string, int> SymbolCounter = new();
private readonly Dictionary<string, List<Variable>> 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<Variable> 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]++;
{
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]++;
{
if (SymbolCounter.TryGetValue(@struct.Key, out int value))
SymbolCounter[@struct.Key] = ++value;
else
SymbolCounter[@struct.Key] = 1;
}
{
if (Symbol2Variable.TryGetValue(@struct.Key, out List<Variable> 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<Variable>();
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<Function>();
return result.OfType<Function>().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<Structure>();
return result.OfType<Structure>().ToArray();
}
public Structure FindStructureInNamespace(string symbolName)
{
if (!Structures.TryGetValue(symbolName, out var result))
return null;
return result;
}
}
}

View File

@@ -6,39 +6,82 @@ using System.Threading.Tasks;
namespace Convention.Symbolization.Internal
{
public sealed class Structure : Variable
public sealed class Structure : Variable<Structure>, ICanFindVariable
{
public readonly string Name;
private Dictionary<VariableSymbol, Variable> VariableSymbolAndDefaultValue;
private Dictionary<string, Variable> MemberFields;
public readonly Namespace ParentNamespace;
private Structure(string name)
public Dictionary<string, Variable> CloneMemberFields()
{
this.Name = name;
}
public Structure(string name, Dictionary<VariableSymbol, Variable> variableSymbolAndDefaultValue)
{
this.Name = name;
this.VariableSymbolAndDefaultValue = variableSymbolAndDefaultValue;
return new(from pair in MemberFields
select new KeyValuePair<string, Variable>(
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)
{
target.VariableSymbolAndDefaultValue[pair.Key] = pair.Value;
}
return target;
this.ParentNamespace = parentNamespace;
}
public bool Equals(Structure other)
public static Structure Create(string structureName, Namespace parent)
{
return Name.Equals(other.Name);
Structure result = new(structureName, parent);
parent.AddStructure(result);
return result;
}
public override int GetHashCode()
public override bool Equals(Structure other)
{
return Name.GetHashCode();
return this == other;
}
public Variable[] Find(string symbolName)
{
if (MemberFields.TryGetValue(symbolName, out var variable))
{
return new[] { variable };
}
return Array.Empty<Variable>();
}
}
public sealed class StructureInstance : CloneableVariable<StructureInstance>,ICanFindVariable
{
public readonly Structure StructureType;
private readonly Dictionary<string, Variable> 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 Variable GetField(string memberName)
{
if (MemberFields.TryGetValue(memberName, out var result))
return result;
else
throw new KeyNotFoundException($"Member '{memberName}' not found in structure '{StructureType.SymbolInfo.SymbolName}'.");
}
public Variable[] Find(string symbolName)
{
if (MemberFields.TryGetValue(symbolName, out var variable))
{
return new[] { variable };
}
return Array.Empty<Variable>();
}
}
}

View File

@@ -51,21 +51,38 @@ namespace Convention.Symbolization.Internal
}
}
public interface ICanFindVariable
{
public Variable[] Find(string symbolName);
}
public abstract class CloneableVariable<T> : Variable<T>, ICloneable
{
protected CloneableVariable(string symbolName, Type variableType) : base(symbolName)
protected CloneableVariable(string symbolName) : base(symbolName)
{
}
protected CloneableVariable(string symbolName, CloneableVariable<T> variable) : base(symbolName)
public object Clone() => CloneVariable(SymbolInfo.SymbolName);
public abstract T CloneVariable(string targetSymbolName);
}
public sealed class NullVariable : CloneableVariable<NullVariable>
{
public NullVariable(string symbolName) : base(symbolName)
{
}
public object Clone() => CloneVariable();
public abstract T CloneVariable();
public override NullVariable CloneVariable(string targetSymbolName)
{
return new(targetSymbolName);
}
public override bool Equals(NullVariable other)
{
return true;
}
}
public readonly struct VariableSymbol
{

View File

@@ -18,7 +18,7 @@ namespace Convention.Symbolization
public SymbolizationRunner(SymbolizationContext context)
{
GlobalNamespace = new();
GlobalNamespace = Internal.Namespace.CreateRootNamespace();
Context = context;
}
public SymbolizationRunner() :this(new()){ }