Files
serein-flow/Serein.Script/SereinScriptILCompiler.cs

1234 lines
56 KiB
C#
Raw Normal View History

using Serein.Library.Api;
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;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
namespace Serein.Script
{
/*
await / async IL代码
*/
/// <summary>
/// IL 代码生成结果
/// </summary>
internal record ILResult
{
/// <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。
}
/// <summary>
/// 脚本编译IL代码
/// </summary>
internal class SereinScriptILCompiler
{
/// <summary>
/// 符号表
/// </summary>
private readonly Dictionary<ASTNode, Type> symbolInfos;
/// <summary>
/// 发射IL
/// </summary>
//private ILGenerator _il;
/// <summary>
/// 创建的对应方法
/// </summary>
private DynamicMethod _method;
/// <summary>
/// 临时变量绑定
/// </summary>
private readonly Dictionary<string, LocalBuilder> _locals = new();
/// <summary>
/// 节点对应的委托缓存,避免重复编译同一节点
/// </summary>
private readonly Dictionary<ASTNode, Delegate> _nodeCache = new();
/// <summary>
/// IL映射
/// </summary>
Dictionary<ASTNode, ILResult> _ilResults = new Dictionary<ASTNode, ILResult>();
private Label _methodExit;
public SereinScriptILCompiler(Dictionary<ASTNode, Type> symbolInfos)
{
this.symbolInfos = symbolInfos;
}
/// <summary>
/// 是否调用了异步方法
/// </summary>
//private bool _isUseAwait = false;
private Dictionary<string, int> _parameterIndexes = new Dictionary<string, int>();
public Delegate Compiler(string compilerMethodName, ProgramNode programNode, Dictionary<string, Type>? argTypes = null)
{
argTypes ??= new Dictionary<string, Type>();
var parameterTypes = argTypes.Values.ToArray();
var parameterNames = argTypes.Keys.ToArray();
// 构建参数索引映射,方便 EmitNode 访问参数
_parameterIndexes.Clear();
for (int i = 0; i < parameterNames.Length; i++)
{
_parameterIndexes[parameterNames[i]] = i;
}
_method = new DynamicMethod(
compilerMethodName,
typeof(object),
parameterTypes,
typeof(SereinScriptILCompiler).Module,
skipVisibility: true);
var il = _method.GetILGenerator();
_ilResults.Clear();
var resultType = symbolInfos[programNode];
_methodExit = il.DefineLabel();
foreach (var node in programNode.Statements)
{
EmitNode(il, node);
}
il.MarkLabel(_methodExit);
if (resultType == typeof(void))
{
il.Emit(OpCodes.Ldnull);
}
else if (resultType.IsValueType)
{
il.Emit(OpCodes.Box, resultType);
}
il.Emit(OpCodes.Ret);
Type delegateType;
if (parameterTypes.Length == 0)
{
delegateType = typeof(Func<object>);
}
else
{
var funcGenericTypeArgs = parameterTypes.Concat(new[] { typeof(object) }).ToArray();
delegateType = Expression.GetFuncType(funcGenericTypeArgs);
}
var @delegate = _method.CreateDelegate(delegateType);
return @delegate;
}
/// <summary>
/// 用于将 GenerateIL() 返回的 ILResult 缓存到 _ilResults 中,避免在 GenerateIL() 中混乱生成逻辑
/// </summary>
/// <param name="il"></param>
/// <param name="node"></param>
/// <returns></returns>
private ILResult EmitNode(ILGenerator il, ASTNode node)
{
ILResult result = GenerateIL(il, node);
_ilResults[node] = result;
return result;
}
private ILResult GenerateIL(ILGenerator il, ASTNode node)
{
switch (node)
{
case ProgramNode programNode: // 程序开始节点不用分析IL
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il => { }
};
case ReturnNode returnNode: // 程序退出节点
ILResult GenerateReturnNodeIL(ReturnNode returnNode)
{
if (returnNode.Value is null) // 没有返回值
{
return new ILResult
{
ReturnType = typeof(void),
Emit = il =>
{
il.Emit(OpCodes.Ldnull); // 返回 null
il.Emit(OpCodes.Br, _methodExit); // 跳转到程序退出
}
};
}
else // 有返回值
{
var valueResult = EmitNode(il, returnNode.Value);
return new ILResult
{
ReturnType = valueResult.ReturnType,
Emit = il =>
{
valueResult.Emit(il); // 推入返回值
il.Emit(OpCodes.Br, _methodExit); // 跳转到程序退出
}
};
}
}
return GenerateReturnNodeIL(returnNode);
#region IL生成
case NullNode nullNode: // null
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il => il.Emit(OpCodes.Ldnull)
};
case CharNode charNode: // char字面量 加载 char本质为 ushort / int
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il =>
{
il.Emit(OpCodes.Ldc_I4, (int)charNode.Value);
il.Emit(OpCodes.Box, typeof(char));
}
};
case StringNode stringNode: // 字符串字面量
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il => il.Emit(OpCodes.Ldstr, stringNode.Value)
};
case BooleanNode booleanNode: // 布尔值字面量
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il =>
{
il.Emit(booleanNode.Value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Box, typeof(bool));
}
};
case NumberIntNode numberIntNode: // int整型数值字面量
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il =>
{
il.Emit(OpCodes.Ldc_I4, numberIntNode.Value);
il.Emit(OpCodes.Box, typeof(int));
}
};
case NumberLongNode numberLongNode: // long整型数值字面量
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il =>
{
il.Emit(OpCodes.Ldc_I8, numberLongNode.Value);
il.Emit(OpCodes.Box, typeof(long));
}
};
case NumberFloatNode numberFloatNode: // float浮点数值字面量
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il =>
{
il.Emit(OpCodes.Ldc_R4, numberFloatNode.Value);
il.Emit(OpCodes.Box, typeof(float));
}
};
case NumberDoubleNode numberDoubleNode: // double浮点数值字面量
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il =>
{
il.Emit(OpCodes.Ldc_R8, numberDoubleNode.Value);
il.Emit(OpCodes.Box, typeof(double));
}
};
#endregion
case IdentifierNode identifierNode:
ILResult GenerateIdentifierNodeIL(IdentifierNode identifierNode)
{
if (_parameterIndexes.TryGetValue(identifierNode.Name, out int paramIndex))
{
// 变量是方法参数,直接加载参数
return new ILResult
{
ReturnType = symbolInfos[identifierNode],
Emit = il =>
{
switch (paramIndex)
{
case 0: il.Emit(OpCodes.Ldarg_0); break;
case 1: il.Emit(OpCodes.Ldarg_1); break;
case 2: il.Emit(OpCodes.Ldarg_2); break;
case 3: il.Emit(OpCodes.Ldarg_3); break;
default: il.Emit(OpCodes.Ldarg, paramIndex); break;
}
}
};
}
else
{
// 变量是本地变量,声明并访问
if (!_locals.TryGetValue(identifierNode.Name, out var local))
{
var varType = symbolInfos.TryGetValue(identifierNode, out var t) ? t : typeof(object);
local = il.DeclareLocal(varType);
_locals[identifierNode.Name] = local;
}
return new ILResult
{
ReturnType = symbolInfos[identifierNode],
Emit = il =>
{
il.Emit(OpCodes.Ldloc, local);
}
};
}
}
return GenerateIdentifierNodeIL(identifierNode);
case IfNode ifNode: // if语句结构
ILResult GenerateIfNodeIL(IfNode ifNode)
{
var elseLabel = il.DefineLabel();
var endLabel = il.DefineLabel();
// 计算条件表达式
var conditionResult = EmitNode(il, ifNode.Condition);
conditionResult.Emit(il); // 条件结果入栈
// 弹出object装箱转bool
il.Emit(OpCodes.Unbox_Any, typeof(bool));
// 条件为 false跳转 else
il.Emit(OpCodes.Brfalse, elseLabel);
// 执行 TrueBranch
foreach (var stmt in ifNode.TrueBranch)
{
var stmtResult = EmitNode(il, stmt);
stmtResult.Emit(il);
if (stmt is ReturnNode) // 如果是返回语句,直接跳到结束标签
{
il.Emit(OpCodes.Br, endLabel);
}
}
// 跳转到 if 结束
il.Emit(OpCodes.Br, endLabel);
// 处理 else 分支
il.MarkLabel(elseLabel);
foreach (var stmt in ifNode.FalseBranch)
{
var stmtResult = EmitNode(il, stmt);
stmtResult.Emit(il);
if (stmt is ReturnNode) // 如果是返回语句,直接跳到结束标签
{
il.Emit(OpCodes.Br, endLabel);
}
}
// 结束标签
il.MarkLabel(endLabel);
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il => { } // 无需额外操作,已在各分支处理
};
}
return GenerateIfNodeIL(ifNode);
case WhileNode whileNode: // while语句结构
ILResult GenerateWhileNode(WhileNode whileNode)
{
// 帮我实现处理逻辑:
var startLabel = il.DefineLabel(); // 循环开始标签
var endLabel = il.DefineLabel(); // 循环结束标签
il.MarkLabel(startLabel); // 标记循环开始
// 计算条件表达式
var conditionResult = EmitNode(il, whileNode.Condition);
conditionResult.Emit(il); // 条件结果入栈
// 弹出object装箱转bool
il.Emit(OpCodes.Unbox_Any, typeof(bool));
// 条件为 false跳转到循环结束
il.Emit(OpCodes.Brfalse, endLabel);
foreach (var stmt in whileNode.Body)
{
var stmtResult = EmitNode(il, stmt);
stmtResult.Emit(il);
if (stmt is ReturnNode) // 如果是返回语句,直接跳到结束标签
{
il.Emit(OpCodes.Br, endLabel);
}
}
il.Emit(OpCodes.Br, startLabel);
il.MarkLabel(endLabel);
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il => { } // 无需额外操作,已在各分支处理
};
}
return GenerateWhileNode(whileNode);
case AssignmentNode assignmentNode: // 赋值语句
ILResult GenerateAssignmentNodeIL(AssignmentNode assignmentNode)
{
if (assignmentNode.Target is not IdentifierNode identifierNode)
throw new Exception("AssignmentNode.Target 必须是 IdentifierNode");
if (!_locals.TryGetValue(identifierNode.Name, out var local))
{
var varType = symbolInfos.TryGetValue(identifierNode, out var t) ? t : typeof(object);
local = il.DeclareLocal(varType);
_locals[identifierNode.Name] = local;
}
var valueResult = EmitNode(il, assignmentNode.Value);
return new ILResult
{
ReturnType = valueResult.ReturnType,
Emit = il =>
{
valueResult.Emit(il); // 先把赋值值推入栈顶
var targetType = local.LocalType;
var sourceType = valueResult.ReturnType;
if (targetType != sourceType)
{
EmitConvert(il, sourceType, targetType); // 尝试类型转换
}
il.Emit(OpCodes.Stloc, local); // 然后保存到局部变量
}
};
}
return GenerateAssignmentNodeIL(assignmentNode);
case BinaryOperationNode binaryOperationNode: // 二元运算操作
ILResult GenerateBinaryOperationNodeIL(BinaryOperationNode binaryOperationNode)
{
void EmitShortCircuit(ILGenerator il, string op, ILResult left, ILResult right)
{
var labelEnd = il.DefineLabel();
var labelFalse = il.DefineLabel();
var labelTrue = il.DefineLabel();
if (op == "&&")
{
left.Emit(il);
il.Emit(OpCodes.Brfalse, labelFalse);
right.Emit(il);
il.Emit(OpCodes.Br, labelEnd);
il.MarkLabel(labelFalse);
il.Emit(OpCodes.Ldc_I4_0);
il.MarkLabel(labelEnd);
}
else if (op == "||")
{
left.Emit(il);
il.Emit(OpCodes.Brtrue, labelTrue);
right.Emit(il);
il.Emit(OpCodes.Br, labelEnd);
il.MarkLabel(labelTrue);
il.Emit(OpCodes.Ldc_I4_1);
il.MarkLabel(labelEnd);
}
}
var left = EmitNode(il, binaryOperationNode.Left);
var right = EmitNode(il, binaryOperationNode.Right);
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il =>
{
switch (binaryOperationNode.Operator)
{
case "&&":
case "||":
EmitShortCircuit(il, binaryOperationNode.Operator, left, right);
break;
default:
left.Emit(il);
right.Emit(il);
switch (binaryOperationNode.Operator)
{
case "+":
il.Emit(OpCodes.Add);
break;
case "-":
il.Emit(OpCodes.Sub);
break;
case "*":
il.Emit(OpCodes.Mul);
break;
case "/":
il.Emit(OpCodes.Div);
break;
case "==":
il.Emit(OpCodes.Ceq);
break;
case "!=":
il.Emit(OpCodes.Ceq);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ceq); // 取反
break;
case ">":
il.Emit(OpCodes.Cgt);
break;
case "<":
il.Emit(OpCodes.Clt);
break;
case ">=":
il.Emit(OpCodes.Clt);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ceq); // !(a < b)
break;
case "<=":
il.Emit(OpCodes.Cgt);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ceq); // !(a > b)
break;
default:
throw new NotSupportedException($"未知的操作符: {binaryOperationNode.Operator}");
}
break;
}
}
};
}
return GenerateBinaryOperationNodeIL(binaryOperationNode);
case CollectionAssignmentNode collectionAssignmentNode: // 集合赋值
ILResult GenerateCollectionAssignmentNodeIL(CollectionAssignmentNode collectionAssignmentNode)
{
// 加载集合、索引和值
var collectionIL = EmitNode(il, collectionAssignmentNode.Collection.Collection);
var indexIL = EmitNode(il, collectionAssignmentNode.Collection.Index);
var valueIL = EmitNode(il, collectionAssignmentNode.Value);
return new ILResult
{
ReturnType = typeof(void),
Emit = il =>
{
collectionIL.Emit(il); // 加载集合
indexIL.Emit(il); // 加载索引
valueIL.Emit(il); // 加载值
var collectionType = collectionIL.ReturnType;
var valueType = valueIL.ReturnType;
if (collectionType.IsArray && collectionType.GetArrayRank() == 1)
{
var elementType = collectionType.GetElementType();
// 如果值类型不匹配,尝试强转(可能需要扩展)
if (elementType != valueType)
{
EmitConvert(il, valueType, elementType);
}
// 发射 Stelem 指令
EmitStoreElement(il, elementType);
}
else
{
// 对象集合,调用 set_Item 方法
var indexerSetter = collectionType
.GetMethods()
.FirstOrDefault(m => m.Name == "set_Item" && m.GetParameters().Length == 2);
if (indexerSetter == null)
throw new InvalidOperationException($"集合类型 {collectionType} 不支持索引赋值");
if (collectionType.IsValueType)
{
il.Emit(OpCodes.Constrained, collectionType);
}
il.EmitCall(OpCodes.Callvirt, indexerSetter, null);
}
}
};
}
return GenerateCollectionAssignmentNodeIL(collectionAssignmentNode);
case CollectionIndexNode collectionIndexNode: // 集合取值
ILResult GenerateCollectionIndexNodeIL(CollectionIndexNode collectionIndexNode)
{
var collectionIL = EmitNode(il, collectionIndexNode.Collection);
var indexIL = EmitNode(il, collectionIndexNode.Index);
var resultType = symbolInfos[collectionIndexNode];
return new ILResult
{
ReturnType = resultType,
Emit = il =>
{
collectionIL.Emit(il);
indexIL.Emit(il);
var collectionType = collectionIL.ReturnType;
if (collectionType.IsArray)
{
var elementType = collectionType.GetElementType();
EmitLoadElement(il, elementType);
}
else
{
// 尝试获取索引器 get_Item 方法(匹配参数类型)
var indexerMethod = collectionType.GetMethod("get_Item", new[] { indexIL.ReturnType });
if (indexerMethod == null)
{
// 退而求其次:只要名字匹配且参数个数相等的第一个
indexerMethod = collectionType.GetMethods()
.FirstOrDefault(m => m.Name == "get_Item" && m.GetParameters().Length == 1);
if (indexerMethod == null)
throw new InvalidOperationException($"集合类型 {collectionType} 没有索引器方法");
}
if (collectionType.IsValueType)
{
il.Emit(OpCodes.Constrained, collectionType);
}
il.EmitCall(OpCodes.Callvirt, indexerMethod, null);
}
}
};
}
return GenerateCollectionIndexNodeIL(collectionIndexNode);
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义,在 Parser. 阶段已经处理,不生成 IL
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il => { }
};
case TypeNode typeNode:// 指示类型的 FullName 由 ClassTypeDefinitionNode 实际使用,不生成 IL
return new ILResult
{
ReturnType = symbolInfos[node],
Emit = il => { }
};
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
ILResult GenerateObjectInstantiationNodeIL(ObjectInstantiationNode objectInstantiationNode)
{
var type = symbolInfos[objectInstantiationNode.Type] ?? throw new Exception($"未找到类型 {objectInstantiationNode.Type.TypeName}");
var ctorArgTypes = objectInstantiationNode.Arguments
.Select(arg => symbolInfos[arg] ?? typeof(object))
.ToArray();
var ctor = type.GetConstructor(ctorArgTypes)
?? throw new Exception($"类型 {type} 找不到匹配的构造函数");
ILResult[] argIlResult = objectInstantiationNode.Arguments.Select(arg => EmitNode(il, arg)) .ToArray();
return new ILResult
{
ReturnType = type,
Emit = il =>
{
// 构造函数参数压栈
foreach (var argIL in argIlResult)
{
argIL.Emit(il);
}
il.Emit(OpCodes.Newobj, ctor); // 调用构造函数,新对象入栈
if (objectInstantiationNode.CtorAssignments.Count == 0)
return;
// 需要成员赋值,存入局部变量
var local = il.DeclareLocal(type);
il.Emit(OpCodes.Stloc, local); // 将对象保存到局部变量
il.Emit(OpCodes.Ldloc, local); // 再加载对象,保证栈顶仍是实例
// 遍历成员赋值
foreach (var assignmentNode in objectInstantiationNode.CtorAssignments)
{
il.Emit(OpCodes.Ldloc, local); // 载入对象引用
var valueIL = EmitNode(il, assignmentNode.Value);
valueIL.Emit(il); // 载入赋值的值
// 先查属性
var prop = type.GetProperty(assignmentNode.MemberName, BindingFlags.Public | BindingFlags.Instance);
if (prop != null && prop.CanWrite)
{
var setMethod = prop.GetSetMethod();
il.EmitCall(OpCodes.Callvirt, setMethod, null);
}
else
{
// 查字段
var field = type.GetField(assignmentNode.MemberName, BindingFlags.Public | BindingFlags.Instance);
if (field != null)
{
il.Emit(OpCodes.Stfld, field);
}
else
{
throw new Exception($"类型 {type} 没有成员 {assignmentNode.MemberName}");
}
}
}
// 最终栈顶是实例对象,供后续调用
il.Emit(OpCodes.Ldloc, local);
}
};
}
return GenerateObjectInstantiationNodeIL(objectInstantiationNode);
case CtorAssignmentNode ctorAssignmentNode: // 构造器赋值
ILResult GenerateCtorAssignmentNodeIL(CtorAssignmentNode ctorAssignmentNode)
{
var classType = symbolInfos[ctorAssignmentNode.Class] ?? throw new Exception($"未找到类型 {ctorAssignmentNode.Class.TypeName}");
return new ILResult
{
ReturnType = typeof(void),
Emit = il =>
{
// 栈顶已有对象引用,先发射赋值值
var valueIL = EmitNode(il, ctorAssignmentNode.Value);
valueIL.Emit(il);
// 查找成员
var prop = classType.GetProperty(ctorAssignmentNode.MemberName, BindingFlags.Public | BindingFlags.Instance);
var field = prop == null ? classType.GetField(ctorAssignmentNode.MemberName, BindingFlags.Public | BindingFlags.Instance) : null;
Type memberType = null;
if (prop != null && prop.CanWrite)
{
memberType = prop.PropertyType;
}
else if (field != null)
{
memberType = field.FieldType;
}
else
{
throw new Exception($"类型 {classType} 没有成员 {ctorAssignmentNode.MemberName}");
}
// 类型转换
if (memberType != null && valueIL.ReturnType != memberType)
{
EmitConvert(il, valueIL.ReturnType, memberType);
}
// 赋值
if (prop != null && prop.CanWrite)
{
var setMethod = prop.GetSetMethod();
il.EmitCall(OpCodes.Callvirt, setMethod, null);
}
else if (field != null)
{
il.Emit(OpCodes.Stfld, field);
}
}
};
}
return GenerateCtorAssignmentNodeIL(ctorAssignmentNode);
case MemberAccessNode memberAccessNode: // 对象成员访问
ILResult GenerateMemberAccessNodeIL(MemberAccessNode memberAccessNode)
{
var targetIL = EmitNode(il, memberAccessNode.Object);
var targetType = targetIL.ReturnType;
var propInfo = targetType.GetProperty(memberAccessNode.MemberName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
?? throw new InvalidOperationException($"属性 {memberAccessNode.MemberName} 不存在");
if (propInfo.GetMethod is null)
throw new InvalidOperationException($"属性 {memberAccessNode.MemberName} 无法获取 MethodInfo");
return new ILResult
{
ReturnType = propInfo.PropertyType,
Emit = il =>
{
targetIL.Emit(il);
if (targetType.IsValueType)
{
il.Emit(OpCodes.Constrained, targetType);
il.EmitCall(OpCodes.Callvirt, propInfo.GetMethod, null);
}
else
{
il.EmitCall(OpCodes.Callvirt, propInfo.GetMethod, null);
}
}
};
}
return GenerateMemberAccessNodeIL(memberAccessNode);
case MemberAssignmentNode memberAssignmentNode:
ILResult GenerateMemberAssignmentNodeIL(MemberAssignmentNode memberAssignmentNode)
{
var objectResult = EmitNode(il, memberAssignmentNode.Object);
var classType = objectResult.ReturnType;
return new ILResult
{
ReturnType = typeof(void),
Emit = il =>
{
objectResult.Emit(il); // 先入栈对象实例
var valueResult = EmitNode(il, memberAssignmentNode.Value);
valueResult.Emit(il); // 再入栈赋值值
var prop = classType.GetProperty(memberAssignmentNode.MemberName, BindingFlags.Public | BindingFlags.Instance);
var field = prop == null ? classType.GetField(memberAssignmentNode.MemberName, BindingFlags.Public | BindingFlags.Instance) : null;
Type memberType = prop != null ? prop.PropertyType : field?.FieldType;
if (memberType != null && valueResult.ReturnType != memberType)
{
EmitConvert(il, valueResult.ReturnType, memberType);
}
if (prop != null && prop.CanWrite)
{
if (classType.IsValueType)
{
il.Emit(OpCodes.Constrained, classType);
}
var setMethod = prop.GetSetMethod();
il.EmitCall(OpCodes.Callvirt, setMethod, null);
}
else if (field != null)
{
il.Emit(OpCodes.Stfld, field);
}
else
{
throw new Exception($"类型 {classType} 没有成员 {memberAssignmentNode.MemberName}");
}
}
};
}
return GenerateMemberAssignmentNodeIL(memberAssignmentNode);
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
ILResult GenerateMemberFunctionCallNodeIL(MemberFunctionCallNode memberFunctionCallNode)
{
var targetIL = EmitNode(il, memberFunctionCallNode.Object);
var argTypes = memberFunctionCallNode.Arguments
.Select(arg => symbolInfos[arg] ?? typeof(object))
.ToArray();
var method = targetIL.ReturnType.GetMethod(memberFunctionCallNode.FunctionName, argTypes)
?? throw new InvalidOperationException($"方法 {memberFunctionCallNode.FunctionName} 找不到匹配的重载");
var argResults = memberFunctionCallNode.Arguments.Select(arg => EmitNode(il, arg)).ToList();
return new ILResult
{
ReturnType = method.ReturnType,
Emit = il =>
{
targetIL.Emit(il);
for (int i = 0; i < argResults.Count; i++)
{
argResults[i].Emit(il);
var paramType = method.GetParameters()[i].ParameterType;
var argType = argResults[i].ReturnType;
if (paramType != argType)
{
EmitConvert(il, argType, paramType);
}
}
if (targetIL.ReturnType.IsValueType)
{
il.Emit(OpCodes.Constrained, targetIL.ReturnType);
il.EmitCall(OpCodes.Callvirt, method, null);
}
else
{
il.EmitCall(OpCodes.Callvirt, method, null);
}
}
};
}
return GenerateMemberFunctionCallNodeIL(memberFunctionCallNode);
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
ILResult GenerateFunctionCallNode(FunctionCallNode functionCallNode)
{
if (!SereinScript.FunctionInfos.TryGetValue(functionCallNode.FunctionName, out var methodInfo))
throw new InvalidOperationException($"没有挂载 {functionCallNode.FunctionName} 方法信息");
var argResults = functionCallNode.Arguments.Select(arg => EmitNode(il, arg)).ToList();
return new ILResult
{
ReturnType = methodInfo.ReturnType,
Emit = il =>
{
// 挂载函数为静态方法,不推入实例
for (int i = 0; i < argResults.Count; i++)
{
argResults[i].Emit(il);
var paramType = methodInfo.GetParameters()[i].ParameterType;
var argType = argResults[i].ReturnType;
if (paramType != argType)
{
EmitConvert(il, argType, paramType);
}
}
if (methodInfo.IsStatic)
il.EmitCall(OpCodes.Call, methodInfo, null);
else
il.EmitCall(OpCodes.Callvirt, methodInfo, null);
}
};
}
return GenerateFunctionCallNode(functionCallNode);
default: // 未定义的节点类型
break;
}
throw new InvalidOperationException($"");
}
/// <summary>
/// 元素读取指令
/// </summary>
/// <param name="il"></param>
/// <param name="elementType"></param>
void EmitLoadElement(ILGenerator il, Type elementType)
{
if (elementType.IsValueType)
{
if (elementType == typeof(int))
il.Emit(OpCodes.Ldelem_I4);
else if (elementType == typeof(float))
il.Emit(OpCodes.Ldelem_R4);
else if (elementType == typeof(double))
il.Emit(OpCodes.Ldelem_R8);
else if (elementType == typeof(bool))
il.Emit(OpCodes.Ldelem_I1);
else if (elementType == typeof(char))
il.Emit(OpCodes.Ldelem_U2);
else
il.Emit(OpCodes.Ldelem, elementType); // 对于其它值类型,通用形式
}
else
{
// 引用类型
il.Emit(OpCodes.Ldelem_Ref);
}
}
/// <summary>
/// 元素发射指令
/// </summary>
/// <param name="il"></param>
/// <param name="elementType"></param>
void EmitStoreElement(ILGenerator il, Type elementType)
{
if (!elementType.IsValueType)
{
il.Emit(OpCodes.Stelem_Ref);
}
else if (elementType == typeof(int))
{
il.Emit(OpCodes.Stelem_I4);
}
else if (elementType == typeof(long))
{
il.Emit(OpCodes.Stelem_I8);
}
else if (elementType == typeof(float))
{
il.Emit(OpCodes.Stelem_R4);
}
else if (elementType == typeof(double))
{
il.Emit(OpCodes.Stelem_R8);
}
else if (elementType == typeof(short))
{
il.Emit(OpCodes.Stelem_I2);
}
else if (elementType == typeof(byte))
{
il.Emit(OpCodes.Stelem_I1);
}
else
{
// 泛型结构体类型
il.Emit(OpCodes.Stelem, elementType);
}
}
/// <summary>
/// 类型转换指令
/// </summary>
/// <param name="il"></param>
/// <param name="fromType"></param>
/// <param name="toType"></param>
void EmitConvert(ILGenerator il, Type fromType, Type toType)
{
if (toType.IsAssignableFrom(fromType))
return;
if (toType.IsValueType)
il.Emit(OpCodes.Unbox_Any, toType);
else
il.Emit(OpCodes.Castclass, toType);
}
/*private void EmitIfNode(IScriptInvokeContext context, ILGenerator il, IfNode ifNode)
{
// Labels
var elseLabel = il.DefineLabel();
var endLabel = il.DefineLabel();
var loopBreakLabel = il.DefineLabel();
// 1. 计算 condition栈顶为 object
EmitNode(il, ifNode.Condition);
// 弹出object装箱转bool
il.Emit(OpCodes.Unbox_Any, typeof(bool));
// 条件为 false跳转 else
il.Emit(OpCodes.Brfalse, elseLabel);
// 2. TrueBranch执行
foreach (var stmt in ifNode.TrueBranch)
{
EmitNode(il, stmt);
if (stmt is ReturnNode)
{
// 设置 context.IsNeedReturn = true
il.Emit(OpCodes.Ldarg_0); // context 参数
il.Emit(OpCodes.Ldc_I4_1);
var isNeedReturnSetter = typeof(IScriptInvokeContext).GetProperty("IsNeedReturn").GetSetMethod();
il.Emit(OpCodes.Callvirt, isNeedReturnSetter);
// 跳出循环直接跳到endLabel
il.Emit(OpCodes.Br, endLabel);
}
}
// 跳转到 if 结束
il.Emit(OpCodes.Br, endLabel);
// 3. else branch
il.MarkLabel(elseLabel);
foreach (var stmt in ifNode.FalseBranch)
{
EmitNode( il, stmt);
if (stmt is ReturnNode)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4_1);
var setter = typeof(IScriptInvokeContext).GetProperty("IsNeedReturn").GetSetMethod();
il.Emit(OpCodes.Callvirt, setter);
il.Emit(OpCodes.Br, endLabel);
}
}
// 4. 结束标签
il.MarkLabel(endLabel);
// 如果方法签名需要返回值,这里可放置默认 return 语句或用局部变量存储返回值
}*/
private static bool IsGenericTask(Type returnType,[NotNullWhen(true)] 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;
}
}
}
}
/*
IL
ldc.i4 4 ldc.i4 123
ldc.i4.s 1 -128~127 ldc.i4.s 42
ldc.i8 8 ldc.i8 123456789L
ldc.r4 4 float ldc.r4 3.14f
ldc.r8 8 double ldc.r8 3.14159
ldstr ldstr "hello"
ldnull null ldnull
ldarg, ldloc ldarg.0, ldloc.1
ldfld ldfld int32 MyField
ldsfld ldsfld string StaticVal
call, callvirt call int32 MyFunc()
newobj newobj instance class MyClass::.ctor()
Pop 使
pop pop
stloc, starg stloc.0, starg.1
stfld pop pop stfld int32 MyField
stsfld stsfld string StaticVal
stelem.* stelem.i4
call, callvirt
ret pop ret
Arithmetic
a + b
add ldloc.0, ldloc.1, add
sub ldloc.0, ldloc.1, sub
mul ldloc.0, ldloc.1, mul
div ldloc.0, ldloc.1, div
div.un
rem ldloc.0, ldloc.1, rem
rem.un
neg ldloc.0, neg
inc ldloc.0, ldc.i4.1, add
/Bitwise & Logical
and & ldloc.0, ldloc.1, and
or | ldloc.0, ldloc.1, or
xor ^
not 使 ldc -1 xor
shl << ldloc.0, ldc.i4.2, shl
shr >>
shr.un
Comparison
int320=false1=true brtrue, brfalse 使
ceq ==
cgt signed
cgt.un unsigned
clt signed
clt.un unsigned
Branch
br label
brtrue label true0
brfalse label false0
beq label pop
bne.un label
bgt, blt, bge, ble
Cast / Convert
conv.i4 int32
conv.r8 double
box -> object
unbox.any object -> T
castclass
isinst null
Object / Field / Property
newobj
call
callvirt
ldfld
stfld
ldsfld
stsfld
ldftn
ldvirtftn
constrained callvirt
newarr
ldlen
ldelem.*
stelem.*
ldloc.*
stloc.*
ldarg.*
starg.*
.try/.catch/.finally
.try, catch, finally
throw
rethrow
leave try
endfinally finally
nop
break
*/