mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
1. 新增了脚本节点之间连接时,入参类型伴随来源节点的返回类型改变而改变。
2. 重新优化了Script项目脚本生成代码的缩进排版 3. 修复了Script中对于Double字面量错误的使用了Float解析的bug
This commit is contained in:
@@ -27,13 +27,15 @@ namespace Serein.Library
|
||||
RunState = RunState.Running;
|
||||
}
|
||||
|
||||
private string _guid = global::System.Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 是否记录流程调用信息
|
||||
/// </summary>
|
||||
public bool IsRecordInvokeInfo { get; set; } = true;
|
||||
string IFlowContext.Guid => _guid;
|
||||
|
||||
/// <summary>
|
||||
/// 标识流程的Guid
|
||||
/// </summary>
|
||||
public string Guid { get; private set; } = global::System.Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// 运行环境
|
||||
@@ -97,7 +99,7 @@ namespace Serein.Library
|
||||
|
||||
FlowInvokeInfo flowInvokeInfo = new FlowInvokeInfo
|
||||
{
|
||||
ContextGuid = this._guid,
|
||||
ContextGuid = this.Guid,
|
||||
Id = id,
|
||||
PreviousNodeGuid = previousNode?.Guid,
|
||||
Method = theNode.MethodDetails?.MethodName,
|
||||
@@ -258,7 +260,7 @@ namespace Serein.Library
|
||||
NextOrientation = ConnectionInvokeType.None;
|
||||
RunState = RunState.Running;
|
||||
flowInvokeInfos.Clear();
|
||||
_guid = global::System.Guid.NewGuid().ToString();
|
||||
Guid = global::System.Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
|
||||
};
|
||||
this.MethodDetails.ParameterDetailss = [.. pd];
|
||||
this.MethodDetails.ReturnType = typeof(object);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,14 +104,12 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
{
|
||||
if(token.IsCancellationRequested) return FlowResult.Fail(this.Guid, context, "流程已通过token取消");
|
||||
|
||||
object? parameter = null;// context.TransmissionData(this); // 表达式节点使用上一节点数据
|
||||
object? parameter = null;// 表达式节点使用上一节点数据
|
||||
var pd = MethodDetails.ParameterDetailss[0];
|
||||
|
||||
var hasNode = context.Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var argSourceNode);
|
||||
if (!hasNode)
|
||||
{
|
||||
/*context.NextOrientation = ConnectionInvokeType.IsError;
|
||||
return new FlowResult(this.Guid, context);*/
|
||||
parameter = null;
|
||||
}
|
||||
else
|
||||
@@ -130,14 +129,6 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
parameter = result.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
else
|
||||
{
|
||||
// 条件节点透传上一节点的数据
|
||||
parameter = context.TransmissionData(this.Guid);
|
||||
}
|
||||
*/
|
||||
try
|
||||
{
|
||||
var result = await GetValueExpressionAsync(context, parameter, Expression);
|
||||
@@ -184,6 +175,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
{ dataName, dataType},
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
IScriptInvokeContext scriptContext = new ScriptInvokeContext(flowContext);
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
public SingleScriptNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
sereinScript = new SereinScript();
|
||||
|
||||
}
|
||||
|
||||
static SingleScriptNode()
|
||||
@@ -106,6 +107,38 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新节点返回类型
|
||||
/// </summary>
|
||||
/// <param name="newType"></param>
|
||||
private void UploadNodeReturnType(Type newType)
|
||||
{
|
||||
MethodDetails.ReturnType = newType;
|
||||
|
||||
|
||||
foreach (var ct in NodeStaticConfig.ConnectionArgSourceTypes)
|
||||
{
|
||||
var newResultNodes = NeedResultNodes[ct].ToArray();
|
||||
foreach (var node in newResultNodes)
|
||||
{
|
||||
if(node is SingleScriptNode scriptNode)
|
||||
{
|
||||
var pds = scriptNode.MethodDetails.ParameterDetailss;
|
||||
foreach (var pd in pds)
|
||||
{
|
||||
if (pd.ArgDataSourceType == ct &&
|
||||
pd.ArgDataSourceNodeGuid == this.Guid)
|
||||
{
|
||||
pd.DataType = newType; // 更新参数类型
|
||||
}
|
||||
}
|
||||
//scriptNode.ReloadScript(); // 重新加载目标脚本节点
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存项目时保存脚本代码、方法入参类型、返回值类型
|
||||
/// </summary>
|
||||
@@ -181,56 +214,75 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private object reloadLockObj = new object();
|
||||
/// <summary>
|
||||
/// 重新加载脚本代码
|
||||
/// </summary>
|
||||
public bool ReloadScript()
|
||||
{
|
||||
lock (reloadLockObj)
|
||||
{
|
||||
if (!CheckRepeatParamter())
|
||||
return false;
|
||||
var argTypes = GetParamterTypeInfo();
|
||||
try
|
||||
{
|
||||
HashSet<string> varNames = new HashSet<string>();
|
||||
foreach (var pd in MethodDetails.ParameterDetailss)
|
||||
{
|
||||
if (varNames.Contains(pd.Name))
|
||||
{
|
||||
throw new Exception($"脚本节点重复的变量名称:{pd.Name} - {Guid}");
|
||||
}
|
||||
varNames.Add(pd.Name);
|
||||
}
|
||||
|
||||
var argTypes = MethodDetails.ParameterDetailss
|
||||
.Select(pd =>
|
||||
{
|
||||
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
|
||||
{
|
||||
var Type = pd.DataType;
|
||||
return (pd.Name, Type);
|
||||
}
|
||||
if (Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var node) &&
|
||||
node.MethodDetails?.ReturnType is not null)
|
||||
{
|
||||
pd.DataType = node.MethodDetails.ReturnType;
|
||||
var Type = node.MethodDetails.ReturnType;
|
||||
return (pd.Name, Type);
|
||||
}
|
||||
return default;
|
||||
})
|
||||
.Where(x => x != default)
|
||||
.ToDictionary(x => x.Name, x => x.Type); // 准备预定义类型
|
||||
|
||||
|
||||
var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点
|
||||
MethodDetails.ReturnType = returnType;
|
||||
return true;
|
||||
UploadNodeReturnType(returnType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.WARN, ex.Message);
|
||||
return false; // 解析失败
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查脚本参数是否有重复的名称
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool CheckRepeatParamter()
|
||||
{
|
||||
bool isSueccess = true;
|
||||
HashSet<string> varNames = new HashSet<string>();
|
||||
foreach (var pd in MethodDetails.ParameterDetailss)
|
||||
{
|
||||
if (varNames.Contains(pd.Name))
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"脚本节点重复的变量名称:{pd.Name} - {Guid}");
|
||||
|
||||
isSueccess = false;
|
||||
}
|
||||
varNames.Add(pd.Name);
|
||||
}
|
||||
return isSueccess;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取参数类型信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private Dictionary<string, Type> GetParamterTypeInfo()
|
||||
{
|
||||
Dictionary<string, Type> argTypes = [];
|
||||
var pds = MethodDetails.ParameterDetailss.ToArray();
|
||||
foreach (var pd in pds)
|
||||
{
|
||||
if (pd.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
|
||||
{
|
||||
argTypes[pd.Name] = pd.DataType;
|
||||
}
|
||||
if (Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var node) &&
|
||||
node.MethodDetails?.ReturnType is not null)
|
||||
{
|
||||
pd.DataType = node.MethodDetails.ReturnType;
|
||||
var Type = node.MethodDetails.ReturnType;
|
||||
argTypes[pd.Name] = Type;
|
||||
}
|
||||
}
|
||||
return argTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -246,39 +298,11 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
methodName = $"FlowMethod_{tmp}";
|
||||
}
|
||||
|
||||
HashSet<string> varNames = new HashSet<string>();
|
||||
foreach (var pd in MethodDetails.ParameterDetailss)
|
||||
{
|
||||
if (varNames.Contains(pd.Name))
|
||||
{
|
||||
throw new Exception($"脚本节点重复的变量名称:{pd.Name} - {Guid}");
|
||||
}
|
||||
varNames.Add(pd.Name);
|
||||
}
|
||||
|
||||
var argTypes = MethodDetails.ParameterDetailss
|
||||
.Select(pd =>
|
||||
{
|
||||
if(pd.ArgDataSourceType == ConnectionArgSourceType.GetPreviousNodeData)
|
||||
{
|
||||
var Type = pd.DataType;
|
||||
return (pd.Name, Type);
|
||||
}
|
||||
if (Env.TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var node) &&
|
||||
node.MethodDetails?.ReturnType is not null)
|
||||
{
|
||||
pd.DataType = node.MethodDetails.ReturnType;
|
||||
var Type = node.MethodDetails.ReturnType;
|
||||
return (pd.Name, Type);
|
||||
}
|
||||
return default;
|
||||
})
|
||||
.Where(x => x != default)
|
||||
.ToDictionary(x => x.Name, x => x.Type); // 准备预定义类型
|
||||
|
||||
|
||||
if (!CheckRepeatParamter())
|
||||
throw new Exception($"脚本节点入参重复");
|
||||
var argTypes = GetParamterTypeInfo();
|
||||
var returnType = sereinScript.ParserScript(Script, argTypes); // 开始解析获取程序主节点
|
||||
MethodDetails.ReturnType = returnType;
|
||||
UploadNodeReturnType(returnType);
|
||||
var scriptMethodInfo = sereinScript.ConvertCSharpCode(methodName, argTypes);
|
||||
return scriptMethodInfo;
|
||||
}
|
||||
@@ -297,6 +321,13 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
/// <returns></returns>
|
||||
public override async Task<FlowResult> ExecutingAsync(IFlowContext context, CancellationToken token)
|
||||
{
|
||||
if (IsScriptChanged)
|
||||
{
|
||||
if (!ReloadScript())
|
||||
{
|
||||
return FlowResult.Fail(this.Guid, context, "脚本解析失败,请检查脚本代码");
|
||||
}
|
||||
}
|
||||
var result = await ExecutingAsync(this, context, token);
|
||||
return result;
|
||||
}
|
||||
@@ -311,6 +342,14 @@ namespace Serein.NodeFlow.Model.Nodes
|
||||
public async Task<FlowResult> ExecutingAsync(NodeModelBase flowCallNode, IFlowContext context, CancellationToken token)
|
||||
{
|
||||
if (token.IsCancellationRequested) return FlowResult.Fail(this.Guid, context, "流程已通过token取消");
|
||||
if (IsScriptChanged)
|
||||
{
|
||||
if (!ReloadScript())
|
||||
{
|
||||
return FlowResult.Fail(this.Guid, context, "脚本解析失败,请检查脚本代码");
|
||||
}
|
||||
}
|
||||
|
||||
var @params = await flowCallNode.GetParametersAsync(context, token);
|
||||
|
||||
IScriptInvokeContext scriptContext = new ScriptInvokeContext(context);
|
||||
|
||||
@@ -189,6 +189,7 @@ namespace Serein.NodeFlow.Model.Operations
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (ToNode.ControlType is not (NodeControlType.GlobalData or NodeControlType.ExpCondition or NodeControlType.ExpOp))
|
||||
{
|
||||
|
||||
@@ -199,6 +200,7 @@ namespace Serein.NodeFlow.Model.Operations
|
||||
}
|
||||
if (ToNode.MethodDetails.ParameterDetailss.Length > 0)
|
||||
{
|
||||
|
||||
var fromNoeReturnType = fromNode.MethodDetails.ReturnType;
|
||||
if (fromNoeReturnType != null
|
||||
&& fromNoeReturnType != typeof(object)
|
||||
@@ -206,6 +208,12 @@ namespace Serein.NodeFlow.Model.Operations
|
||||
&& fromNoeReturnType != typeof(Unit))
|
||||
{
|
||||
var toNodePds = toNode.MethodDetails.ParameterDetailss;
|
||||
if (toNodePds.Any(pd=>pd.IsExplicitData))
|
||||
{
|
||||
checkTypeState = true; // 目标节点使用了显式的入参,无需关心参数是否匹配
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ParameterDetails toNodePd in toNodePds)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(toNodePd.ArgDataSourceNodeGuid) // 入参没有设置数据来源节点
|
||||
@@ -217,6 +225,7 @@ namespace Serein.NodeFlow.Model.Operations
|
||||
}
|
||||
if (toPds.Count == 0)
|
||||
{
|
||||
|
||||
var any = toNodePds.Any(pd => pd.ArgDataSourceNodeGuid == fromNode.Guid); // 判断目标节点是否已有该节点的连接
|
||||
checkTypeState = any;
|
||||
}
|
||||
@@ -225,6 +234,8 @@ namespace Serein.NodeFlow.Model.Operations
|
||||
checkTypeState = true; // 类型检查初步通过
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,21 +29,21 @@ namespace Serein.Script.Node
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// int 整数型字面量
|
||||
/// long 整数型字面量
|
||||
/// </summary>
|
||||
public class NumberLongNode(long vlaue) : NumberNode<long>(vlaue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// int 整数型字面量
|
||||
/// float 字面量
|
||||
/// </summary>
|
||||
public class NumberFloatNode(float vlaue) : NumberNode<float>(vlaue)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// int 整数型字面量
|
||||
/// double 字面量
|
||||
/// </summary>
|
||||
public class NumberDoubleNode(double vlaue) : NumberNode<double>(vlaue)
|
||||
{
|
||||
|
||||
@@ -321,11 +321,11 @@ namespace Serein.Script
|
||||
async Task<object?> InterpreterFunctionCallNodeAsync(IScriptInvokeContext context, FunctionCallNode functionCallNode)
|
||||
{
|
||||
// 获取流程上下文
|
||||
if (context.FlowContext != null && functionCallNode.FunctionName.Equals("getFlowApi", StringComparison.OrdinalIgnoreCase))
|
||||
if (context.FlowContext != null && functionCallNode.FunctionName.Equals("getFlowContext", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return context.FlowContext;
|
||||
}
|
||||
else if (functionCallNode.FunctionName.Equals("getScriptApi", StringComparison.OrdinalIgnoreCase))
|
||||
else if (functionCallNode.FunctionName.Equals("getScriptContext", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -1087,7 +1087,7 @@ namespace Serein.Script
|
||||
}
|
||||
else if (_currentToken.Type == TokenType.NumberDouble)
|
||||
{
|
||||
var value = float.Parse(_currentToken.Value);
|
||||
var value = double.Parse(_currentToken.Value);
|
||||
NextToken(); // 消耗 double 浮点数
|
||||
return new NumberDoubleNode(value).SetTokenInfo(factorToken);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,13 @@ namespace Serein.Script
|
||||
_codeBuilder.Append(code);
|
||||
}
|
||||
|
||||
private void CompleteCurrentStatement()
|
||||
{
|
||||
_codeBuilder.Append($";{Environment.NewLine}");
|
||||
|
||||
}
|
||||
private string Tab => new string (' ', _indentLevel* 4);
|
||||
|
||||
private void Indent() => _indentLevel++;
|
||||
private void Unindent() => _indentLevel--;
|
||||
|
||||
@@ -119,7 +126,10 @@ namespace Serein.Script
|
||||
foreach (var stmt in programNode.Statements)
|
||||
{
|
||||
ConvertCode(stmt);
|
||||
Append(";");
|
||||
if (stmt is not (IfNode or WhileNode))
|
||||
{
|
||||
CompleteCurrentStatement();
|
||||
}
|
||||
}
|
||||
if (_symbolInfos[programNode] == typeof(void))
|
||||
{
|
||||
@@ -167,16 +177,16 @@ namespace Serein.Script
|
||||
case ReturnNode returnNode: // 程序退出节点
|
||||
void ConvertCodeOfReturnNode(ReturnNode returnNode)
|
||||
{
|
||||
|
||||
Append(Tab);
|
||||
if (returnNode.Value is not null)
|
||||
{
|
||||
Append($"return ");
|
||||
ConvertCode(returnNode.Value);
|
||||
Append(";");
|
||||
AppendLine(string.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
AppendLine("return defult;");
|
||||
AppendLine("return defult");
|
||||
}
|
||||
}
|
||||
ConvertCodeOfReturnNode(returnNode);
|
||||
@@ -212,41 +222,22 @@ namespace Serein.Script
|
||||
{
|
||||
var varName = identifierNode.Name;
|
||||
Append(varName);
|
||||
/*if (_local.TryGetValue(varName, out var type))
|
||||
{
|
||||
// 定义过,需要使用变量
|
||||
Append(varName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_symbolInfos.TryGetValue(identifierNode, out type))
|
||||
{
|
||||
// 不存在,定义变量
|
||||
Append($"global::{type.FullName} {varName}");
|
||||
_local[varName] = type;
|
||||
//Append(varName);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"加载符号表时,无法匹配 IdentifierNode 节点的类型。 name : {varName}");
|
||||
}
|
||||
}*/
|
||||
}
|
||||
ConvertCodeOfIdentifierNode(identifierNode);
|
||||
break;
|
||||
case IfNode ifNode: // if语句结构
|
||||
void ConvertCodeOfIfNode(IfNode ifNOde)
|
||||
{
|
||||
AppendLine("");
|
||||
Append($"if(");
|
||||
|
||||
Append($"{Tab}if(");
|
||||
ConvertCode(ifNOde.Condition); // 解析条件
|
||||
Append($" == true)");
|
||||
Append($" == true){Environment.NewLine}");
|
||||
AppendLine("{");
|
||||
Indent();
|
||||
foreach (var item in ifNOde.TrueBranch)
|
||||
{
|
||||
ConvertCode(item);
|
||||
AppendLine(string.Empty);
|
||||
CompleteCurrentStatement();
|
||||
}
|
||||
Unindent();
|
||||
AppendLine("}");
|
||||
@@ -256,7 +247,7 @@ namespace Serein.Script
|
||||
foreach (var item in ifNOde.FalseBranch)
|
||||
{
|
||||
ConvertCode(item);
|
||||
AppendLine(string.Empty);
|
||||
CompleteCurrentStatement();
|
||||
}
|
||||
Unindent();
|
||||
AppendLine("}");
|
||||
@@ -275,8 +266,7 @@ namespace Serein.Script
|
||||
foreach (var item in whileNode.Body)
|
||||
{
|
||||
ConvertCode(item);
|
||||
Append(";");
|
||||
AppendLine(string.Empty);
|
||||
CompleteCurrentStatement();
|
||||
}
|
||||
Unindent();
|
||||
AppendLine("}");
|
||||
@@ -286,6 +276,8 @@ namespace Serein.Script
|
||||
case AssignmentNode assignmentNode: // 变量赋值语句
|
||||
void ConvertCodeOfAssignmentNode(AssignmentNode assignmentNode)
|
||||
{
|
||||
|
||||
Append(Tab);
|
||||
ConvertCode(assignmentNode.Target);
|
||||
Append(" = ");
|
||||
if (assignmentNode.Value is null)
|
||||
@@ -296,8 +288,6 @@ namespace Serein.Script
|
||||
{
|
||||
ConvertCode(assignmentNode.Value);
|
||||
}
|
||||
Append(";");
|
||||
AppendLine(string.Empty);
|
||||
}
|
||||
ConvertCodeOfAssignmentNode(assignmentNode);
|
||||
break;
|
||||
@@ -318,7 +308,6 @@ namespace Serein.Script
|
||||
ConvertCode(collectionAssignmentNode.Collection);
|
||||
Append(" = ");
|
||||
ConvertCode(collectionAssignmentNode.Value);
|
||||
Append(";");
|
||||
AppendLine(string.Empty);
|
||||
}
|
||||
ConvertCodeOfCollectionAssignmentNode(collectionAssignmentNode);
|
||||
@@ -333,6 +322,25 @@ namespace Serein.Script
|
||||
}
|
||||
ConvertCodeOfCollectionIndexNode(collectionIndexNode);
|
||||
break;
|
||||
case ArrayDefintionNode arrayDefintionNode:
|
||||
void ConvertCodeOfArrayDefintionNode(ArrayDefintionNode arrayDefintionNode)
|
||||
{
|
||||
var arrType = this._symbolInfos[arrayDefintionNode];
|
||||
var tab = new string(' ', (_indentLevel + 1) * 4);
|
||||
Append($"new global::{arrType.FullName}{{{Environment.NewLine}");
|
||||
for (int index = 0; index < arrayDefintionNode.Elements.Count; index++)
|
||||
{
|
||||
ASTNode? e = arrayDefintionNode.Elements[index];
|
||||
Append(tab + " ");
|
||||
ConvertCode(e);
|
||||
if (index < arrayDefintionNode.Elements.Count - 1)
|
||||
Append($", {Environment.NewLine}");
|
||||
|
||||
}
|
||||
Append($"{Environment.NewLine}{tab}}}");
|
||||
}
|
||||
ConvertCodeOfArrayDefintionNode(arrayDefintionNode);
|
||||
break;
|
||||
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
|
||||
void ConvertCodeOfClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
|
||||
{
|
||||
@@ -417,8 +425,6 @@ namespace Serein.Script
|
||||
ConvertCode(memberAssignmentNode.Object);
|
||||
Append($".{memberAssignmentNode.MemberName} = ");
|
||||
ConvertCode(memberAssignmentNode.Value);
|
||||
Append($";");
|
||||
AppendLine(string.Empty);
|
||||
}
|
||||
ConvertCodeOfMemberAssignmentNode(memberAssignmentNode);
|
||||
break;
|
||||
@@ -495,6 +501,9 @@ namespace Serein.Script
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using Serein.Library.Utils;
|
||||
using Serein.Script.Node;
|
||||
using Serein.Script.Node.FlowControl;
|
||||
@@ -104,12 +105,22 @@ namespace Serein.Script
|
||||
return typeof(void);
|
||||
case ReturnNode returnNode: // 程序退出节点
|
||||
Type AnalysisReturnNode(ReturnNode returnNode)
|
||||
{
|
||||
if(returnNode.Value is null)
|
||||
{
|
||||
var resultType = typeof(void);
|
||||
NodeSymbolInfos[returnNode] = resultType;
|
||||
return resultType;
|
||||
}
|
||||
else
|
||||
{
|
||||
var resultType = Analysis(returnNode.Value);
|
||||
NodeSymbolInfos[returnNode.Value] = resultType;
|
||||
NodeSymbolInfos[returnNode] = resultType;
|
||||
return resultType;
|
||||
}
|
||||
|
||||
}
|
||||
return AnalysisReturnNode(returnNode);
|
||||
case NullNode nullNode: // null
|
||||
NodeSymbolInfos[nullNode] = typeof(object);
|
||||
@@ -406,9 +417,25 @@ namespace Serein.Script
|
||||
{
|
||||
var objectType = Analysis(memberFunctionCallNode.Object);
|
||||
var types = memberFunctionCallNode.Arguments.Select(arg => Analysis(arg)).ToArray();
|
||||
|
||||
|
||||
var methodInfo = objectType.GetMethod(memberFunctionCallNode.FunctionName, types);
|
||||
if (methodInfo is null)
|
||||
{
|
||||
var t = objectType.GetMethods().Where(m => m.Name.Equals(memberFunctionCallNode.FunctionName)).ToArray();
|
||||
if(t.Length > 0)
|
||||
{
|
||||
var content = string.Join($";{Environment.NewLine}", t.Select(m => m.ToString()));
|
||||
throw new Exception($"类型 {objectType} 没有指定的重载方法 " +
|
||||
$"{memberFunctionCallNode.FunctionName}({string.Join(",", types.Select(t => t.Name))})," +
|
||||
$"但存在其它重载方法:{content}");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"类型 {objectType} 没有方法 {memberFunctionCallNode.FunctionName}");
|
||||
}
|
||||
}
|
||||
|
||||
for (int index = 0; index < memberFunctionCallNode.Arguments.Count; index++)
|
||||
{
|
||||
ASTNode argNode = memberFunctionCallNode.Arguments[index];
|
||||
@@ -428,6 +455,16 @@ namespace Serein.Script
|
||||
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
|
||||
Type AnalysisFunctionCallNode(FunctionCallNode functionCallNode)
|
||||
{
|
||||
// 获取流程上下文
|
||||
if (functionCallNode.FunctionName.Equals("getFlowContext", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return typeof(IFlowContext);
|
||||
}
|
||||
else if (functionCallNode.FunctionName.Equals("getScriptContext", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return typeof(IScriptInvokeContext);
|
||||
}
|
||||
|
||||
if (!SereinScript.FunctionInfos.TryGetValue(functionCallNode.FunctionName, out var methodInfo))
|
||||
{
|
||||
throw new Exception($"脚本没有挂载方法 {functionCallNode.FunctionName}");
|
||||
|
||||
@@ -1281,7 +1281,7 @@ namespace Serein.Workbench.Views
|
||||
private ContextMenu ConfiguerSelectionRectangle()
|
||||
{
|
||||
var contextMenu = new ContextMenu();
|
||||
contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("删除", (s, e) =>
|
||||
/*contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("删除", (s, e) =>
|
||||
{
|
||||
if (selectNodeControls.Count > 0)
|
||||
{
|
||||
@@ -1296,7 +1296,7 @@ namespace Serein.Workbench.Views
|
||||
}
|
||||
}
|
||||
SelectionRectangle.Visibility = Visibility.Collapsed;
|
||||
}));
|
||||
}));*/
|
||||
return contextMenu;
|
||||
// nodeControl.ContextMenu = contextMenu;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user