private static Expression ValidateOneArgument(ParameterInfo parameter, Expression expression) { RequiresCanRead(expression, nameof(expression)); var pType = parameter.ParameterType; // NB: No writeability check is performed; LINQ doesn't either, so you can pass e.g. // a constant by ref, causing the write-back to be discarded. We're just being // consistent here. if (pType.IsByRef) { pType = pType.GetElementType(); } TypeUtils.ValidateType(pType); if (!TypeUtils.AreReferenceAssignable(pType, expression.Type)) { if (!TryQuote(pType, ref expression)) { throw Error.ExpressionTypeDoesNotMatchParameter(expression.Type, pType); } } return(expression); }
private static BlockExpression BlockCore(Type type, ReadOnlyCollection <ParameterExpression> variableList, ReadOnlyCollection <Expression> expressionList) { ContractUtils.RequiresNotEmpty(expressionList, "expressions"); RequiresCanRead(expressionList, "expressions"); ValidateVariables(variableList, "variables"); Expression last = expressionList.Last(); if (type != typeof(void)) { if (!TypeUtils.AreReferenceAssignable(type, last.Type)) { throw Error.ArgumentTypesMustMatch(); } } if (!TypeUtils.AreEquivalent(type, last.Type)) { return(new ScopeWithType(variableList, expressionList, type)); } else { if (expressionList.Count == 1) { return(new Scope1(variableList, expressionList[0])); } else { return(new ScopeN(variableList, expressionList)); } } }
private void EmitBinaryMethod(BinaryExpression b, CompilationFlags flags) { if (b.IsLifted) { ParameterExpression p1 = Expression.Variable(b.Left.Type.GetNonNullableType(), name: null); ParameterExpression p2 = Expression.Variable(b.Right.Type.GetNonNullableType(), name: null); MethodCallExpression mc = Expression.Call(null, b.Method, p1, p2); Type resultType; if (b.IsLiftedToNull) { resultType = mc.Type.GetNullableType(); } else { Debug.Assert(mc.Type == typeof(bool)); Debug.Assert(b.NodeType == ExpressionType.Equal || b.NodeType == ExpressionType.NotEqual || b.NodeType == ExpressionType.LessThan || b.NodeType == ExpressionType.LessThanOrEqual || b.NodeType == ExpressionType.GreaterThan || b.NodeType == ExpressionType.GreaterThanOrEqual); resultType = typeof(bool); } Debug.Assert(TypeUtils.AreReferenceAssignable(p1.Type, b.Left.Type.GetNonNullableType())); Debug.Assert(TypeUtils.AreReferenceAssignable(p2.Type, b.Right.Type.GetNonNullableType())); EmitLift(b.NodeType, resultType, mc, new[] { p1, p2 }, new[] { b.Left, b.Right }); } else { EmitMethodCallExpression(Expression.Call(null, b.Method, b.Left, b.Right), flags); } }
internal ComInvokeBinder( CallInfo callInfo, DynamicMetaObject[] args, bool[] isByRef, BindingRestrictions restrictions, Expression method, Expression dispatch, ComMethodDesc methodDesc ) { Debug.Assert(callInfo != null, "arguments"); Debug.Assert(args != null, "args"); Debug.Assert(isByRef != null, "isByRef"); Debug.Assert(method != null, "method"); Debug.Assert(dispatch != null, "dispatch"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(ComMethodDesc), method.Type), "method"); Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(IDispatch), dispatch.Type), "dispatch"); _method = method; _dispatch = dispatch; _methodDesc = methodDesc; _callInfo = callInfo; _args = args; _isByRef = isByRef; _restrictions = restrictions; // Set Instance to some value so that CallBinderHelper has the right number of parameters to work with _instance = dispatch; }
public static MemberExpression Field(Expression expression, FieldInfo field) { ContractUtils.RequiresNotNull(field, "field"); if (field.IsStatic) { if (expression != null) { throw new ArgumentException(Strings.OnlyStaticFieldsHaveNullInstance, "expression"); } } else { if (expression == null) { throw new ArgumentException(Strings.OnlyStaticFieldsHaveNullInstance, "field"); } RequiresCanRead(expression, "expression"); if (!TypeUtils.AreReferenceAssignable(field.DeclaringType, expression.Type)) { throw Error.FieldInfoNotDefinedForType(field.DeclaringType, field.Name, expression.Type); } } return(MemberExpression.Make(expression, field)); }
/// <inheritdoc/> public override void GenerateCode(Emit.MethodBodyGenerator generator, Emit.MethodCompileOption options) { Type = VariableType != null?VariableType.ResolveType(generator.Context) : TypeProvider.AnyType; if (Value != null) { var defValue = Value.Accept(generator); defValue.GenerateCode(generator, AssignOption); if (VariableType == null) { Type = defValue.Type; } else if (!TypeUtils.AreReferenceAssignable(Type, defValue.Type) && defValue.Type.TryImplicitConvert(Type, out System.Reflection.MethodInfo opConvert)) { // When converting value type to Any, must do Box if (defValue.Type.IsValueType && opConvert.GetParameters()[0].ParameterType.IsValueType == false) { generator.Box(defValue.Type); } generator.CallStatic(opConvert); } else if (defValue.Type.IsValueType && !Type.IsValueType) { generator.Box(defValue.Type); } } //initialize var variable = generator.DeclareVariable(Type, Name); generator.StoreVariable(variable); return; }
private static Expression Convert(Expression arg, Type type) { if (TypeUtils.AreReferenceAssignable(type, arg.Type)) { return(arg); } return(Expression.Convert(arg, type)); }
private static void ValidateAccessorArgumentTypes(MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection <Expression> arguments) { if (indexes.Length > 0) { if (indexes.Length != arguments.Count) { throw Error.IncorrectNumberOfMethodCallArguments(method); } Expression[] newArgs = null; for (int i = 0, n = indexes.Length; i < n; i++) { Expression arg = arguments[i]; ParameterInfo pi = indexes[i]; RequiresCanRead(arg, "arguments"); Type pType = pi.ParameterType; if (pType.IsByRef) { throw Error.AccessorsCannotHaveByRefArgs(); } TypeUtils.ValidateType(pType); if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) { if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), pType) && pType.IsAssignableFrom(arg.GetType())) { arg = Expression.Quote(arg); } else { throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method); } } if (newArgs == null && arg != arguments[i]) { newArgs = new Expression[arguments.Count]; for (int j = 0; j < i; j++) { newArgs[j] = arguments[j]; } } if (newArgs != null) { newArgs[i] = arg; } } if (newArgs != null) { arguments = new TrueReadOnlyCollection <Expression>(newArgs); } } else if (arguments.Count > 0) { throw Error.IncorrectNumberOfMethodCallArguments(method); } }
internal Expression ReduceTypeEqual() { Type cType = Expression.Type; // For value types (including Void, but not nullables), we can // determine the result now if (cType.GetTypeInfo().IsValueType&& !cType.IsNullableType()) { return(Expression.Block(Expression, Expression.Constant(cType == _typeOperand.GetNonNullableType()))); } // Can check the value right now for constants. if (Expression.NodeType == ExpressionType.Constant) { return(ReduceConstantTypeEqual()); } // If the expression type is a sealed reference type or a nullable // type, it will match if the value is not null and the type operand // either matches or one is a nullable type while the other is its // type argument (T to the other's T?). if (cType.GetTypeInfo().IsSealed) { if (cType.GetNonNullableType() != _typeOperand.GetNonNullableType()) { return(Expression.Block(Expression, Expression.Constant(false))); } else if (cType.IsNullableType()) { return(Expression.NotEqual(Expression, Expression.Constant(null, Expression.Type))); } else { return(Expression.ReferenceNotEqual(Expression, Expression.Constant(null, Expression.Type))); } } Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(object), Expression.Type), "Expecting reference types only after this point."); // expression is a ByVal parameter. Can safely reevaluate. var parameter = Expression as ParameterExpression; if (parameter != null && !parameter.IsByRef) { return(ByValParameterTypeEqual(parameter)); } // Create a temp so we only evaluate the left side once parameter = Expression.Parameter(typeof(object)); return(Expression.Block( new[] { parameter }, Expression.Assign(parameter, Expression), ByValParameterTypeEqual(parameter) )); }
internal Expression ReduceTypeEqual() { Type cType = Expression.Type; // For value types (including Void, but not nullables), we can // determine the result now if (cType.IsValueType && !cType.IsNullableType()) { return(Expression.Block(Expression, Expression.Constant(cType == _typeOperand.GetNonNullableType()))); } // Can check the value right now for constants. if (Expression.NodeType == ExpressionType.Constant) { return(ReduceConstantTypeEqual()); } // If the operand type is a sealed reference type or a nullable // type, it will match if value is not null if (cType.IsSealed && (cType == _typeOperand)) { if (cType.IsNullableType()) { return(Expression.NotEqual(Expression, Expression.Constant(null, Expression.Type))); } else { return(Expression.ReferenceNotEqual(Expression, Expression.Constant(null, Expression.Type))); } } // expression is a ByVal parameter. Can safely reevaluate. var parameter = Expression as ParameterExpression; if (parameter != null && !parameter.IsByRef) { return(ByValParameterTypeEqual(parameter)); } // Create a temp so we only evaluate the left side once parameter = Expression.Parameter(typeof(object)); // Convert to object if necessary var expression = Expression; if (!TypeUtils.AreReferenceAssignable(typeof(object), expression.Type)) { expression = Expression.Convert(expression, typeof(object)); } return(Expression.Block( new[] { parameter }, Expression.Assign(parameter, expression), ByValParameterTypeEqual(parameter) )); }
private void EmitExpressionAddress(Expression node, Type type) { Debug.Assert(TypeUtils.AreReferenceAssignable(type, node.Type)); EmitExpression(node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitNoExpressionStart); LocalBuilder tmp = GetLocal(type); _ilg.Emit(OpCodes.Stloc, tmp); _ilg.Emit(OpCodes.Ldloca, tmp); }
internal Expression ReduceTypeEqual() { Type cType = Expression.Type; if (cType.IsValueType || TypeOperand.IsPointer) { if (cType.IsNullableType()) { // If the expression type is a nullable type, it will match if // the value is not null and the type operand // either matches or is its type argument (T to its T?). if (cType.GetNonNullableType() != TypeOperand.GetNonNullableType()) { return(Expression.Block(Expression, Utils.Constant(value: false))); } else { return(Expression.NotEqual(Expression, Expression.Constant(null, Expression.Type))); } } else { // For other value types (including Void), we can // determine the result now return(Expression.Block(Expression, Utils.Constant(cType == TypeOperand.GetNonNullableType()))); } } Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(object), Expression.Type), "Expecting reference types only after this point."); // Can check the value right now for constants. if (Expression.NodeType == ExpressionType.Constant) { return(ReduceConstantTypeEqual()); } // expression is a ByVal parameter. Can safely reevaluate. var parameter = Expression as ParameterExpression; if (parameter != null && !parameter.IsByRef) { return(ByValParameterTypeEqual(parameter)); } // Create a temp so we only evaluate the left side once parameter = Expression.Parameter(typeof(object)); return(Expression.Block( new TrueReadOnlyCollection <ParameterExpression>(parameter), new TrueReadOnlyCollection <Expression>( Expression.Assign(parameter, Expression), ByValParameterTypeEqual(parameter) ) )); }
private void EmitSwitchExpression(Expression expr, CompilationFlags flags) { SwitchExpression node = (SwitchExpression)expr; // Try to emit it as an IL switch. Works for integer types. if (TryEmitSwitchInstruction(node, flags)) { return; } // Try to emit as a hashtable lookup. Works for strings. if (TryEmitHashtableSwitch(node, flags)) { return; } // // Fall back to a series of tests. We need to IL gen instead of // transform the tree to avoid stack overflow on a big switch. // var switchValue = Expression.Parameter(node.SwitchValue.Type, "switchValue"); var testValue = Expression.Parameter(GetTestValueType(node), "testValue"); _scope.AddLocal(this, switchValue); _scope.AddLocal(this, testValue); EmitExpression(node.SwitchValue); _scope.EmitSet(switchValue); // Emit tests var labels = new Label[node.Cases.Count]; var isGoto = new bool[node.Cases.Count]; for (int i = 0, n = node.Cases.Count; i < n; i++) { DefineSwitchCaseLabel(node.Cases[i], out labels[i], out isGoto[i]); foreach (Expression test in node.Cases[i].TestValues) { // Pull the test out into a temp so it runs on the same // stack as the switch. This simplifies spilling. EmitExpression(test); _scope.EmitSet(testValue); Debug.Assert(TypeUtils.AreReferenceAssignable(testValue.Type, test.Type)); EmitExpressionAndBranch(true, Expression.Equal(switchValue, testValue, false, node.Comparison), labels[i]); } } // Define labels Label end = _ilg.DefineLabel(); Label @default = (node.DefaultBody == null) ? end : _ilg.DefineLabel(); // Emit the case and default bodies EmitSwitchCases(node, labels, isGoto, @default, end, flags); }
/// <summary> /// Creates a <see cref="NewArrayExpression"/> of the specified type from the provided initializers. /// </summary> /// <param name="type">A Type that represents the element type of the array.</param> /// <param name="initializers">The expressions used to create the array elements.</param> /// <returns>A <see cref="NewArrayExpression"/> that has the <see cref="NodeType"/> property equal to <see cref="ExpressionType.NewArrayInit"/> and the <see cref="NewArrayExpression.Expressions"/> property set to the specified value.</returns> public static NewArrayExpression NewArrayInit(Type type, IEnumerable <Expression> initializers) { ContractUtils.RequiresNotNull(type, nameof(type)); ContractUtils.RequiresNotNull(initializers, nameof(initializers)); if (type == typeof(void)) { throw Error.ArgumentCannotBeOfTypeVoid(nameof(type)); } TypeUtils.ValidateType(type, nameof(type)); if (type.IsByRef) { throw Error.TypeMustNotBeByRef(nameof(type)); } if (type.IsPointer) { throw Error.TypeMustNotBePointer(nameof(type)); } ReadOnlyCollection <Expression> initializerList = initializers.ToReadOnly(); Expression[] newList = null; for (int i = 0, n = initializerList.Count; i < n; i++) { Expression expr = initializerList[i]; RequiresCanRead(expr, nameof(initializers), i); if (!TypeUtils.AreReferenceAssignable(type, expr.Type)) { if (!TryQuote(type, ref expr)) { throw Error.ExpressionTypeCannotInitializeArrayType(expr.Type, type); } if (newList == null) { newList = new Expression[initializerList.Count]; for (int j = 0; j < i; j++) { newList[j] = initializerList[j]; } } } if (newList != null) { newList[i] = expr; } } if (newList != null) { initializerList = new TrueReadOnlyCollection <Expression>(newList); } return(NewArrayExpression.Make(ExpressionType.NewArrayInit, type.MakeArrayType(), initializerList)); }
private void EmitExpressionAddress(Expression node, Type type) { Debug.Assert(TypeUtils.AreReferenceAssignable(type, node.Type)); EmitExpression(node, false); LocalBuilder tmp = _ilg.GetLocal(type); _ilg.Emit(OpCodes.Stloc, tmp); _ilg.Emit(OpCodes.Ldloca, tmp); _ilg.FreeLocal(tmp); }
/// <summary> /// Reduces this node to a simpler expression. If CanReduce returns /// true, this should return a valid expression. This method is /// allowed to return another node which itself must be reduced. /// /// Unlike Reduce, this method checks that the reduced node satisfies /// certain invaraints. /// </summary> /// <returns>the reduced expression</returns> public Expression ReduceAndCheck() { ContractUtils.Requires(CanReduce, "this", Strings.MustBeReducible); var newNode = Reduce(); // 1. Reduction must return a new, non-null node // 2. Reduction must return a new node whose result type can be assigned to the type of the original node ContractUtils.Requires(newNode != null && newNode != this, "this", Strings.MustReduceToDifferent); ContractUtils.Requires(TypeUtils.AreReferenceAssignable(Type, newNode.Type), "this", Strings.ReducedNotCompatible); return(newNode); }
// For optimized Equal/NotEqual, we can eliminate reference // conversions. IL allows comparing managed pointers regardless of // type. See ECMA-335 "Binary Comparison or Branch Operations", in // Partition III, Section 1.5 Table 4. private static Expression GetEqualityOperand(Expression expression) { if (expression.NodeType == ExpressionType.Convert) { var convert = (UnaryExpression)expression; if (TypeUtils.AreReferenceAssignable(convert.Type, convert.Operand.Type)) { return(convert.Operand); } } return(expression); }
private Expression ReduceStaticAssign(Expression lhs) { lhs = MakeWriteable(lhs); var rhs = Right.Expression; if (!TypeUtils.AreReferenceAssignable(lhs.Type, rhs.Type)) { rhs = DynamicConvert(rhs, lhs.Type, CSharpBinderFlags.None, Context); } return(Expression.Assign(lhs, rhs)); }
private static void ValidateAccessorArgumentTypes(MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection <Expression> arguments, string?paramName) { if (indexes.Length > 0) { if (indexes.Length != arguments.Count) { throw Error.IncorrectNumberOfMethodCallArguments(method, paramName); } Expression[]? newArgs = null; for (int i = 0, n = indexes.Length; i < n; i++) { Expression arg = arguments[i]; ParameterInfo pi = indexes[i]; ExpressionUtils.RequiresCanRead(arg, nameof(arguments), i); Type pType = pi.ParameterType; if (pType.IsByRef) { throw Error.AccessorsCannotHaveByRefArgs(nameof(indexes), i); } TypeUtils.ValidateType(pType, nameof(indexes), i); if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) { if (!TryQuote(pType, ref arg)) { throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method, nameof(arguments), i); } } if (newArgs == null && arg != arguments[i]) { newArgs = new Expression[arguments.Count]; for (int j = 0; j < i; j++) { newArgs[j] = arguments[j]; } } if (newArgs != null) { newArgs[i] = arg; } } if (newArgs != null) { arguments = new TrueReadOnlyCollection <Expression>(newArgs); } } else if (arguments.Count > 0) { throw Error.IncorrectNumberOfMethodCallArguments(method, paramName); } }
public static MethodInfo GetImplicitConversion(this System.Type type, string name, System.Type returnType, params System.Type[] parameterTypes) { var results = type.GetMember(name, MemberTypes.Method, DeclaredStatic); foreach (MethodInfo method in results) { if (method.MatchesArgumentTypes(parameterTypes) && TypeUtils.AreReferenceAssignable(method.ReturnType, returnType)) { return(method); } } throw new System.InvalidOperationException(string.Format("the convertion method {0}.{1}({2})", type.FullName, name, StringHelpers.Join(Separator, parameterTypes))); }
public static bool MatchesArgumentTypes(this MethodBase method, Type[] types) { var parameters = method.GetParameters(); var length = types.Length; if (parameters.Length < length) { return(false); } int i; for (i = 0; i < parameters.Length; i++) { var param = parameters[i]; var dest = param.ParameterType; if (param.IsDefined(typeof(ParamArrayAttribute), false)) { // parameters is extra example print(string, params string[] args) and print('hello') // in this case 2 and 1 if (parameters.Length > length) { return(true); } //No further check required if matchs return(ParamArrayMatchs(types, i, dest.GetElementType())); } // matches current index if (i >= length) { return(false); } var src = types[i]; if (src is null) { if (dest.IsValueType && !dest.IsNullableType()) { return(false); } } else if (!TypeUtils.AreReferenceAssignable(dest, src)) { return(false); } } if (i == length) { return(true); } return(false); }
// Standard argument validation, taken from ValidateArgumentTypes private static void ValidateGotoType(Type expectedType, ref Expression value, string paramName) { RequiresCanRead(value, paramName); if (!TypeUtils.AreReferenceAssignable(expectedType, value.Type)) { // C# autoquotes return values, so we'll do that here if (TypeUtils.IsSameOrSubclass(typeof(Expression), expectedType) && expectedType.IsAssignableFrom(value.GetType())) { value = Expression.Quote(value); } throw Error.ExpressionTypeDoesNotMatchLabel(value.Type, expectedType); } }
// Standard argument validation, taken from ValidateArgumentTypes private static void ValidateGotoType(Type expectedType, ref Expression value, string paramName) { ExpressionUtils.RequiresCanRead(value, paramName); if (expectedType != typeof(void)) { if (!TypeUtils.AreReferenceAssignable(expectedType, value.Type)) { // C# auto-quotes return values, so we'll do that here if (!TryQuote(expectedType, ref value)) { throw Error.ExpressionTypeDoesNotMatchLabel(value.Type, expectedType); } } } }
public static UnaryExpression Throw(Expression value, Type type) { ContractUtils.RequiresNotNull(type, "type"); if (value != null) { RequiresCanRead(value, "value"); ContractUtils.Requires( TypeUtils.AreReferenceAssignable(typeof(Exception), value.Type), "value", Strings.ArgumentMustBeException ); } return(new UnaryExpression(ExpressionType.Throw, value, type, null)); }
/// <summary> /// Creates a new array expression of the specified type from the provided initializers. /// </summary> /// <param name="type">A Type that represents the element type of the array.</param> /// <param name="initializers">The expressions used to create the array elements.</param> /// <returns>An instance of the <see cref="NewArrayExpression"/>.</returns> public static NewArrayExpression NewArrayInit(Type type, IEnumerable <Expression> initializers) { ContractUtils.RequiresNotNull(type, "type"); ContractUtils.RequiresNotNull(initializers, "initializers"); if (type.Equals(typeof(void))) { throw Error.ArgumentCannotBeOfTypeVoid(); } ReadOnlyCollection <Expression> initializerList = initializers.ToReadOnly(); Expression[] newList = null; for (int i = 0, n = initializerList.Count; i < n; i++) { Expression expr = initializerList[i]; RequiresCanRead(expr, "initializers"); if (!TypeUtils.AreReferenceAssignable(type, expr.Type)) { if (TypeUtils.IsSameOrSubclass(typeof(LambdaExpression), type) && type.IsAssignableFrom(expr.GetType())) { expr = Expression.Quote(expr); } else { throw Error.ExpressionTypeCannotInitializeArrayType(expr.Type, type); } if (newList == null) { newList = new Expression[initializerList.Count]; for (int j = 0; j < i; j++) { newList[j] = initializerList[j]; } } } if (newList != null) { newList[i] = expr; } } if (newList != null) { initializerList = new TrueReadOnlyCollection <Expression>(newList); } return(NewArrayExpression.Make(ExpressionType.NewArrayInit, type.MakeArrayType(), initializerList)); }
private static bool IsCompatible(PropertyInfo pi, Expression[]?args) { MethodInfo?mi = pi.GetGetMethod(nonPublic: true); ParameterInfo[] parms; if (mi != null) { parms = mi.GetParametersCached(); } else { mi = pi.GetSetMethod(nonPublic: true); if (mi == null) { return(false); } //The setter has an additional parameter for the value to set, //need to remove the last type to match the arguments. parms = mi.GetParametersCached(); if (parms.Length == 0) { return(false); } parms = parms.RemoveLast(); } if (args == null) { return(parms.Length == 0); } if (parms.Length != args.Length) { return(false); } for (int i = 0; i < args.Length; i++) { if (args[i] == null) { return(false); } if (!TypeUtils.AreReferenceAssignable(parms[i].ParameterType, args[i].Type)) { return(false); } } return(true); }
/// <inheritdoc/> Expression IExpressionVisitor <Expression> .VisitArrayLiteral(ArrayListExpression node) { var type = node.ArrayType != null?node.ArrayType.ResolveType(Context) : TypeProvider.AnyType; node.Type = typeof(Collections.List <>).MakeGenericType(type); node.ElementType = type; if (node.Arguments != null) { var types = node.Arguments.Map(arg => arg.Accept(this).Type); if (node.Constructor == null) { var ctors = node.Type.GetConstructors(ReflectionUtils.PublicInstance); var ctor = ReflectionUtils.BindToMethod(ctors, types, out ArgumentConversions conversions); if (ctor == null) { ExecutionException.ThrowMissingMethod(node.Type, "ctor", node); } node.Constructor = ctor; node.ArgumentConversions = conversions; } } else if (node.Constructor == null) { node.Constructor = node.Type.GetConstructor(ReflectionUtils.PublicInstance, null, new Type[0], null); } var items = node.Expressions; if (items.Count > 0) { var arrayConversions = new ArgumentConversions(items.Count); for (int index = 0; index < items.Count; index++) { var expression = items[index].Accept(this); if (!TypeUtils.AreReferenceAssignable(type, expression.Type) && expression.Type.TryImplicitConvert(type, out System.Reflection.MethodInfo implicitCall)) { if (expression.Type.IsValueType && implicitCall.GetParameters()[0].ParameterType == TypeProvider.ObjectType) { arrayConversions.Append(index, new BoxConversion(index, expression.Type)); } arrayConversions.Append(index, new ParamConversion(index, implicitCall)); } } node.ArrayConversions = arrayConversions; } return(node); }
//Validate that the body of the try expression must have the same type as the body of every try block. private static void ValidateTryAndCatchHaveSameType(Type type, Expression tryBody, ReadOnlyCollection <CatchBlock> handlers) { Debug.Assert(tryBody != null); // Type unification ... all parts must be reference assignable to "type" if (type != null) { if (type != typeof(void)) { if (!TypeUtils.AreReferenceAssignable(type, tryBody.Type)) { throw Error.ArgumentTypesMustMatch(); } foreach (CatchBlock cb in handlers) { if (!TypeUtils.AreReferenceAssignable(type, cb.Body.Type)) { throw Error.ArgumentTypesMustMatch(); } } } } else if (tryBody.Type == typeof(void)) { //The body of every try block must be null or have void type. foreach (CatchBlock cb in handlers) { Debug.Assert(cb.Body != null); if (cb.Body.Type != typeof(void)) { throw Error.BodyOfCatchMustHaveSameTypeAsBodyOfTry(); } } } else { //Body of every catch must have the same type of body of try. type = tryBody.Type; foreach (CatchBlock cb in handlers) { Debug.Assert(cb.Body != null); if (!TypeUtils.AreEquivalent(cb.Body.Type, type)) { throw Error.BodyOfCatchMustHaveSameTypeAsBodyOfTry(); } } } }
public object VisitInstanceOf(InstanceOfExpression node) { var value = node.Target.Accept(this); if (value is null && node.TypeSyntax is RefTypeSyntax refType && refType.Name.Equals("null")) { return(Boolean.True); } var type = node.TypeSyntax.ResolveType(TypeContext); var valueType = value.GetType(); if (TypeUtils.AreReferenceAssignable(type, valueType)) { return(Boolean.True); } return(Boolean.False); }
//CONFORMING internal static void ValidateLift(IList <ParameterExpression> variables, IList <Expression> arguments) { System.Diagnostics.Debug.Assert(variables != null); System.Diagnostics.Debug.Assert(arguments != null); if (variables.Count != arguments.Count) { throw Error.IncorrectNumberOfIndexes(); } for (int i = 0, n = variables.Count; i < n; i++) { if (!TypeUtils.AreReferenceAssignable(variables[i].Type, TypeUtils.GetNonNullableType(arguments[i].Type))) { throw Error.ArgumentTypesMustMatch(); } } }