This commit is contained in:
ninemine
2025-07-02 15:21:26 +08:00
parent d0dfe39fe9
commit 9345700d8a
10 changed files with 207 additions and 1 deletions

View File

@@ -0,0 +1,16 @@
using System;
namespace Convention.Symbolization
{
[Serializable]
public class InvalidGrammarException : Exception
{
public InvalidGrammarException() { }
public InvalidGrammarException(string message) : base(message) { }
public InvalidGrammarException(string message, Exception inner) : base(message, inner) { }
protected InvalidGrammarException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Linq;
using System.Reflection;
namespace Convention.Symbolization.Internal
{
public abstract class Function : CloneableVariable<Function>
{
public readonly FunctionSymbol FunctionInfo;
protected Function(string symbolName,string functionName, Type returnType, Type[] parameterTypes, Modification[] modifiers) : base(symbolName)
{
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;
public readonly Type ReturnType;
public readonly Type[] ParameterTypes;
public readonly Modification[] Modifiers;
public readonly string FullName;
public FunctionSymbol(string symbolName, Type returnType, Type[] parameterTypes, Modification[] modifiers)
{
this.FunctionName = symbolName;
this.ReturnType = returnType;
this.ParameterTypes = parameterTypes;
this.Modifiers = modifiers;
this.FullName = $"{returnType.FullName} {symbolName}({string.Join(',', parameterTypes.ToList().ConvertAll(x => x.FullName))}) {string.Join(' ', modifiers.ToList().ConvertAll(x => x.ToString()))}";
}
public bool Equals(FunctionSymbol other)
{
return other.FullName.Equals(FullName);
}
public override int GetHashCode()
{
return FullName.GetHashCode();
}
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Convention.Symbolization.Internal
{
public abstract class Keyword : Variable
{
protected Keyword(string keyword, Type realType) : base(new(keyword, realType))
{
Keywords.Add(keyword, this);
}
public static readonly Dictionary<string, Keyword> Keywords = new();
public abstract SymbolizationContext Execute(SymbolizationContext context, Variable[] leftParameters, Variable[] rightParameters);
public override string ToString()
{
return SymbolInfo.SymbolName;
}
}
public abstract class Keyword<T> : Keyword where T:Keyword<T>,new()
{
private static T MyInstance = new();
public static T Instance
{
get
{
return MyInstance;
}
}
protected Keyword(string keyword) : base(keyword, typeof(T))
{
}
public override bool Equals(Variable other)
{
return MyInstance == other;
}
}
}
namespace Convention.Symbolization.Keyword
{
public sealed class ExitScope : Internal.Keyword<ExitScope>
{
public ExitScope() : base("__exit_scope__")
{
}
public override SymbolizationContext Execute(SymbolizationContext context, Internal.Variable[] leftParameters, Internal.Variable[] rightParameters)
{
context.CurrentNamespace.EndAndTApplyUpdate();
return context.ParentContext;
}
}
public sealed class Namespace : Internal.Keyword<Namespace>
{
public Namespace() : base("namespace")
{
}
public override SymbolizationContext Execute(SymbolizationContext context, Internal.Variable[] leftParameters, Internal.Variable[] rightParameters)
{
if (leftParameters.Length != 0)
throw new InvalidGrammarException($"{this}: has invalid subject");
if (rightParameters.Length != 1)
throw new InvalidGrammarException($"{this}: needs to have one and only one object");
Internal.Namespace subNamespace = context.CurrentNamespace.CreateOrGetSubNamespace(rightParameters[0].ToString());
subNamespace.BeginUpdate();
SymbolizationContext subContext = new(context, subNamespace);
return subContext;
}
}
public sealed class Structure : Internal.Keyword<Structure>
{
public Structure() : base("struct")
{
}
public override SymbolizationContext Execute(SymbolizationContext context, Internal.Variable[] leftParameters, Internal.Variable[] rightParameters)
{
if (leftParameters.Length != 0)
throw new InvalidGrammarException($"{this}: has invalid subject");
if (rightParameters.Length != 1)
throw new InvalidGrammarException($"{this}: needs to have one and only one object");
Internal.Namespace subNamespace = context.CurrentNamespace.CreateOrGetSubNamespace(rightParameters[0].ToString());
subNamespace.BeginUpdate();
SymbolizationContext subContext = new(context, subNamespace);
return subContext;
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Convention.Symbolization.Internal
{
public abstract class Modification : Variable
{
}
}

View File

@@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Convention.Symbolization.Internal
{
public sealed class Namespace : Variable<Namespace>, ICanFindVariable
{
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 EndAndTApplyUpdate()
{
Updateable--;
if (Updateable == 0)
Refresh();
}
private readonly Dictionary<string, int> SymbolCounter = new();
private readonly Dictionary<string, List<Variable>> Symbol2Variable = new();
public void Refresh()
{
// Refresh Symbols
SymbolCounter.Clear();
foreach (var ns in SubNamespaces)
{
ns.Value.Refresh();
foreach (var symbol in ns.Value.SymbolCounter)
{
if (SymbolCounter.ContainsKey(symbol.Key))
SymbolCounter[symbol.Key] += symbol.Value;
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.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.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 CreateRootNamespace()
{
return new("global");
}
private Namespace(string symbolName) : base(symbolName) { }
public override bool Equals(Namespace other)
{
return this == other;
}
public string GetNamespaceName() => this.SymbolInfo.SymbolName;
public bool ContainsSymbol(string symbolName)
{
return SymbolCounter.ContainsKey(symbolName);
}
public int CountSymbol(string symbolName)
{
return SymbolCounter.TryGetValue(symbolName, out var count) ? count : 0;
}
public Variable[] Find(string symbolName)
{
if (!Symbol2Variable.TryGetValue(symbolName,out var result))
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

@@ -0,0 +1,53 @@
using System;
namespace Convention.Symbolization.Primitive
{
public class PrimitiveType<T> : Internal.Variable
{
public PrimitiveType() : base(new(typeof(T).Name, typeof(T)))
{
}
public override bool Equals(Internal.Variable other)
{
return other is PrimitiveType<T>;
}
public virtual T CloneValue(T value)
{
if (Utility.IsNumber(typeof(T)))
return value;
else if (Utility.IsString(typeof(T)))
return (T)(object)new string((string)(object)value);
else if (value is ICloneable cloneable)
return (T)cloneable.Clone();
else if (value is Internal.Variable)
return value;
return value;
}
public virtual T DefaultValue() => default;
}
public class PrimitiveInstance<T> : Internal.CloneableVariable<PrimitiveInstance<T>>
{
private readonly PrimitiveType<T> MyPrimitiveType = new();
public T Value;
public PrimitiveInstance(string symbolName, T value, PrimitiveType<T> primitiveType) : base(symbolName)
{
this.Value = value;
this.MyPrimitiveType = primitiveType;
}
public override PrimitiveInstance<T> CloneVariable(string targetSymbolName)
{
return new(targetSymbolName, MyPrimitiveType.CloneValue(this.Value), this.MyPrimitiveType);
}
public override bool Equals(PrimitiveInstance<T> other)
{
return this.Value.Equals(other.Value);
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Convention.Symbolization.Internal
{
public class SymbolizationReader
{
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Convention.Symbolization.Internal
{
public sealed class Structure : Variable<Structure>, ICanFindVariable
{
private Dictionary<string, Variable> MemberFields;
public readonly Namespace ParentNamespace;
public Dictionary<string, Variable> CloneMemberFields()
{
return new(from pair in MemberFields
select new KeyValuePair<string, Variable>(
pair.Key,
pair.Value is ICloneable cloneable ? (cloneable.Clone() as Variable) : pair.Value)
);
}
private Structure(string symbolName, Namespace parentNamespace) : base(symbolName)
{
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))
{
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

@@ -0,0 +1,108 @@
using System;
namespace Convention.Symbolization.Internal
{
public abstract class Variable : IEquatable<Variable>
{
public readonly VariableSymbol SymbolInfo;
protected Variable(VariableSymbol symbolInfo)
{
this.SymbolInfo = symbolInfo;
}
public abstract bool Equals(Variable other);
public override bool Equals(object obj)
{
return Equals(obj as Variable);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
public abstract class Variable<T> : Variable, IEquatable<T>
{
protected Variable(string symbolName) : base(new VariableSymbol(symbolName, typeof(T))) { }
public abstract bool Equals(T other);
public override bool Equals(Variable other)
{
return other is T variable && Equals(variable);
}
public override bool Equals(object obj)
{
return obj is T variable && Equals(variable);
}
public virtual int GetVariableHashCode()
{
return base.GetHashCode();
}
public override sealed int GetHashCode()
{
return GetVariableHashCode();
}
}
public interface ICanFindVariable
{
public Variable[] Find(string symbolName);
}
public abstract class CloneableVariable<T> : Variable<T>, ICloneable
{
protected CloneableVariable(string symbolName) : 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 override NullVariable CloneVariable(string targetSymbolName)
{
return new(targetSymbolName);
}
public override bool Equals(NullVariable other)
{
return true;
}
}
public readonly struct VariableSymbol
{
public readonly string SymbolName;
public readonly Type VariableType;
public VariableSymbol(string symbolName, Type variableType)
{
this.SymbolName = symbolName;
this.VariableType = variableType;
}
public bool Equals(VariableSymbol other)
{
return other.SymbolName.Equals(SymbolName) && other.VariableType.Equals(VariableType);
}
public override int GetHashCode()
{
return new Tuple<string, Type>(SymbolName, VariableType).GetHashCode();
}
}
}