Files
Flee/ExpressionElements/Assignment.cs
2025-10-09 16:16:59 +08:00

69 lines
2.4 KiB
C#

using System;
using Flee.ExpressionElements.Base;
using Flee.ExpressionElements.MemberElements;
using Flee.InternalTypes;
using Flee.PublicTypes;
namespace Flee.ExpressionElements
{
internal class AssignmentElement : ExpressionElement
{
private readonly string _variableName;
private readonly ExpressionElement _valueExpression;
private readonly ExpressionContext _context;
public AssignmentElement(string variableName, ExpressionElement valueExpression, ExpressionContext context)
{
_variableName = variableName;
_valueExpression = valueExpression;
_context = context;
// 检查变量是否存在
if (!_context.Variables.ContainsKey(_variableName))
{
this.ThrowCompileException("UndefinedVariable", CompileExceptionReason.UndefinedName, _variableName);
}
}
public override void Emit(FleeILGenerator ilg, IServiceProvider services)
{
// 首先计算右侧表达式的值
_valueExpression.Emit(ilg, services);
// 获取一个临时本地变量来存储值
var valueType = _valueExpression.ResultType;
int tempIndex = ilg.GetTempLocalIndex(valueType);
// 存储值到临时变量
Utility.EmitStoreLocal(ilg, tempIndex);
// 加载变量集合 (arg 2)
ilg.Emit(System.Reflection.Emit.OpCodes.Ldarg_2); // 加载 VariableCollection
// 加载变量名
ilg.Emit(System.Reflection.Emit.OpCodes.Ldstr, _variableName);
// 加载要设置的值
Utility.EmitLoadLocal(ilg, tempIndex);
// 如果值类型是值类型,需要装箱
if (valueType.IsValueType)
{
ilg.Emit(System.Reflection.Emit.OpCodes.Box, valueType);
}
// 调用 Variables[string] 的 setter
var indexerSetter = typeof(VariableCollection).GetProperty("Item", new Type[] { typeof(string) }).GetSetMethod();
ilg.Emit(System.Reflection.Emit.OpCodes.Callvirt, indexerSetter);
// 加载返回值到栈上
Utility.EmitLoadLocal(ilg, tempIndex);
}
public override Type ResultType
{
get { return _valueExpression.ResultType; }
}
}
}