69 lines
2.4 KiB
C#
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; }
|
|
}
|
|
}
|
|
}
|