1. 重新设计了Generate项目及相关特性的命名,避免与其他类型混淆。

2. 补充了部分注释。
3. 修改了删除容器节点时,容器内子节点未正确删除的问题。
This commit is contained in:
fengjiayi
2025-07-30 21:15:07 +08:00
parent 93148b11a5
commit 152077e9b5
188 changed files with 2713 additions and 1406 deletions

View File

@@ -32,7 +32,7 @@ namespace Serein.Script
/// </summary>
/// <param name="varName"></param>
/// <returns></returns>
object GetVarValue(string varName);
object? GetVarValue(string varName);
/// <summary>
/// 设置变量的值

View File

@@ -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; }

View File

@@ -14,7 +14,7 @@ namespace Serein.Script.Node.FlowControl
/// <summary>
/// 返回值来源
/// </summary>
public ASTNode Value { get; }
public ASTNode? Value { get; }
public ReturnNode(ASTNode returnNode)
{

View File

@@ -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))

View File

@@ -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))

View File

@@ -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<>))

View File

@@ -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; // 后缀后应结束
}

View File

@@ -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>
/// 获取某个集合类型支持的索引参数类型