diff --git a/Library/Api/IDynamicContext.cs b/Library/Api/IDynamicContext.cs
index 4487eda..5fb69e7 100644
--- a/Library/Api/IDynamicContext.cs
+++ b/Library/Api/IDynamicContext.cs
@@ -17,10 +17,11 @@ namespace Serein.Library.Api
string Guid {get; }
///
- /// 运行环境,包含IOC容器。
+ /// 运行环境
///
IFlowEnvironment Env { get; }
+
///
/// 是否正在运行
///
diff --git a/Library/Api/IFlowControl.cs b/Library/Api/IFlowControl.cs
index cfdbf86..3031921 100644
--- a/Library/Api/IFlowControl.cs
+++ b/Library/Api/IFlowControl.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Threading.Tasks;
namespace Serein.Library.Api
@@ -8,6 +9,13 @@ namespace Serein.Library.Api
///
public interface IFlowControl
{
+
+ ///
+ /// 单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。
+ /// 当某个类型注册绑定成功后,将不会因为其它地方尝试注册相同类型的行为导致类型被重新创建。
+ ///
+ ISereinIOC IOC { get; }
+
///
/// 需要你提供一个由你实现的ISereinIOC接口实现类
/// 当你将流程运行环境集成在你的项目时,并希望流程运行时使用你提供的对象,而非自动创建
@@ -15,7 +23,8 @@ namespace Serein.Library.Api
/// 注意,是流程运行时,而非运行环境
///
///
- void UseExternalIOC(ISereinIOC ioc);
+ /// 用于每次启动时,重置IOC后默认注册某些类型
+ void UseExternalIOC(ISereinIOC ioc, Action setDefultMemberOnReset = null);
///
/// 开始运行流程
diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs
index 222e7c4..2288cdc 100644
--- a/Library/Api/IFlowEnvironment.cs
+++ b/Library/Api/IFlowEnvironment.cs
@@ -759,8 +759,7 @@ namespace Serein.Library.Api
///
- /// 单例模式IOC容器,内部维护了一个实例字典,默认使用类型的FullName作为Key,如果以“接口-实现类”的方式注册,那么将使用接口类型的FullName作为Key。
- /// 当某个类型注册绑定成功后,将不会因为其它地方尝试注册相同类型的行为导致类型被重新创建。
+ /// 运行环境使用的IOC,默认情况下无需对其进行调用
///
ISereinIOC IOC { get; }
diff --git a/Library/FlowNode/DynamicContext.cs b/Library/FlowNode/DynamicContext.cs
index c32262c..ca50cfc 100644
--- a/Library/FlowNode/DynamicContext.cs
+++ b/Library/FlowNode/DynamicContext.cs
@@ -15,7 +15,8 @@ namespace Serein.Library
///
/// 动态流程上下文
///
- ///
+ /// 脚本运行时的IOC
+ /// 脚本运行时使用的IOC容器
public DynamicContext(IFlowEnvironment flowEnvironment)
{
Env = flowEnvironment;
diff --git a/Library/FlowNode/LightweightFlowEnvironment.cs b/Library/FlowNode/LightweightFlowEnvironment.cs
index 40644f7..a08d692 100644
--- a/Library/FlowNode/LightweightFlowEnvironment.cs
+++ b/Library/FlowNode/LightweightFlowEnvironment.cs
@@ -372,6 +372,8 @@ namespace Serein.Library
private readonly IFlowEnvironment flowEnvironment;
public static Serein.Library.Utils.ObjectPool FlowContextPool { get; set; }
+ public ISereinIOC IOC => throw new NotImplementedException();
+
public LightweightFlowControl(IFlowCallTree flowCallTree, IFlowEnvironment flowEnvironment)
{
this.flowCallTree = flowCallTree;
@@ -478,7 +480,12 @@ namespace Serein.Library
public void UseExternalIOC(ISereinIOC ioc)
{
throw new NotImplementedException();
- }
+ }
+
+ public void UseExternalIOC(ISereinIOC ioc, Action setDefultMemberOnReset = null)
+ {
+ throw new NotImplementedException();
+ }
#endregion
}
diff --git a/Library/FlowNode/NodeDebugSetting.cs b/Library/FlowNode/NodeDebugSetting.cs
index cf979e0..72eaa1b 100644
--- a/Library/FlowNode/NodeDebugSetting.cs
+++ b/Library/FlowNode/NodeDebugSetting.cs
@@ -3,6 +3,7 @@ using Serein.Library.Api;
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
@@ -77,7 +78,8 @@ namespace Serein.Library
partial void OnIsInterruptChanged(bool oldValue, bool newValue)
{
- if (newValue && _getInterruptTask is null)
+ Debug.WriteLine($" {nameof(NodeDebugSetting)}.{nameof(NodeDebugSetting.OnIsInterruptChanged)} 暂未实现,需要重新设计中断逻辑");
+ /*if (newValue && _getInterruptTask is null)
{
// 设置获取中断的委托
_getInterruptTask = () => NodeModel.Env.IOC.Get().WaitTriggerAsync(NodeModel.Guid);
@@ -97,7 +99,7 @@ namespace Serein.Library
_getInterruptTask = null;
}
- }
+ }*/
}
diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs
index 267817b..61af606 100644
--- a/Library/FlowNode/ParameterDetails.cs
+++ b/Library/FlowNode/ParameterDetails.cs
@@ -335,7 +335,7 @@ namespace Serein.Library
- #region “枚举-类型”转换器
+ /*#region “枚举-类型”转换器
if (ExplicitType is not null && ExplicitType.IsEnum && DataType != ExplicitType)
{
var resultEnum = Enum.Parse(ExplicitType, DataValue);
@@ -347,7 +347,7 @@ namespace Serein.Library
return value;
}
}
- #endregion
+ #endregion*/
// 需要获取预入参数据
object inputParameter;
diff --git a/Library/Utils/BenchmarkHelpers.cs b/Library/Utils/BenchmarkHelpers.cs
index 46b207d..4c61d1d 100644
--- a/Library/Utils/BenchmarkHelpers.cs
+++ b/Library/Utils/BenchmarkHelpers.cs
@@ -128,6 +128,7 @@ namespace Serein.Library.Utils
total += ms;
Console.WriteLine($"运行1次耗时 :{total} 毫秒:");
+ Debug.WriteLine($"运行1次耗时 :{total} 毫秒:");
return result;
}
}
diff --git a/Library/Utils/EmitHelper.cs b/Library/Utils/EmitHelper.cs
index 8980b90..955a3f8 100644
--- a/Library/Utils/EmitHelper.cs
+++ b/Library/Utils/EmitHelper.cs
@@ -17,15 +17,26 @@ namespace Serein.Library.Utils
public class EmitMethodInfo
{
+ ///
+ /// 方法声明类型
+ ///
public Type DeclaringType { get; set; }
+
+ ///
+ /// 方法类型
+ ///
+ public EmitMethodType EmitMethodType { get; set; }
+
///
/// 是异步方法
///
- public bool IsTask { get; set; }
+ public bool IsAsync { get; set; }
///
/// 是静态的
///
public bool IsStatic { get; set; }
+
+
}
public enum EmitMethodType
@@ -41,16 +52,7 @@ namespace Serein.Library.Utils
///
/// 有返回值的异步方法
///
- HasResultTask,
-
- ///
- /// 普通的方法。如果方法返回void时,将会返回null。
- ///
- StaticFunc,
- ///
- /// 无返回值的异步方法
- ///
- StaticTask,
+ TaskHasResult,
}
public static bool IsGenericTask(Type returnType, out Type taskResult)
@@ -179,26 +181,31 @@ namespace Serein.Library.Utils
}
// 处理返回值,如果没有返回值,则返回null
il.Emit(OpCodes.Ret); // 返回
+ EmitMethodType emitMethodType;
if (IsTask)
{
if (IsTaskGenerics)
{
+ emitMethodType = EmitMethodType.TaskHasResult;
@delegate = dynamicMethod.CreateDelegate(typeof(Func
public class FlowWorkOptions()
{
+ ///
+ /// 流程IOC容器
+ ///
+ public ISereinIOC FlowIOC { get; set; }
///
/// 流程运行环境
///
@@ -46,7 +50,7 @@ namespace Serein.NodeFlow
///
/// 上下文线程池
///
- public Serein.Library.Utils.ObjectPool FlowContextPool { get; set; }
+ public Serein.Library.Utils.ObjectPool FlowContextPool { get; set; }
///
/// 每个画布需要启用的节点
diff --git a/NodeFlow/Model/Node/NodeModelBaseFunc.cs b/NodeFlow/Model/Node/NodeModelBaseFunc.cs
index 7916b40..4967871 100644
--- a/NodeFlow/Model/Node/NodeModelBaseFunc.cs
+++ b/NodeFlow/Model/Node/NodeModelBaseFunc.cs
@@ -141,11 +141,11 @@ namespace Serein.NodeFlow.Model
}
else
{
- var instance = Env.IOC.Get(md.ActingInstanceType);
+ var instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
if (instance is null)
{
- Env.IOC.Register(md.ActingInstanceType).Build();
- instance = Env.IOC.Get(md.ActingInstanceType);
+ Env.FlowControl.IOC.Register(md.ActingInstanceType).Build();
+ instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
}
object[] args = await this.GetParametersAsync(context, token);
var result = await dd.InvokeAsync(instance, args);
diff --git a/NodeFlow/Model/Node/SingleFlipflopNode.cs b/NodeFlow/Model/Node/SingleFlipflopNode.cs
index 1ff3aad..08b50a4 100644
--- a/NodeFlow/Model/Node/SingleFlipflopNode.cs
+++ b/NodeFlow/Model/Node/SingleFlipflopNode.cs
@@ -39,11 +39,11 @@ namespace Serein.NodeFlow.Model
throw new Exception("不存在对应委托");
}
- var instance = context.Env.IOC.Get(md.ActingInstanceType);
+ var instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
if (instance is null)
{
- Env.IOC.Register(md.ActingInstanceType).Build();
- instance = Env.IOC.Get(md.ActingInstanceType);
+ Env.FlowControl.IOC.Register(md.ActingInstanceType).Build();
+ instance = Env.FlowControl.IOC.Get(md.ActingInstanceType);
}
await dd.InvokeAsync(instance, [context]);
var args = await this.GetParametersAsync(context, token);
diff --git a/NodeFlow/Model/Node/SingleFlowCallNode.cs b/NodeFlow/Model/Node/SingleFlowCallNode.cs
index 18ef262..433e117 100644
--- a/NodeFlow/Model/Node/SingleFlowCallNode.cs
+++ b/NodeFlow/Model/Node/SingleFlowCallNode.cs
@@ -246,6 +246,10 @@ namespace Serein.NodeFlow.Model
}
else
{
+ /*var tempName = node.MethodDetails.MethodName;
+ var index = node.MethodDetails.MethodName.IndexOf('(');
+ var methodName = tempName[..(index - 1)];
+ return GetApiInvokeName(node, methodName);*/
FlowLibraryService service = node.Env.IOC.Get();
if (service.TryGetMethodInfo(md.AssemblyName, md.MethodName, out var methodInfo))
{
diff --git a/NodeFlow/Model/Operation/CreateNodeOperation.cs b/NodeFlow/Model/Operation/CreateNodeOperation.cs
index bf61998..d0caf9a 100644
--- a/NodeFlow/Model/Operation/CreateNodeOperation.cs
+++ b/NodeFlow/Model/Operation/CreateNodeOperation.cs
@@ -69,11 +69,11 @@ namespace Serein.NodeFlow.Model.Operation
public override async Task ExecuteAsync()
{
if (!ValidationParameter()) return false; // 执行时验证
-
+
IFlowNode? nodeModel;
if (IsBaseNode)
{
- nodeModel = FlowNodeExtension.CreateNode(flowEnvironment, NodeControlType); // 加载基础节点
+ nodeModel = FlowNodeExtension.CreateNode(flowEnvironment.IOC, NodeControlType); // 加载基础节点
}
else
{
@@ -89,7 +89,7 @@ namespace Serein.NodeFlow.Model.Operation
return false;
//throw new InvalidOperationException($"无法创建节点,因为没有找到{MethodDetailsInfo.AssemblyName}.{MethodDetailsInfo.MethodName}方法,请检查是否已加载对应程序集");
}
- nodeModel = FlowNodeExtension.CreateNode(flowEnvironment, NodeControlType, methodDetails); // 一般的加载节点方法
+ nodeModel = FlowNodeExtension.CreateNode(flowEnvironment.IOC, NodeControlType, methodDetails); // 一般的加载节点方法
}
nodeModel.Guid ??= Guid.NewGuid().ToString();
diff --git a/NodeFlow/Services/FlowWorkManagement.cs b/NodeFlow/Services/FlowWorkManagement.cs
index 4395a9f..febdb0f 100644
--- a/NodeFlow/Services/FlowWorkManagement.cs
+++ b/NodeFlow/Services/FlowWorkManagement.cs
@@ -113,8 +113,9 @@ namespace Serein.NodeFlow.Services
private bool RegisterAllType(List nodes)
{
var env = WorkOptions.Environment;
+ var ioc = WorkOptions.FlowIOC;
+
-
var nodeMds = nodes.Select(item => item.MethodDetails).ToList(); // 获取环境中所有节点的方法信息
var allMds = new List();
@@ -127,7 +128,7 @@ namespace Serein.NodeFlow.Services
{
if (md.ActingInstanceType != null)
{
- env.IOC.Register(md.ActingInstanceType);
+ ioc.Register(md.ActingInstanceType);
}
else
{
@@ -135,10 +136,10 @@ namespace Serein.NodeFlow.Services
isSuccessful = false ;
}
}
- env.IOC.Build(); // 绑定初始化时注册的类型
+ ioc.Build(); // 绑定初始化时注册的类型
foreach (var md in allMds)
{
- var instance = env.IOC.Get(md.ActingInstanceType);
+ var instance = ioc.Get(md.ActingInstanceType);
if (instance is null)
{
SereinEnv.WriteLine(InfoType.ERROR, $"{md.MethodName} - 无法获取类型[{md.ActingInstanceType}]的实例");
@@ -154,7 +155,7 @@ namespace Serein.NodeFlow.Services
var env = WorkOptions.Environment;
var initMds = WorkOptions.InitMds;
var pool = WorkOptions.FlowContextPool;
- var ioc = WorkOptions.Environment.IOC;
+ var ioc = WorkOptions.FlowIOC;
foreach (var md in initMds) // 初始化
{
if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行初始化
@@ -167,7 +168,7 @@ namespace Serein.NodeFlow.Services
context.Reset();
pool.Free(context);
}
- env.IOC.Build(); // 绑定初始化时注册的类型
+ ioc.Build(); // 绑定初始化时注册的类型
var isSuccessful = true;
return isSuccessful;
}
@@ -176,7 +177,7 @@ namespace Serein.NodeFlow.Services
var env = WorkOptions.Environment;
var loadMds = WorkOptions.LoadMds;
var pool = WorkOptions.FlowContextPool;
- var ioc = WorkOptions.Environment.IOC;
+ var ioc = WorkOptions.FlowIOC;
foreach (var md in loadMds) // 加载时
{
if (!env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行初始化
@@ -189,7 +190,7 @@ namespace Serein.NodeFlow.Services
context.Reset();
pool.Free(context);
}
- env.IOC.Build(); // 绑定初始化时注册的类型
+ ioc.Build(); // 绑定初始化时注册的类型
var isSuccessful = true;
return isSuccessful;
@@ -199,7 +200,7 @@ namespace Serein.NodeFlow.Services
var env = WorkOptions.Environment;
var mds = WorkOptions.ExitMds;
var pool = WorkOptions.FlowContextPool;
- var ioc = WorkOptions.Environment.IOC;
+ var ioc = WorkOptions.FlowIOC;
// var fit = ioc.Get();
// fit.CancelAllTrigger(); // 取消所有中断
diff --git a/Serein.Script/IScriptInvokeContext.cs b/Serein.Script/IScriptInvokeContext.cs
index 48529bd..7c63a38 100644
--- a/Serein.Script/IScriptInvokeContext.cs
+++ b/Serein.Script/IScriptInvokeContext.cs
@@ -13,7 +13,7 @@ namespace Serein.Script
IDynamicContext FlowContext { get; }
///
- /// 是否该退出了(由外部发出停止信号)
+ /// 是否该退出了(由 TokenSource 控制,用于响应外部发出停止信号)
///
bool IsReturn { get; }
@@ -40,7 +40,7 @@ namespace Serein.Script
///
///
///
- bool SetVarValue(string varName, object value);
+ bool SetVarValue(string varName, object? value);
///
/// 结束调用
diff --git a/Serein.Script/Node/AssignmentNode.cs b/Serein.Script/Node/AssignmentNode.cs
index 04d43e8..a8486b6 100644
--- a/Serein.Script/Node/AssignmentNode.cs
+++ b/Serein.Script/Node/AssignmentNode.cs
@@ -8,17 +8,16 @@ namespace Serein.Script.Node
{
///
- /// 赋值节点
+ /// 变量赋值节点
///
public class AssignmentNode : ASTNode
{
///
/// 变量名称
///
- //public string Variable { get; }
public ASTNode Target { get; }
///
- /// 对应的节点
+ /// 值来源
///
public ASTNode Value { get; }
diff --git a/Serein.Script/ScriptInvokeContext.cs b/Serein.Script/ScriptInvokeContext.cs
index b6c30c0..ce98d2d 100644
--- a/Serein.Script/ScriptInvokeContext.cs
+++ b/Serein.Script/ScriptInvokeContext.cs
@@ -14,7 +14,7 @@ namespace Serein.Script
///
/// 定义的变量
///
- private Dictionary _variables = new Dictionary();
+ private Dictionary _variables = new Dictionary();
///
/// 取消令牌源,用于控制脚本的执行
diff --git a/Serein.Script/SereinSciptException.cs b/Serein.Script/SereinSciptException.cs
index 83295b8..47d2380 100644
--- a/Serein.Script/SereinSciptException.cs
+++ b/Serein.Script/SereinSciptException.cs
@@ -13,4 +13,5 @@ namespace Serein.Script
Message = $"异常信息 : {message} ,代码在第{node.Row}行: {node.Code.Trim()}";
}
}
+
}
diff --git a/Serein.Script/SereinScript.cs b/Serein.Script/SereinScript.cs
index 5bd5644..d5283c4 100644
--- a/Serein.Script/SereinScript.cs
+++ b/Serein.Script/SereinScript.cs
@@ -10,6 +10,9 @@ using System.Threading.Tasks;
namespace Serein.Script
{
+
+
+
public class SereinScript
{
///
@@ -47,7 +50,7 @@ namespace Serein.Script
}
Dictionary symbolInfos = TypeAnalysis.NodeSymbolInfos.ToDictionary();
SereinScriptInterpreter Interpreter = new SereinScriptInterpreter(symbolInfos);
- return await Interpreter.InterpretAsync(context, programNode);
+ return await Interpreter.InterpreterAsync(context, programNode);
}
diff --git a/Serein.Script/SereinScriptInterpreter.cs b/Serein.Script/SereinScriptInterpreter.cs
index 03ab98c..0bc87ed 100644
--- a/Serein.Script/SereinScriptInterpreter.cs
+++ b/Serein.Script/SereinScriptInterpreter.cs
@@ -3,445 +3,342 @@ using Serein.Library;
using Serein.Library.Utils;
using Serein.Script.Node;
using Serein.Script.Node.FlowControl;
+using System;
using System.ComponentModel.Design;
+using System.Reactive;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Xml.Linq;
-
namespace Serein.Script
{
///
- /// 脚本解释器,负责解析和执行 Serein 脚本
+ /// 脚本解释器,负责执行 Serein 脚本
///
public class SereinScriptInterpreter
{
private readonly Dictionary symbolInfos;
+ ///
+ /// 缓存对象方法调用节点
+ ///
+ private Dictionary MethodNodeDelegateCaches { get; } = new Dictionary();
public SereinScriptInterpreter(Dictionary symbolInfos)
{
this.symbolInfos = symbolInfos;
}
-
-
-
- ///
- /// 入口节点
- ///
- ///
- ///
- private async Task ExecutionProgramNodeAsync(IScriptInvokeContext context,ProgramNode programNode)
+ public async Task InterpreterAsync(IScriptInvokeContext context, ProgramNode programNode)
{
- // 加载变量
- ASTNode statement = null;
- try
+ var nodes = programNode.Statements;
+ object? result = null;
+ foreach (var node in nodes)
{
- // 遍历 ProgramNode 中的所有语句并执行它们
- for (int index = 0; index < programNode.Statements.Count; index++)
- {
- statement = programNode.Statements[index];
- // 直接退出
- if (statement is ReturnNode returnNode) // 遇到 Return 语句 提前退出
- {
- return await EvaluateAsync(context, statement);
- }
- else
- {
- var result = await InterpretAsync(context, statement);
- if (context.IsNeedReturn)
- {
- return result;
- }
- }
- }
- return null;
- }
- catch (Exception ex )
- {
- if(statement is not null)
- {
- SereinEnv.WriteLine(InfoType.ERROR, $"脚本异常发生在[行{statement.Row}]:{ex.Message}{Environment.NewLine}\t{statement.Code}");
- }
- throw;
+ result = await InterpretAsync(context, node); // 解释每个节点
+ if (context.IsReturn) break; // 如果需要提前返回,则停止执行
}
+ return result; // 返回最后一个节点的结果
}
- ///
- /// 类型定义
- ///
- ///
- ///
- private void ExecutionClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
- {
- var className = classTypeDefinitionNode.ClassType.TypeName;
- if (SereinScript.MountType.ContainsKey(className) && !classTypeDefinitionNode.IsOverlay)
- {
- //SereinEnv.WriteLine(InfoType.WARN, $"异常信息 : 类型重复定义,代码在第{classTypeDefinitionNode.Row}行: {classTypeDefinitionNode.Code.Trim()}");
- return;
- }
- if(DynamicObjectHelper.GetCacheType(className) == null)
- {
- var propertyTypes = classTypeDefinitionNode.Propertys.ToDictionary(p => p.Key, p => symbolInfos[p.Value]);
- var type = DynamicObjectHelper.CreateTypeWithProperties(propertyTypes, className); // 覆盖
- SereinScript.MountType[className] = type; // 定义对象
- }
-
- }
-
- ///
- /// IF...ELSE... 语句块
- ///
- ///
- ///
- ///
- private async Task ExecutionIfNodeAsync(IScriptInvokeContext context, IfNode ifNode)
- {
- var result = await EvaluateAsync(context, ifNode.Condition) ?? throw new SereinSciptException(ifNode, $"条件语句返回了 null");
-
- if (result is not bool condition)
- {
- throw new SereinSciptException(ifNode, "条件语句返回值不为 bool 类型");
- }
-
- var branchNodes = condition ? ifNode.TrueBranch : ifNode.FalseBranch;
- if(branchNodes is null || branchNodes.Count < 1)
- {
- return null;
- }
- else
- {
-
- foreach (var branchNode in branchNodes)
+ /*
+ async Task InterpreterAsync(IScriptInvokeContext context, ProgramNode node)
{
- if (branchNode is ReturnNode) // 遇到 Return 语句 提前退出
- {
- var reulst = await EvaluateAsync(context, branchNode);
- context.IsNeedReturn = true;
- return reulst;
- }
- else
- {
- await InterpretAsync(context, branchNode);
- }
- }
- return null;
- }
-
- }
-
- ///
- /// WHILE(){...} 语句块
- ///
- ///
- ///
- ///
- private async Task ExectutionWhileNodeAsync(IScriptInvokeContext context, WhileNode whileNode)
- {
-
- while (true)
- {
- if (context.IsReturn) // 停止流程
- {
- throw new SereinSciptException(whileNode, $"while循环已由外部主动停止");
- }
- var result = await EvaluateAsync(context, whileNode.Condition) ?? throw new SereinSciptException(whileNode, $"条件语句返回了 null");
- if (result is not bool condition)
- {
- throw new SereinSciptException(whileNode, $"条件语句返回值不为 bool 类型(当前返回值类型为 {result.GetType()})");
- }
- if (!condition)
- {
- break;
- }
- foreach(var branchNode in whileNode.Body)
- {
- if (branchNode is ReturnNode) // 遇到 Return 语句 提前退出
- {
- var reulst = await EvaluateAsync(context, branchNode);
- context.IsNeedReturn = true;
- return reulst;
- }
- else
- {
- await InterpretAsync(context, branchNode);
- }
- //await InterpretAsync(context, node);
- }
- }
- return null;
- }
-
- ///
- /// 操作节点
- ///
- ///
- ///
- private async Task ExecutionAssignmentNodeAsync(IScriptInvokeContext context, AssignmentNode assignmentNode)
- {
- if(assignmentNode.Target is IdentifierNode identifierNode)
- {
- var value = await EvaluateAsync(context, assignmentNode.Value);
- if (value is not null)
- {
- context.SetVarValue(identifierNode.Name, value);
- }
- }
- else
- {
-
- }
- /*var targetObject = await EvaluateAsync(context, assignmentNode.TargetNode);
- var value = await EvaluateAsync(context, assignmentNode.Value);
- if(value is not null)
- {
- context.SetVarValue(targetObject, value);
- }*/
- }
-
-
-
- private async Task InterpretFunctionCallAsync(IScriptInvokeContext context, FunctionCallNode functionCallNode)
- {
- if (functionCallNode.FunctionName.Equals("GetFlowContext", StringComparison.OrdinalIgnoreCase))
- {
- return context.FlowContext;
- }
-
- // 评估函数参数
- var arguments = new object?[functionCallNode.Arguments.Count];
- for (int i = 0; i < functionCallNode.Arguments.Count; i++)
- {
- ASTNode? arg = functionCallNode.Arguments[i];
- arguments[i] = await EvaluateAsync(context, arg); // 评估每个参数
- }
-
- var funcName = functionCallNode.FunctionName;
-
- object? instance = null; // 静态方法不需要传入实例,所以可以传入null
-
-
- // 查找并执行对应的函数
- if (SereinScript.FunctionDelegates .TryGetValue(funcName, out DelegateDetails? function))
- {
- if (!function.EmitMethodInfo.IsStatic)
- {
- if(SereinScript.DelegateInstances.TryGetValue(funcName, out var action))
- {
- instance = action.Invoke();// 非静态的方法需要获取相应的实例
-
- if (instance is null)
- {
- throw new SereinSciptException(functionCallNode, $"函数 {funcName} 尝试获取实例时返回了 null ");
- }
- }
- else
- {
- throw new SereinSciptException(functionCallNode, $"挂载函数 {funcName} 时需要同时给定获取实例的 Func");
- }
- }
-
- var result = await function.InvokeAsync(instance,arguments);
- return result;
- }
- else
- {
- throw new Exception($"Unknown function: {functionCallNode.FunctionName}");
- }
- }
-
-
- ///
- /// 解释操作
- ///
- ///
- ///
- ///
- ///
- public async Task InterpretAsync(IScriptInvokeContext context, ASTNode node)
- {
- if(node == null)
- {
- return null;
- }
-
- switch (node)
- {
- case ProgramNode programNode: // AST树入口
-
- var scritResult = await ExecutionProgramNodeAsync(context, programNode);
- return scritResult; // 遍历 ProgramNode 中的所有语句并执行它们
- case ClassTypeDefinitionNode classTypeDefinitionNode: // 定义类型
- ExecutionClassTypeDefinitionNode(classTypeDefinitionNode);
- break;
- case AssignmentNode assignment: // 出现在 = 右侧的表达式
- await ExecutionAssignmentNodeAsync(context, assignment);
- break;
- case CollectionAssignmentNode collectionAssignmentNode:
- await SetCollectionValue(context,collectionAssignmentNode);
- break;
- case ExpressionNode objectMemberExpressionNode:
- break;
- case MemberAssignmentNode memberAssignmentNode: // 设置对象属性
- await SetMemberValue(context, memberAssignmentNode);
- break;
- case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
- return await CallMemberFunction(context, memberFunctionCallNode);
- case IfNode ifNode: // 执行 if...else... 语句块
- return await ExecutionIfNodeAsync(context, ifNode);
- break;
- case WhileNode whileNode: // 循环语句块
- return await ExectutionWhileNodeAsync(context, whileNode);
- break;
- case FunctionCallNode functionCallNode: // 方法调用节点
- return await InterpretFunctionCallAsync(context, functionCallNode);
- case ReturnNode returnNode:
- return await EvaluateAsync(context, returnNode);
- default:
- throw new SereinSciptException(node, "解释器 InterpretAsync() 未实现节点行为");
- }
- return null;
- }
-
- ///
- /// 评估
- ///
- ///
- ///
- ///
- ///
- private async Task EvaluateAsync(IScriptInvokeContext context, ASTNode node)
- {
- if(node == null)
- {
- return null;
- }
- switch (node)
- {
- case NullNode nullNode:
return null;
- case BooleanNode booleanNode:
- return booleanNode.Value; // 返回数值
- case NumberIntNode numberNode:
- return numberNode.Value; // 返回 int 整型数
- case NumberLongNode numberNode:
- return numberNode.Value; // 返回 long 整型数
- case NumberFloatNode numberNode:
- return numberNode.Value; // 返回 float 浮点型
- case NumberDoubleNode numberNode:
- return numberNode.Value; // 返回 double 浮点型
- case StringNode stringNode:
- return stringNode.Value; // 返回字符串值
- case CharNode charNode:
- return charNode.Value; // 返回Char
- case IdentifierNode identifierNode:
- return context.GetVarValue(identifierNode.Name);
- //throw new SereinSciptException(identifierNode, "尝试使用值为null的变量");
- //throw new SereinSciptException(identifierNode, "尝试使用未声明的变量");
- case BinaryOperationNode binOpNode:
- // 递归计算二元操作
- var left = await EvaluateAsync(context, binOpNode.Left);
- //if (left == null ) throw new SereinSciptException(binOpNode.Left, $"左值尝试使用 null");
- var right = await EvaluateAsync(context, binOpNode.Right);
- //if (right == null) throw new SereinSciptException(binOpNode.Right, "右值尝试使用计算 null");
- return EvaluateBinaryOperation(left, binOpNode.Operator, right);
- case ObjectInstantiationNode objectInstantiationNode: // 对象实例化
- if (!SereinScript.MountType.TryGetValue(objectInstantiationNode.Type.TypeName, out var type))
+ }
+ return await InterpreterAsync(context, node);
+ */
+ private async Task InterpretAsync(IScriptInvokeContext context, ASTNode node)
+ {
+ switch (node)
+ {
+ case ProgramNode programNode: // 程序开始节点
+ throw new Exception();
+ case ReturnNode returnNode: // 程序退出节点
+ async Task InterpreterReturnNodeAsync(IScriptInvokeContext context, ReturnNode returnNode)
{
- type = symbolInfos[objectInstantiationNode.Type];
- if (type is null)
+ object? returnValue = await InterpretAsync(context, returnNode.Value);
+ context.IsNeedReturn = true;
+ return returnValue;
+ }
+ return await InterpreterReturnNodeAsync(context, returnNode);
+ #region 字面量节点
+ case NullNode nullNode: // null
+ return null; // 返回 null
+ case CharNode charNode: // char字面量
+ return charNode.Value; // 返回字符值
+ case StringNode stringNode: // 字符串字面量
+ return stringNode.Value; // 返回字符串值
+ case BooleanNode booleanNode: // 布尔值字面量
+ return booleanNode.Value; // 返回布尔值
+ case NumberIntNode numberIntNode: // int整型数值字面量
+ return numberIntNode.Value; // 返回 int 整型数值
+ case NumberLongNode numberLongNode: // long整型数值字面量
+ return numberLongNode.Value; // 返回 long 整型数值
+ case NumberFloatNode numberFloatNode: // float浮点数值字面量
+ return numberFloatNode.Value; // 返回 float 浮点数值
+ case NumberDoubleNode numberDoubleNode: // double浮点数值字面量
+ return numberDoubleNode.Value; // 返回 double 浮点数值
+ #endregion
+ case IdentifierNode identifierNode: // 变量定义
+ return context.GetVarValue(identifierNode.Name);
+ case IfNode ifNode: // if语句结构
+ async Task InterpreterIfNodeAsync(IScriptInvokeContext context, IfNode ifNode)
+ {
+ var result = await InterpretAsync(context, ifNode.Condition) ?? throw new SereinSciptException(ifNode, $"条件语句返回了 null");
+ if (result is not bool condition) throw new SereinSciptException(ifNode, "条件语句返回值不为 bool 类型");
+ var branchNodes = condition ? ifNode.TrueBranch : ifNode.FalseBranch;
+ if (branchNodes.Count == 0) return default;
+ object? data = default;
+ foreach (var branchNode in branchNodes)
{
- throw new SereinSciptException(objectInstantiationNode, $"使用了未定义的类型\"{objectInstantiationNode.Type.TypeName}\"");
+ data = await InterpretAsync(context, branchNode);
+ if (branchNode is ReturnNode) // 遇到 Return 语句 提前退出
+ {
+ context.IsNeedReturn = true;
+ break;
+ }
+ }
+ return data;
+ }
+
+ return await InterpreterIfNodeAsync(context, ifNode);
+ case WhileNode whileNode: // while语句结构
+ async Task InterpreterWhileNodeAsync(IScriptInvokeContext context, WhileNode whileNode)
+ {
+ object? data = default;
+ while (true)
+ {
+ var result = await InterpretAsync(context, whileNode.Condition) ?? throw new SereinSciptException(whileNode, $"循环节点条件返回了 null");
+ if (result is not bool condition) throw new SereinSciptException(whileNode, "循环节点条件返回值不为 bool 类型");
+ if (!condition) break;
+ if (whileNode.Body.Count == 0) break;
+ foreach (var node in whileNode.Body)
+ {
+ data = await InterpretAsync(context, node);
+ if (node is ReturnNode) // 遇到 Return 语句 提前退出
+ {
+ context.IsNeedReturn = true;
+ break ;
+ }
+ }
+ }
+ return data;
+ }
+ await InterpreterWhileNodeAsync(context, whileNode);
+ return default;
+ case AssignmentNode assignmentNode: // 变量赋值语句
+ async Task InterpreterAssignmentNodeAsync(IScriptInvokeContext context, AssignmentNode assignmentNode)
+ {
+ if (assignmentNode.Target is IdentifierNode identifierNode)
+ {
+ var value = await InterpretAsync(context, assignmentNode.Value);
+ context.SetVarValue(identifierNode.Name, value);
}
}
- object?[] args = new object[objectInstantiationNode.Arguments.Count];
- for (int i = 0; i < objectInstantiationNode.Arguments.Count; i++)
+ await InterpreterAssignmentNodeAsync(context, assignmentNode);
+ return default;
+ case BinaryOperationNode binaryOperationNode: // 二元运算操作
+ async Task InterpreterBinaryOperationNodeAsync(IScriptInvokeContext context, BinaryOperationNode binaryOperationNode)
{
- var argNode = objectInstantiationNode.Arguments[i];
- args[i] = await EvaluateAsync(context, argNode);
+ // 递归计算二元操作
+ var left = await InterpretAsync(context, binaryOperationNode.Left);
+ if (left == null ) throw new SereinSciptException(binaryOperationNode.Left, $"左值尝试使用 null");
+ var right = await InterpretAsync(context, binaryOperationNode.Right);
+ if (right == null) throw new SereinSciptException(binaryOperationNode.Right, "右值尝试使用计算 null");
+ var op = binaryOperationNode.Operator;
+ var result = BinaryOperationEvaluator.EvaluateValue(left, op, right);
+ return result;
}
- var obj = Activator.CreateInstance(type, args: args);// 创建对象
- if (obj == null)
+ return await InterpreterBinaryOperationNodeAsync(context, binaryOperationNode);
+ case CollectionAssignmentNode collectionAssignmentNode: // 集合赋值节点
+ async Task InterpreterCollectionAssignmentNodeAsync(IScriptInvokeContext context, CollectionAssignmentNode collectionAssignmentNode)
{
- throw new SereinSciptException(objectInstantiationNode, $"类型创建失败\"{objectInstantiationNode.Type.TypeName}\"");
+ var collectionValue = await InterpretAsync(context, collectionAssignmentNode.Collection.Collection);
+ if (collectionValue is null)
+ {
+ throw new ArgumentNullException($"解析{collectionAssignmentNode}节点时,集合返回空。");
+ }
+ var indexValue = await InterpretAsync(context, collectionAssignmentNode.Collection.Index);
+ if (indexValue is null)
+ {
+ throw new ArgumentNullException($"解析{collectionAssignmentNode}节点时,索引返回空。");
+ }
+ var valueValue = await InterpretAsync(context, collectionAssignmentNode.Value);
+ SetCollectionValue(collectionValue, indexValue, valueValue);
}
- for (int i = 0; i < objectInstantiationNode.CtorAssignments.Count; i++)
+ await InterpreterCollectionAssignmentNodeAsync(context, collectionAssignmentNode);
+ return default;
+ case CollectionIndexNode collectionIndexNode: // 集合获取索引对应值
+ async Task InterpreterCollectionIndexNodeAsync(IScriptInvokeContext context, CollectionIndexNode collectionIndexNode)
{
- var ctorAssignmentNode = objectInstantiationNode.CtorAssignments[i];
- var propertyName = ctorAssignmentNode.MemberName;
- var value = await EvaluateAsync(context, ctorAssignmentNode.Value);
- SetPropertyValue(obj, propertyName, value);
+ var collectionValue = await InterpretAsync(context, collectionIndexNode.Collection);
+ if (collectionValue is null)
+ {
+ throw new ArgumentNullException($"解析{collectionIndexNode}节点时,集合返回空。");
+ }
+ var indexValue = await InterpretAsync(context, collectionIndexNode.Index);
+ if (indexValue is null)
+ {
+ throw new ArgumentNullException($"解析{collectionIndexNode}节点时,索引返回空。");
+ }
+ var result = GetCollectionValue(collectionValue, indexValue);
+ return result;
}
+ return await InterpreterCollectionIndexNodeAsync(context, collectionIndexNode);
+ case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
+ void InterpreterClassTypeDefinitionNode(IScriptInvokeContext context, ClassTypeDefinitionNode classTypeDefinitionNode)
+ {
+ var className = classTypeDefinitionNode.ClassType.TypeName;
+ if (SereinScript.MountType.ContainsKey(className))
+ {
+ //SereinEnv.WriteLine(InfoType.WARN, $"异常信息 : 类型重复定义,代码在第{classTypeDefinitionNode.Row}行: {classTypeDefinitionNode.Code.Trim()}");
+ return;
+ }
+ if (DynamicObjectHelper.GetCacheType(className) == null)
+ {
+ var propertyTypes = classTypeDefinitionNode.Propertys.ToDictionary(p => p.Key, p => symbolInfos[p.Value]);
+ var type = DynamicObjectHelper.CreateTypeWithProperties(propertyTypes, className); // 实例化新的类型
+ SereinScript.MountType[className] = type; // 定义对象
+ }
+ }
+ InterpreterClassTypeDefinitionNode(context, classTypeDefinitionNode);
+ return default;
+ case TypeNode typeNode: // 类型
+ return default;
+ case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
+ async Task InterpreterObjectInstantiationNodeAsync(IScriptInvokeContext context, ObjectInstantiationNode objectInstantiationNode)
+ {
+ if (!SereinScript.MountType.TryGetValue(objectInstantiationNode.Type.TypeName, out var type))
+ {
+ type = symbolInfos[objectInstantiationNode.Type];
+ if (type is null)
+ {
+ throw new SereinSciptException(objectInstantiationNode, $"使用了未定义的类型\"{objectInstantiationNode.Type.TypeName}\"");
+ }
+ }
- return obj;
- case FunctionCallNode callNode: // 调用方法
- return await InterpretFunctionCallAsync(context, callNode); // 调用方法返回函数的返回值
- case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
- return await CallMemberFunction(context, memberFunctionCallNode);
+ // 获取参数
+ var args = objectInstantiationNode.Arguments.Count == 0 ? [] :
+ (await objectInstantiationNode.Arguments.SelectAsync(
+ async argNode => await InterpretAsync(context, argNode)))
+ .ToArray();
+
+ var obj = Activator.CreateInstance(type, args: args);// 创建对象
+ if (obj is null)
+ {
+ throw new SereinSciptException(objectInstantiationNode, $"类型创建失败\"{objectInstantiationNode.Type.TypeName}\"");
+ }
+
+ for (int i = 0; i < objectInstantiationNode.CtorAssignments.Count; i++)
+ {
+ var ctorAssignmentNode = objectInstantiationNode.CtorAssignments[i];
+ var propertyName = ctorAssignmentNode.MemberName;
+ var value = await InterpretAsync(context, ctorAssignmentNode.Value);
+ SetPropertyValue(obj, propertyName, value);
+ }
+ return obj;
+ }
+ return await InterpreterObjectInstantiationNodeAsync(context, objectInstantiationNode);
+ case CtorAssignmentNode ctorAssignmentNode:
+ return default;
+ case ExpressionNode expressionNode: // 类型表达式(链式调用)
+ return await InterpretAsync(context, expressionNode.Value); // 直接计算表达式的值
case MemberAccessNode memberAccessNode: // 对象成员访问
- return await GetMemberValue(context, memberAccessNode);
- case CollectionIndexNode collectionIndexNode:
- return await GetCollectionValue(context, collectionIndexNode);
- case ReturnNode returnNode: // 返回内容
- return await EvaluateAsync(context, returnNode.Value); // 直接返回响应的内容
- case ExpressionNode expressionNode: // 表达式
- return await EvaluateAsync(context, expressionNode.Value);
- default:
- throw new SereinSciptException(node, $"解释器 EvaluateAsync() 未实现{node}节点行为");
- }
- }
+ async Task InterpreterMemberAccessNodeAsync(IScriptInvokeContext context, MemberAccessNode memberAccessNode)
+ {
+ var target = await InterpretAsync(context, memberAccessNode.Object);
+ var memberName = memberAccessNode.MemberName;
+ if(target is null) throw new SereinSciptException(memberAccessNode, $"无法获取成员,对象为 null \"{memberAccessNode.Object.Code}\"");
+ var value = GetPropertyValue(target, memberName);
+ return value;
+ }
+ return await InterpreterMemberAccessNodeAsync(context, memberAccessNode);
+ case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
+ async Task InterpreterMemberAssignmentNodeAsync(IScriptInvokeContext context, MemberAssignmentNode memberAssignmentNode)
+ {
+ var target = await InterpretAsync(context, memberAssignmentNode.Object);
+ var memberName = memberAssignmentNode.MemberName;
+ var value = await InterpretAsync(context, memberAssignmentNode.Value);
+ if (target is null) throw new SereinSciptException(memberAssignmentNode, $"无法设置成员,对象为 null \"{memberAssignmentNode.Object.Code}\"");
+ SetPropertyValue(target, memberName, value);
+ return value;
+ }
+ return await InterpreterMemberAssignmentNodeAsync(context, memberAssignmentNode);
+ case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
+ async Task InterpreterMemberFunctionCallNodeAsync(IScriptInvokeContext context, MemberFunctionCallNode memberFunctionCallNode)
+ {
+ var target = await InterpretAsync(context, memberFunctionCallNode.Object);
+ if (!MethodNodeDelegateCaches.TryGetValue(memberFunctionCallNode, out DelegateDetails? delegateDetails))
+ {
+ var methodName = memberFunctionCallNode.FunctionName;
+ var methodInfo = memberFunctionCallNode.Arguments.Count == 0 ? target?.GetType().GetMethod(methodName, []) : target?.GetType().GetMethod(methodName);// 获取参数列表的类型
+ if (methodInfo is null) throw new SereinSciptException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\"");
+ delegateDetails = new DelegateDetails(methodInfo);
+ MethodNodeDelegateCaches[memberFunctionCallNode] = delegateDetails;
+ } // 查询是否有缓存
- private object EvaluateBinaryOperation(object left, string op, object right)
- {
- return BinaryOperationEvaluator.EvaluateValue(left, op, right);
- // 根据运算符执行不同的运算
- switch (op)
- {
- case "+":
- if (left is string || right is string)
- {
- return left?.ToString() + right?.ToString(); // 字符串拼接
- }
- else if (left is int leftInt && right is int rightInt)
- {
- return leftInt + rightInt; // 整数加法
- }
- else if (left is long leftLong && right is long rightLong)
- {
- return leftLong + rightLong; // 整数加法
- }
- else if (left is double leftDouble && right is double rightDouble)
- {
- return leftDouble + rightDouble; // 整数加法
- }
- else
- {
- dynamic leftValue = Convert.ToDouble(left);
- dynamic rightValue = Convert.ToDouble(right);
- return leftValue + rightValue;
- }
- throw new Exception("Invalid types for + operator");
- case "-":
- return (int)left - (int)right;
- case "*":
- return (int)left * (int)right;
- case "/":
- return (int)left / (int)right;
+ // 获取参数
+ var arguments = memberFunctionCallNode.Arguments.Count == 0 ? [] :
+ (await memberFunctionCallNode.Arguments.SelectAsync(
+ async argNode => await InterpretAsync(context, argNode)))
+ .ToArray();
- case ">":
- return (int)left > (int)right;
- case "<":
- return (int)left < (int)right;
- case "==":
- return Equals(left, right);
- case "!=":
- return !Equals(left, right);
+ // 调用方法
+ var reuslt = await delegateDetails.InvokeAsync(target, arguments);
+ return reuslt;
+ }
+ return await InterpreterMemberFunctionCallNodeAsync(context, memberFunctionCallNode);
+ case FunctionCallNode functionCallNode: // 外部挂载的函数调用
+ async Task InterpreterFunctionCallNodeAsync(IScriptInvokeContext context, FunctionCallNode functionCallNode)
+ {
+ // 获取流程上下文
+ if (functionCallNode.FunctionName.Equals("getFlowApi", StringComparison.OrdinalIgnoreCase))
+ {
+ return context.FlowContext;
+ }
+ else if (functionCallNode.FunctionName.Equals("getScriptApi", StringComparison.OrdinalIgnoreCase))
+ {
+ return context;
+ }
- default:
- throw new NotImplementedException("未定义的操作符: " + op);
+ // 获取参数
+ var arguments = functionCallNode.Arguments.Count == 0 ? [] :
+ (await functionCallNode.Arguments.SelectAsync(
+ async argNode => await InterpretAsync(context, argNode)))
+ .ToArray();
+
+
+ var funcName = functionCallNode.FunctionName;
+
+ object? instance = null; // 静态方法不需要传入实例,所以可以传入null
+
+ // 查找并执行对应的函数
+ if (!SereinScript.FunctionDelegates.TryGetValue(funcName, out DelegateDetails? function))
+ throw new SereinSciptException(functionCallNode, $"没有挂载方法\"{functionCallNode.FunctionName}\"");
+
+ if (!function.EmitMethodInfo.IsStatic)
+ {
+ if (!SereinScript.DelegateInstances.TryGetValue(funcName, out var action))
+ {
+ throw new SereinSciptException(functionCallNode, $"挂载方法 {funcName} 时需要同时给定获取实例的 Func");
+ }
+
+ instance = action.Invoke();// 非静态的方法需要获取相应的实例
+ if (instance is null)
+ {
+ throw new SereinSciptException(functionCallNode, $"函数 {funcName} 尝试获取实例时返回了 null ");
+ }
+ }
+
+ var result = await function.InvokeAsync(instance, arguments);
+ return result;
+ }
+ return await InterpreterFunctionCallNodeAsync(context, functionCallNode);
+ default: // 未定义的节点类型
+ throw new Exception($"解释器未实现的节点类型 {node.GetType()}");
}
}
@@ -449,54 +346,11 @@ namespace Serein.Script
///
/// 设置对象成员
///
- ///
- ///
- ///
- public async Task SetMemberValue(IScriptInvokeContext context, MemberAssignmentNode memberAssignmentNode)
- {
- var target = await EvaluateAsync(context, memberAssignmentNode.Object);
- var value = await EvaluateAsync(context, memberAssignmentNode.Value);
- // 设置值
- var lastMember = memberAssignmentNode.MemberName;
-
- var lastProperty = target?.GetType().GetProperty(lastMember);
- if (lastProperty is null)
- {
- var lastField = target?.GetType().GetRuntimeField(lastMember);
- if (lastField is null)
- {
- throw new SereinSciptException(memberAssignmentNode, $"对象没有成员\"{memberAssignmentNode.MemberName}\"");
- }
- else
- {
- var convertedValue = Convert.ChangeType(value, lastField.FieldType);
- lastField.SetValue(target, convertedValue);
- }
- }
- else
- {
- if(value is null)
- {
- lastProperty.SetValue(target, null);
- return;
- }
- var valueTtpe = value.GetType();
- if (lastProperty.PropertyType.IsAssignableFrom(valueTtpe))
- {
- lastProperty.SetValue(target, value);
- }
- else if (lastProperty.PropertyType.FullName == valueTtpe.FullName)
- {
- lastProperty.SetValue(target, value);
- }
- else {
- throw new SereinSciptException(memberAssignmentNode, $"对象成员赋值时类型异常:\"{memberAssignmentNode.MemberName}\"");
- }
- //var convertedValue = Convert.ChangeType(value, );
- }
- }
-
- public void SetPropertyValue(object target, string memberName, object? value)
+ /// 对象
+ /// 属性名称
+ /// 属性值
+ ///
+ private void SetPropertyValue(object target, string memberName, object? value)
{
var targetType = target?.GetType();
if (targetType is null) return;
@@ -534,132 +388,49 @@ namespace Serein.Script
{
throw new Exception($"类型 {targetType} 对象成员\"{memberName}\" 赋值时异常");
}
- //var convertedValue = Convert.ChangeType(value, );
}
}
///
- /// 获取对象成员
+ /// 从对象获取值
///
- ///
+ /// 对象
+ /// 成员名称
///
- ///
- public async Task GetMemberValue(IScriptInvokeContext context, MemberAccessNode memberAccessNode)
+ ///
+ private object? GetPropertyValue(object target, string memberName)
{
- var target = await EvaluateAsync(context, memberAccessNode.Object);
- var lastMember = memberAccessNode.MemberName;
-
- var lastProperty = target?.GetType().GetProperty(lastMember);
- if (lastProperty is null)
+ var targetType = target?.GetType();
+ if (targetType is null) return null;
+ var propertyInfo = targetType.GetProperty(memberName);
+ if (propertyInfo is null)
{
- var lastField = target?.GetType().GetRuntimeField(lastMember);
- if (lastField is null)
+ var fieldInfo = target?.GetType().GetRuntimeField(memberName);
+ if (fieldInfo is null)
{
- throw new SereinSciptException(memberAccessNode, $"对象没有成员\"{memberAccessNode.MemberName}\"");
+ throw new Exception($"类型 {targetType} 对象没有成员\"{memberName}\"");
}
else
{
- return lastField.GetValue(target);
+ return fieldInfo.GetValue(target);
}
}
else
{
- return lastProperty.GetValue(target);
+ return propertyInfo.GetValue(target);
}
}
-
+
///
- /// 获取集合中的成员
+ /// 设置集合成员
///
- ///
+ ///
+ ///
+ ///
///
- ///
- public async Task GetCollectionValue(IScriptInvokeContext context, CollectionIndexNode collectionIndexNode)
+ ///
+ private void SetCollectionValue(object collectionValue, object indexValue, object valueValue)
{
- var target = await EvaluateAsync(context, collectionIndexNode.Collection); // 获取对象
- if (target is null)
- {
- throw new ArgumentNullException($"解析{collectionIndexNode}节点时,TargetValue返回空。");
- }
-
- // 解析数组/集合名与索引部分
- var targetType = target.GetType(); // 目标对象的类型
- #region 处理键值对
- if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
- {
- // 目标是键值对
- var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
- if (method is not null)
- {
- var key = await EvaluateAsync(context, collectionIndexNode.Index); // 获取索引值;
- var result = method.Invoke(target, new object[] { key });
- return result;
- }
- }
- #endregion
- #region 处理集合对象
- else
- {
- var indexValue = await EvaluateAsync(context, collectionIndexNode.Index); // 获取索引值
- object? result;
- if (indexValue is int index)
- {
- // 获取数组或集合对象
- // 访问数组或集合中的指定索引
- if (target is Array array)
- {
- if (index < 0 || index >= array.Length)
- {
- throw new ArgumentException($"解析{collectionIndexNode}节点时,数组下标越界。");
- }
- result = array.GetValue(index);
- return result;
- }
- else if (target is IList list)
- {
- if (index < 0 || index >= list.Count)
- {
- throw new ArgumentException($"解析{collectionIndexNode}节点时,数组下标越界。");
- }
- result = list[index];
- return result;
- }
- else if (target is string chars)
- {
- return chars[index];
- }
- else
- {
- throw new ArgumentException($"解析{collectionIndexNode}节点时,左值并非有效集合。");
- }
- }
- }
- #endregion
-
- throw new ArgumentException($"解析{collectionIndexNode}节点时,左值并非有效集合。");
-
- }
-
- ///
- /// 设置集合中的成员
- ///
- ///
- ///
- ///
- public async Task SetCollectionValue(IScriptInvokeContext context, CollectionAssignmentNode collectionAssignmentNode)
- {
- var collectionValue = await EvaluateAsync(context, collectionAssignmentNode.Collection.Collection);
- var indexValue = await EvaluateAsync(context, collectionAssignmentNode.Collection.Index);
-
- if (collectionValue is null)
- {
- throw new ArgumentNullException($"解析{collectionAssignmentNode}节点时,集合返回空。");
- }
- if (indexValue is null)
- {
- throw new ArgumentNullException($"解析{collectionAssignmentNode}节点时,索引返回空。");
- }
-
// 解析数组/集合名与索引部分
var targetType = collectionValue.GetType(); // 目标对象的类型
#region 处理键值对
@@ -669,7 +440,6 @@ namespace Serein.Script
var method = targetType.GetMethod("set_Item", BindingFlags.Public | BindingFlags.Instance);
if (method is not null)
{
- var valueValue = await EvaluateAsync(context, collectionAssignmentNode.Value);
method.Invoke(collectionValue, [indexValue, valueValue]);
}
}
@@ -687,7 +457,6 @@ namespace Serein.Script
{
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
}
- var valueValue = await EvaluateAsync(context, collectionAssignmentNode.Value);
array.SetValue(valueValue, index);
return;
}
@@ -697,77 +466,67 @@ namespace Serein.Script
{
throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
}
- var valueValue = await EvaluateAsync(context, collectionAssignmentNode.Value);
list[index] = valueValue;
return;
}
- else
+ }
+ }
+ #endregion
+ throw new ArgumentException($"解析异常, {collectionValue} 并非有效集合。");
+ }
+
+ ///
+ /// 获取集合中的成员
+ ///
+ ///
+ ///
+ ///
+ ///
+ private object? GetCollectionValue(object collectionValue, object indexValue)
+ {
+ // 解析数组/集合名与索引部分
+ var targetType = collectionValue.GetType(); // 目标对象的类型
+ #region 处理键值对
+ if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
+ {
+ // 目标是键值对
+ var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
+ if (method is not null)
+ {
+ var value = method.Invoke(collectionValue, [indexValue]);
+ return value;
+ }
+ }
+ #endregion
+ #region 处理集合对象
+ else
+ {
+ if (indexValue is int index)
+ {
+ // 获取数组或集合对象
+ // 访问数组或集合中的指定索引
+ if (collectionValue is Array array)
{
- throw new ArgumentException($"解析{collectionValue}节点时,左值并非有效集合。");
+ if (index < 0 || index >= array.Length)
+ {
+ throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
+ }
+
+ return array.GetValue(index);
+ }
+ else if (collectionValue is IList list)
+ {
+ if (index < 0 || index >= list.Count)
+ {
+ throw new ArgumentException($"解析{collectionValue}节点时,数组下标越界。");
+ }
+ return list[index];
}
}
}
#endregion
throw new ArgumentException($"解析{collectionValue}节点时,左值并非有效集合。");
-
- }
-
- ///
- /// 缓存method委托
- ///
- private Dictionary MethodToDelegateCaches { get; } = new Dictionary();
-
- public async Task CallMemberFunction(IScriptInvokeContext context, MemberFunctionCallNode memberFunctionCallNode)
- {
- var target = await EvaluateAsync(context, memberFunctionCallNode.Object);
- var lastMember = memberFunctionCallNode.FunctionName;
- if(lastMember == "ToUpper")
- {
-
- }
- MethodInfo? methodInfo = null;
- if (memberFunctionCallNode.Arguments.Count == 0)
- {
-
- // 查询无参方法
- methodInfo = target?.GetType().GetMethod(lastMember, []) ?? throw new SereinSciptException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\"");
- }
- else
- {
- // 获取参数列表的类型
- methodInfo = target?.GetType().GetMethod(lastMember) ?? throw new SereinSciptException(memberFunctionCallNode, $"对象没有方法\"{memberFunctionCallNode.FunctionName}\"");
-
- }
-
- /*Type[] paramTypes = new
- {
-
- }*/
-
- if (!MethodToDelegateCaches.TryGetValue(methodInfo.MetadataToken, out DelegateDetails? delegateDetails))
- {
- delegateDetails = new DelegateDetails(methodInfo);
- MethodToDelegateCaches[methodInfo.MetadataToken] = delegateDetails;
- }
-
- if(memberFunctionCallNode.Arguments.Count == 0)
- {
- var reuslt = await delegateDetails.InvokeAsync(target, []);
- return reuslt;
- }
- else
- {
- var arguments = new object?[memberFunctionCallNode.Arguments.Count];
- for (int i = 0; i < memberFunctionCallNode.Arguments.Count; i++)
- {
- ASTNode? arg = memberFunctionCallNode.Arguments[i];
- arguments[i] = await EvaluateAsync(context, arg); // 评估每个参数
- }
- var reuslt = await delegateDetails.InvokeAsync(target, arguments);
- return reuslt;
- }
-
}
diff --git a/Serein.Script/SereinScriptLexer.cs b/Serein.Script/SereinScriptLexer.cs
index 9a5a2a7..862ceca 100644
--- a/Serein.Script/SereinScriptLexer.cs
+++ b/Serein.Script/SereinScriptLexer.cs
@@ -198,7 +198,6 @@ namespace Serein.Script
this._index = token.StartIndex;
}
-
internal Token NextToken()
{
@@ -525,7 +524,6 @@ namespace Serein.Script
return ReadOnlySpan.Empty;
}
-
public int GetIndex()
{
return _index;
diff --git a/Serein.Script/SereinScriptTypeAnalysis.cs b/Serein.Script/SereinScriptTypeAnalysis.cs
index d73776f..15d5810 100644
--- a/Serein.Script/SereinScriptTypeAnalysis.cs
+++ b/Serein.Script/SereinScriptTypeAnalysis.cs
@@ -75,7 +75,6 @@ namespace Serein.Script
}
-
///
/// 类型获取
///
@@ -542,6 +541,8 @@ namespace Serein.Script
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
break;
+ case CtorAssignmentNode ctorAssignmentNode:
+ break;
case ExpressionNode expressionNode: // 类型表达式(链式调用)
break;
case MemberAccessNode memberAccessNode: // 对象成员访问