namespace Mono.CSharp {
using System;
using System.Collections;
+ using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
#if NET_4_0
+ using System.Linq;
using SLE = System.Linq.Expressions;
#endif
Type[] predefined = predefined_operators [(int) Oper];
foreach (Type t in predefined) {
- Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false);
+ Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false, false);
if (oper_expr == null)
continue;
}
Mode mode;
- bool is_expr = false;
- bool recurse = false;
+ bool is_expr, recurse;
Expression expr;
- //
- // This is expensive for the simplest case.
- //
- UserOperatorCall method;
+ // Holds the real operation
+ Expression operation;
public UnaryMutator (Mode m, Expression e)
{
expr = e;
}
- string OperName ()
- {
- return IsDecrement ?
- Operator.GetName (Operator.OpType.Decrement) :
- Operator.GetName (Operator.OpType.Increment);
- }
-
- /// <summary>
- /// Returns whether an object of type `t' can be incremented
- /// or decremented with add/sub (ie, basically whether we can
- /// use pre-post incr-decr operations on it, but it is not a
- /// System.Decimal, which we require operator overloading to catch)
- /// </summary>
- static bool IsIncrementableNumber (Type t)
- {
- return (t == TypeManager.sbyte_type) ||
- (t == TypeManager.byte_type) ||
- (t == TypeManager.short_type) ||
- (t == TypeManager.ushort_type) ||
- (t == TypeManager.int32_type) ||
- (t == TypeManager.uint32_type) ||
- (t == TypeManager.int64_type) ||
- (t == TypeManager.uint64_type) ||
- (t == TypeManager.char_type) ||
- (TypeManager.IsSubclassOf (t, TypeManager.enum_type)) ||
- (t == TypeManager.float_type) ||
- (t == TypeManager.double_type) ||
- (t.IsPointer && t != TypeManager.void_ptr_type);
- }
-
- Expression ResolveOperator (ResolveContext ec)
- {
- type = expr.Type;
-
- //
- // The operand of the prefix/postfix increment decrement operators
- // should be an expression that is classified as a variable,
- // a property access or an indexer access
- //
- if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
- expr = expr.ResolveLValue (ec, expr);
- } else {
- ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
- }
-
- //
- // Step 1: Perform Operator Overload location
- //
- MethodGroupExpr mg;
- string op_name;
-
- if (IsDecrement)
- op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
- else
- op_name = Operator.GetMetadataName (Operator.OpType.Increment);
-
- mg = MemberLookup (ec.Compiler, ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
-
- if (mg != null) {
- Arguments args = new Arguments (1);
- args.Add (new Argument (expr));
- mg = mg.OverloadResolve (ec, ref args, false, loc);
- if (mg == null)
- return null;
-
- method = new UserOperatorCall (mg, args, null, loc);
- Convert.ImplicitConversionRequired (ec, method, type, loc);
- return this;
- }
-
- if (!IsIncrementableNumber (type)) {
- ec.Report.Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
- TypeManager.CSharpName (type) + "'");
- return null;
- }
-
- return this;
- }
-
public override Expression CreateExpressionTree (ResolveContext ec)
{
return new SimpleAssign (this, this).CreateExpressionTree (ec);
return ResolveOperator (ec);
}
- //
- // Loads the proper "1" into the stack based on the type, then it emits the
- // opcode for the operation requested
- //
- void LoadOneAndEmitOp (EmitContext ec, Type t)
- {
- //
- // Measure if getting the typecode and using that is more/less efficient
- // that comparing types. t.GetTypeCode() is an internal call.
- //
- ILGenerator ig = ec.ig;
-
- if (t == TypeManager.uint64_type || t == TypeManager.int64_type)
- LongConstant.EmitLong (ig, 1);
- else if (t == TypeManager.double_type)
- ig.Emit (OpCodes.Ldc_R8, 1.0);
- else if (t == TypeManager.float_type)
- ig.Emit (OpCodes.Ldc_R4, 1.0F);
- else if (t.IsPointer){
- Type et = TypeManager.GetElementType (t);
- int n = GetTypeSize (et);
-
- if (n == 0)
- ig.Emit (OpCodes.Sizeof, et);
- else {
- IntConstant.EmitInt (ig, n);
- ig.Emit (OpCodes.Conv_I);
- }
- } else
- ig.Emit (OpCodes.Ldc_I4_1);
-
- //
- // Now emit the operation
- //
-
- Binary.Operator op = (mode & Mode.IsDecrement) != 0 ? Binary.Operator.Subtraction : Binary.Operator.Addition;
- Binary.EmitOperatorOpcode (ec, op, t);
-
- if (t == TypeManager.sbyte_type){
- if (ec.HasSet (EmitContext.Options.CheckedScope))
- ig.Emit (OpCodes.Conv_Ovf_I1);
- else
- ig.Emit (OpCodes.Conv_I1);
- } else if (t == TypeManager.byte_type){
- if (ec.HasSet (EmitContext.Options.CheckedScope))
- ig.Emit (OpCodes.Conv_Ovf_U1);
- else
- ig.Emit (OpCodes.Conv_U1);
- } else if (t == TypeManager.short_type){
- if (ec.HasSet (EmitContext.Options.CheckedScope))
- ig.Emit (OpCodes.Conv_Ovf_I2);
- else
- ig.Emit (OpCodes.Conv_I2);
- } else if (t == TypeManager.ushort_type || t == TypeManager.char_type){
- if (ec.HasSet (EmitContext.Options.CheckedScope))
- ig.Emit (OpCodes.Conv_Ovf_U2);
- else
- ig.Emit (OpCodes.Conv_U2);
- }
-
- }
-
void EmitCode (EmitContext ec, bool is_expr)
{
recurse = true;
//
if (recurse) {
((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement));
- if (method == null)
- LoadOneAndEmitOp (ec, expr.Type);
- else
- ec.ig.Emit (OpCodes.Call, (MethodInfo)method.Method);
+
+ operation.Emit (ec);
+
recurse = false;
return;
}
get { return (mode & Mode.IsDecrement) != 0; }
}
+ //
+ // Returns whether an object of type `t' can be incremented
+ // or decremented with add/sub (ie, basically whether we can
+ // use pre-post incr-decr operations on it, but it is not a
+ // System.Decimal, which we require operator overloading to catch)
+ //
+ static bool IsPredefinedOperator (Type t)
+ {
+ return (TypeManager.IsPrimitiveType (t) && t != TypeManager.bool_type) ||
+ TypeManager.IsEnumType (t) ||
+ t.IsPointer && t != TypeManager.void_ptr_type;
+ }
+
#if NET_4_0
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
- if (method != null)
- return method.MakeExpression (ctx);
-
- bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope);
- var one = SLE.Expression.Constant (1);
- var left = expr.MakeExpression (ctx);
-
- SLE.Expression binary;
- if (IsDecrement) {
- binary = is_checked ? SLE.Expression.SubtractChecked (left, one) : SLE.Expression.Subtract (left, one);
- } else {
- binary = is_checked ? SLE.Expression.AddChecked (left, one) : SLE.Expression.Add (left, one);
- }
-
var target = ((RuntimeValueExpression) expr).MetaObject.Expression;
- binary = SLE.Expression.Convert (binary, target.Type);
-
- return SLE.Expression.Assign (target, binary);
+ var source = SLE.Expression.Convert (operation.MakeExpression (ctx), target.Type);
+ return SLE.Expression.Assign (target, source);
}
#endif
target.expr = expr.Clone (clonectx);
}
+
+ Expression ResolveOperator (ResolveContext ec)
+ {
+ type = expr.Type;
+
+ if (expr is RuntimeValueExpression) {
+ operation = expr;
+ } else {
+ // Use itself at the top of the stack
+ operation = new EmptyExpression (type);
+ }
+
+ //
+ // The operand of the prefix/postfix increment decrement operators
+ // should be an expression that is classified as a variable,
+ // a property access or an indexer access
+ //
+ if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
+ expr = expr.ResolveLValue (ec, expr);
+ } else {
+ ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
+ }
+
+ //
+ // 1. Check predefined types
+ //
+ if (IsPredefinedOperator (type)) {
+ // TODO: Move to IntConstant once I get rid of int32_type
+ var one = new IntConstant (1, loc);
+
+ // TODO: Cache this based on type when using EmptyExpression in
+ // context cache
+ Binary.Operator op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition;
+ operation = new Binary (op, operation, one);
+ operation = operation.Resolve (ec);
+ if (operation.Type != type)
+ operation = Convert.ExplicitNumericConversion (operation, type);
+
+ return this;
+ }
+
+ //
+ // Step 2: Perform Operator Overload location
+ //
+ MethodGroupExpr mg;
+ string op_name;
+
+ if (IsDecrement)
+ op_name = Operator.GetMetadataName (Operator.OpType.Decrement);
+ else
+ op_name = Operator.GetMetadataName (Operator.OpType.Increment);
+
+ mg = MemberLookup (ec.Compiler, ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
+
+ if (mg != null) {
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (expr));
+ mg = mg.OverloadResolve (ec, ref args, false, loc);
+ if (mg == null)
+ return null;
+
+ args[0].Expr = operation;
+ operation = new UserOperatorCall (mg, args, null, loc);
+ operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
+ return this;
+ }
+
+ string name = IsDecrement ?
+ Operator.GetName (Operator.OpType.Decrement) :
+ Operator.GetName (Operator.OpType.Increment);
+
+ Unary.Error_OperatorCannotBeApplied (ec, loc, name, type);
+ return null;
+ }
}
/// <summary>
if (do_isinst)
ig.Emit (OpCodes.Isinst, type);
-#if GMCS_SOURCE
if (TypeManager.IsGenericParameter (type) || TypeManager.IsNullableType (type))
ig.Emit (OpCodes.Unbox_Any, type);
-#endif
}
public override Expression DoResolve (ResolveContext ec)
} else if (TypeManager.IsDynamicType (expr.Type)) {
Arguments arg = new Arguments (1);
arg.Add (new Argument (expr));
- return new DynamicConversion (type, true, arg, loc).Resolve (ec);
+ return new DynamicConversion (type, CSharpBinderFlags.ConvertExplicit, arg, loc).Resolve (ec);
}
expr = Convert.ExplicitConversion (ec, expr, type, loc);
public class ImplicitCast : ShimExpression
{
- public ImplicitCast (Expression expr, Type target)
+ bool arrayAccess;
+
+ public ImplicitCast (Expression expr, Type target, bool arrayAccess)
: base (expr)
{
this.loc = expr.Location;
this.type = target;
+ this.arrayAccess = arrayAccess;
}
public override Expression DoResolve (ResolveContext ec)
{
expr = expr.Resolve (ec);
- if (expr != null)
+ if (expr == null)
+ return null;
+
+ if (arrayAccess)
+ expr = ConvertExpressionToArrayIndex (ec, expr);
+ else
expr = Convert.ImplicitConversionRequired (ec, expr, type, loc);
return expr;
if (lgen) {
if (!TypeManager.IsReferenceType (l))
return null;
- left = new BoxedCast (left, TypeManager.object_type);
+
+ l = TypeManager.object_type;
+ left = new BoxedCast (left, l);
} else if (l.IsInterface) {
l = TypeManager.object_type;
} else if (TypeManager.IsStruct (l)) {
if (rgen) {
if (!TypeManager.IsReferenceType (r))
return null;
- right = new BoxedCast (right, TypeManager.object_type);
+
+ r = TypeManager.object_type;
+ right = new BoxedCast (right, r);
} else if (r.IsInterface) {
r = TypeManager.object_type;
} else if (TypeManager.IsStruct (r)) {
if (best_operator == null) {
ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
- OperName (oper), left.GetSignatureForError (), right.GetSignatureForError ());
+ OperName (oper), TypeManager.CSharpName (l), TypeManager.CSharpName (r));
best_operator = po;
break;
public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
{
- Arguments binder_args = new Arguments (4);
+ Arguments binder_args = new Arguments (3);
MemberAccess sle = new MemberAccess (new MemberAccess (
new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc);
- MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc);
+ CSharpBinderFlags flags = 0;
+ if (ec.HasSet (ResolveContext.Options.CheckedScope))
+ flags = CSharpBinderFlags.CheckedContext;
- binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc)));
- binder_args.Add (new Argument (new BoolLiteral (ec.HasSet (ResolveContext.Options.CheckedScope), loc)));
+ if ((oper & Operator.LogicalMask) != 0)
+ flags |= CSharpBinderFlags.BinaryOperationLogical;
- bool member_access = left is DynamicMemberBinder || right is DynamicMemberBinder;
- binder_args.Add (new Argument (new BoolLiteral (member_access, loc)));
+ binder_args.Add (new Argument (new EnumConstant (new IntLiteral ((int) flags, loc), TypeManager.binder_flags)));
+ binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc)));
binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (), loc)));
- return new New (new MemberAccess (binder, "CSharpBinaryOperationBinder", loc), binder_args, loc);
+ return new Invocation (DynamicExpressionStatement.GetBinder ("BinaryOperation", loc), binder_args);
}
public override Expression CreateExpressionTree (ResolveContext ec)
// A boolean-expression is an expression that yields a result
// of type bool
//
- public class BooleanExpression : Expression
+ public class BooleanExpression : ShimExpression
{
- Expression expr;
-
public BooleanExpression (Expression expr)
+ : base (expr)
{
- this.expr = expr;
this.loc = expr.Location;
}
- protected override void CloneTo (CloneContext clonectx, Expression t)
- {
- BooleanExpression target = (BooleanExpression) t;
- target.expr = expr.Clone (clonectx);
- }
-
public override Expression CreateExpressionTree (ResolveContext ec)
{
// TODO: We should emit IsTrue (v4) instead of direct user operator
// call but that would break csc compatibility
- throw new NotSupportedException ();
+ return base.CreateExpressionTree (ec);
}
public override Expression DoResolve (ResolveContext ec)
Assign ass = expr as Assign;
if (ass != null && ass.Source is Constant) {
- ec.Report.Warning (665, 3, expr.Location,
+ ec.Report.Warning (665, 3, loc,
"Assignment in conditional expression is always constant. Did you mean to use `==' instead ?");
}
return converted;
}
-
- public override void Emit (EmitContext ec)
- {
- throw new InternalErrorException ("Should not be reached");
- }
}
/// <summary>
} else {
ec.Report.Error (173, loc,
"Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
- true_expr.GetSignatureForError (), false_expr.GetSignatureForError ());
+ TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type));
return null;
}
}
return GetHoistedVariable (ec.CurrentAnonymousMethod);
}
+ public override string GetSignatureForError ()
+ {
+ return Name;
+ }
+
public override void Emit (EmitContext ec)
{
Emit (ec, false);
}
}
}
-
- if (type.IsPointer){
- if (!ec.IsUnsafe){
- UnsafeError (ec, loc);
- return null;
- }
- }
-
+
//
// Only base will allow this invocation to happen.
//
return false;
method = TypeManager.DropGenericMethodArguments (method);
- if (method.DeclaringType.Module == RootContext.ToplevelTypes.Builder) {
+ if (TypeManager.IsBeingCompiled (method)) {
IMethodData md = TypeManager.GetMethod (method);
if (md != null)
return md.IsExcluded ();
} else {
call_op = OpCodes.Callvirt;
-#if GMCS_SOURCE
if ((instance_expr != null) && (instance_expr.Type.IsGenericParameter))
ig.Emit (OpCodes.Constrained, instance_expr.Type);
-#endif
}
if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
target.expr = expr.Clone (clonectx);
}
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- mg.MutateHoistedGenericType (storey);
- type = storey.MutateType (type);
- if (arguments != null) {
- arguments.MutateHoistedGenericType (storey);
- }
- }
- }
-/*
- //
- // It's either a cast or delegate invocation
- //
- public class InvocationOrCast : ExpressionStatement
- {
- Expression expr;
- Expression argument;
-
- public InvocationOrCast (Expression expr, Expression argument)
- {
- this.expr = expr;
- this.argument = argument;
- this.loc = expr.Location;
- }
-
- public override Expression CreateExpressionTree (ResolveContext ec)
- {
- throw new NotSupportedException ("ET");
- }
-
- public override Expression DoResolve (ResolveContext ec)
+#if NET_4_0
+ public override SLE.Expression MakeExpression (BuilderContext ctx)
{
- Expression e = ResolveCore (ec);
- if (e == null)
- return null;
-
- return e.Resolve (ec);
+ return MakeExpression (ctx, mg.InstanceExpression, (MethodInfo) mg, arguments);
}
- Expression ResolveCore (EmitContext ec)
+ public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodInfo mi, Arguments args)
{
- //
- // First try to resolve it as a cast.
- //
- TypeExpr te = expr.ResolveAsBaseTerminal (ec, true);
- if (te != null) {
- return new Cast (te, argument, loc);
- }
-
- //
- // 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 || expr.eclass == ExprClass.TypeParameter) {
- return new Cast (expr, argument, loc);
- }
-
- if (expr.eclass == ExprClass.Namespace) {
- expr.Error_UnexpectedKind (null, "type", loc);
- return null;
- }
+ var instance_expr = instance == null ? null : instance.MakeExpression (ctx);
+ SLE.Expression expr = SLE.Expression.Call (instance_expr, mi,
+ Arguments.MakeExpression (args, ctx));
- //
- // It's a delegate invocation.
- //
- if (!TypeManager.IsDelegateType (expr.Type)) {
- Error (149, "Method name expected");
- return null;
+ if (mi.ReturnType == typeof (void)) {
+ expr = SLE.Expression.Block (
+ expr,
+ SLE.Expression.Default (typeof (object)));
}
- ArrayList args = new ArrayList (1);
- args.Add (new Argument (argument, Argument.AType.Expression));
- return new DelegateInvocation (expr, args, loc);
+ return expr;
}
+#endif
- public override ExpressionStatement ResolveStatement (EmitContext ec)
+ public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
- Expression e = ResolveCore (ec);
- if (e == null)
- return null;
-
- ExpressionStatement s = e as ExpressionStatement;
- if (s == null) {
- Error_InvalidExpressionStatement ();
- return null;
+ mg.MutateHoistedGenericType (storey);
+ type = storey.MutateType (type);
+ if (arguments != null) {
+ arguments.MutateHoistedGenericType (storey);
}
-
- return s.ResolveStatement (ec);
- }
-
- public override void Emit (EmitContext ec)
- {
- throw new Exception ("Cannot happen");
- }
-
- public override void EmitStatement (EmitContext ec)
- {
- throw new Exception ("Cannot happen");
- }
-
- protected override void CloneTo (CloneContext clonectx, Expression t)
- {
- InvocationOrCast target = (InvocationOrCast) t;
-
- target.expr = expr.Clone (clonectx);
- target.argument = argument.Clone (clonectx);
}
}
-*/
/// <summary>
/// Implements the new expression
bool DoEmitTypeParameter (EmitContext ec)
{
-#if GMCS_SOURCE
ILGenerator ig = ec.ig;
-// IMemoryLocation ml;
MethodInfo ci = TypeManager.activator_create_instance.MakeGenericMethod (
new Type [] { type });
ig.Emit (OpCodes.Call, ci);
ig.MarkLabel (label_end);
return true;
-#else
- throw new InternalErrorException ();
-#endif
}
//
int num_arguments = 0;
protected int dimensions;
protected readonly string rank;
+ Expression first_emit;
+ LocalTemporary first_emit_temp;
- protected ArrayList array_data;
+ protected List<Expression> array_data;
IDictionary bounds;
args.Add (new Argument (new TypeOf (new TypeExpression (array_element_type, loc), loc)));
if (array_data != null) {
for (int i = 0; i < array_data.Count; ++i) {
- Expression e = (Expression) array_data [i];
+ Expression e = array_data [i];
if (e == null)
e = Convert.ImplicitConversion (ec, (Expression) initializers [i], array_element_type, loc);
return;
}
}
-
}
- Expression first_emit;
- LocalTemporary first_emit_temp;
-
protected virtual Expression ResolveArrayElement (ResolveContext ec, Expression element)
{
element = element.Resolve (ec);
// We use this to store all the date values in the order in which we
// will need to store them in the byte blob later
//
- array_data = new ArrayList ();
+ array_data = new List<Expression> ();
bounds = new System.Collections.Specialized.HybridDictionary ();
if (arguments != null)
byte [] element;
int count = array_data.Count;
- if (TypeManager.IsEnumType (array_element_type))
- array_element_type = TypeManager.GetEnumUnderlyingType (array_element_type);
-
- factor = GetTypeSize (array_element_type);
+ Type element_type = array_element_type;
+ if (TypeManager.IsEnumType (element_type))
+ element_type = TypeManager.GetEnumUnderlyingType (element_type);
+
+ factor = GetTypeSize (element_type);
if (factor == 0)
- throw new Exception ("unrecognized type in MakeByteBlob: " + array_element_type);
+ throw new Exception ("unrecognized type in MakeByteBlob: " + element_type);
data = new byte [(count * factor + 3) & ~3];
int idx = 0;
continue;
}
- if (array_element_type == TypeManager.int64_type){
+ if (element_type == TypeManager.int64_type){
if (!(v is Expression)){
long val = (long) v;
val = (val >> 8);
}
}
- } else if (array_element_type == TypeManager.uint64_type){
+ } else if (element_type == TypeManager.uint64_type){
if (!(v is Expression)){
ulong val = (ulong) v;
val = (val >> 8);
}
}
- } else if (array_element_type == TypeManager.float_type) {
+ } else if (element_type == TypeManager.float_type) {
if (!(v is Expression)){
element = BitConverter.GetBytes ((float) v);
if (!BitConverter.IsLittleEndian)
System.Array.Reverse (data, idx, 4);
}
- } else if (array_element_type == TypeManager.double_type) {
+ } else if (element_type == TypeManager.double_type) {
if (!(v is Expression)){
element = BitConverter.GetBytes ((double) v);
if (!BitConverter.IsLittleEndian)
System.Array.Reverse (data, idx, 8);
}
- } else if (array_element_type == TypeManager.char_type){
+ } else if (element_type == TypeManager.char_type){
if (!(v is Expression)){
int val = (int) ((char) v);
data [idx] = (byte) (val & 0xff);
data [idx+1] = (byte) (val >> 8);
}
- } else if (array_element_type == TypeManager.short_type){
+ } else if (element_type == TypeManager.short_type){
if (!(v is Expression)){
int val = (int) ((short) v);
data [idx] = (byte) (val & 0xff);
data [idx+1] = (byte) (val >> 8);
}
- } else if (array_element_type == TypeManager.ushort_type){
+ } else if (element_type == TypeManager.ushort_type){
if (!(v is Expression)){
int val = (int) ((ushort) v);
data [idx] = (byte) (val & 0xff);
data [idx+1] = (byte) (val >> 8);
}
- } else if (array_element_type == TypeManager.int32_type) {
+ } else if (element_type == TypeManager.int32_type) {
if (!(v is Expression)){
int val = (int) v;
data [idx+2] = (byte) ((val >> 16) & 0xff);
data [idx+3] = (byte) (val >> 24);
}
- } else if (array_element_type == TypeManager.uint32_type) {
+ } else if (element_type == TypeManager.uint32_type) {
if (!(v is Expression)){
uint val = (uint) v;
data [idx+2] = (byte) ((val >> 16) & 0xff);
data [idx+3] = (byte) (val >> 24);
}
- } else if (array_element_type == TypeManager.sbyte_type) {
+ } else if (element_type == TypeManager.sbyte_type) {
if (!(v is Expression)){
sbyte val = (sbyte) v;
data [idx] = (byte) val;
}
- } else if (array_element_type == TypeManager.byte_type) {
+ } else if (element_type == TypeManager.byte_type) {
if (!(v is Expression)){
byte val = (byte) v;
data [idx] = (byte) val;
}
- } else if (array_element_type == TypeManager.bool_type) {
+ } else if (element_type == TypeManager.bool_type) {
if (!(v is Expression)){
bool val = (bool) v;
data [idx] = (byte) (val ? 1 : 0);
}
- } else if (array_element_type == TypeManager.decimal_type){
+ } else if (element_type == TypeManager.decimal_type){
if (!(v is Expression)){
int [] bits = Decimal.GetBits ((decimal) v);
int p = idx;
data [p++] = (byte) (nbits [j] >> 24);
}
}
- } else
- throw new Exception ("Unrecognized type in MakeByteBlob: " + array_element_type);
+ } else {
+ throw new Exception ("Unrecognized type in MakeByteBlob: " + element_type);
+ }
- idx += factor;
+ idx += factor;
}
return data;
}
+#if NET_4_0
+ public override SLE.Expression MakeExpression (BuilderContext ctx)
+ {
+ var initializers = new SLE.Expression [array_data.Count];
+ for (var i = 0; i < initializers.Length; i++) {
+ if (array_data [i] == null)
+ initializers [i] = SLE.Expression.Default (array_element_type);
+ else
+ initializers [i] = array_data [i].MakeExpression (ctx);
+ }
+
+ return SLE.Expression.NewArrayInit (array_element_type, initializers);
+ }
+#endif
+
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
array_element_type = storey.MutateType (array_element_type);
// the static initializer will initialize at least 25% of array values.
// NOTE: const_initializers_count does not contain default constant values.
if (const_initializers_count >= 4 && const_initializers_count * 4 > (array_data.Count) &&
- TypeManager.IsPrimitiveType (array_element_type)) {
+ (TypeManager.IsPrimitiveType (array_element_type) || TypeManager.IsEnumType (array_element_type))) {
EmitStaticInitializers (ec);
if (!only_constant_initializers)
public override void Emit (EmitContext ec)
{
- int size = GetTypeSize (type_queried);
-
- if (size == 0)
- ec.ig.Emit (OpCodes.Sizeof, type_queried);
- else
- IntConstant.EmitInt (ec.ig, size);
+ ec.ig.Emit (OpCodes.Sizeof, type_queried);
}
protected override void CloneTo (CloneContext clonectx, Expression t)
if (expr_type == null)
return;
- Namespace.Error_TypeArgumentsCannotBeUsed (expr_type, loc);
+ expr_type.Error_TypeArgumentsCannotBeUsed (rc.Compiler.Report, loc);
return;
}
/// <summary>
/// Implements array access
/// </summary>
- public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
+ public class ArrayAccess : Expression, IDynamicAssign, IMemoryLocation {
//
// Points to our "data" repository
//
} else if (TypeManager.IsStruct (type)){
ig.Emit (OpCodes.Ldelema, type);
ig.Emit (OpCodes.Ldobj, type);
-#if GMCS_SOURCE
} else if (type.IsGenericParameter) {
ig.Emit (OpCodes.Ldelem, type);
-#endif
} else if (type.IsPointer)
ig.Emit (OpCodes.Ldelem_I);
else
has_type_arg = true;
is_stobj = true;
return OpCodes.Stobj;
-#if GMCS_SOURCE
} else if (t.IsGenericParameter) {
has_type_arg = true;
return OpCodes.Stelem;
-#endif
-
} else if (t.IsPointer)
return OpCodes.Stelem_I;
else
}
}
+#if NET_4_0
+ public SLE.Expression MakeAssignExpression (BuilderContext ctx)
+ {
+ return SLE.Expression.ArrayAccess (
+ ea.Expr.MakeExpression (ctx),
+ Arguments.MakeExpression (ea.Arguments, ctx));
+ }
+
+ public override SLE.Expression MakeExpression (BuilderContext ctx)
+ {
+ return SLE.Expression.ArrayIndex (
+ ea.Expr.MakeExpression (ctx),
+ Arguments.MakeExpression (ea.Arguments, ctx));
+ }
+#endif
+
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
type = storey.MutateType (type);
/// <summary>
/// Expressions that represent an indexer call.
/// </summary>
- public class IndexerAccess : Expression, IAssignMethod
+ public class IndexerAccess : Expression, IDynamicAssign
{
class IndexerMethodGroupExpr : MethodGroupExpr
{
eclass = ExprClass.IndexerAccess;
return this;
}
+
+ public override void Emit (EmitContext ec)
+ {
+ Emit (ec, false);
+ }
public void Emit (EmitContext ec, bool leave_copy)
{
}
}
- public override void Emit (EmitContext ec)
+ public override string GetSignatureForError ()
{
- Emit (ec, false);
+ return TypeManager.CSharpSignature (get != null ? get : set, false);
}
- public override string GetSignatureForError ()
+#if NET_4_0
+ public SLE.Expression MakeAssignExpression (BuilderContext ctx)
{
- return TypeManager.CSharpSignature (get != null ? get : set, false);
+ var value = new[] { set_expr.MakeExpression (ctx) };
+ var args = Arguments.MakeExpression (arguments, ctx).Concat (value);
+
+ return SLE.Expression.Block (
+ SLE.Expression.Call (instance_expr.MakeExpression (ctx), set, args),
+ value [0]);
+ }
+
+ public override SLE.Expression MakeExpression (BuilderContext ctx)
+ {
+ var args = Arguments.MakeExpression (arguments, ctx);
+ return SLE.Expression.Call (instance_expr.MakeExpression (ctx), get, args);
}
+#endif
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
public class ArrayIndexCast : TypeCast
{
public ArrayIndexCast (Expression expr)
- : base (expr, expr.Type)
+ : base (expr, TypeManager.int32_type)
{
- if (type == TypeManager.int32_type)
- throw new ArgumentException ("unnecessary conversion");
+ if (expr.Type == TypeManager.int32_type)
+ throw new ArgumentException ("unnecessary array index conversion");
}
public override Expression CreateExpressionTree (ResolveContext ec)
{
- Arguments args = new Arguments (2);
- args.Add (new Argument (child.CreateExpressionTree (ec)));
- args.Add (new Argument (new TypeOf (new TypeExpression (TypeManager.int32_type, loc), loc)));
- return CreateExpressionFactoryCall (ec, "ConvertChecked", args);
+ using (ec.Set (ResolveContext.Options.CheckedScope)) {
+ return base.CreateExpressionTree (ec);
+ }
}
public override void Emit (EmitContext ec)
{
child.Emit (ec);
- if (type == TypeManager.uint32_type)
+ var expr_type = child.Type;
+
+ if (expr_type == TypeManager.uint32_type)
ec.ig.Emit (OpCodes.Conv_U);
- else if (type == TypeManager.int64_type)
+ else if (expr_type == TypeManager.int64_type)
ec.ig.Emit (OpCodes.Conv_Ovf_I);
- else if (type == TypeManager.uint64_type)
+ else if (expr_type == TypeManager.uint64_type)
ec.ig.Emit (OpCodes.Conv_Ovf_I_Un);
else
throw new InternalErrorException ("Cannot emit cast to unknown array element type", type);
Constant c = count as Constant;
if (c != null && c.IsNegative) {
ec.Report.Error (247, loc, "Cannot use a negative size with stackalloc");
- return null;
}
if (ec.HasAny (ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope)) {
AnonymousTypeClass CreateAnonymousType (ResolveContext ec, ArrayList parameters)
{
- AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters);
+ AnonymousTypeClass type = parent.Module.Compiled.GetAnonymousType (parameters);
if (type != null)
return type;
if (ec.Report.Errors == 0)
type.CloseType ();
- parent.Module.AddAnonymousType (type);
+ parent.Module.Compiled.AddAnonymousType (type);
return type;
}