public void GenerateSet(Expression right, MethodBodyGenerator generator, MethodCompileOption option = MethodCompileOption.None) { // first parameter to be Any if (right.Type != TypeProvider.AnyType) { if (right.Type.IsValueType) { generator.Box(right.Type); } generator.CallStatic(ReflectionHelpers.ImplicitAny); } generator.LoadString(Name); generator.LoadToken(right.Type); generator.Call((Func <RuntimeTypeHandle, Type>)Type.GetTypeFromHandle); generator.Call(typeof(IDynamicInvocable).GetInstanceMethod(nameof(IDynamicInvocable.SafeSetValue), TypeProvider.AnyType, typeof(string), typeof(Type))); if ((option & MethodCompileOption.Return) == 0) { generator.Pop(); return; } }
void CallPostFixMember(MethodBodyGenerator generator, IBinder binder, MethodCompileOption option) { // if no duplicate ex: i++ single line if ((option & MethodCompileOption.Dupplicate) == 0) { binder.GenerateSet(Operand, generator); return; } // i++ where i is member // intially member is loaded var temp = generator.DeclareVariable(binder.Type); // store the result to variable generator.StoreVariable(temp); // load the variable generator.LoadVariable(temp); // call operator generator.CallStatic(Method); // store operation result to member binder.GenerateSet(Operand, generator); //load the temp variable generator.LoadVariable(temp); }
public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption option) { if (NodeType == ExpressionType.Parenthesized) { Operand.GenerateCode(generator, option); return; } var operand = Operand; IBinder binder = null; if (operand.NodeType == ExpressionType.Identifier) { //todo only for get; set; member //i++ or Member++ binder = ((NameExpression)operand).Binder; } else if (operand.NodeType == ExpressionType.MemberAccess) { binder = ((MemberExpression)operand).Binder; } // todo: Conversion if value is short, byte lower data type switch (NodeType) { case ExpressionType.PostfixMinusMinus: case ExpressionType.PostfixPlusPlus: if (binder == null) { throw new NullReferenceException(nameof(binder)); } if ((binder.Attributes & BindingAttributes.HasThis) != 0) { generator.LoadArgument(0); } operand.GenerateCode(generator, MethodCompileOption.Dupplicate); if ((binder.Attributes & BindingAttributes.Member) != 0) { CallPostFixMember(generator, binder, option); return; } if ((option & MethodCompileOption.Dupplicate) != 0) { generator.Duplicate(); } // call the operator generator.CallStatic(Method); // update value binder.GenerateSet(operand, generator); break; case ExpressionType.PrefixMinusMinus: case ExpressionType.PrefixPlusPlus: if (binder == null) { throw new NullReferenceException(nameof(binder)); } if ((binder.Attributes & BindingAttributes.HasThis) != 0) { generator.LoadArgument(0); } operand.GenerateCode(generator, MethodCompileOption.Dupplicate); // call the operator generator.CallStatic(Method); if ((binder.Attributes & BindingAttributes.Member) != 0) { CallPreFixMember(generator, binder, option); return; } if ((option & MethodCompileOption.Dupplicate) != 0) { generator.Duplicate(); } // update value binder.GenerateSet(Operand, generator); break; default: // call the operator operand.GenerateCode(generator, AssignOption); generator.CallStatic(Method); break; } }