EP RScript 仍存在一些问题, 但是能够运行

This commit is contained in:
2025-10-09 18:02:00 +08:00
parent a8cfb012fc
commit f8d81d9198
14 changed files with 756 additions and 573 deletions

View File

@@ -0,0 +1,11 @@
using System;
namespace Convention.RScript
{
[Serializable]
public class RScriptExceptionException : Exception
{
public RScriptExceptionException(string message, int runtimePointer) : base($"when running {runtimePointer}, {message}") { }
public RScriptExceptionException(string message, int runtimePointer, Exception inner) : base($"when running {runtimePointer}, {message}", inner) { }
}
}

View File

@@ -0,0 +1,138 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Convention.RScript
{
public class RScriptImportClass : ICollection<Type>
{
private readonly HashSet<Type> importedTypes = new();
private readonly Dictionary<string, List<MethodInfo>> cacheImportedFunctions = new();
public int Count => ((ICollection<Type>)importedTypes).Count;
public bool IsReadOnly => ((ICollection<Type>)importedTypes).IsReadOnly;
private void DoAdd(Type type)
{
foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public))
{
if (cacheImportedFunctions.ContainsKey(method.Name) == false)
cacheImportedFunctions.Add(method.Name, new());
cacheImportedFunctions[method.Name].Add(method);
}
}
public Type[] GetImports()
{
return importedTypes.ToArray();
}
public int CountMethod(string methodName)
{
return cacheImportedFunctions.TryGetValue(methodName, out var list) ? list.Count : 0;
}
public MethodInfo GetMethod(string methodName)
{
if (cacheImportedFunctions.TryGetValue(methodName, out var list))
{
if (list.Count != 1)
{
throw new AmbiguousMatchException($"Have more than one {methodName} is imported");
}
return list[0];
}
return null;
}
public MethodInfo GetMethodByReturn(string methodName, Type returnType)
{
if (cacheImportedFunctions.TryGetValue(methodName, out var list))
{
var query = from item in list where item.ReturnType == returnType select item;
if (query.Count() != 1)
{
throw new AmbiguousMatchException($"Have more than one {methodName} is imported");
}
return query.First();
}
return null;
}
public MethodInfo GetMethod(string methodName, params Type[] parameters)
{
static bool Pr(Type[] parameters1, Type[] parameters2)
{
if (parameters1.Length != parameters2.Length)
return false;
for (int i = 0, e = parameters1.Length; i != e; i++)
{
if (parameters1[i] != parameters2[i])
return false;
}
return true;
}
if (cacheImportedFunctions.TryGetValue(methodName, out var list))
{
var query = from item in list
where Pr((from _param in item.GetParameters() select _param.ParameterType).ToArray(), parameters)
select item;
if (query.Count() != 1)
{
throw new AmbiguousMatchException($"Have more than one {methodName} is imported");
}
return query.First();
}
return null;
}
public bool TryAdd(Type type)
{
var stats = importedTypes.Add(type);
if (stats)
{
DoAdd(type);
}
return stats;
}
public void Add(Type type)
{
TryAdd(type);
}
public IEnumerator<Type> GetEnumerator()
{
return ((IEnumerable<Type>)importedTypes).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)importedTypes).GetEnumerator();
}
public void Clear()
{
((ICollection<Type>)importedTypes).Clear();
}
public bool Contains(Type item)
{
return ((ICollection<Type>)importedTypes).Contains(item);
}
public void CopyTo(Type[] array, int arrayIndex)
{
((ICollection<Type>)importedTypes).CopyTo(array, arrayIndex);
}
public bool Remove(Type item)
{
return ((ICollection<Type>)importedTypes).Remove(item);
}
}
}

View File

@@ -0,0 +1,151 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Convention.RScript
{
public struct RScriptVariableEntry
{
public Type type;
public object data;
}
public class RScriptVariables : IDictionary<string, RScriptVariableEntry>
{
private readonly Dictionary<string, Stack<RScriptVariableEntry>> variables = new();
public RScriptVariableEntry this[string key]
{
get
{
return variables[key].Peek();
}
set
{
var current = variables[key].Peek();
if (current.type != value.type)
throw new ArgumentException($"current type is {current.type}, but setter.value is {value.type}");
variables[key].Pop();
variables[key].Push(value);
}
}
public ICollection<string> Keys => variables.Keys;
public ICollection<RScriptVariableEntry> Values => (from item in variables.Values select item.Peek()).ToArray();
public int Count => variables.Count;
public bool IsReadOnly => false;
public void Add(string key, RScriptVariableEntry value)
{
if (variables.ContainsKey(key) == false)
variables.Add(key, new());
variables[key].Push(value);
}
public void Add(KeyValuePair<string, RScriptVariableEntry> item)
{
Add(item.Key, item.Value);
}
public void ClearAllLayers()
{
variables.Clear();
}
/// <summary>
/// <see cref="ClearAllLayers"/>
/// </summary>
public void Clear()
{
ClearAllLayers();
}
public bool Contains(KeyValuePair<string, RScriptVariableEntry> item)
{
if (variables.TryGetValue(item.Key, out var items))
{
var current = items.Peek();
return current.data == item.Value.data;
}
return false;
}
public bool ContainsKey(string key)
{
return variables.ContainsKey(key);
}
public void CopyTo(KeyValuePair<string, RScriptVariableEntry>[] array, int arrayIndex)
{
foreach (var (key, items) in variables)
{
array[arrayIndex++] = new(key, items.Peek());
}
}
public IEnumerator<KeyValuePair<string, RScriptVariableEntry>> GetEnumerator()
{
return (from items in variables select new KeyValuePair<string, RScriptVariableEntry>(items.Key, items.Value.Peek())).GetEnumerator();
}
public bool Remove(string key)
{
if (variables.TryGetValue(key, out var items))
{
items.Pop();
if (items.Count == 0)
{
variables.Remove(key);
}
return true;
}
return false;
}
public bool Remove(KeyValuePair<string, RScriptVariableEntry> item)
{
if (variables.TryGetValue(item.Key, out var items))
{
if (item.Value.data == items.Peek().data)
{
items.Pop();
if (items.Count == 0)
{
variables.Remove(item.Key);
}
return true;
}
}
return false;
}
public bool TryGetValue(string key, [MaybeNullWhen(false)] out RScriptVariableEntry value)
{
if (variables.TryGetValue(key, out var items))
{
value = items.Peek();
return true;
}
value = default;
return false;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void SetValue(string varName, object value)
{
var top = variables[varName].Pop();
top.data = value;
variables[varName].Push(top);
}
}
}