/// <summary>
/// Returns a stringified representation of the Operator
/// </summary>
- string OperName ()
+ static public string OperName (Operator oper)
{
switch (oper){
case Operator.UnaryPlus:
oper_names [(int) Operator.AddressOf] = "op_AddressOf";
}
- void error23 (Type t)
+ void Error23 (Type t)
{
Report.Error (
- 23, loc, "Operator " + OperName () +
+ 23, loc, "Operator " + OperName (oper) +
" cannot be applied to operand of type `" +
TypeManager.CSharpName (t) + "'");
}
case Operator.LogicalNot:
if (expr_type != TypeManager.bool_type) {
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
(expr_type == TypeManager.int64_type) ||
(expr_type == TypeManager.uint64_type) ||
(expr_type.IsSubclassOf (TypeManager.enum_type)))){
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
if (expr_type == TypeManager.uint64_type)
return new ULongConstant (~ ((ULongConstant) e).Value);
- throw new Exception (
- "FIXME: Implement constant OnesComplement of:" +
- expr_type);
+ Error23 (expr_type);
+ return null;
}
throw new Exception ("Can not constant fold");
}
op_name = oper_names [(int) oper];
- mg = MemberLookup (ec, expr_type, op_name, loc);
-
- if (mg == null && expr_type.BaseType != null)
- mg = MemberLookup (ec, expr_type.BaseType, op_name, loc);
+ mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
if (mg != null) {
Expression e = StaticCallExpr.MakeSimpleCall (
ec, (MethodGroupExpr) mg, expr, loc);
if (e == null){
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
if (oper == Operator.LogicalNot){
if (expr_type != TypeManager.bool_type) {
- error23 (expr.Type);
+ Error23 (expr.Type);
return null;
}
(expr_type == TypeManager.int64_type) ||
(expr_type == TypeManager.uint64_type) ||
(expr_type.IsSubclassOf (TypeManager.enum_type)))){
- error23 (expr.Type);
+ Error23 (expr.Type);
return null;
}
type = expr_type;
// -92233720368547758087 (-2^63) to be wrote as
// decimal integer literal.
//
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
return this;
}
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
return null;
}
+ if (!TypeManager.VerifyUnManaged (expr.Type, loc)){
+ return null;
+ }
+
+ //
+ // This construct is needed because dynamic types
+ // are not known by Type.GetType, so we have to try then to use
+ // ModuleBuilder.GetType.
+ //
string ptr_type_name = expr.Type.FullName + "*";
type = Type.GetType (ptr_type_name);
- if (type == null){
+ if (type == null)
type = RootContext.ModuleBuilder.GetType (ptr_type_name);
- }
return this;
}
"The * or -> operator can only be applied to pointers");
return null;
}
-
- type = expr_type.GetElementType ();
- return this;
+
+ //
+ // We create an Indirection expression, because
+ // it can implement the IMemoryLocation.
+ //
+ return new Indirection (expr);
}
- Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+ Error (187, loc, "No such operator '" + OperName (oper) + "' defined for type '" +
TypeManager.CSharpName (expr_type) + "'");
return null;
}
break;
case Operator.AddressOf:
- ((IMemoryLocation)expr).AddressOf (ec);
- break;
-
- case Operator.Indirection:
- expr.Emit (ec);
- LoadFromPtr (ig, Type, false);
+ ((IMemoryLocation)expr).AddressOf (ec, AddressOp.LoadStore);
break;
default:
expr.Emit (ec);
}
+
+ public override string ToString ()
+ {
+ return "Unary (" + oper + ", " + expr + ")";
+ }
}
+ //
+ // Unary operators are turned into Indirection expressions
+ // after semantic analysis (this is so we can take the address
+ // of an indirection).
+ //
+ public class Indirection : Expression, IMemoryLocation, IAssignMethod {
+ Expression expr;
+
+ public Indirection (Expression expr)
+ {
+ this.expr = expr;
+ this.type = expr.Type.GetElementType ();
+ eclass = ExprClass.Variable;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ expr.Emit (ec);
+ LoadFromPtr (ec.ig, Type, false);
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source)
+ {
+ expr.Emit (ec);
+ source.Emit (ec);
+ StoreFromPtr (ec.ig, type);
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp Mode)
+ {
+ expr.Emit (ec);
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ //
+ // Born fully resolved
+ //
+ return this;
+ }
+ }
+
/// <summary>
/// Unary Mutator expressions (pre and post ++ and --)
/// </summary>
expr = e;
}
- string OperName ()
+ static string OperName (Mode mode)
{
return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
"++" : "--";
}
- void error23 (Type t)
+ void Error23 (Type t)
{
Report.Error (
- 23, loc, "Operator " + OperName () +
+ 23, loc, "Operator " + OperName (mode) +
" cannot be applied to operand of type `" +
TypeManager.CSharpName (t) + "'");
}
else
op_name = "op_Decrement";
- mg = MemberLookup (ec, expr_type, op_name, loc);
+ mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
if (mg == null && expr_type.BaseType != null)
- mg = MemberLookup (ec, expr_type.BaseType, op_name, loc);
+ mg = MemberLookup (ec, expr_type.BaseType, op_name,
+ MemberTypes.Method, AllBindingFlags, loc);
if (mg != null) {
method = StaticCallExpr.MakeSimpleCall (
return null;
}
- Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+ Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +
TypeManager.CSharpName (expr_type) + "'");
return null;
}
/// <summary>
/// Returns a stringified representation of the Operator
/// </summary>
- string OperName ()
+ static string OperName (Operator oper)
{
switch (oper){
case Operator.Multiply:
return ConvertImplicit (ec, expr, target_type, new Location (-1));
}
-
+
+ public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
+ {
+ Report.Error (
+ 34, loc, "Operator `" + OperName (oper)
+ + "' is ambiguous on operands of type `"
+ + TypeManager.CSharpName (l) + "' "
+ + "and `" + TypeManager.CSharpName (r)
+ + "'");
+ }
+
//
// Note that handling the case l == Decimal || r == Decimal
// is taken care of by the Step 1 Operator Overload resolution.
type = TypeManager.double_type;
} else if (l == TypeManager.float_type || r == TypeManager.float_type){
//
- // if either operand is of type float, th eother operand is
- // converd to type float.
+ // if either operand is of type float, the other operand is
+ // converted to type float.
//
if (r != TypeManager.double_type)
right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
if ((other == TypeManager.sbyte_type) ||
(other == TypeManager.short_type) ||
(other == TypeManager.int32_type) ||
- (other == TypeManager.int64_type)){
- string oper = OperName ();
-
- Error (34, loc, "Operator `" + OperName ()
- + "' is ambiguous on operands of type `"
- + TypeManager.CSharpName (l) + "' "
- + "and `" + TypeManager.CSharpName (r)
- + "'");
- }
+ (other == TypeManager.int64_type))
+ Error_OperatorAmbiguous (loc, oper, l, r);
type = TypeManager.uint64_type;
} else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
//
return true;
}
- void error19 ()
+ static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
{
Error (19, loc,
- "Operator " + OperName () + " cannot be applied to operands of type `" +
- TypeManager.CSharpName (left.Type) + "' and `" +
- TypeManager.CSharpName (right.Type) + "'");
-
+ "Operator " + name + " cannot be applied to operands of type `" +
+ TypeManager.CSharpName (l) + "' and `" +
+ TypeManager.CSharpName (r) + "'");
}
+ void error19 ()
+ {
+ 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);
+ }
+
Expression CheckShiftArguments (EmitContext ec)
{
Expression e;
string op = "op_" + oper;
- left_expr = MemberLookup (ec, l, op, loc);
- if (left_expr == null && l.BaseType != null)
- left_expr = MemberLookup (ec, l.BaseType, op, loc);
-
- right_expr = MemberLookup (ec, r, op, loc);
- if (right_expr == null && r.BaseType != null)
- right_expr = MemberLookup (ec, r.BaseType, op, loc);
-
- MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
+ MethodGroupExpr union;
+ left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
+ if (r != l){
+ right_expr = MemberLookup (
+ ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
+ union = Invocation.MakeUnionSet (left_expr, right_expr);
+ } else
+ union = (MethodGroupExpr) left_expr;
if (union != null) {
Arguments = new ArrayList ();
method = Invocation.OverloadResolve (ec, union, Arguments, loc);
if (method != null) {
MethodInfo mi = (MethodInfo) method;
+
type = mi.ReturnType;
return this;
} else {
// If any of the arguments is a string, cast to string
//
if (l == TypeManager.string_type){
+
+ if (r == TypeManager.void_type) {
+ error19 ();
+ return null;
+ }
+
if (r == TypeManager.string_type){
if (left is Constant && right is Constant){
StringConstant ls = (StringConstant) left;
} else if (r == TypeManager.string_type){
// object + string
+
+ if (l == TypeManager.void_type) {
+ error19 ();
+ return null;
+ }
+
method = TypeManager.string_concat_object_object;
+ left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
Arguments = new ArrayList ();
Arguments.Add (new Argument (left, Argument.AType.Expression));
Arguments.Add (new Argument (right, Argument.AType.Expression));
- left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
type = TypeManager.string_type;
return this;
type = l;
return this;
}
+
+ //
+ // Pointer arithmetic:
+ //
+ // T* operator + (T* x, int y);
+ // T* operator + (T* x, uint y);
+ // T* operator + (T* x, long y);
+ // T* operator + (T* x, ulong y);
+ //
+ // T* operator + (int y, T* x);
+ // T* operator + (uint y, T *x);
+ // T* operator + (long y, T *x);
+ // T* operator + (ulong y, T *x);
+ //
+ // T* operator - (T* x, int y);
+ // T* operator - (T* x, uint y);
+ // T* operator - (T* x, long y);
+ // T* operator - (T* x, ulong y);
+ //
+ // long operator - (T* x, T *y)
+ //
+ if (l.IsPointer){
+ if (r.IsPointer && oper == Operator.Subtraction){
+ if (r == l)
+ return new PointerArithmetic (
+ false, left, right, TypeManager.int64_type);
+ } else if (is_32_or_64 (r))
+ return new PointerArithmetic (
+ oper == Operator.Addition, left, right, l);
+ } else if (r.IsPointer && is_32_or_64 (l) && oper == Operator.Addition)
+ return new PointerArithmetic (
+ true, right, left, r);
}
//
}
}
+ //
+ // Pointer comparison
+ //
+ if (l.IsPointer && r.IsPointer){
+ if (oper == Operator.Equality || oper == Operator.Inequality ||
+ oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||
+ oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){
+ type = TypeManager.bool_type;
+ return this;
+ }
+ }
+
//
// We are dealing with numbers
//
return this;
}
- /// <summary>
- /// Constant expression reducer for binary operations
- /// </summary>
- public Expression ConstantFold (EmitContext ec)
- {
- object l = ((Constant) left).GetValue ();
- object r = ((Constant) right).GetValue ();
-
- if (l is string && r is string)
- return new StringConstant ((string) l + (string) r);
-
- Type result_type = null;
-
- //
- // Enumerator folding
- //
- if (left.Type == right.Type && left is EnumConstant)
- result_type = left.Type;
-
- switch (oper){
- case Operator.BitwiseOr:
- if ((l is int) && (r is int)){
- IntConstant v;
- int res = (int)l | (int)r;
-
- v = new IntConstant (res);
- if (result_type == null)
- return v;
- else
- return new EnumConstant (v, result_type);
- }
- break;
-
- case Operator.BitwiseAnd:
- if ((l is int) && (r is int)){
- IntConstant v;
- int res = (int)l & (int)r;
-
- v = new IntConstant (res);
- if (result_type == null)
- return v;
- else
- return new EnumConstant (v, result_type);
- }
- break;
- }
-
- return null;
- }
-
public override Expression DoResolve (EmitContext ec)
{
left = left.Resolve (ec);
eclass = ExprClass.Value;
if (left is Constant && right is Constant){
- //
- // This is temporary until we do the full folding
- //
- Expression e = ConstantFold (ec);
+ Expression e = ConstantFold.BinaryFold (
+ ec, oper, (Constant) left, (Constant) right, loc);
if (e != null)
return e;
}
}
}
+ public class PointerArithmetic : Expression {
+ Expression left, right;
+ bool is_add;
+
+ //
+ // We assume that `l' is always a pointer
+ //
+ public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t)
+ {
+ type = t;
+ eclass = ExprClass.Variable;
+ left = l;
+ right = r;
+ is_add = is_addition;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ //
+ // We are born fully resolved
+ //
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ Type op_type = left.Type;
+ ILGenerator ig = ec.ig;
+ int size = GetTypeSize (op_type.GetElementType ());
+
+ if (right.Type.IsPointer){
+ //
+ // handle (pointer - pointer)
+ //
+ left.Emit (ec);
+ right.Emit (ec);
+ ig.Emit (OpCodes.Sub);
+
+ if (size != 1){
+ if (size == 0)
+ ig.Emit (OpCodes.Sizeof, op_type);
+ else
+ IntLiteral.EmitInt (ig, size);
+ ig.Emit (OpCodes.Div);
+ }
+ ig.Emit (OpCodes.Conv_I8);
+ } else {
+ //
+ // handle + and - on (pointer op int)
+ //
+ left.Emit (ec);
+ ig.Emit (OpCodes.Conv_I);
+ right.Emit (ec);
+ if (size != 1){
+ if (size == 0)
+ ig.Emit (OpCodes.Sizeof, op_type);
+ else
+ IntLiteral.EmitInt (ig, size);
+ ig.Emit (OpCodes.Mul);
+ }
+ if (is_add)
+ ig.Emit (OpCodes.Add);
+ else
+ ig.Emit (OpCodes.Sub);
+ }
+ }
+ }
+
/// <summary>
/// Implements the ternary conditiona operator (?:)
/// </summary>
if (expr == null || trueExpr == null || falseExpr == null)
return null;
+ eclass = ExprClass.Value;
if (trueExpr.Type == falseExpr.Type)
type = trueExpr.Type;
else {
Expression conv;
+ Type true_type = trueExpr.Type;
+ Type false_type = falseExpr.Type;
+ if (trueExpr is NullLiteral){
+ type = false_type;
+ return this;
+ } else if (falseExpr is NullLiteral){
+ type = true_type;
+ return this;
+ }
+
//
// First, if an implicit conversion exists from trueExpr
// to falseExpr, then the result type is of type falseExpr.Type
//
- conv = ConvertImplicit (ec, trueExpr, falseExpr.Type, loc);
+ conv = ConvertImplicit (ec, trueExpr, false_type, loc);
if (conv != null){
//
// Check if both can convert implicitl to each other's type
//
- if (ConvertImplicit (ec, falseExpr, trueExpr.Type, loc) != null){
+ if (ConvertImplicit (ec, falseExpr, true_type, loc) != null){
Report.Error (
172, loc,
"Can not compute type of conditional expression " +
"' convert implicitly to each other");
return null;
}
- type = falseExpr.Type;
+ type = false_type;
trueExpr = conv;
- } else if ((conv = ConvertImplicit(ec, falseExpr,trueExpr.Type,loc))!= null){
- type = trueExpr.Type;
+ } else if ((conv = ConvertImplicit(ec, falseExpr, true_type,loc))!= null){
+ type = true_type;
falseExpr = conv;
} else {
Error (173, loc, "The type of the conditional expression can " +
return falseExpr;
}
- eclass = ExprClass.Value;
return this;
}
Store (ig, vi.Idx);
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
VariableInfo vi = VariableInfo;
int idx = vi.Idx;
- vi.Used = true;
- vi.Assigned = true;
+ if ((mode & AddressOp.Load) != 0)
+ vi.Used = true;
+ if ((mode & AddressOp.Store) != 0)
+ vi.Assigned = true;
if (idx <= 255)
ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
{
type = pars.GetParameterInfo (ec.TypeContainer, idx, out is_ref);
eclass = ExprClass.Variable;
-
+
return this;
}
source.Emit (ec);
- if (is_ref){
- if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
- ig.Emit (OpCodes.Stind_I4);
- else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
- ig.Emit (OpCodes.Stind_I8);
- else if (type == TypeManager.char_type || type == TypeManager.short_type ||
- type == TypeManager.ushort_type)
- ig.Emit (OpCodes.Stind_I2);
- else if (type == TypeManager.float_type)
- ig.Emit (OpCodes.Stind_R4);
- else if (type == TypeManager.double_type)
- ig.Emit (OpCodes.Stind_R8);
- else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
- type == TypeManager.bool_type)
- ig.Emit (OpCodes.Stind_I1);
- else if (type == TypeManager.intptr_type)
- ig.Emit (OpCodes.Stind_I);
- else
- ig.Emit (OpCodes.Stind_Ref);
- } else {
+ if (is_ref)
+ StoreFromPtr (ig, type);
+ else {
if (arg_idx <= 255)
ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
else
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
int arg_idx = idx;
// to pass just the value
//
if (ArgType == AType.Ref || ArgType == AType.Out){
+ AddressOp mode = AddressOp.Store;
+
+ if (ArgType == AType.Ref)
+ mode |= AddressOp.Load;
+
if (expr is ParameterReference){
ParameterReference pr = (ParameterReference) expr;
if (pr.is_ref)
pr.EmitLoad (ec);
- else
- pr.AddressOf (ec);
+ else {
+
+ pr.AddressOf (ec, mode);
+ }
} else
- ((IMemoryLocation)expr).AddressOf (ec);
+ ((IMemoryLocation)expr).AddressOf (ec, mode);
} else
expr.Emit (ec);
}
else
argument_count = args.Count;
- if (candidate_pd.Count == 0 && argument_count == 0)
+ int cand_count = candidate_pd.Count;
+
+ if (cand_count == 0 && argument_count == 0)
return 1;
- if (candidate_pd.ParameterModifier (candidate_pd.Count - 1) != Parameter.Modifier.PARAMS)
- if (candidate_pd.Count != argument_count)
+ if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+ if (cand_count != argument_count)
return 0;
if (best == null) {
int x = 0;
+
+ if (argument_count == 0 && cand_count == 1 &&
+ candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
+ return 1;
+
for (int j = argument_count; j > 0;) {
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 ();
-
+
x = BetterConversion (ec, a, t, null, loc);
if (x <= 0)
x = BetterConversion (ec, a, ct, bt, loc);
y = BetterConversion (ec, a, bt, ct, loc);
-
+
if (x < y)
- break;
+ return 0;
rating1 += x;
rating2 += y;
if (pd_count - 1 > arg_count)
return false;
-
+
+ if (pd_count == 1 && arg_count == 0)
+ 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. So, we now check if the element type
- // of the params array is compatible with each argument type
- //
+ // is less than or equal to the argument count.
+
+ for (int i = 0; i < pd_count - 1; ++i) {
+
+ Argument a = (Argument) arguments [i];
+
+ Parameter.Modifier a_mod = a.GetParameterModifier ();
+ Parameter.Modifier p_mod = pd.ParameterModifier (i);
+
+ if (a_mod == p_mod) {
+
+ if (a_mod == Parameter.Modifier.NONE)
+ if (!StandardConversionExists (a.Type, pd.ParameterType (i)))
+ return false;
+
+ if (a_mod == Parameter.Modifier.REF ||
+ a_mod == Parameter.Modifier.OUT)
+ if (pd.ParameterType (i) != a.Type)
+ return false;
+ } else
+ return false;
+
+ }
Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
- for (int i = pd_count - 1; i < arg_count - 1; i++) {
+ for (int i = pd_count - 1; i < arg_count; i++) {
Argument a = (Argument) arguments [i];
if (!StandardConversionExists (a.Type, element_type))
if (IsParamsMethodApplicable (Arguments, candidate) &&
IsApplicable (Arguments, method))
continue;
-
+
int x = BetterFunction (ec, Arguments, method, candidate,
chose_params_expanded, loc);
if (x != 1) {
- Console.WriteLine ("Candidate : " + FullMethodDesc (candidate));
- Console.WriteLine ("Best : " + FullMethodDesc (method));
+ //Console.WriteLine ("Candidate : " + FullMethodDesc (candidate));
+ //Console.WriteLine ("Best : " + FullMethodDesc (method));
Report.Error (
121, loc,
"Ambiguous call when selecting function due to implicit casts");
// it.
if (instance_expr is IMemoryLocation){
((IMemoryLocation)instance_expr).
- AddressOf (ec);
+ AddressOf (ec, AddressOp.LoadStore);
}
else {
Type t = instance_expr.Type;
value_target = new LocalTemporary (ec, type);
ml = (IMemoryLocation) value_target;
- ml.AddressOf (ec);
+ ml.AddressOf (ec, AddressOp.Store);
}
if (method != null)
{
int factor;
byte [] data;
-
+ byte [] element;
int count = ArrayData.Count;
factor = GetTypeSize (underlying_type);
}
}
} else if (underlying_type == TypeManager.float_type) {
-#if __MonoCS__
-#else
- unsafe {
- if (!(v is Expression)){
- float val = (float) v;
-
- byte *ptr = (byte *) &val;
+ if (!(v is Expression)){
+ element = BitConverter.GetBytes ((float) v);
- for (int j = 0; j < factor; ++j)
- data [idx + j] = (byte) ptr [j];
- }
+ for (int j = 0; j < factor; ++j)
+ data [idx + j] = element [j];
}
-#endif
} else if (underlying_type == TypeManager.double_type) {
-#if __MonoCS__
-#else
- unsafe {
- if (!(v is Expression)){
- double val = (double) v;
+ if (!(v is Expression)){
+ element = BitConverter.GetBytes ((double) v);
- byte *ptr = (byte *) &val;
-
- for (int j = 0; j < factor; ++j)
- data [idx + j] = (byte) ptr [j];
- }
+ for (int j = 0; j < factor; ++j)
+ data [idx + j] = element [j];
}
-#endif
} else if (underlying_type == TypeManager.char_type){
-
if (!(v is Expression)){
int val = (int) ((char) v);
ec.ig.Emit (OpCodes.Starg, 0);
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
ec.ig.Emit (OpCodes.Ldarg_0);
if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
Expression enum_member = MemberLookup (
- ec, decl_type, "value__", loc);
+ ec, decl_type, "value__", MemberTypes.Field,
+ AllBindingFlags, loc);
Enum en = TypeManager.LookupEnum (decl_type);
public override Expression DoResolve (EmitContext ec)
{
- Expr = Expr.Resolve (ec);
+ bool last_const_check = ec.ConstantCheckState;
+ ec.ConstantCheckState = true;
+ Expr = Expr.Resolve (ec);
+ ec.ConstantCheckState = last_const_check;
+
if (Expr == null)
return null;
public override void Emit (EmitContext ec)
{
bool last_check = ec.CheckState;
+ bool last_const_check = ec.ConstantCheckState;
ec.CheckState = true;
+ ec.ConstantCheckState = true;
Expr.Emit (ec);
ec.CheckState = last_check;
+ ec.ConstantCheckState = last_const_check;
}
}
public override Expression DoResolve (EmitContext ec)
{
+ bool last_const_check = ec.ConstantCheckState;
+
+ ec.ConstantCheckState = false;
Expr = Expr.Resolve (ec);
+ ec.ConstantCheckState = last_const_check;
if (Expr == null)
return null;
public override void Emit (EmitContext ec)
{
bool last_check = ec.CheckState;
+ bool last_const_check = ec.ConstantCheckState;
ec.CheckState = false;
+ ec.ConstantCheckState = false;
Expr.Emit (ec);
ec.CheckState = last_check;
+ ec.ConstantCheckState = last_const_check;
}
}
return true;
}
-
+
+ Expression MakePointerAccess ()
+ {
+ Type t = Expr.Type;
+
+ if (t == TypeManager.void_ptr_type){
+ Report.Error (
+ 242, loc,
+ "The array index operation is not valid for void pointers");
+ return null;
+ }
+ if (Arguments.Count != 1){
+ Report.Error (
+ 196, loc,
+ "A pointer must be indexed by a single value");
+ return null;
+ }
+ Expression p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t);
+ return new Indirection (p);
+ }
+
public override Expression DoResolve (EmitContext ec)
{
if (!CommonResolve (ec))
//
// I am experimenting with this pattern.
//
- if (Expr.Type.IsSubclassOf (TypeManager.array_type))
+ Type t = Expr.Type;
+
+ if (t.IsSubclassOf (TypeManager.array_type))
return (new ArrayAccess (this)).Resolve (ec);
+ else if (t.IsPointer)
+ return MakePointerAccess ();
else
return (new IndexerAccess (this)).Resolve (ec);
}
if (!CommonResolve (ec))
return null;
- if (Expr.Type.IsSubclassOf (TypeManager.array_type))
+ Type t = Expr.Type;
+ if (t.IsSubclassOf (TypeManager.array_type))
return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
+ else if (t.IsPointer)
+ return MakePointerAccess ();
else
return (new IndexerAccess (this)).ResolveLValue (ec, right_side);
}
}
Type t = ea.Expr.Type;
-
if (t.GetArrayRank () != ea.Arguments.Count){
Report.Error (22, ea.loc,
"Incorrect number of indexes for array " +
}
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
int rank = ea.Expr.Type.GetArrayRank ();
ILGenerator ig = ec.ig;
return null;
}
- member_lookup = MemberLookup (ec, base_type, "get_Item", loc);
+ member_lookup = MemberLookup (ec, base_type, "get_Item", MemberTypes.Method, AllBindingFlags, loc);
if (member_lookup == null)
return null;
ig.Emit (OpCodes.Call, (ConstructorInfo) method);
}
-
}
// <summary>
throw new Exception ("This should never be called");
}
}
+
+ //
+ // This class is used to represent the address of an array, used
+ // only by the Fixed statement, this is like the C "&a [0]" construct.
+ //
+ public class ArrayPtr : Expression {
+ Expression array;
+
+ public ArrayPtr (Expression array)
+ {
+ Type array_type = array.Type.GetElementType ();
+
+ this.array = array;
+
+ string array_ptr_type_name = array_type.FullName + "*";
+
+ type = Type.GetType (array_ptr_type_name);
+ if (type == null){
+ ModuleBuilder mb = RootContext.ModuleBuilder;
+
+ type = mb.GetType (array_ptr_type_name);
+ }
+
+ eclass = ExprClass.Value;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ array.Emit (ec);
+ IntLiteral.EmitInt (ig, 0);
+ ig.Emit (OpCodes.Ldelema, array.Type.GetElementType ());
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ //
+ // We are born fully resolved
+ //
+ return this;
+ }
+ }
+
+ //
+ // Used by the fixed statement
+ //
+ public class StringPtr : Expression {
+ LocalBuilder b;
+
+ public StringPtr (LocalBuilder b)
+ {
+ this.b = b;
+ eclass = ExprClass.Value;
+ type = TypeManager.char_ptr_type;
+ }
+
+ 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)
+ {
+ 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
+ //
+ public class StackAlloc : Expression {
+ Type otype;
+ string t;
+ Expression count;
+ Location loc;
+
+ public StackAlloc (string type, Expression count, Location l)
+ {
+ t = type;
+ this.count = count;
+ loc = l;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ count = count.Resolve (ec);
+ if (count == null)
+ return null;
+
+ if (count.Type != TypeManager.int32_type){
+ count = ConvertImplicitRequired (ec, count, TypeManager.int32_type, loc);
+ if (count == null)
+ return null;
+ }
+
+ if (ec.InCatch || ec.InFinally){
+ Report.Error (255, loc,
+ "stackalloc can not be used in a catch or finally block");
+ return null;
+ }
+
+ otype = RootContext.LookupType (ec.TypeContainer, t, false, loc);
+
+ if (otype == null)
+ return null;
+
+ if (!TypeManager.VerifyUnManaged (otype, loc))
+ return null;
+
+ string ptr_name = otype.FullName + "*";
+ type = Type.GetType (ptr_name);
+ if (type == null){
+ ModuleBuilder mb = RootContext.ModuleBuilder;
+
+ type = mb.GetType (ptr_name);
+ }
+ eclass = ExprClass.Value;
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ int size = GetTypeSize (otype);
+ ILGenerator ig = ec.ig;
+
+ if (size == 0)
+ ig.Emit (OpCodes.Sizeof, otype);
+ else
+ IntConstant.EmitInt (ig, size);
+ count.Emit (ec);
+ ig.Emit (OpCodes.Mul);
+ ig.Emit (OpCodes.Localloc);
+ }
+ }
}