通过Emit优化Script脚本的解释执行;出于后期更新的方向,暂时隐藏表达式节点、条件表达式节点、全局数据节点;流程图转c#代码新增对于Script脚本的支持,Script脚本现在可以原生导出为C#代码。

This commit is contained in:
fengjiayi
2025-07-26 19:36:54 +08:00
parent 9a8de6b571
commit 29f2be5c80
32 changed files with 2175 additions and 432 deletions

View File

@@ -18,8 +18,12 @@ namespace Serein.Script
/// <summary>
/// 将 Serein 脚本转换为 C# 脚本的类
/// </summary>
internal class SereinScriptToCsharpScript
public class SereinScriptToCsharpScript
{
public const string ClassName = nameof(SereinScriptToCsharpScript);
public SereinScriptMethodInfo sereinScriptMethodInfo ;
/// <summary>
/// 符号表
/// </summary>
@@ -62,19 +66,35 @@ namespace Serein.Script
private List<Action<StringBuilder>> _classDefinitions = new List<Action<StringBuilder>>();
public string CompileToCSharp(string mehtodName, ProgramNode programNode, Dictionary<string, Type>? param)
public SereinScriptMethodInfo CompileToCSharp(string mehtodName, ProgramNode programNode, Dictionary<string, Type>? param)
{
_codeBuilder.Clear();
sereinScriptMethodInfo = new SereinScriptMethodInfo()
{
ClassName = ClassName,
ParamInfos = new List<SereinScriptMethodInfo.SereinScriptParamInfo>(),
MethodName = mehtodName,
};
var sb = _codeBuilder;
var methodResultType = _symbolInfos[programNode];
if(methodResultType == typeof(void))
{
methodResultType = typeof(object);
}
var taskFullName = typeof(Task).FullName;
var returnContent = _isTaskMain ? $"global::{taskFullName}<global::{methodResultType.FullName}>" : $"global::{methodResultType.FullName}";
var taskFullName = typeof(Task).FullName;
string? returnContent;
if (_isTaskMain)
{
returnContent = $"global::{taskFullName}<global::{methodResultType.FullName}>";
sereinScriptMethodInfo.IsAsync = true;
}
else
{
returnContent = $"global::{methodResultType.FullName}";
sereinScriptMethodInfo.IsAsync = false;
}
AppendLine("public class SereinScriptToCsharp");
AppendLine($"public partial class {ClassName}");
AppendLine( "{");
Indent();
if(param is null || param.Count == 0)
@@ -92,10 +112,13 @@ namespace Serein.Script
ConvertCode(stmt); // 递归遍历
Append(";");
}
if(!_symbolInfos.Keys.Any(node => node is ReturnNode))
if (_symbolInfos[programNode] == typeof(void))
{
AppendLine("");
AppendLine("return null;");
}
Unindent();
AppendLine("}");
Unindent();
@@ -105,16 +128,24 @@ namespace Serein.Script
{
cd.Invoke(sb);
}
return sb.ToString();
sereinScriptMethodInfo.CsharpCode = sb.ToString();
sereinScriptMethodInfo.ReturnType = methodResultType;
return sereinScriptMethodInfo;
}
private string GetMethodParamster(Dictionary<string, Type> param)
{
var values = param.Select(kvp =>
{
_local[kvp.Key] = kvp.Value;
return $"global::{kvp.Value.FullName} {kvp.Key}";
var paramName = kvp.Key;
var type = kvp.Value;
_local[paramName] = type;
sereinScriptMethodInfo.ParamInfos.Add(new SereinScriptMethodInfo.SereinScriptParamInfo
{
ParameterType = type,
ParamName = paramName,
});
return $"global::{type.FullName} {paramName}";
});
return string.Join(',', values);
}