using Serein.Library;
using Serein.Script.Node;
using Serein.Script.Node.FlowControl;
using System.Reflection;
namespace Serein.Script
{
public class SereinScript
{
///
/// 类型分析
///
public SereinScriptTypeAnalysis TypeAnalysis { get; } = new SereinScriptTypeAnalysis();
private ProgramNode? programNode;
public static Task ExecuteAsync(string script, Dictionary? argTypes = null)
{
SereinScriptParser parser = new SereinScriptParser();
SereinScriptTypeAnalysis analysis = new SereinScriptTypeAnalysis();
var programNode = parser.Parse(script);
analysis.Reset();
if (argTypes is not null) analysis.LoadSymbol(argTypes); // 提前加载脚本节点定义的符号
analysis.Analysis(programNode); // 分析节点类型
SereinScriptInterpreter Interpreter = new SereinScriptInterpreter(analysis.NodeSymbolInfos);
IScriptInvokeContext context = new ScriptInvokeContext();
var task = Interpreter.InterpreterAsync(context, programNode);
return task; // 脚本返回类型
}
///
/// 解析脚本
///
/// 脚本
/// 挂载的变量
///
public Type ParserScript(string script, Dictionary? argTypes = null)
{
SereinScriptParser parser = new SereinScriptParser();
var programNode = parser.Parse(script);
TypeAnalysis.NodeSymbolInfos.Clear(); // 清空符号表
if(argTypes is not null) TypeAnalysis.LoadSymbol(argTypes); // 提前加载脚本节点定义的符号
TypeAnalysis.Analysis(programNode); // 分析节点类型
var returnType = TypeAnalysis.NodeSymbolInfos[programNode]; // 获取返回类型
this.programNode = programNode;
return returnType; // 脚本返回类型
}
///
/// 执行脚本
///
///
///
///
public async Task InterpreterAsync(IScriptInvokeContext context)
{
if(programNode is null)
{
throw new ArgumentNullException(nameof(programNode));
}
Dictionary symbolInfos = TypeAnalysis.NodeSymbolInfos.ToDictionary();
SereinScriptInterpreter Interpreter = new SereinScriptInterpreter(symbolInfos);
return await Interpreter.InterpreterAsync(context, programNode);
}
///
/// 转换为 C# 代码,并且附带方法信息
///
/// 脚本
/// 挂载的变量
///
public SereinScriptMethodInfo? ConvertCSharpCode(string mehtodName, Dictionary? argTypes = null)
{
if (string.IsNullOrWhiteSpace(mehtodName)) return null;
if (programNode is null) return null;
SereinScriptToCsharpScript tool = new SereinScriptToCsharpScript(TypeAnalysis);
return tool.CompileToCSharp(mehtodName, programNode, argTypes);
}
///
/// 编译为 IL 代码
///
/// 脚本
/// 挂载的变量
///
[Obsolete("因为暂未想到如何支持异步方法,所以暂时废弃生成", true)]
private Delegate CompilerIL(string dynamicMethodName, ProgramNode programNode, Dictionary? argTypes = null)
{
SereinScriptILCompiler compiler = new SereinScriptILCompiler(TypeAnalysis.NodeSymbolInfos);
var @delegate = compiler.Compiler(dynamicMethodName, programNode, argTypes); // 编译脚本
return @delegate;
}
///
/// 挂载的函数
///
public static Dictionary FunctionDelegates { get; private set; } = [];
///
/// 挂载方法的信息
///
public static Dictionary FunctionInfos { get; private set; } = [];
///
/// 挂载的类型
///
public static Dictionary MountType = new Dictionary();
///
/// 挂载的函数调用的对象(用于解决函数需要实例才能调用的场景)
///
// public static Dictionary> DelegateInstances = new Dictionary>();
///
/// 挂载函数
///
///
///
public static void AddStaticFunction(string functionName, MethodInfo methodInfo)
{
FunctionDelegates[functionName] = new DelegateDetails(methodInfo);
FunctionInfos[functionName] = methodInfo;
}
///
/// 挂载函数
///
/// 函数名称
/// 方法信息
/*public static void AddFunction(string functionName, MethodInfo methodInfo, Func? callObj = null)
{
if (!methodInfo.IsStatic && callObj is null)
{
SereinEnv.WriteLine(InfoType.WARN, "函数挂载失败:试图挂载非静态的函数,但没有传入相应的获取实例的方法。");
return;
}
if (!methodInfo.IsStatic && callObj is not null && !DelegateInstances.ContainsKey(functionName))
{
// 非静态函数需要给定类型
DelegateInstances.Add(functionName, callObj);
}
if (!FunctionDelegates.ContainsKey(functionName))
{
FunctionDelegates[functionName] = new DelegateDetails(methodInfo);
}
}*/
///
/// 挂载类型
///
/// 函数名称
/// 指定类型名称
public static void AddClassType(Type type, string typeName = "")
{
if (string.IsNullOrEmpty(typeName))
{
typeName = type.Name;
}
if (!MountType.ContainsKey(typeName))
{
MountType[typeName] = type;
}
}
}
}