mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
1. 重新设计了Generate项目及相关特性的命名,避免与其他类型混淆。
2. 补充了部分注释。 3. 修改了删除容器节点时,容器内子节点未正确删除的问题。
This commit is contained in:
@@ -32,7 +32,7 @@ namespace Serein.Script
|
||||
/// </summary>
|
||||
/// <param name="varName"></param>
|
||||
/// <returns></returns>
|
||||
object GetVarValue(string varName);
|
||||
object? GetVarValue(string varName);
|
||||
|
||||
/// <summary>
|
||||
/// 设置变量的值
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Serein.Script.Node
|
||||
{
|
||||
public abstract class ASTNode
|
||||
{
|
||||
public string Code { get; private set; }
|
||||
public string Code { get; private set; } = string.Empty;
|
||||
public int Row { get; private set; }
|
||||
public int StartIndex { get; private set; }
|
||||
public int Length { get; private set; }
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Serein.Script.Node.FlowControl
|
||||
/// <summary>
|
||||
/// 返回值来源
|
||||
/// </summary>
|
||||
public ASTNode Value { get; }
|
||||
public ASTNode? Value { get; }
|
||||
|
||||
public ReturnNode(ASTNode returnNode)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,9 @@ namespace Serein.Script
|
||||
{
|
||||
}
|
||||
|
||||
public IFlowContext FlowContext{ get; }
|
||||
#pragma warning disable CS8766 // 返回类型中引用类型的为 Null 性与隐式实现的成员不匹配(可能是由于为 Null 性特性)。
|
||||
public IFlowContext? FlowContext{ get; }
|
||||
#pragma warning restore CS8766 // 返回类型中引用类型的为 Null 性与隐式实现的成员不匹配(可能是由于为 Null 性特性)。
|
||||
|
||||
/// <summary>
|
||||
/// 定义的变量
|
||||
@@ -48,13 +50,24 @@ namespace Serein.Script
|
||||
public bool IsNeedReturn { get; set; }
|
||||
|
||||
|
||||
object IScriptInvokeContext.GetVarValue(string varName)
|
||||
/// <summary>
|
||||
/// 获取变量的值
|
||||
/// </summary>
|
||||
/// <param name="varName"></param>
|
||||
/// <returns></returns>
|
||||
object? IScriptInvokeContext.GetVarValue(string varName)
|
||||
{
|
||||
_variables.TryGetValue(varName, out var value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置变量的值
|
||||
/// </summary>
|
||||
/// <param name="varName"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
bool IScriptInvokeContext.SetVarValue(string varName, object? value)
|
||||
{
|
||||
if (!_variables.TryAdd(varName, value))
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Serein.Script
|
||||
/// <returns>字符串构建器本身</returns>
|
||||
public static StringBuilder AppendCode(this StringBuilder sb,
|
||||
int retractCount = 0,
|
||||
string code = null,
|
||||
string? code = null,
|
||||
bool isWrapping = true)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(code))
|
||||
|
||||
@@ -3,6 +3,7 @@ using Serein.Script.Node;
|
||||
using Serein.Script.Node.FlowControl;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
@@ -15,15 +16,32 @@ using System.Xml.Linq;
|
||||
namespace Serein.Script
|
||||
{
|
||||
|
||||
/*
|
||||
暂未想到如何编译出具备 await / async 功能的IL代码,暂时放弃
|
||||
*/
|
||||
/*
|
||||
暂未想到如何编译出具备 await / async 功能的IL代码,暂时放弃
|
||||
*/
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// IL 代码生成结果
|
||||
/// </summary>
|
||||
internal record ILResult
|
||||
{
|
||||
public Type ReturnType { get; set; }
|
||||
/// <summary>
|
||||
/// 返回类型
|
||||
/// </summary>
|
||||
public Type? ReturnType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 临时变量,可用于缓存值,避免重复计算
|
||||
/// </summary>
|
||||
public LocalBuilder? TempVar { get; set; } // 可用于缓存
|
||||
|
||||
/// <summary>
|
||||
/// 发射 IL 代码的委托,接受 ILGenerator 参数
|
||||
/// </summary>
|
||||
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。
|
||||
public Action<ILGenerator> Emit { get; set; } // 用于推入值的代码
|
||||
#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +80,7 @@ namespace Serein.Script
|
||||
/// </summary>
|
||||
Dictionary<ASTNode, ILResult> _ilResults = new Dictionary<ASTNode, ILResult>();
|
||||
|
||||
|
||||
private Label _methodExit;
|
||||
|
||||
public SereinScriptILCompiler(Dictionary<ASTNode, Type> symbolInfos)
|
||||
@@ -72,7 +91,7 @@ namespace Serein.Script
|
||||
/// <summary>
|
||||
/// 是否调用了异步方法
|
||||
/// </summary>
|
||||
private bool _isUseAwait = false;
|
||||
//private bool _isUseAwait = false;
|
||||
|
||||
private Dictionary<string, int> _parameterIndexes = new Dictionary<string, int>();
|
||||
|
||||
@@ -1065,12 +1084,12 @@ namespace Serein.Script
|
||||
// 如果方法签名需要返回值,这里可放置默认 return 语句或用局部变量存储返回值
|
||||
}*/
|
||||
|
||||
private static bool IsGenericTask(Type returnType, out Type taskResult)
|
||||
private static bool IsGenericTask(Type returnType,[NotNullWhen(true)] out Type? taskResult)
|
||||
{
|
||||
// 判断是否为 Task 类型或泛型 Task<T>
|
||||
if (returnType == typeof(Task))
|
||||
{
|
||||
taskResult = null;
|
||||
taskResult = typeof(void);
|
||||
return true;
|
||||
}
|
||||
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
|
||||
@@ -286,7 +286,7 @@
|
||||
{
|
||||
var start = _index;
|
||||
bool hasDot = false;
|
||||
bool hasSuffix = false;
|
||||
//bool hasSuffix = false;
|
||||
|
||||
while (_index < _input.Length)
|
||||
{
|
||||
@@ -303,7 +303,7 @@
|
||||
}
|
||||
else if (ch is 'f' or 'F' or 'd' or 'D' or 'l' or 'L')
|
||||
{
|
||||
hasSuffix = true;
|
||||
//hasSuffix = true;
|
||||
_index++;
|
||||
break; // 后缀后应结束
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@ namespace Serein.Script
|
||||
Type argType = types[index];
|
||||
NodeSymbolInfos[argNode] = argType;
|
||||
}
|
||||
var isAsync = IsGenericTask(methodInfo.ReturnType, out var taskResult);
|
||||
var isAsync = EmitHelper.IsGenericTask(methodInfo.ReturnType, out var taskResult);
|
||||
var methodReturnType = isAsync ? taskResult : methodInfo.ReturnType;
|
||||
AsyncMethods[memberFunctionCallNode] = isAsync;
|
||||
NodeSymbolInfos[memberFunctionCallNode.Object] = objectType;
|
||||
@@ -402,7 +402,7 @@ namespace Serein.Script
|
||||
Type argType = types[index];
|
||||
NodeSymbolInfos[argNode] = argType;
|
||||
}
|
||||
var isAsync = IsGenericTask(methodInfo.ReturnType, out var taskResult);
|
||||
var isAsync = EmitHelper.IsGenericTask(methodInfo.ReturnType, out var taskResult);
|
||||
var methodReturnType = isAsync ? taskResult : methodInfo.ReturnType;
|
||||
AsyncMethods[functionCallNode] = isAsync;
|
||||
NodeSymbolInfos[functionCallNode] = methodReturnType;
|
||||
@@ -583,43 +583,15 @@ namespace Serein.Script
|
||||
{
|
||||
return resultType;
|
||||
}
|
||||
try
|
||||
resultType = Type.GetType(typeName); // 从命名空间查询类型
|
||||
if (resultType != null)
|
||||
{
|
||||
resultType = Type.GetType(typeName); // 从命名空间查询类型
|
||||
if (resultType != null)
|
||||
{
|
||||
return resultType;
|
||||
}
|
||||
throw new InvalidOperationException($"无法匹配类型 {typeName}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw;
|
||||
return resultType;
|
||||
}
|
||||
throw new InvalidOperationException($"无法匹配类型 {typeName}");
|
||||
}
|
||||
|
||||
private static bool IsGenericTask(Type returnType, out Type taskResult)
|
||||
{
|
||||
// 判断是否为 Task 类型或泛型 Task<T>
|
||||
if (returnType == typeof(Task))
|
||||
{
|
||||
taskResult = typeof(void);
|
||||
return true;
|
||||
}
|
||||
else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
{
|
||||
// 获取泛型参数类型
|
||||
Type genericArgument = returnType.GetGenericArguments()[0];
|
||||
taskResult = genericArgument;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult = null;
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取某个集合类型支持的索引参数类型
|
||||
|
||||
Reference in New Issue
Block a user