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; } } } }