// Author:
// Miguel de Icaza (miguel@ximian.com)
//
-// (C) 2001 Ximian, Inc.
-//
+// (C) 2001, 2002, 2003 Ximian, Inc.
+// (C) 2003, 2004 Novell, Inc.
//
#define USE_OLD
ec.ig.Emit (OpCodes.Pop);
}
}
+
+ public class ParenthesizedExpression : Expression
+ {
+ public Expression Expr;
+
+ public ParenthesizedExpression (Expression expr, Location loc)
+ {
+ this.Expr = expr;
+ this.loc = loc;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ Expr = Expr.Resolve (ec);
+ return Expr;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new Exception ("Should not happen");
+ }
+ }
/// <summary>
/// Unary expressions.
result = null;
if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
- result = new Cast (new TypeExpr (TypeManager.int32_type, loc), e, loc);
+ result = new Cast (new TypeExpression (TypeManager.int32_type, loc), e, loc);
result = result.Resolve (ec);
} else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
- result = new Cast (new TypeExpr (TypeManager.uint32_type, loc), e, loc);
+ result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
result = result.Resolve (ec);
} else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
- result = new Cast (new TypeExpr (TypeManager.int64_type, loc), e, loc);
+ result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
result = result.Resolve (ec);
} else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
- result = new Cast (new TypeExpr (TypeManager.uint64_type, loc), e, loc);
+ result = new Cast (new TypeExpression (TypeManager.uint64_type, loc), e, loc);
result = result.Resolve (ec);
}
return null;
}
+ IVariable variable = Expr as IVariable;
+ if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
+ Error (212, "You can only take the address of an unfixed expression inside " +
+ "of a fixed statement initializer");
+ return null;
+ }
+
+ if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+ Error (213, "You can not fix an already fixed expression");
+ return null;
+ }
+
+ // According to the specs, a variable is considered definitely assigned if you take
+ // its address.
+ if ((variable != null) && (variable.VariableInfo != null))
+ variable.VariableInfo.SetAssigned (ec);
+
type = TypeManager.GetPointerType (Expr.Type);
return this;
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
- Type expr_type = Expr.Type;
switch (Oper) {
case Operator.UnaryPlus:
throw new Exception ("This should be caught by Resolve");
case Operator.UnaryNegation:
- Expr.Emit (ec);
- ig.Emit (OpCodes.Neg);
+ if (ec.CheckState) {
+ ig.Emit (OpCodes.Ldc_I4_0);
+ if (type == TypeManager.int64_type)
+ ig.Emit (OpCodes.Conv_U8);
+ Expr.Emit (ec);
+ ig.Emit (OpCodes.Sub_Ovf);
+ } else {
+ Expr.Emit (ec);
+ ig.Emit (OpCodes.Neg);
+ }
+
break;
case Operator.LogicalNot:
}
}
- /// <summary>
- /// This will emit the child expression for `ec' avoiding the logical
- /// not. The parent will take care of changing brfalse/brtrue
- /// </summary>
- public void EmitLogicalNot (EmitContext ec)
+ public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
{
- if (Oper != Operator.LogicalNot)
- throw new Exception ("EmitLogicalNot can only be called with !expr");
-
- Expr.Emit (ec);
+ if (Oper == Operator.LogicalNot)
+ Expr.EmitBranchable (ec, target, !onTrue);
+ else
+ base.EmitBranchable (ec, target, onTrue);
}
public override string ToString ()
public Indirection (Expression expr, Location l)
{
this.expr = expr;
- this.type = TypeManager.TypeToCoreType (expr.Type.GetElementType ());
+ this.type = TypeManager.GetElementType (expr.Type);
eclass = ExprClass.Variable;
loc = l;
}
ILGenerator ig = ec.ig;
if (temporary != null){
- if (have_temporary){
+ if (have_temporary) {
temporary.Emit (ec);
- return;
+ } else {
+ expr.Emit (ec);
+ ec.ig.Emit (OpCodes.Dup);
+ temporary.Store (ec);
+ have_temporary = true;
}
- expr.Emit (ec);
- ec.ig.Emit (OpCodes.Dup);
- temporary.Store (ec);
- have_temporary = true;
} else
expr.Emit (ec);
public new void CacheTemporaries (EmitContext ec)
{
- temporary = new LocalTemporary (ec, type);
+ temporary = new LocalTemporary (ec, expr.Type);
}
public override string ToString ()
//
type = expr_type;
if (expr.eclass == ExprClass.Variable){
+ LocalVariableReference var = expr as LocalVariableReference;
+ if ((var != null) && var.IsReadOnly)
+ Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
if (IsIncrementableNumber (expr_type) ||
expr_type == TypeManager.decimal_type){
return this;
static int PtrTypeSize (Type t)
{
- return GetTypeSize (t.GetElementType ());
+ return GetTypeSize (TypeManager.GetElementType (t));
}
//
ia.CacheTemporaries (ec);
+ //
+ // NOTE: We should probably handle three cases:
+ //
+ // * method invocation required.
+ // * direct stack manipulation possible
+ // * the object requires an "instance" field
+ //
if (temp_storage == null){
//
// Temporary improvement: if we are dealing with something that does
// For now: only localvariables when not remapped
//
- if (method == null &&
- (expr is LocalVariableReference && ec.RemapToProxy == false) ||
- (expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic)){
+ if (method == null &&
+ ((expr is LocalVariableReference) ||(expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic))){
if (empty_expr == null)
empty_expr = new EmptyExpression ();
ia.EmitAssign (ec, temp_storage);
break;
}
+
+ temp_storage.Release (ec);
}
public override void Emit (EmitContext ec)
return null;
expr = expr.Resolve (ec);
+ if (expr == null)
+ return null;
return this;
}
}
throw new Exception ("never reached");
}
+
+ public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
+ {
+ ILGenerator ig = ec.ig;
+
+ switch (action){
+ case Action.AlwaysFalse:
+ if (! onTrue)
+ ig.Emit (OpCodes.Br, target);
+
+ return;
+ case Action.AlwaysTrue:
+ if (onTrue)
+ ig.Emit (OpCodes.Br, target);
+
+ return;
+ case Action.LeaveOnStack:
+ // the `e != null' rule.
+ expr.Emit (ec);
+ ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ return;
+ case Action.Probe:
+ expr.Emit (ec);
+ ig.Emit (OpCodes.Isinst, probe_type);
+ ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
+ return;
+ }
+ throw new Exception ("never reached");
+ }
public override Expression DoResolve (EmitContext ec)
{
if (TypeManager.IsValueType (probe_type)){
Report.Error (77, loc, "The as operator should be used with a reference type only (" +
- TypeManager.CSharpName (probe_type) + " is a value type");
+ TypeManager.CSharpName (probe_type) + " is a value type)");
return null;
}
Expression real_expr = expr;
if (real_expr is EnumConstant)
real_expr = ((EnumConstant) real_expr).Child;
-
+
if (real_expr is ByteConstant){
byte v = ((ByteConstant) real_expr).Value;
if (real_expr is DoubleConstant){
double v = ((DoubleConstant) real_expr).Value;
- if (target_type == TypeManager.byte_type)
+ if (target_type == TypeManager.byte_type){
return new ByteConstant ((byte) v);
- if (target_type == TypeManager.sbyte_type)
+ } if (target_type == TypeManager.sbyte_type)
return new SByteConstant ((sbyte) v);
if (target_type == TypeManager.short_type)
return new ShortConstant ((short) v);
if (expr == null)
return null;
- int errors = Report.Errors;
-
type = ec.DeclSpace.ResolveType (target_type, false, Location);
if (type == null)
Operator oper;
Expression left, right;
- //
- // After resolution, method might contain the operator overload
- // method.
- //
- protected MethodBase method;
- ArrayList Arguments;
-
- bool DelegateOperation;
-
// This must be kept in sync with Operator!!!
public static readonly string [] oper_names;
//
// If either operand is of type uint, and the other
// operand is of type sbyte, short or int, othe operands are
- // converted to type long.
+ // converted to type long (unless we have an int constant).
//
Type other = null;
IntConstant ic = (IntConstant) right;
int val = ic.Value;
- if (val >= 0)
+ if (val >= 0){
right = new UIntConstant ((uint) val);
-
- type = l;
- return true;
+ type = l;
+
+ return true;
+ }
}
other = r;
- }
- else if (r == TypeManager.uint32_type){
+ } else if (r == TypeManager.uint32_type){
if (left is IntConstant){
IntConstant ic = (IntConstant) left;
int val = ic.Value;
- if (val >= 0)
+ if (val >= 0){
left = new UIntConstant ((uint) val);
-
- type = r;
- return true;
+ type = r;
+ return true;
+ }
}
other = l;
Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
}
- static bool is_32_or_64 (Type t)
- {
- return (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
- t == TypeManager.int64_type || t == TypeManager.uint64_type);
- }
-
static bool is_unsigned (Type t)
{
return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
else
return false;
}
+
+ Expression Make32or64 (EmitContext ec, Expression e)
+ {
+ Type t= e.Type;
+
+ if (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
+ t == TypeManager.int64_type || t == TypeManager.uint64_type)
+ return e;
+ Expression ee = Convert.ImplicitConversion (ec, e, TypeManager.int32_type, loc);
+ if (ee != null)
+ return ee;
+ ee = Convert.ImplicitConversion (ec, e, TypeManager.uint32_type, loc);
+ if (ee != null)
+ return ee;
+ ee = Convert.ImplicitConversion (ec, e, TypeManager.int64_type, loc);
+ if (ee != null)
+ return ee;
+ ee = Convert.ImplicitConversion (ec, e, TypeManager.uint64_type, loc);
+ if (ee != null)
+ return ee;
+ return null;
+ }
Expression CheckShiftArguments (EmitContext ec)
{
Expression e;
- Type l = left.Type;
- Type r = right.Type;
e = ForceConversion (ec, right, TypeManager.int32_type);
if (e == null){
left = e;
type = e.Type;
+ if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
+ right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31), loc);
+ right = right.DoResolve (ec);
+ } else {
+ right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63), loc);
+ right = right.DoResolve (ec);
+ }
+
return this;
}
Error_OperatorCannotBeApplied ();
union = (MethodGroupExpr) left_expr;
if (union != null) {
- Arguments = new ArrayList ();
- Arguments.Add (new Argument (left, Argument.AType.Expression));
- Arguments.Add (new Argument (right, Argument.AType.Expression));
+ ArrayList args = new ArrayList (2);
+ args.Add (new Argument (left, Argument.AType.Expression));
+ args.Add (new Argument (right, Argument.AType.Expression));
- method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null);
+ MethodBase method = Invocation.OverloadResolve (ec, union, args, Location.Null);
if (method != null) {
MethodInfo mi = (MethodInfo) method;
- type = mi.ReturnType;
- return this;
+ return new BinaryMethod (mi.ReturnType, method, args);
} else {
overload_failed = true;
}
}
}
- //
- // Step 2: Default operations on CLI native types.
- //
-
//
// Step 0: String concatenation (because overloading will get this wrong)
//
// If any of the arguments is a string, cast to string
//
- if (l == TypeManager.string_type){
-
- if (r == TypeManager.void_type) {
- Error_OperatorCannotBeApplied ();
- return null;
- }
-
- if (r == TypeManager.string_type){
- if (left is Constant && right is Constant){
- StringConstant ls = (StringConstant) left;
- StringConstant rs = (StringConstant) right;
-
- return new StringConstant (
- ls.Value + rs.Value);
- }
-
- if (left is Binary){
- Binary b = (Binary) left;
-
- //
- // Call String.Concat (string, string, string) or
- // String.Concat (string, string, string, string)
- // if possible.
- //
- if (b.oper == Operator.Addition &&
- (b.method == TypeManager.string_concat_string_string_string ||
- b.method == TypeManager.string_concat_string_string_string_string)){
- ArrayList bargs = b.Arguments;
- int count = bargs.Count;
-
- if (count == 2){
- Arguments = bargs;
- Arguments.Add (new Argument (right, Argument.AType.Expression));
- type = TypeManager.string_type;
- method = TypeManager.string_concat_string_string_string;
-
- return this;
- } else if (count == 3){
- Arguments = bargs;
- Arguments.Add (new Argument (right, Argument.AType.Expression));
- type = TypeManager.string_type;
- method = TypeManager.string_concat_string_string_string_string;
- return this;
- }
- }
- }
-
- // string + string
- method = TypeManager.string_concat_string_string;
- } else {
- // string + object
- method = TypeManager.string_concat_object_object;
- right = Convert.ImplicitConversion (
- ec, right, TypeManager.object_type, loc);
- if (right == null){
- Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
- return null;
- }
- }
- type = TypeManager.string_type;
-
- Arguments = new ArrayList ();
- Arguments.Add (new Argument (left, Argument.AType.Expression));
- Arguments.Add (new Argument (right, Argument.AType.Expression));
-
- return this;
-
- } else if (r == TypeManager.string_type){
- // object + string
+ // Simple constant folding
+ if (left is StringConstant && right is StringConstant)
+ return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
+
+ if (l == TypeManager.string_type || r == TypeManager.string_type) {
- if (l == TypeManager.void_type) {
+ if (r == TypeManager.void_type || l == TypeManager.void_type) {
Error_OperatorCannotBeApplied ();
return null;
}
- method = TypeManager.string_concat_object_object;
- left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
- if (left == null){
- Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
- return null;
+ // try to fold it in on the left
+ if (left is StringConcat) {
+ ((StringConcat) left).Append (ec, right);
+ return left.Resolve (ec);
}
- Arguments = new ArrayList ();
- Arguments.Add (new Argument (left, Argument.AType.Expression));
- Arguments.Add (new Argument (right, Argument.AType.Expression));
-
- type = TypeManager.string_type;
-
- return this;
+
+ // Otherwise, start a new concat expression
+ return new StringConcat (ec, loc, left, right).Resolve (ec);
}
//
// +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
//
if (oper == Operator.Addition || oper == Operator.Subtraction) {
- if (l.IsSubclassOf (TypeManager.delegate_type) &&
- r.IsSubclassOf (TypeManager.delegate_type)) {
-
- Arguments = new ArrayList ();
- Arguments.Add (new Argument (left, Argument.AType.Expression));
- Arguments.Add (new Argument (right, Argument.AType.Expression));
-
- if (oper == Operator.Addition)
- method = TypeManager.delegate_combine_delegate_delegate;
- else
- method = TypeManager.delegate_remove_delegate_delegate;
-
- if (l != r) {
- Error_OperatorCannotBeApplied ();
- return null;
+ if (l.IsSubclassOf (TypeManager.delegate_type)){
+ if (right.eclass == ExprClass.MethodGroup && RootContext.V2){
+ Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
+ if (tmp == null)
+ return null;
+ right = tmp;
+ r = right.Type;
+ }
+
+ if (r.IsSubclassOf (TypeManager.delegate_type)){
+ MethodInfo method;
+ ArrayList args = new ArrayList (2);
+
+ args = new ArrayList (2);
+ args.Add (new Argument (left, Argument.AType.Expression));
+ args.Add (new Argument (right, Argument.AType.Expression));
+
+ if (oper == Operator.Addition)
+ method = TypeManager.delegate_combine_delegate_delegate;
+ else
+ method = TypeManager.delegate_remove_delegate_delegate;
+
+ if (l != r) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ return new BinaryDelegate (l, method, args);
}
-
- DelegateOperation = true;
- type = l;
- return this;
}
-
+
//
// Pointer arithmetic:
//
return new PointerArithmetic (
false, left, right, TypeManager.int64_type,
loc);
- } else if (is_32_or_64 (r))
- return new PointerArithmetic (
- oper == Operator.Addition, left, right, l, loc);
- } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
- return new PointerArithmetic (
- true, right, left, r, loc);
+ } else {
+ Expression t = Make32or64 (ec, right);
+ if (t != null)
+ return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc);
+ }
+ } else if (r.IsPointer && oper == Operator.Addition){
+ Expression t = Make32or64 (ec, left);
+ if (t != null)
+ return new PointerArithmetic (true, right, t, r, loc);
+ }
}
//
Expression temp;
// U operator - (E e, E f)
- if (lie && rie && oper == Operator.Subtraction){
- if (l == r){
- type = TypeManager.EnumToUnderlying (l);
- return this;
- }
- Error_OperatorCannotBeApplied ();
- return null;
+ if (lie && rie){
+ if (oper == Operator.Subtraction){
+ if (l == r){
+ type = TypeManager.EnumToUnderlying (l);
+ return this;
+ }
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
}
//
Type enum_type = lie ? l : r;
Type other_type = lie ? r : l;
Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
-;
if (underlying_type != other_type){
+ temp = Convert.ImplicitConversion (ec, lie ? right : left, underlying_type, loc);
+ if (temp != null){
+ if (lie)
+ right = temp;
+ else
+ left = temp;
+ type = enum_type;
+ return this;
+ }
+
Error_OperatorCannotBeApplied ();
return null;
}
return CheckShiftArguments (ec);
if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
- if (l != TypeManager.bool_type || r != TypeManager.bool_type){
+ if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
+ type = TypeManager.bool_type;
+ return this;
+ }
+
+ if (l != r) {
Error_OperatorCannotBeApplied ();
return null;
}
- type = TypeManager.bool_type;
- return this;
+ Expression e = new ConditionalLogicalOperator (
+ oper == Operator.LogicalAnd, left, right, l, loc);
+ return e.Resolve (ec);
}
//
if (l == r){
if (!((l == TypeManager.int32_type) ||
(l == TypeManager.uint32_type) ||
+ (l == TypeManager.short_type) ||
+ (l == TypeManager.ushort_type) ||
(l == TypeManager.int64_type) ||
- (l == TypeManager.uint64_type)))
+ (l == TypeManager.uint64_type))){
type = l;
+ }
} else {
Error_OperatorCannotBeApplied ();
return null;
public override Expression DoResolve (EmitContext ec)
{
- left = left.Resolve (ec);
+ if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
+ left = ((ParenthesizedExpression) left).Expr;
+ left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
+ if (left == null)
+ return null;
+
+ if (left.eclass == ExprClass.Type) {
+ Error (75, "Casting a negative value needs to have the value in parentheses.");
+ return null;
+ }
+ } else
+ left = left.Resolve (ec);
right = right.Resolve (ec);
if (left == null || right == null)
/// The expression's code is generated, and we will generate a branch to `target'
/// if the resulting expression value is equal to isTrue
/// </remarks>
- public bool EmitBranchable (EmitContext ec, Label target, bool onTrue)
+ public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
{
- if (method != null)
- return false;
-
ILGenerator ig = ec.ig;
//
// but on top of that we want for == and != to use a special path
// if we are comparing against null
//
- if (oper == Operator.Equality || oper == Operator.Inequality){
+ if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
-
- if (left is NullLiteral){
- right.Emit (ec);
- if (my_on_true)
- ig.Emit (OpCodes.Brtrue, target);
- else
- ig.Emit (OpCodes.Brfalse, target);
- return true;
- } else if (right is NullLiteral){
+
+ //
+ // put the constant on the rhs, for simplicity
+ //
+ if (left is Constant) {
+ Expression swap = right;
+ right = left;
+ left = swap;
+ }
+
+ if (((Constant) right).IsZeroInteger) {
left.Emit (ec);
if (my_on_true)
ig.Emit (OpCodes.Brtrue, target);
else
ig.Emit (OpCodes.Brfalse, target);
- return true;
- } else if (left is BoolConstant){
- right.Emit (ec);
- if (my_on_true != ((BoolConstant) left).Value)
- ig.Emit (OpCodes.Brtrue, target);
- else
- ig.Emit (OpCodes.Brfalse, target);
- return true;
- } else if (right is BoolConstant){
+
+ return;
+ } else if (right is BoolConstant) {
left.Emit (ec);
if (my_on_true != ((BoolConstant) right).Value)
ig.Emit (OpCodes.Brtrue, target);
else
ig.Emit (OpCodes.Brfalse, target);
- return true;
+
+ return;
}
- } else if (oper == Operator.LogicalAnd){
- if (left is Binary){
- Binary left_binary = (Binary) left;
+ } else if (oper == Operator.LogicalAnd) {
- if (onTrue){
- Label tests_end = ig.DefineLabel ();
-
- if (left_binary.EmitBranchable (ec, tests_end, false)){
- if (right is Binary){
- Binary right_binary = (Binary) right;
-
- if (right_binary.EmitBranchable (ec, target, true)){
- ig.MarkLabel (tests_end);
- return true;
- }
- }
- right.Emit (ec);
- ig.Emit (OpCodes.Brtrue, target);
- ig.MarkLabel (tests_end);
- return true;
- }
- } else {
- if (left_binary.EmitBranchable (ec, target, false)){
- if (right is Binary){
- Binary right_binary = (Binary) right;
-
- if (right_binary.EmitBranchable (ec, target, false))
- return true;
- }
- right.Emit (ec);
- if (onTrue)
- ig.Emit (OpCodes.Brtrue, target);
- else
- ig.Emit (OpCodes.Brfalse, target);
- return true;
- }
- }
- //
- // Give up, and let the regular Emit work, but we could
- // also optimize the left-non-Branchable, but-right-Branchable
- //
+ if (onTrue) {
+ Label tests_end = ig.DefineLabel ();
+
+ left.EmitBranchable (ec, tests_end, false);
+ right.EmitBranchable (ec, target, true);
+ ig.MarkLabel (tests_end);
+ } else {
+ left.EmitBranchable (ec, target, false);
+ right.EmitBranchable (ec, target, false);
}
- return false;
+
+ return;
+
} else if (oper == Operator.LogicalOr){
- if (left is Binary){
- Binary left_binary = (Binary) left;
-
- if (onTrue){
- if (left_binary.EmitBranchable (ec, target, true)){
- if (right is Binary){
- Binary right_binary = (Binary) right;
-
- if (right_binary.EmitBranchable (ec, target, true))
- return true;
- }
- right.Emit (ec);
- ig.Emit (OpCodes.Brtrue, target);
- return true;
- }
-
- //
- // Give up, and let the regular Emit work, but we could
- // also optimize the left-non-Branchable, but-right-Branchable
- //
- } else {
- Label tests_end = ig.DefineLabel ();
-
- if (left_binary.EmitBranchable (ec, tests_end, true)){
- if (right is Binary){
- Binary right_binary = (Binary) right;
-
- if (right_binary.EmitBranchable (ec, target, false)){
- ig.MarkLabel (tests_end);
- return true;
- }
- }
- right.Emit (ec);
- ig.Emit (OpCodes.Brfalse, target);
- ig.MarkLabel (tests_end);
- return true;
- }
- }
+ if (onTrue) {
+ left.EmitBranchable (ec, target, true);
+ right.EmitBranchable (ec, target, true);
+
+ } else {
+ Label tests_end = ig.DefineLabel ();
+ left.EmitBranchable (ec, tests_end, true);
+ right.EmitBranchable (ec, target, false);
+ ig.MarkLabel (tests_end);
}
- return false;
- } else if (!(oper == Operator.LessThan ||
- oper == Operator.GreaterThan ||
- oper == Operator.LessThanOrEqual ||
- oper == Operator.GreaterThanOrEqual))
- return false;
-
- left.Emit (ec);
+ return;
+
+ } else if (!(oper == Operator.LessThan || oper == Operator.GreaterThan ||
+ oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
+ oper == Operator.Equality || oper == Operator.Inequality)) {
+ base.EmitBranchable (ec, target, onTrue);
+ return;
+ }
+
+ left.Emit (ec);
right.Emit (ec);
Type t = left.Type;
- bool isUnsigned = is_unsigned (t);
-
+ bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
+
switch (oper){
case Operator.Equality:
if (onTrue)
break;
case Operator.LessThanOrEqual:
- if (t == TypeManager.double_type || t == TypeManager.float_type)
- isUnsigned = true;
-
if (onTrue)
if (isUnsigned)
ig.Emit (OpCodes.Ble_Un, target);
case Operator.GreaterThanOrEqual:
- if (t == TypeManager.double_type || t == TypeManager.float_type)
- isUnsigned = true;
if (onTrue)
if (isUnsigned)
ig.Emit (OpCodes.Bge_Un, target);
else
ig.Emit (OpCodes.Blt, target);
break;
-
default:
- return false;
+ Console.WriteLine (oper);
+ throw new Exception ("what is THAT");
}
-
- return true;
}
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
Type l = left.Type;
- Type r = right.Type;
OpCode opcode;
- if (method != null) {
-
- // Note that operators are static anyway
-
- if (Arguments != null)
- Invocation.EmitArguments (ec, method, Arguments);
-
- if (method is MethodInfo)
- ig.Emit (OpCodes.Call, (MethodInfo) method);
- else
- ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-
- if (DelegateOperation)
- ig.Emit (OpCodes.Castclass, type);
-
- return;
- }
-
//
// Handle short-circuit operators differently
// than the rest
//
- if (oper == Operator.LogicalAnd){
+ if (oper == Operator.LogicalAnd) {
Label load_zero = ig.DefineLabel ();
Label end = ig.DefineLabel ();
- bool process = true;
-
- if (left is Binary){
- Binary left_binary = (Binary) left;
-
- if (left_binary.EmitBranchable (ec, load_zero, false)){
- right.Emit (ec);
- ig.Emit (OpCodes.Br, end);
- process = false;
- }
- }
-
- if (process){
- left.Emit (ec);
- ig.Emit (OpCodes.Brfalse, load_zero);
- right.Emit (ec);
- ig.Emit (OpCodes.Br, end);
- }
+
+ left.EmitBranchable (ec, load_zero, false);
+ right.Emit (ec);
+ ig.Emit (OpCodes.Br, end);
+
ig.MarkLabel (load_zero);
ig.Emit (OpCodes.Ldc_I4_0);
ig.MarkLabel (end);
return;
- } else if (oper == Operator.LogicalOr){
+ } else if (oper == Operator.LogicalOr) {
Label load_one = ig.DefineLabel ();
Label end = ig.DefineLabel ();
- bool process = true;
-
- if (left is Binary){
- Binary left_binary = (Binary) left;
- if (left_binary.EmitBranchable (ec, load_one, true)){
- right.Emit (ec);
- ig.Emit (OpCodes.Br, end);
- process = false;
- }
- }
-
- if (process){
- left.Emit (ec);
- ig.Emit (OpCodes.Brtrue, load_one);
- right.Emit (ec);
- ig.Emit (OpCodes.Br, end);
- }
+ left.EmitBranchable (ec, load_one, true);
+ right.Emit (ec);
+ ig.Emit (OpCodes.Br, end);
+
ig.MarkLabel (load_one);
ig.Emit (OpCodes.Ldc_I4_1);
ig.MarkLabel (end);
right.Emit (ec);
bool isUnsigned = is_unsigned (left.Type);
-
+
switch (oper){
case Operator.Multiply:
if (ec.CheckState){
else
ig.Emit (OpCodes.Clt);
- ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Ldc_I4_0);
- opcode = OpCodes.Sub;
+ opcode = OpCodes.Ceq;
break;
case Operator.BitwiseOr:
ig.Emit (opcode);
}
+ }
+
+ //
+ // Object created by Binary when the binary operator uses an method instead of being
+ // a binary operation that maps to a CIL binary operation.
+ //
+ public class BinaryMethod : Expression {
+ public MethodBase method;
+ public ArrayList Arguments;
+
+ public BinaryMethod (Type t, MethodBase m, ArrayList args)
+ {
+ method = m;
+ Arguments = args;
+ type = t;
+ eclass = ExprClass.Value;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ if (Arguments != null)
+ Invocation.EmitArguments (ec, method, Arguments);
+
+ if (method is MethodInfo)
+ ig.Emit (OpCodes.Call, (MethodInfo) method);
+ else
+ ig.Emit (OpCodes.Call, (ConstructorInfo) method);
+ }
+ }
+
+ //
+ // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+ // b, c, d... may be strings or objects.
+ //
+ public class StringConcat : Expression {
+ ArrayList operands;
+ bool invalid = false;
+
+
+ public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+ {
+ this.loc = loc;
+ type = TypeManager.string_type;
+ eclass = ExprClass.Value;
+
+ operands = new ArrayList (2);
+ Append (ec, left);
+ Append (ec, right);
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (invalid)
+ return null;
+
+ return this;
+ }
+
+ public void Append (EmitContext ec, Expression operand)
+ {
+ //
+ // Constant folding
+ //
+ if (operand is StringConstant && operands.Count != 0) {
+ StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
+ if (last_operand != null) {
+ operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
+ return;
+ }
+ }
+
+ //
+ // Conversion to object
+ //
+ if (operand.Type != TypeManager.string_type) {
+ Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
+
+ if (no == null) {
+ Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
+ invalid = true;
+ }
+ operand = no;
+ }
+
+ operands.Add (operand);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ MethodInfo concat_method = null;
+
+ //
+ // Are we also concating objects?
+ //
+ bool is_strings_only = true;
+
+ //
+ // Do conversion to arguments; check for strings only
+ //
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
+ is_strings_only &= e.Type == TypeManager.string_type;
+ }
+
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
+
+ if (! is_strings_only && e.Type == TypeManager.string_type) {
+ // need to make sure this is an object, because the EmitParams
+ // method might look at the type of this expression, see it is a
+ // string and emit a string [] when we want an object [];
+
+ e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
+ }
+ operands [i] = new Argument (e, Argument.AType.Expression);
+ }
+
+ //
+ // Find the right method
+ //
+ switch (operands.Count) {
+ case 1:
+ //
+ // This should not be possible, because simple constant folding
+ // is taken care of in the Binary code.
+ //
+ throw new Exception ("how did you get here?");
+
+ case 2:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_string :
+ TypeManager.string_concat_object_object ;
+ break;
+ case 3:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_string_string :
+ TypeManager.string_concat_object_object_object ;
+ break;
+ case 4:
+ //
+ // There is not a 4 param overlaod for object (the one that there is
+ // is actually a varargs methods, and is only in corlib because it was
+ // introduced there before.).
+ //
+ if (!is_strings_only)
+ goto default;
+
+ concat_method = TypeManager.string_concat_string_string_string_string;
+ break;
+ default:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_dot_dot_dot :
+ TypeManager.string_concat_object_dot_dot_dot ;
+ break;
+ }
+
+ Invocation.EmitArguments (ec, concat_method, operands);
+ ec.ig.Emit (OpCodes.Call, concat_method);
+ }
+ }
- public bool IsBuiltinOperator {
+ //
+ // Object created with +/= on delegates
+ //
+ public class BinaryDelegate : Expression {
+ MethodInfo method;
+ ArrayList args;
+
+ public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
+ {
+ method = mi;
+ this.args = args;
+ type = t;
+ eclass = ExprClass.Value;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ Invocation.EmitArguments (ec, method, args);
+
+ ig.Emit (OpCodes.Call, (MethodInfo) method);
+ ig.Emit (OpCodes.Castclass, type);
+ }
+
+ public Expression Right {
get {
- return method == null;
+ Argument arg = (Argument) args [1];
+ return arg.Expr;
+ }
+ }
+
+ public bool IsAddition {
+ get {
+ return method == TypeManager.delegate_combine_delegate_delegate;
}
}
}
+
+ //
+ // User-defined conditional logical operator
+ public class ConditionalLogicalOperator : Expression {
+ Expression left, right;
+ bool is_and;
+
+ public ConditionalLogicalOperator (bool is_and, Expression left, Expression right, Type t, Location loc)
+ {
+ type = t;
+ eclass = ExprClass.Value;
+ this.loc = loc;
+ this.left = left;
+ this.right = right;
+ this.is_and = is_and;
+ }
+
+ protected void Error19 ()
+ {
+ Binary.Error_OperatorCannotBeApplied (loc, is_and ? "&&" : "||", type, type);
+ }
+
+ protected void Error218 ()
+ {
+ Error (218, "The type ('" + TypeManager.CSharpName (type) + "') must contain " +
+ "declarations of operator true and operator false");
+ }
+
+ Expression op_true, op_false, op;
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ MethodInfo method;
+ Expression operator_group;
+
+ operator_group = MethodLookup (ec, type, is_and ? "op_BitwiseAnd" : "op_BitwiseOr", loc);
+ if (operator_group == null) {
+ Error19 ();
+ return null;
+ }
+
+ ArrayList arguments = new ArrayList ();
+ arguments.Add (new Argument (left, Argument.AType.Expression));
+ arguments.Add (new Argument (right, Argument.AType.Expression));
+ method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc) as MethodInfo;
+ if ((method == null) || (method.ReturnType != type)) {
+ Error19 ();
+ return null;
+ }
+
+ op = new StaticCallExpr (method, arguments, loc);
+
+ op_true = GetOperatorTrue (ec, left, loc);
+ op_false = GetOperatorFalse (ec, left, loc);
+ if ((op_true == null) || (op_false == null)) {
+ Error218 ();
+ return null;
+ }
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+ Label false_target = ig.DefineLabel ();
+ Label end_target = ig.DefineLabel ();
+
+ ig.Emit (OpCodes.Nop);
+
+ (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
+ left.Emit (ec);
+ ig.Emit (OpCodes.Br, end_target);
+ ig.MarkLabel (false_target);
+ op.Emit (ec);
+ ig.MarkLabel (end_target);
+
+ ig.Emit (OpCodes.Nop);
+ }
+ }
public class PointerArithmetic : Expression {
Expression left, right;
{
Type op_type = left.Type;
ILGenerator ig = ec.ig;
- int size = GetTypeSize (op_type.GetElementType ());
+ int size = GetTypeSize (TypeManager.GetElementType (op_type));
Type rtype = right.Type;
if (rtype.IsPointer){
Label false_target = ig.DefineLabel ();
Label end_target = ig.DefineLabel ();
- Statement.EmitBoolExpression (ec, expr, false_target, false);
+ expr.EmitBranchable (ec, false_target, false);
trueExpr.Emit (ec);
ig.Emit (OpCodes.Br, end_target);
ig.MarkLabel (false_target);
public readonly string Name;
public readonly Block Block;
LocalInfo local_info;
- VariableInfo variable_info;
bool is_readonly;
public LocalVariableReference (Block block, string name, Location l)
}
public VariableInfo VariableInfo {
- get { return variable_info; }
+ get { return local_info.VariableInfo; }
}
public bool IsReadOnly {
is_readonly = local_info.ReadOnly;
}
- variable_info = Block.GetVariableInfo (local_info);
type = local_info.VariableType;
+#if false
+ if (ec.InAnonymousMethod)
+ Block.LiftVariable (local_info);
+#endif
}
-
- public override Expression DoResolve (EmitContext ec)
- {
- DoResolveBase (ec);
+ protected Expression DoResolve (EmitContext ec, bool is_lvalue)
+ {
Expression e = Block.GetConstantExpression (Name);
if (e != null) {
local_info.Used = true;
return e;
}
+ VariableInfo variable_info = local_info.VariableInfo;
if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
return null;
+ if (!is_lvalue)
+ local_info.Used = true;
+
+ if (local_info.LocalBuilder == null)
+ return ec.RemapLocal (local_info);
+
return this;
}
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ DoResolveBase (ec);
+
+ return DoResolve (ec, false);
+ }
override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
DoResolveBase (ec);
+ VariableInfo variable_info = local_info.VariableInfo;
if (variable_info != null)
variable_info.SetAssigned (ec);
- Expression e = DoResolve (ec);
+ Expression e = DoResolve (ec, true);
if (e == null)
return null;
Error (1604, "cannot assign to `" + Name + "' because it is readonly");
return null;
}
+
+ if (local_info.LocalBuilder == null)
+ return ec.RemapLocalLValue (local_info, right_side);
return this;
}
+ public bool VerifyFixed (bool is_expression)
+ {
+ return !is_expression || local_info.IsFixed;
+ }
+
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
- if (local_info.LocalBuilder == null){
- ec.EmitThis ();
- ig.Emit (OpCodes.Ldfld, local_info.FieldBuilder);
- } else
- ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
-
- local_info.Used = true;
+ ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
}
public void EmitAssign (EmitContext ec, Expression source)
{
ILGenerator ig = ec.ig;
- local_info.Assigned = true;
-
- if (local_info.LocalBuilder == null){
- ec.EmitThis ();
- source.Emit (ec);
- ig.Emit (OpCodes.Stfld, local_info.FieldBuilder);
- } else {
- source.Emit (ec);
- ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
- }
+ source.Emit (ec);
+ ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
}
public void AddressOf (EmitContext ec, AddressOp mode)
{
- if (local_info.LocalBuilder == null){
- ec.EmitThis ();
- ec.ig.Emit (OpCodes.Ldflda, local_info.FieldBuilder);
- } else
- ec.ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+ ILGenerator ig = ec.ig;
+
+ ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
}
}
get { return vi; }
}
+ public bool VerifyFixed (bool is_expression)
+ {
+ return !is_expression || TypeManager.IsValueType (type);
+ }
+
public bool IsAssigned (EmitContext ec, Location loc)
{
if (!ec.DoFlowAnalysis || !is_out ||
if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
return null;
+ if (ec.RemapToProxy)
+ return ec.RemapParameter (idx);
+
return this;
}
SetAssigned (ec);
+ if (ec.RemapToProxy)
+ return ec.RemapParameterLValue (idx, right_side);
+
return this;
}
{
ILGenerator ig = ec.ig;
- if (ec.RemapToProxy){
- ig.Emit (OpCodes.Ldarg_0);
- ec.EmitArgument (idx);
- return;
- }
-
int arg_idx = idx;
if (!ec.IsStatic)
{
ILGenerator ig = ec.ig;
- if (ec.RemapToProxy){
- ig.Emit (OpCodes.Ldarg_0);
- source.Emit (ec);
- ec.EmitStoreArgument (idx);
- return;
- }
-
int arg_idx = idx;
if (!ec.IsStatic)
public void AddressOf (EmitContext ec, AddressOp mode)
{
- if (ec.RemapToProxy){
- Report.Error (-1, "Report this: Taking the address of a remapped parameter not supported");
- return;
- }
-
int arg_idx = idx;
if (!ec.IsStatic)
}
/// <summary>
- /// Determines "better conversion" as specified in 7.4.2.3
- /// Returns : 1 if a->p is better
- /// 0 if a->q or neither is better
+ /// Determines "better conversion" as specified in 7.4.2.3
+ ///
+ /// Returns : 1 if a->p is better
+ /// 0 if a->q or neither is better
/// </summary>
static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
{
Expression argument_expr = a.Expr;
if (argument_type == null)
- throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
+ throw new Exception ("Expression of type " + a.Expr +
+ " does not resolve its type");
//
- // This is a special case since csc behaves this way. I can't find
- // it anywhere in the spec but oh well ...
+ // This is a special case since csc behaves this way.
//
- if (argument_expr is NullLiteral && p == TypeManager.string_type && q == TypeManager.object_type)
+ if (argument_expr is NullLiteral &&
+ p == TypeManager.string_type &&
+ q == TypeManager.object_type)
return 1;
- else if (argument_expr is NullLiteral && p == TypeManager.object_type && q == TypeManager.string_type)
+ else if (argument_expr is NullLiteral &&
+ p == TypeManager.object_type &&
+ q == TypeManager.string_type)
return 0;
+ //
+ // csc behaves this way so we emulate it. Basically, if the argument
+ // is null and one of the types to compare is 'object' and the other
+ // is a reference type, we prefer the other.
+ //
+ // I can't find this anywhere in the spec but we can interpret this
+ // to mean that null can be of any type you wish in such a context
+ //
+ if (p != null && q != null) {
+ if (argument_expr is NullLiteral &&
+ !p.IsValueType &&
+ q == TypeManager.object_type)
+ return 1;
+ else if (argument_expr is NullLiteral &&
+ !q.IsValueType &&
+ p == TypeManager.object_type)
+ return 0;
+ }
+
if (p == q)
return 0;
// we can optimize this case: a positive int32
// always fits on a uint64
//
+
+ //
+ // This special case is needed because csc behaves like this.
+ // int -> uint is better than int -> ulong!
+ //
+ if (q == TypeManager.uint32_type)
+ return 0;
+
if (q == TypeManager.int64_type)
return 0;
else if (value >= 0)
}
/// <summary>
- /// Determines "Better function"
+ /// Determines "Better function" between candidate
+ /// and the current best match
/// </summary>
/// <remarks>
- /// and returns an integer indicating :
- /// 0 if candidate ain't better
- /// 1 if candidate is better than the current best match
+ /// Returns an integer indicating :
+ /// 0 if candidate ain't better
+ /// 1 if candidate is better than the current best match
/// </remarks>
static int BetterFunction (EmitContext ec, ArrayList args,
- MethodBase candidate, MethodBase best,
- bool expanded_form, Location loc)
+ MethodBase candidate, bool candidate_params,
+ MethodBase best, bool best_params,
+ Location loc)
{
ParameterData candidate_pd = GetParameterData (candidate);
ParameterData best_pd;
argument_count = args.Count;
int cand_count = candidate_pd.Count;
-
+
+ //
+ // If there is no best method, than this one
+ // is better, however, if we already found a
+ // best method, we cant tell. This happens
+ // if we have:
+ //
+ // interface IFoo {
+ // void DoIt ();
+ // }
+ //
+ // interface IBar {
+ // void DoIt ();
+ // }
+ //
+ // interface IFooBar : IFoo, IBar {}
+ //
+ // We cant tell if IFoo.DoIt is better than IBar.DoIt
+ //
+ // However, we have to consider that
+ // Trim (); is better than Trim (params char[] chars);
+ //
if (cand_count == 0 && argument_count == 0)
- return 1;
+ return best == null || best_params ? 1 : 0;
if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
if (cand_count != argument_count)
return 0;
-
+
if (best == null) {
int x = 0;
candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
return 1;
- for (int j = argument_count; j > 0;) {
- j--;
+ for (int j = 0; j < argument_count; ++j) {
Argument a = (Argument) args [j];
Type t = candidate_pd.ParameterType (j);
if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
- if (expanded_form)
- t = t.GetElementType ();
+ if (candidate_params)
+ t = TypeManager.GetElementType (t);
x = BetterConversion (ec, a, t, null, loc);
Type bt = best_pd.ParameterType (j);
if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
- if (expanded_form)
- ct = ct.GetElementType ();
+ if (candidate_params)
+ ct = TypeManager.GetElementType (ct);
if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
- if (expanded_form)
- bt = bt.GetElementType ();
-
+ if (best_params)
+ bt = TypeManager.GetElementType (bt);
+
x = BetterConversion (ec, a, ct, bt, loc);
y = BetterConversion (ec, a, bt, ct, loc);
rating2 += y;
}
+ //
+ // If a method (in the normal form) with the
+ // same signature as the expanded form of the
+ // current best params method already exists,
+ // the expanded form is not applicable so we
+ // force it to select the candidate
+ //
+ if (!candidate_params && best_params && cand_count == argument_count)
+ return 1;
+
if (rating1 > rating2)
return 1;
else
{
string ret_type = "";
+ if (mb == null)
+ return "";
+
if (mb is MethodInfo)
ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
MemberInfo [] miset;
MethodGroupExpr union;
- if (mg1 == null){
+ if (mg1 == null) {
if (mg2 == null)
return null;
return (MethodGroupExpr) mg2;
ArrayList common = new ArrayList ();
- foreach (MethodBase l in left_set.Methods){
- foreach (MethodBase r in right_set.Methods){
- if (l != r)
- continue;
+ foreach (MethodBase r in right_set.Methods){
+ if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
common.Add (r);
- break;
- }
}
-
+
miset = new MemberInfo [length1 + length2 - common.Count];
left_set.Methods.CopyTo (miset, 0);
int k = length1;
- foreach (MemberInfo mi in right_set.Methods){
- if (!common.Contains (mi))
- miset [k++] = mi;
+ foreach (MethodBase r in right_set.Methods) {
+ if (!common.Contains (r))
+ miset [k++] = r;
}
-
+
union = new MethodGroupExpr (miset, loc);
return union;
}
/// <summary>
- /// Determines is the candidate method, if a params method, is applicable
- /// in its expanded form to the given set of arguments
+ /// Determines if the candidate method, if a params method, is applicable
+ /// in its expanded form to the given set of arguments
/// </summary>
static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
{
return true;
//
- // If we have come this far, the case which remains is when the number of parameters
- // is less than or equal to the argument count.
+ // If we have come this far, the case which
+ // remains is when the number of parameters is
+ // less than or equal to the argument count.
//
for (int i = 0; i < pd_count - 1; ++i) {
if (a_mod == p_mod) {
if (a_mod == Parameter.Modifier.NONE)
- if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+ if (!Convert.ImplicitConversionExists (ec,
+ a.Expr,
+ pd.ParameterType (i)))
return false;
if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
}
- Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
+ Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
for (int i = pd_count - 1; i < arg_count; i++) {
Argument a = (Argument) arguments [i];
- if (!Convert.ImplicitStandardConversionExists (a.Expr, element_type))
+ if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
return false;
}
}
/// <summary>
- /// Determines if the candidate method is applicable (section 14.4.2.1)
- /// to the given set of arguments
+ /// Determines if the candidate method is applicable (section 14.4.2.1)
+ /// to the given set of arguments
/// </summary>
static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
{
else
arg_count = arguments.Count;
- ParameterData pd = GetParameterData (candidate);
- int pd_count = pd.Count;
+ ParameterData pd = GetParameterData (candidate);
if (arg_count != pd.Count)
return false;
-
+
for (int i = arg_count; i > 0; ) {
i--;
Parameter.Modifier p_mod = pd.ParameterModifier (i) &
~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+
if (a_mod == p_mod ||
(a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
- if (a_mod == Parameter.Modifier.NONE)
- if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
+ if (a_mod == Parameter.Modifier.NONE) {
+ if (!Convert.ImplicitConversionExists (ec,
+ a.Expr,
+ pd.ParameterType (i)))
return false;
+ }
if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
Type pt = pd.ParameterType (i);
if (!pt.IsByRef)
pt = TypeManager.GetReferenceType (pt);
-
+
if (pt != a.Type)
return false;
}
return true;
}
-
-
/// <summary>
/// Find the Applicable Function Members (7.4.2.1)
///
ArrayList Arguments, Location loc)
{
MethodBase method = null;
- Type current_type = null;
+ Type applicable_type = null;
int argument_count;
ArrayList candidates = new ArrayList ();
-
- foreach (MethodBase candidate in me.Methods){
- int x;
+ //
+ // Used to keep a map between the candidate
+ // and whether it is being considered in its
+ // normal or expanded form
+ //
+ // false is normal form, true is expanded form
+ //
+ Hashtable candidate_to_form = new PtrHashtable ();
+
+
+ //
+ // First we construct the set of applicable methods
+ //
+ // We start at the top of the type hierarchy and
+ // go down to find applicable methods
+ //
+ applicable_type = me.DeclaringType;
+
+ if (me.Name == "Invoke" && TypeManager.IsDelegateType (applicable_type)) {
+ Error_InvokeOnDelegate (loc);
+ return null;
+ }
- // If we're going one level higher in the class hierarchy, abort if
- // we already found an applicable method.
- if (candidate.DeclaringType != current_type) {
- current_type = candidate.DeclaringType;
- if (method != null)
- break;
- }
+ bool found_applicable = false;
- // Check if candidate is applicable (section 14.4.2.1)
- if (!IsApplicable (ec, Arguments, candidate))
- continue;
+ foreach (MethodBase candidate in me.Methods){
+ Type decl_type = candidate.DeclaringType;
- candidates.Add (candidate);
- x = BetterFunction (ec, Arguments, candidate, method, false, loc);
-
- if (x == 0)
- continue;
+ //
+ // If we have already found an applicable method
+ // we eliminate all base types (Section 14.5.5.1)
+ //
+ if (decl_type != applicable_type &&
+ (applicable_type.IsSubclassOf (decl_type) ||
+ TypeManager.ImplementsInterface (applicable_type, decl_type)) &&
+ found_applicable)
+ continue;
- method = candidate;
- }
+
+ // Check if candidate is applicable (section 14.4.2.1)
+ if (IsApplicable (ec, Arguments, candidate)) {
+ // Candidate is applicable in normal form
+ candidates.Add (candidate);
+ applicable_type = candidate.DeclaringType;
+ found_applicable = true;
+ candidate_to_form [candidate] = false;
+ } else if (IsParamsMethodApplicable (ec, Arguments, candidate)) {
+ // Candidate is applicable in expanded form
+ candidates.Add (candidate);
+ applicable_type = candidate.DeclaringType;
+ found_applicable = true;
+ candidate_to_form [candidate] = true;
+ }
+ }
+
+
+ //
+ // Now we actually find the best method
+ //
+ int candidate_top = candidates.Count;
+ for (int ix = 0; ix < candidate_top; ix++){
+ MethodBase candidate = (MethodBase) candidates [ix];
+
+ bool cand_params = (bool) candidate_to_form [candidate];
+ bool method_params = false;
+
+ if (method != null)
+ method_params = (bool) candidate_to_form [method];
+
+ int x = BetterFunction (ec, Arguments,
+ candidate, cand_params,
+ method, method_params,
+ loc);
+
+ if (x == 0)
+ continue;
+
+ method = candidate;
+ }
if (Arguments == null)
argument_count = 0;
else
argument_count = Arguments.Count;
- //
- // Now we see if we can find params functions, applicable in their expanded form
- // since if they were applicable in their normal form, they would have been selected
- // above anyways
- //
- bool chose_params_expanded = false;
-
- if (method == null) {
- candidates = new ArrayList ();
- foreach (MethodBase candidate in me.Methods){
- if (!IsParamsMethodApplicable (ec, Arguments, candidate))
- continue;
-
- candidates.Add (candidate);
-
- int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
- if (x == 0)
- continue;
-
- method = candidate;
- chose_params_expanded = true;
- }
- }
if (method == null) {
//
VerifyArgumentsCompat (ec, Arguments, argument_count, c, false,
null, loc);
+ break;
}
-
+
+ if (!Location.IsNull (loc)) {
+ string report_name = me.Name;
+ if (report_name == ".ctor")
+ report_name = me.DeclaringType.ToString ();
+
+ Error_WrongNumArguments (loc, report_name, argument_count);
+ }
+
return null;
}
// Now check that there are no ambiguities i.e the selected method
// should be better than all the others
//
+ bool best_params = (bool) candidate_to_form [method];
- foreach (MethodBase candidate in candidates){
- if (candidate == method)
- continue;
+ for (int ix = 0; ix < candidate_top; ix++){
+ MethodBase candidate = (MethodBase) candidates [ix];
+ if (candidate == method)
+ continue;
+
//
- // If a normal method is applicable in the sense that it has the same
- // number of arguments, then the expanded params method is never applicable
- // so we debar the params method.
+ // If a normal method is applicable in
+ // the sense that it has the same
+ // number of arguments, then the
+ // expanded params method is never
+ // applicable so we debar the params
+ // method.
//
- if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
- IsApplicable (ec, Arguments, method))
- continue;
-
- int x = BetterFunction (ec, Arguments, method, candidate,
- chose_params_expanded, loc);
+ // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
+// IsApplicable (ec, Arguments, method)))
+// continue;
+
+ bool cand_params = (bool) candidate_to_form [candidate];
+ int x = BetterFunction (ec, Arguments,
+ method, best_params,
+ candidate, cand_params,
+ loc);
if (x != 1) {
Report.Error (
}
//
- // And now check if the arguments are all compatible, perform conversions
- // if necessary etc. and return if everything is all right
+ // And now check if the arguments are all
+ // compatible, perform conversions if
+ // necessary etc. and return if everything is
+ // all right
//
-
- if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
- chose_params_expanded, null, loc))
+ if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
+ best_params, null, loc))
return null;
return method;
}
+ static void Error_WrongNumArguments (Location loc, String name, int arg_count)
+ {
+ Report.Error (1501, loc,
+ "No overload for method `" + name + "' takes `" +
+ arg_count + "' arguments");
+ }
+
+ static void Error_InvokeOnDelegate (Location loc)
+ {
+ Report.Error (1533, loc,
+ "Invoke cannot be called directly on a delegate");
+ }
+
static void Error_InvalidArguments (Location loc, int idx, MethodBase method,
Type delegate_type, string arg_sig, string par_desc)
{
Parameter.Modifier pm = pd.ParameterModifier (j);
if (pm == Parameter.Modifier.PARAMS){
+ if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
+ if (!Location.IsNull (loc))
+ Error_InvalidArguments (
+ loc, j, method, delegate_type,
+ Argument.FullDesc (a), pd.ParameterDesc (j));
+ return false;
+ }
+
if (chose_params_expanded)
- parameter_type = TypeManager.TypeToCoreType (parameter_type.GetElementType ());
+ parameter_type = TypeManager.GetElementType (parameter_type);
} else {
//
// Check modifiers
~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
Parameter.Modifier p_mod = pd.ParameterModifier (j) &
~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
-
if (a_mod != p_mod &&
pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
if (!Location.IsNull (loc)) {
- Console.WriteLine ("A:P: " + a.GetParameterModifier ());
- Console.WriteLine ("PP:: " + pd.ParameterModifier (j));
- Console.WriteLine ("PT: " + parameter_type.IsByRef);
Report.Error (1502, loc,
"The best overloaded match for method '" + FullMethodDesc (method)+
"' has some invalid arguments");
if (expr is BaseAccess)
is_base = true;
- Expression old = expr;
-
expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
if (expr == null)
return null;
int count = arguments.Count - idx;
Argument a = (Argument) arguments [idx];
Type t = a.Expr.Type;
- string array_type = t.FullName + "[]";
- LocalBuilder array;
-
- array = ig.DeclareLocal (TypeManager.LookupType (array_type));
+
IntConstant.EmitInt (ig, count);
ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
- ig.Emit (OpCodes.Stloc, array);
int top = arguments.Count;
for (int j = idx; j < top; j++){
a = (Argument) arguments [j];
- ig.Emit (OpCodes.Ldloc, array);
+ ig.Emit (OpCodes.Dup);
IntConstant.EmitInt (ig, j - idx);
bool is_stobj;
else
ig.Emit (op);
}
- ig.Emit (OpCodes.Ldloc, array);
}
/// <summary>
ILGenerator ig = ec.ig;
IntConstant.EmitInt (ig, 0);
- ig.Emit (OpCodes.Newarr, pd.ParameterType (0).GetElementType ());
+ ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (0)));
}
return;
ILGenerator ig = ec.ig;
IntConstant.EmitInt (ig, 0);
- ig.Emit (OpCodes.Newarr, pd.ParameterType (top).GetElementType ());
+ ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
}
}
{
ILGenerator ig = ec.ig;
bool struct_call = false;
+ bool this_call = false;
Type decl_type = method.DeclaringType;
//
// If this is ourselves, push "this"
//
- if (instance_expr == null){
+ if (instance_expr == null) {
+ this_call = true;
ig.Emit (OpCodes.Ldarg_0);
} else {
//
}
EmitArguments (ec, method, Arguments);
-
- if (is_static || struct_call || is_base){
+ //
+ // If you have:
+ // this.DoFoo ();
+ // and DoFoo is not virtual, you can omit the callvirt,
+ // because you don't need the null checking behavior.
+ //
+ if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){
if (method is MethodInfo) {
ig.Emit (OpCodes.Call, (MethodInfo) method);
} else
}
}
+ public class InvocationOrCast : ExpressionStatement
+ {
+ Expression expr;
+ Expression argument;
+
+ public InvocationOrCast (Expression expr, Expression argument, Location loc)
+ {
+ this.expr = expr;
+ this.argument = argument;
+ this.loc = loc;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ //
+ // First try to resolve it as a cast.
+ //
+ type = ec.DeclSpace.ResolveType (expr, true, loc);
+ if (type != null) {
+ Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
+ return cast.Resolve (ec);
+ }
+
+ //
+ // This can either be a type or a delegate invocation.
+ // Let's just resolve it and see what we'll get.
+ //
+ expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+ if (expr == null)
+ return null;
+
+ //
+ // Ok, so it's a Cast.
+ //
+ if (expr.eclass == ExprClass.Type) {
+ Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
+ return cast.Resolve (ec);
+ }
+
+ //
+ // It's a delegate invocation.
+ //
+ if (!TypeManager.IsDelegateType (expr.Type)) {
+ Error (149, "Method name expected");
+ return null;
+ }
+
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument (argument, Argument.AType.Expression));
+ DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+ return invocation.Resolve (ec);
+ }
+
+ void error201 ()
+ {
+ Error (201, "Only assignment, call, increment, decrement and new object " +
+ "expressions can be used as a statement");
+ }
+
+ public override ExpressionStatement ResolveStatement (EmitContext ec)
+ {
+ //
+ // First try to resolve it as a cast.
+ //
+ type = ec.DeclSpace.ResolveType (expr, true, loc);
+ if (type != null) {
+ error201 ();
+ return null;
+ }
+
+ //
+ // This can either be a type or a delegate invocation.
+ // Let's just resolve it and see what we'll get.
+ //
+ expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+ if ((expr == null) || (expr.eclass == ExprClass.Type)) {
+ error201 ();
+ return null;
+ }
+
+ //
+ // It's a delegate invocation.
+ //
+ if (!TypeManager.IsDelegateType (expr.Type)) {
+ Error (149, "Method name expected");
+ return null;
+ }
+
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument (argument, Argument.AType.Expression));
+ DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
+ return invocation.ResolveStatement (ec);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ throw new Exception ("Cannot happen");
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ throw new Exception ("Cannot happen");
+ }
+ }
+
//
// This class is used to "disable" the code generation for the
// temporary variable when initializing value types.
/// </summary>
public class New : ExpressionStatement, IMemoryLocation {
public readonly ArrayList Arguments;
- public readonly Expression RequestedType;
+
+ //
+ // During bootstrap, it contains the RequestedType,
+ // but if `type' is not null, it *might* contain a NewDelegate
+ // (because of field multi-initialization)
+ //
+ public Expression RequestedType;
MethodBase method = null;
loc = l;
}
- public Expression ValueTypeVariable {
- get {
- return value_target;
- }
-
- set {
- value_target = value;
- value_target_set = true;
+ public bool SetValueTypeVariable (Expression value)
+ {
+ value_target = value;
+ value_target_set = true;
+ if (!(value_target is IMemoryLocation)){
+ Error_UnexpectedKind ("variable");
+ return false;
}
+ return true;
}
//
//
// This leads to bugs (#37014)
//
- if (type != null)
+ if (type != null){
+ if (RequestedType is NewDelegate)
+ return RequestedType;
return this;
+ }
type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
bool IsDelegate = TypeManager.IsDelegateType (type);
- if (IsDelegate)
- return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+ if (IsDelegate){
+ RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+ if (RequestedType != null)
+ if (!(RequestedType is NewDelegate))
+ throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
+ return RequestedType;
+ }
if (type.IsInterface || type.IsAbstract){
Error (144, "It is not possible to create instances of interfaces or abstract classes");
return null;
}
- bool is_struct = false;
- is_struct = type.IsValueType;
+ bool is_struct = type.IsValueType;
eclass = ExprClass.Value;
//
}
}
- method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
- Arguments, loc);
+ method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
}
return null;
}
}
+
return this;
}
// you can't share LocalBuilders among ILGeneators.
if (!value_target_set)
value_target = new LocalTemporary (ec, type);
-
+
ml = (IMemoryLocation) value_target;
ml.AddressOf (ec, AddressOp.Store);
}
this.rank = rank;
loc = l;
- //this.rank = rank.Substring (0, rank.LastIndexOf ("["));
+ //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
//
- //string tmp = rank.Substring (rank.LastIndexOf ("["));
+ //string tmp = rank.Substring (rank.LastIndexOf ('['));
//
//dimensions = tmp.Length - 1;
expect_initializers = true;
if (conv == null)
return false;
-
- if (conv is StringConstant)
+
+ if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) {
+ // These are subclasses of Constant that can appear as elements of an
+ // array that cannot be statically initialized (with num_automatic_initializers
+ // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
array_data.Add (conv);
- else if (conv is Constant) {
+ } else if (conv is Constant) {
+ // These are the types of Constant that can appear in arrays that can be
+ // statically allocated.
array_data.Add (conv);
num_automatic_initializers++;
} else
underlying_type = type;
if (underlying_type.IsArray)
- underlying_type = TypeManager.TypeToCoreType (underlying_type.GetElementType ());
+ underlying_type = TypeManager.GetElementType (underlying_type);
dimensions = type.GetArrayRank ();
return true;
}
}
- array_element_type = TypeManager.TypeToCoreType (type.GetElementType ());
+ array_element_type = TypeManager.GetElementType (type);
if (arg_count == 1) {
is_one_dimensional = true;
eclass = ExprClass.Value;
return this;
} else {
- ModuleBuilder mb = CodeGen.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.Module.Builder;
ArrayList args = new ArrayList ();
if (arguments != null) {
if (!(v is Expression)){
int [] bits = Decimal.GetBits ((decimal) v);
int p = idx;
+
+ // FIXME: For some reason, this doesn't work on the MS runtime.
+ int [] nbits = new int [4];
+ nbits [0] = bits [3];
+ nbits [1] = bits [2];
+ nbits [2] = bits [0];
+ nbits [3] = bits [1];
for (int j = 0; j < 4; j++){
- data [p++] = (byte) (bits [j] & 0xff);
- data [p++] = (byte) ((bits [j] >> 8) & 0xff);
- data [p++] = (byte) ((bits [j] >> 16) & 0xff);
- data [p++] = (byte) (bits [j] >> 24);
+ data [p++] = (byte) (nbits [j] & 0xff);
+ data [p++] = (byte) ((nbits [j] >> 8) & 0xff);
+ data [p++] = (byte) ((nbits [j] >> 16) & 0xff);
+ data [p++] = (byte) (nbits [j] >> 24);
}
}
} else
ig.Emit (OpCodes.Call,
TypeManager.void_initializearray_array_fieldhandle);
}
-
+
//
// Emits pieces of the array that can not be computed at compile
// time (variables and string locations).
int dims = bounds.Count;
int [] current_pos = new int [dims];
int top = array_data.Count;
- LocalBuilder temp = ig.DeclareLocal (type);
-
- ig.Emit (OpCodes.Stloc, temp);
MethodInfo set = null;
if (dims != 1){
Type [] args;
ModuleBuilder mb = null;
- mb = CodeGen.ModuleBuilder;
+ mb = CodeGen.Module.Builder;
args = new Type [dims + 1];
int j;
e = ((EnumConstant) e).Child;
}
- if (e is StringConstant || !(e is Constant) ||
+ if (e is StringConstant || e is DecimalConstant || !(e is Constant) ||
num_automatic_initializers <= max_automatic_initializers) {
Type etype = e.Type;
- ig.Emit (OpCodes.Ldloc, temp);
+ if (is_expression || i != top - 1)
+ ig.Emit (OpCodes.Dup);
for (int idx = 0; idx < dims; idx++)
IntConstant.EmitInt (ig, current_pos [idx]);
// If we are dealing with a struct, get the
// address of it, so we can store it.
//
- if ((dims == 1) &&
+ if ((dims == 1) &&
etype.IsSubclassOf (TypeManager.value_type) &&
- (!TypeManager.IsBuiltinType (etype) ||
+ (!TypeManager.IsBuiltinOrEnum (etype) ||
etype == TypeManager.decimal_type)) {
if (e is New){
New n = (New) e;
e.Emit (ec);
- if (dims == 1)
- ArrayAccess.EmitStoreOpcode (ig, array_element_type);
- else
- ig.Emit (OpCodes.Call, set);
-
- }
+ if (dims == 1)
+ ArrayAccess.EmitStoreOpcode (ig, array_element_type);
+ else
+ ig.Emit (OpCodes.Call, set);
+
+ }
}
//
current_pos [j] = 0;
}
}
-
- if (is_expression)
- ig.Emit (OpCodes.Ldloc, temp);
}
void EmitArrayArguments (EmitContext ec)
//
bool dynamic_initializers = true;
- if (underlying_type != TypeManager.string_type &&
- underlying_type != TypeManager.object_type) {
- if (num_automatic_initializers > max_automatic_initializers)
- EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
- }
+ // This will never be true for array types that cannot be statically
+ // initialized. num_automatic_initializers will always be zero. See
+ // CheckIndices.
+ if (num_automatic_initializers > max_automatic_initializers)
+ EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
if (dynamic_initializers)
EmitDynamicInitializers (ec, !is_statement);
}
return ret;
}
+
+ public Expression TurnIntoConstant ()
+ {
+ //
+ // Should use something like the above attribute thing.
+ // It should return a subclass of Constant that just returns
+ // the computed value of the array
+ //
+ throw new Exception ("Does not support yet Turning array into a Constant");
+ }
}
/// <summary>
get { return variable_info; }
}
+ public bool VerifyFixed (bool is_expression)
+ {
+ if ((variable_info == null) || (variable_info.LocalInfo == null))
+ return false;
+ else
+ return variable_info.LocalInfo.IsFixed;
+ }
+
public bool ResolveBase (EmitContext ec)
{
eclass = ExprClass.Variable;
}
if ((block != null) && (block.ThisVariable != null))
- variable_info = block.GetVariableInfo (block.ThisVariable);
+ variable_info = block.ThisVariable.VariableInfo;
return true;
}
}
}
+ //
+ // 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>
public class TypeOf : Expression {
public readonly Expression QueriedType;
- Type typearg;
+ protected Type typearg;
public TypeOf (Expression queried_type, Location l)
{
if (typearg == null)
return null;
+ if (typearg == TypeManager.void_type) {
+ Error (673, "System.Void cannot be used from C# - " +
+ "use typeof (void) to get the void type object");
+ return null;
+ }
+
type = TypeManager.type_type;
eclass = ExprClass.Type;
return this;
}
}
+ /// <summary>
+ /// Implements the `typeof (void)' operator
+ /// </summary>
+ public class TypeOfVoid : TypeOf {
+ public TypeOfVoid (Location l) : base (null, l)
+ {
+ loc = l;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ type = TypeManager.type_type;
+ typearg = TypeManager.void_type;
+ eclass = ExprClass.Type;
+ return this;
+ }
+ }
+
/// <summary>
/// Implements the sizeof expression
/// </summary>
// Implicitly default to `this' unless we're static.
if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext)
- left = ec.This;
+ left = ec.GetThis (loc);
} else {
left_is_type = left is TypeExpr;
left_is_explicit = true;
FieldExpr fe = (FieldExpr) member_lookup;
FieldInfo fi = fe.FieldInfo;
Type decl_type = fi.DeclaringType;
-
+
if (fi is FieldBuilder) {
Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
}
if (member_lookup is EventExpr) {
-
EventExpr ee = (EventExpr) member_lookup;
//
// a FieldExpr
//
- if (ee.EventInfo.DeclaringType == ec.ContainerType) {
+ if (ee.EventInfo.DeclaringType == ec.ContainerType ||
+ TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
MemberInfo mi = GetFieldFromEvent (ee);
if (mi == null) {
//
// If this happens, then we have an event with its own
// accessors and private field etc so there's no need
- // to transform ourselves : we should instead flag an error
+ // to transform ourselves.
//
- Assign.error70 (ee.EventInfo, loc);
- return null;
+ return ee;
}
Expression ml = ExprClassFromMemberInfo (ec, mi, loc);
Report.Error (-200, loc, "Internal error!!");
return null;
}
+
+ if (!left_is_explicit)
+ left = null;
return ResolveMemberAccess (ec, ml, left, loc, left_original);
}
}
-
+
if (member_lookup is IMemberExpr) {
IMemberExpr me = (IMemberExpr) member_lookup;
mg.IsExplicitImpl = left_is_explicit;
if (!me.IsStatic){
- if (IdenticalNameAndTypeName (ec, left_original, loc))
+ if ((ec.IsFieldInitializer || ec.IsStatic) &&
+ IdenticalNameAndTypeName (ec, left_original, loc))
return member_lookup;
SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
// it will fail to find any members at all
//
- int errors = Report.Errors;
-
Type expr_type = expr.Type;
if (expr is TypeExpr){
if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
"is inaccessible because of its protection level");
return null;
}
-
+
if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){
Enum en = TypeManager.LookupEnum (expr_type);
-
+
if (en != null) {
object value = en.LookupEnumValue (ec, Identifier, loc);
if (member_lookup == null)
return null;
- if (member_lookup is TypeExpr)
+ if (member_lookup is TypeExpr) {
+ if (!(expr is TypeExpr) && !(expr is SimpleName)) {
+ Error (572, "Can't reference type `" + Identifier + "' through an expression; try `" +
+ member_lookup.Type + "' instead");
+ return null;
+ }
+
return member_lookup;
+ }
member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
if (member_lookup == null)
public override Expression ResolveAsTypeStep (EmitContext ec)
{
+ string fname = null;
+ MemberAccess full_expr = this;
+ while (full_expr != null) {
+ if (fname != null)
+ fname = String.Concat (full_expr.Identifier, ".", fname);
+ else
+ fname = full_expr.Identifier;
+
+ if (full_expr.Expr is SimpleName) {
+ string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
+ Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
+ if (fully_qualified != null)
+ return new TypeExpression (fully_qualified, loc);
+ }
+
+ full_expr = full_expr.Expr as MemberAccess;
+ }
+
Expression new_expr = expr.ResolveAsTypeStep (ec);
if (new_expr == null)
//
Type t = Expr.Type;
+ if (t == TypeManager.array_type){
+ Report.Error (21, loc, "Cannot use indexer on System.Array");
+ return null;
+ }
+
if (t.IsArray)
return (new ArrayAccess (this, loc)).Resolve (ec);
else if (t.IsPointer)
public override Expression DoResolve (EmitContext ec)
{
+#if false
ExprClass eclass = ea.Expr.eclass;
-#if false
// As long as the type is valid
if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
eclass == ExprClass.Value)) {
ea.Arguments.Count);
return null;
}
- type = TypeManager.TypeToCoreType (t.GetElementType ());
- if (type.IsPointer && !ec.InUnsafe){
+
+ type = TypeManager.GetElementType (t);
+ if (type.IsPointer && !ec.InUnsafe){
UnsafeError (ea.Location);
return null;
}
MethodInfo FetchGetMethod ()
{
- ModuleBuilder mb = CodeGen.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.Module.Builder;
int arg_count = ea.Arguments.Count;
Type [] args = new Type [arg_count];
MethodInfo get;
MethodInfo FetchAddressMethod ()
{
- ModuleBuilder mb = CodeGen.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.Module.Builder;
int arg_count = ea.Arguments.Count;
Type [] args = new Type [arg_count];
MethodInfo address;
if (rank == 1)
EmitStoreOpcode (ig, t);
else {
- ModuleBuilder mb = CodeGen.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.Module.Builder;
int arg_count = ea.Arguments.Count;
Type [] args = new Type [arg_count + 1];
MethodInfo set;
class Indexers {
- public ArrayList properties;
+ public ArrayList Properties;
static Hashtable map;
+ public struct Indexer {
+ public readonly Type Type;
+ public readonly MethodInfo Getter, Setter;
+
+ public Indexer (Type type, MethodInfo get, MethodInfo set)
+ {
+ this.Type = type;
+ this.Getter = get;
+ this.Setter = set;
+ }
+ }
+
static Indexers ()
{
map = new Hashtable ();
Indexers ()
{
- properties = new ArrayList ();
+ Properties = new ArrayList ();
}
void Append (MemberInfo [] mi)
get = property.GetGetMethod (true);
set = property.GetSetMethod (true);
- properties.Add (new Pair (get, set));
+ Properties.Add (new Indexer (property.PropertyType, get, set));
}
}
static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc)
{
Indexers ix = (Indexers) map [lookup_type];
-
+
if (ix != null)
return ix;
copy = copy.BaseType;
}
- Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+ if (!lookup_type.IsInterface)
+ return ix;
+
+ TypeExpr [] ifaces = TypeManager.GetInterfaces (lookup_type);
if (ifaces != null) {
- foreach (Type itype in ifaces) {
+ foreach (TypeExpr iface in ifaces) {
+ Type itype = iface.Type;
MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
if (mi != null){
if (ix == null)
ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc);
if (ilist != null) {
found_any = true;
- if (ilist.properties != null) {
- foreach (Pair o in ilist.properties) {
- if (o.First != null)
- AllGetters.Add(o.First);
+ if (ilist.Properties != null) {
+ foreach (Indexers.Indexer ix in ilist.Properties) {
+ if (ix.Getter != null)
+ AllGetters.Add(ix.Getter);
}
}
}
if (!CommonResolve (ec))
return null;
- Type right_type = right_side.Type;
-
bool found_any = false, found_any_setters = false;
Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
if (ilist != null) {
found_any = true;
- if (ilist.properties != null) {
- foreach (Pair o in ilist.properties) {
- if (o.Second != null)
- AllSetters.Add(o.Second);
+ if (ilist.Properties != null) {
+ foreach (Indexers.Indexer ix in ilist.Properties) {
+ if (ix.Setter != null)
+ AllSetters.Add(ix.Setter);
}
}
}
// Now look for the actual match in the list of indexers to set our "return" type
//
type = TypeManager.void_type; // default value
- foreach (Pair t in ilist.properties){
- if (t.Second == set){
- if (t.First != null)
- type = ((MethodInfo) t.First).ReturnType;
+ foreach (Indexers.Indexer ix in ilist.Properties){
+ if (ix.Setter == set){
+ type = ix.Type;
break;
}
}
Expression left;
if (ec.IsStatic)
- left = new TypeExpr (base_type, loc);
+ left = new TypeExpression (base_type, loc);
else
- left = ec.This;
+ left = ec.GetThis (loc);
e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
protected override bool CommonResolve (EmitContext ec)
{
- instance_expr = ec.This;
+ instance_expr = ec.GetThis (loc);
current_type = ec.ContainerType.BaseType;
indexer_type = current_type;
// the type specification, we just use this to construct the type
// one bit at a time.
// </summary>
- public class ComposedCast : Expression {
+ public class ComposedCast : TypeExpr {
Expression left;
string dim;
loc = l;
}
- public override Expression ResolveAsTypeStep (EmitContext ec)
+ public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
{
Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
if (ltype == null)
return this;
}
- public override Expression DoResolve (EmitContext ec)
- {
- return ResolveAsTypeStep (ec);
- }
-
- public override void Emit (EmitContext ec)
- {
- throw new Exception ("This should never be called");
- }
-
- public override string ToString ()
- {
- return left + dim;
+ public override string Name {
+ get {
+ return left + dim;
+ }
}
}
public ArrayPtr (Expression array, Location l)
{
- Type array_type = array.Type.GetElementType ();
+ Type array_type = TypeManager.GetElementType (array.Type);
this.array = array;
array.Emit (ec);
IntLiteral.EmitInt (ig, 0);
- ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ());
+ ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType (array.Type));
}
public override Expression DoResolve (EmitContext ec)
return null;
}
- if (ec.InCatch || ec.InFinally){
+ if (ec.CurrentBranching.InCatch () ||
+ ec.CurrentBranching.InFinally (true)) {
Error (255,
- "stackalloc can not be used in a catch or finally block");
+ "stackalloc can not be used in a catch or finally block");
return null;
}