// resolve phase
//
public class UserOperatorCall : Expression {
- public delegate Expression ExpressionTreeExpression (ResolveContext ec, MethodGroupExpr mg);
-
protected readonly Arguments arguments;
- protected readonly MethodGroupExpr mg;
- readonly ExpressionTreeExpression expr_tree;
+ protected readonly MethodSpec oper;
+ readonly Func<ResolveContext, Expression, Expression> expr_tree;
- public UserOperatorCall (MethodGroupExpr mg, Arguments args, ExpressionTreeExpression expr_tree, Location loc)
+ public UserOperatorCall (MethodSpec oper, Arguments args, Func<ResolveContext, Expression, Expression> expr_tree, Location loc)
{
- this.mg = mg;
+ this.oper = oper;
this.arguments = args;
this.expr_tree = expr_tree;
- type = mg.BestCandidate.ReturnType;
+ type = oper.ReturnType;
eclass = ExprClass.Value;
this.loc = loc;
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
if (expr_tree != null)
- return expr_tree (ec, mg);
+ return expr_tree (ec, new TypeOfMethod (oper, loc));
Arguments args = Arguments.CreateForExpressionTree (ec, arguments,
new NullLiteral (loc),
- mg.CreateExpressionTree (ec));
+ new TypeOfMethod (oper, loc));
return CreateExpressionFactoryCall (ec, "Call", args);
}
public override void Emit (EmitContext ec)
{
- mg.EmitCall (ec, arguments);
+ Invocation.EmitCall (ec, null, oper, arguments, loc);
}
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
- var method = mg.BestCandidate.GetMetaInfo () as MethodInfo;
+ var method = oper.GetMetaInfo () as MethodInfo;
return SLE.Expression.Call (method, Arguments.MakeExpression (arguments, ctx));
}
-
- public MethodGroupExpr Method {
- get { return mg; }
- }
}
public class ParenthesizedExpression : ShimExpression
return CreateExpressionTree (ec, null);
}
- Expression CreateExpressionTree (ResolveContext ec, MethodGroupExpr user_op)
+ Expression CreateExpressionTree (ResolveContext ec, Expression user_op)
{
string method_name;
switch (Oper) {
Arguments args = new Arguments (2);
args.Add (new Argument (Expr.CreateExpressionTree (ec)));
if (user_op != null)
- args.Add (new Argument (user_op.CreateExpressionTree (ec)));
+ args.Add (new Argument (user_op));
+
return CreateExpressionFactoryCall (ec, method_name, args);
}
return null;
Expr = args [0].Expr;
- return new UserOperatorCall (user_op, args, CreateExpressionTree, expr.Location);
+ return new UserOperatorCall (user_op.BestCandidate, args, CreateExpressionTree, expr.Location);
}
//
return null;
args[0].Expr = operation;
- operation = new UserOperatorCall (mg, args, null, loc);
+ operation = new UserOperatorCall (mg.BestCandidate, args, null, loc);
operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
return this;
}
method = inequal_method;
}
- var mg = MethodGroupExpr.CreatePredefined (method, left, b.loc);
- return new UserOperatorCall (mg, args, b.CreateExpressionTree, b.loc);
+ return new UserOperatorCall (method, args, b.CreateExpressionTree, b.loc);
}
}
}
MethodGroupExpr mg = MethodGroupExpr.CreatePredefined (method, TypeManager.delegate_type, loc);
- Expression expr = new UserOperatorCall (mg, args, CreateExpressionTree, loc);
+ Expression expr = new UserOperatorCall (mg.BestCandidate, args, CreateExpressionTree, loc);
return new ClassCast (expr, l);
}
// TODO: CreateExpressionTree is allocated every time
if ((oper & Operator.LogicalMask) != 0) {
- oper_expr = new ConditionalLogicalOperator (mg, args, CreateExpressionTree,
+ oper_expr = new ConditionalLogicalOperator (mg.BestCandidate, args, CreateExpressionTree,
oper == Operator.LogicalAnd, loc).Resolve (ec);
} else {
- oper_expr = new UserOperatorCall (mg, args, CreateExpressionTree, loc);
+ oper_expr = new UserOperatorCall (mg.BestCandidate, args, CreateExpressionTree, loc);
}
left = larg.Expr;
return CreateExpressionTree (ec, null);
}
- Expression CreateExpressionTree (ResolveContext ec, MethodGroupExpr method)
+ Expression CreateExpressionTree (ResolveContext ec, Expression method)
{
string method_name;
bool lift_arg = false;
if (method != null) {
if (lift_arg)
args.Add (new Argument (new BoolConstant (false, loc)));
-
- args.Add (new Argument (method.CreateExpressionTree (ec)));
+
+ args.Add (new Argument (method));
}
return CreateExpressionFactoryCall (ec, method_name, args);
//
public class ConditionalLogicalOperator : UserOperatorCall {
readonly bool is_and;
- Expression oper;
+ Expression oper_expr;
- public ConditionalLogicalOperator (MethodGroupExpr oper_method, Arguments arguments,
- ExpressionTreeExpression expr_tree, bool is_and, Location loc)
- : base (oper_method, arguments, expr_tree, loc)
+ public ConditionalLogicalOperator (MethodSpec oper, Arguments arguments, Func<ResolveContext, Expression, Expression> expr_tree, bool is_and, Location loc)
+ : base (oper, arguments, expr_tree, loc)
{
this.is_and = is_and;
eclass = ExprClass.Unresolved;
protected override Expression DoResolve (ResolveContext ec)
{
- var method = mg.BestCandidate;
- type = method.ReturnType;
- AParametersCollection pd = method.Parameters;
+ AParametersCollection pd = oper.Parameters;
if (!TypeManager.IsEqual (type, type) || !TypeManager.IsEqual (type, pd.Types [0]) || !TypeManager.IsEqual (type, pd.Types [1])) {
ec.Report.Error (217, loc,
"A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator",
- TypeManager.CSharpSignature (method));
+ oper.GetSignatureForError ());
return null;
}
if (op_true == null || op_false == null) {
ec.Report.Error (218, loc,
"The type `{0}' must have operator `true' and operator `false' defined when `{1}' is used as a short circuit operator",
- TypeManager.CSharpName (type), TypeManager.CSharpSignature (method));
+ TypeManager.CSharpName (type), oper.GetSignatureForError ());
return null;
}
- oper = is_and ? op_false : op_true;
+ oper_expr = is_and ? op_false : op_true;
eclass = ExprClass.Value;
return this;
}
ec.Emit (OpCodes.Dup);
arguments.RemoveAt (0);
- oper.EmitBranchable (ec, end_target, true);
+ oper_expr.EmitBranchable (ec, end_target, true);
base.Emit (ec);
ec.MarkLabel (end_target);
}
public override bool Resolve (IMemberContext ec)
{
- // should not be called
- throw new NotSupportedException ();
+ // Nothing to be resolved
+ return true;
}
}
if (constraints == null)
return true;
- return ConstraintChecker.CheckAll (open_type, args.Arguments, constraints, loc, ec.Compiler.Report);
+ return ConstraintChecker.CheckAll (ec, open_type, args.Arguments, constraints, loc);
}
public override bool CheckAccessLevel (IMemberContext mc)
/// Check the constraints; we're called from ResolveAsTypeTerminal()
/// after fully resolving the constructed type.
/// </summary>
- public static bool CheckAll (MemberSpec context, TypeSpec[] targs, TypeParameterSpec[] tparams, Location loc, Report report)
+ public static bool CheckAll (IMemberContext mc, MemberSpec context, TypeSpec[] targs, TypeParameterSpec[] tparams, Location loc)
{
for (int i = 0; i < tparams.Length; i++) {
- if (!CheckConstraint (context, targs [i], tparams [i], loc, report))
+ if (!CheckConstraint (mc, context, targs [i], tparams [i], loc))
return false;
}
return true;
}
- static bool CheckConstraint (MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, Location loc, Report report)
+ static bool CheckConstraint (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, Location loc)
{
//
// First, check the `class' and `struct' constraints.
//
if (tparam.HasSpecialClass && !TypeManager.IsReferenceType (atype)) {
- report.Error (452, loc,
+ mc.Compiler.Report.Error (452, loc,
"The type `{0}' must be a reference type in order to use it as type parameter `{1}' in the generic type or method `{2}'",
TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
return false;
}
if (tparam.HasSpecialStruct && (!TypeManager.IsValueType (atype) || TypeManager.IsNullableType (atype))) {
- report.Error (453, loc,
+ mc.Compiler.Report.Error (453, loc,
"The type `{0}' must be a non-nullable value type in order to use it as type parameter `{1}' in the generic type or method `{2}'",
TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
return false;
// The class constraint comes next.
//
if (tparam.HasTypeConstraint) {
- CheckConversion (context, atype, tparam, tparam.BaseType, loc, report);
+ CheckConversion (mc, context, atype, tparam, tparam.BaseType, loc);
}
//
//
if (tparam.Interfaces != null) {
if (TypeManager.IsNullableType (atype)) {
- report.Error (313, loc,
+ mc.Compiler.Report.Error (313, loc,
"The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. The nullable type `{0}' never satisfies interface constraint",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError ());
} else {
foreach (TypeSpec iface in tparam.Interfaces) {
- CheckConversion (context, atype, tparam, iface, loc, report);
+ CheckConversion (mc, context, atype, tparam, iface, loc);
}
}
}
return true;
if (!HasDefaultConstructor (atype)) {
- report.SymbolRelatedToPreviousError (atype);
- report.Error (310, loc,
+ mc.Compiler.Report.SymbolRelatedToPreviousError (atype);
+ mc.Compiler.Report.Error (310, loc,
"The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'",
TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ());
return false;
return true;
}
- static void CheckConversion (MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, TypeSpec ttype, Location loc, Report report)
+ static void CheckConversion (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, TypeSpec ttype, Location loc)
{
var expr = new EmptyExpression (atype);
if (!Convert.ImplicitStandardConversionExists (expr, ttype)) {
- report.SymbolRelatedToPreviousError (tparam);
+ mc.Compiler.Report.SymbolRelatedToPreviousError (tparam);
if (TypeManager.IsValueType (atype)) {
- report.Error (315, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'",
+ mc.Compiler.Report.Error (315, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing conversion from `{0}' to `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
} else if (atype.IsGenericParameter) {
- report.Error (314, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing or type parameter conversion from `{0}' to `{3}'",
+ mc.Compiler.Report.Error (314, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no boxing or type parameter conversion from `{0}' to `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
} else {
- report.Error (311, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no implicit reference conversion from `{0}' to `{3}'",
+ mc.Compiler.Report.Error (311, loc, "The type `{0}' cannot be used as type parameter `{1}' in the generic type or method `{2}'. There is no implicit reference conversion from `{0}' to `{3}'",
atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ());
}
}