public readonly Operator Oper;
public Expression Expr;
+ Expression enum_conversion;
public Unary (Operator op, Expression expr, Location loc)
{
protected Expression ResolveOperator (EmitContext ec, Expression expr)
{
+ eclass = ExprClass.Value;
+
if (predefined_operators == null)
CreatePredefinedOperatorsTable ();
//
// E operator ~(E x);
//
- if (Oper == Operator.OnesComplement && TypeManager.IsEnumType (expr_type)) {
- best_expr = ResolvePrimitivePredefinedType (EmptyCast.Create (expr, TypeManager.GetEnumUnderlyingType (expr_type)));
- if (best_expr == null)
- return null;
-
- Expr = EmptyCast.Create (best_expr, expr_type);
- type = Expr.Type;
- return this;
- }
+ if (Oper == Operator.OnesComplement && TypeManager.IsEnumType (expr_type))
+ return ResolveEnumOperator (ec, expr);
return ResolveUserType (ec, expr);
}
+ protected virtual Expression ResolveEnumOperator (EmitContext ec, Expression expr)
+ {
+ Type underlying_type = TypeManager.GetEnumUnderlyingType (expr.Type);
+ Expression best_expr = ResolvePrimitivePredefinedType (EmptyCast.Create (expr, underlying_type));
+ if (best_expr == null)
+ return null;
+
+ Expr = best_expr;
+ enum_conversion = Convert.ExplicitNumericConversion (new EmptyExpression (best_expr.Type), underlying_type);
+ type = expr.Type;
+ return EmptyCast.Create (this, type);
+ }
+
public override Expression CreateExpressionTree (EmitContext ec)
{
return CreateExpressionTree (ec, null);
{
string method_name;
switch (Oper) {
+ case Operator.AddressOf:
+ Error_PointerInsideExpressionTree ();
+ return null;
case Operator.UnaryNegation:
if (ec.CheckState && user_op == null && !IsFloat (type))
method_name = "NegateChecked";
public override Expression DoResolve (EmitContext ec)
{
- eclass = ExprClass.Value;
-
if (Oper == Operator.AddressOf) {
Expr = Expr.DoResolveLValue (ec, new EmptyExpression ());
throw new Exception ("This should not happen: Operator = "
+ Oper.ToString ());
}
+
+ //
+ // Same trick as in Binary expression
+ //
+ if (enum_conversion != null)
+ enum_conversion.Emit (ec);
}
public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
}
type = TypeManager.GetPointerType (Expr.Type);
+ eclass = ExprClass.Value;
return this;
}
this.expr = expr;
loc = l;
}
+
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ Error_PointerInsideExpressionTree ();
+ return null;
+ }
public override void Emit (EmitContext ec)
{
//
Expression ResolveOperatorEnum (EmitContext ec, bool lenum, bool renum, Type ltype, Type rtype)
{
- Expression temp;
+ //
+ // bool operator == (E x, E y);
+ // bool operator != (E x, E y);
+ // bool operator < (E x, E y);
+ // bool operator > (E x, E y);
+ // bool operator <= (E x, E y);
+ // bool operator >= (E x, E y);
+ //
+ // E operator & (E x, E y);
+ // E operator | (E x, E y);
+ // E operator ^ (E x, E y);
+ //
+ // U operator - (E e, E f)
+ // E operator - (E e, U x)
+ //
+ // E operator + (U x, E e)
+ // E operator + (E e, U x)
+ //
+ if (!((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0 ||
+ (oper == Operator.Subtraction && lenum) || (oper == Operator.Addition && lenum != renum)))
+ return null;
- if (lenum || renum) {
- //
- // bool operator == (E x, E y);
- // bool operator != (E x, E y);
- // bool operator < (E x, E y);
- // bool operator > (E x, E y);
- // bool operator <= (E x, E y);
- // bool operator >= (E x, E y);
- //
- if ((oper & Operator.ComparisonMask) != 0) {
- type = TypeManager.bool_type;
- } else if ((oper & Operator.BitwiseMask) != 0) {
- type = ltype;
- }
+ Expression ltemp = left;
+ Expression rtemp = right;
+ Type underlying_type;
- if (type != null) {
- if (!TypeManager.IsEqual (ltype, rtype)) {
- if (!lenum) {
- temp = Convert.ImplicitConversion (ec, left, rtype, loc);
- if (temp == null)
- return null;
- left = temp;
- } else {
- temp = Convert.ImplicitConversion (ec, right, ltype, loc);
- if (temp == null)
- return null;
- right = temp;
- }
- }
+ if (TypeManager.IsEqual (ltype, rtype)) {
+ underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
- return this;
- }
- }
+ if (left is Constant)
+ left = ((Constant) left).ConvertExplicitly (false, underlying_type);
+ else
+ left = EmptyCast.Create (left, underlying_type);
- Type underlying_type;
- if (lenum && !renum) {
- //
- // E operator + (E e, U x)
- // E operator - (E e, U x)
- //
- if (oper == Operator.Addition || oper == Operator.Subtraction) {
- underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
- temp = left;
- left = EmptyCast.Create (left, underlying_type, true);
- if (!DoBinaryOperatorPromotion (ec)) {
- left = temp;
+ if (right is Constant)
+ right = ((Constant) right).ConvertExplicitly (false, underlying_type);
+ else
+ right = EmptyCast.Create (right, underlying_type);
+ } else if (lenum) {
+ if (oper != Operator.Subtraction && oper != Operator.Addition) {
+ Constant c = right as Constant;
+ if (c == null || !c.IsDefaultValue)
return null;
- }
-
- enum_conversion = Convert.ExplicitNumericConversion (
- new EmptyExpression (left.Type), underlying_type);
+ }
- return ResolveOperatorPredefined (ec, standard_operators, true, ltype);
+ underlying_type = TypeManager.GetEnumUnderlyingType (ltype);
+ if (left is Constant)
+ left = ((Constant) left).ConvertExplicitly (false, underlying_type);
+ else
+ left = EmptyCast.Create (left, underlying_type);
+ } else if (renum) {
+ if (oper != Operator.Addition) {
+ Constant c = left as Constant;
+ if (c == null || !c.IsDefaultValue)
+ return null;
}
+ underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
+ if (right is Constant)
+ right = ((Constant) right).ConvertExplicitly (false, underlying_type);
+ else
+ right = EmptyCast.Create (right, underlying_type);
+ } else {
return null;
}
- if (renum) {
- //
- // E operator + (U x, E e)
- //
- if (oper == Operator.Addition) {
- underlying_type = TypeManager.GetEnumUnderlyingType (rtype);
- temp = Convert.ImplicitConversion (ec, left, underlying_type, loc);
- if (temp == null)
- return null;
+ //
+ // C# specification uses explicit cast syntax which means binary promotion
+ // should happen, however it seems that csc does not do that
+ //
+ if (!DoBinaryOperatorPromotion (ec)) {
+ left = ltemp;
+ right = rtemp;
+ return null;
+ }
- left = temp;
- type = rtype;
- return this;
- }
+ Type res_type = null;
+ if ((oper & Operator.BitwiseMask) != 0 || oper == Operator.Subtraction || oper == Operator.Addition) {
+ Type promoted_type = lenum ? left.Type : right.Type;
+ enum_conversion = Convert.ExplicitNumericConversion (
+ new EmptyExpression (promoted_type), underlying_type);
+
+ if (oper == Operator.Subtraction && renum && lenum)
+ res_type = underlying_type;
+ else if (oper == Operator.Addition && renum)
+ res_type = rtype;
+ else
+ res_type = ltype;
}
+
+ Expression expr = ResolveOperatorPredefined (ec, standard_operators, true, res_type);
+ if (!is_compound || expr == null)
+ return expr;
//
- // U operator - (E e, E f)
+ // TODO: Need to corectly implemented Coumpound Assigment for all operators
+ // Section: 7.16.2
//
- if (oper == Operator.Subtraction) {
- if (!TypeManager.IsEqual (ltype, rtype))
- return null;
+ if (Convert.ImplicitConversionExists (ec, left, rtype))
+ return expr;
- type = TypeManager.GetEnumUnderlyingType (ltype);
- return this;
- }
+ if (!Convert.ImplicitConversionExists (ec, ltemp, rtype))
+ return null;
- return null;
+ expr = Convert.ExplicitConversion (ec, expr, rtype, loc);
+ return expr;
}
//
return null;
} else if (l.IsInterface) {
l = TypeManager.object_type;
+ } else if (l.IsValueType) {
+ return null;
}
if (rgen) {
return null;
} else if (r.IsInterface) {
r = TypeManager.object_type;
+ } else if (r.IsValueType) {
+ return null;
}
+
const string ref_comparison = "Possible unintended reference comparison. " +
"Consider casting the {0} side of the expression to `string' to compare the values";
is_add = is_addition;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ Error_PointerInsideExpressionTree ();
+ return null;
+ }
+
public override Expression DoResolve (EmitContext ec)
{
eclass = ExprClass.Variable;
public bool Resolve (EmitContext ec, Location loc)
{
+ if (Expr == null)
+ return false;
+
using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) {
// Verify that the argument is readable
if (ArgType != AType.Out)
this.loc = loc;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ throw new NotSupportedException ("ET");
+ }
+
public override Expression DoResolve (EmitContext ec)
{
eclass = ExprClass.Variable;
}
}
- //
- // This produces the value that renders an instance, used by the iterators code
- //
- public class ProxyInstance : Expression, IMemoryLocation {
- public override Expression DoResolve (EmitContext ec)
- {
- eclass = ExprClass.Variable;
- type = ec.ContainerType;
- return this;
- }
-
- public override void Emit (EmitContext ec)
- {
- ec.ig.Emit (OpCodes.Ldarg_0);
-
- }
-
- public void AddressOf (EmitContext ec, AddressOp mode)
- {
- ec.ig.Emit (OpCodes.Ldarg_0);
- }
- }
-
/// <summary>
/// Implements the typeof operator
/// </summary>
loc = l;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ Error_PointerInsideExpressionTree ();
+ return null;
+ }
+
public override Expression DoResolve (EmitContext ec)
{
TypeExpr texpr = QueriedType.ResolveAsTypeTerminal (ec, false);
eclass = ExprClass.Value;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ Error_PointerInsideExpressionTree ();
+ return null;
+ }
+
public override void Emit(EmitContext ec)
{
array.Emit (ec);
//
// Encapsulates a conversion rules required for array indexes
//
- public class ArrayIndexCast : Expression
+ public class ArrayIndexCast : TypeCast
{
- Expression expr;
-
public ArrayIndexCast (Expression expr)
+ : base (expr, expr.Type)
{
- this.expr = expr;
- this.loc = expr.Location;
}
public override Expression CreateExpressionTree (EmitContext ec)
{
ArrayList args = new ArrayList (2);
- args.Add (new Argument (expr.CreateExpressionTree (ec)));
+ args.Add (new Argument (child.CreateExpressionTree (ec)));
args.Add (new Argument (new TypeOf (new TypeExpression (TypeManager.int32_type, loc), loc)));
return CreateExpressionFactoryCall ("ConvertChecked", args);
}
- public override Expression DoResolve (EmitContext ec)
- {
- type = expr.Type;
- eclass = expr.eclass;
- return this;
- }
-
public override void Emit (EmitContext ec)
{
- expr.Emit (ec);
+ child.Emit (ec);
if (type == TypeManager.int32_type)
return;
}
}
- //
- // Used by the fixed statement
- //
- public class StringPtr : Expression {
- LocalBuilder b;
-
- public StringPtr (LocalBuilder b, Location l)
- {
- this.b = b;
- eclass = ExprClass.Value;
- type = TypeManager.char_ptr_type;
- loc = l;
- }
-
- public override Expression DoResolve (EmitContext ec)
- {
- // This should never be invoked, we are born in fully
- // initialized state.
-
- return this;
- }
-
- public override void Emit (EmitContext ec)
- {
- if (TypeManager.int_get_offset_to_string_data == null) {
- // TODO: Move to resolve !!
- TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
- TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
- }
-
- ILGenerator ig = ec.ig;
-
- ig.Emit (OpCodes.Ldloc, b);
- ig.Emit (OpCodes.Conv_I);
- ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
- ig.Emit (OpCodes.Add);
- }
- }
-
//
// Implements the `stackalloc' keyword
//
loc = l;
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ throw new NotSupportedException ("ET");
+ }
+
public override Expression DoResolve (EmitContext ec)
{
count = count.Resolve (ec);
{
this.Name = name;
}
+
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ ElementInitializer target = (ElementInitializer) t;
+ target.source = source.Clone (clonectx);
+ }
public override Expression CreateExpressionTree (EmitContext ec)
{
return CreateExpressionFactoryCall ("ElementInit", args);
}
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ CollectionElementInitializer target = (CollectionElementInitializer) t;
+
+ target.Arguments = new ArrayList (Arguments.Count);
+ foreach (Expression e in Arguments)
+ target.Arguments.Add (e.Clone (clonectx));
+ }
+
public override Expression DoResolve (EmitContext ec)
{
if (eclass != ExprClass.Invalid)
public override Expression CreateExpressionTree (EmitContext ec)
{
// Should not be reached
- throw new NotSupportedException ();
+ throw new NotSupportedException ("ET");
}
public override Expression DoResolve (EmitContext ec)
t.initializer = initializer.Clone (clonectx);
}
+ public override Expression CreateExpressionTree (EmitContext ec)
+ {
+ throw new NotSupportedException ("ET");
+ }
+
public override bool Equals (object o)
{
AnonymousTypeParameter other = o as AnonymousTypeParameter;