EP 0.1.1
This commit is contained in:
16
Convention/[Symbolization]/Detail/Exception.cs
Normal file
16
Convention/[Symbolization]/Detail/Exception.cs
Normal 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) { }
|
||||
}
|
||||
}
|
75
Convention/[Symbolization]/Detail/Functional.cs
Normal file
75
Convention/[Symbolization]/Detail/Functional.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
101
Convention/[Symbolization]/Detail/Keyword.cs
Normal file
101
Convention/[Symbolization]/Detail/Keyword.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
12
Convention/[Symbolization]/Detail/Modification.cs
Normal file
12
Convention/[Symbolization]/Detail/Modification.cs
Normal 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
|
||||
{
|
||||
}
|
||||
}
|
184
Convention/[Symbolization]/Detail/Namespace.cs
Normal file
184
Convention/[Symbolization]/Detail/Namespace.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
53
Convention/[Symbolization]/Detail/PrimitiveType.cs
Normal file
53
Convention/[Symbolization]/Detail/PrimitiveType.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
13
Convention/[Symbolization]/Detail/Reader.cs
Normal file
13
Convention/[Symbolization]/Detail/Reader.cs
Normal 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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
87
Convention/[Symbolization]/Detail/Structure.cs
Normal file
87
Convention/[Symbolization]/Detail/Structure.cs
Normal 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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
108
Convention/[Symbolization]/Detail/Variable.cs
Normal file
108
Convention/[Symbolization]/Detail/Variable.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user