/// </summary>
/// <remarks>
/// The LocalTemporary class is used to hold temporary values of a given
- /// type to "simulate" the expression semantics on property and indexer
- /// access whose return values are void.
+ /// type to "simulate" the expression semantics. The local variable is
+ /// never captured.
///
/// The local temporary is used to alter the normal flow of code generation
/// basically it creates a local variable, and its emit instruction generates
public class LocalTemporary : Expression, IMemoryLocation, IAssignMethod {
LocalBuilder builder;
- public LocalTemporary (Type t)
+ public LocalTemporary (TypeSpec t)
{
type = t;
eclass = ExprClass.Value;
}
- public LocalTemporary (LocalBuilder b, Type t)
+ public LocalTemporary (LocalBuilder b, TypeSpec t)
: this (t)
{
builder = b;
public override void Emit (EmitContext ec)
{
- ILGenerator ig = ec.ig;
-
if (builder == null)
throw new InternalErrorException ("Emit without Store, or after Release");
- ig.Emit (OpCodes.Ldloc, builder);
+ ec.Emit (OpCodes.Ldloc, builder);
}
#region IAssignMethod Members
public void Store (EmitContext ec)
{
- ILGenerator ig = ec.ig;
if (builder == null)
builder = ec.GetTemporaryLocal (type);
- ig.Emit (OpCodes.Stloc, builder);
+ ec.Emit (OpCodes.Stloc, builder);
}
public void AddressOf (EmitContext ec, AddressOp mode)
if (builder == null)
builder = ec.GetTemporaryLocal (type);
- ILGenerator ig = ec.ig;
-
if (builder.LocalType.IsByRef) {
//
// if is_address, than this is just the address anyways,
// so we just return this.
//
- ig.Emit (OpCodes.Ldloc, builder);
+ ec.Emit (OpCodes.Ldloc, builder);
} else {
- ig.Emit (OpCodes.Ldloca, builder);
+ ec.Emit (OpCodes.Ldloca, builder);
}
}
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- type = storey.MutateType (type);
- }
}
/// <summary>
if (target == null || !ok)
return null;
- Type target_type = target.Type;
- Type source_type = source.Type;
+ TypeSpec target_type = target.Type;
+ TypeSpec source_type = source.Type;
eclass = ExprClass.Value;
type = target_type;
return null;
}
- if ((RootContext.Version == LanguageVersion.ISO_1) &&
- (source is MethodGroupExpr)){
- ((MethodGroupExpr) source).ReportUsageError (ec);
- return null;
- }
-
- if (!TypeManager.IsEqual (target_type, source_type)) {
+ if (target_type != source_type) {
Expression resolved = ResolveConversions (ec);
if (resolved != this)
if (tassign == null)
throw new InternalErrorException (target.GetType () + " does not support dynamic assignment");
- var target_object = tassign.MakeAssignExpression (ctx);
+ var target_object = tassign.MakeAssignExpression (ctx, source);
//
// Some hacking is needed as DLR does not support void type and requires
return System.Linq.Expressions.Expression.Assign (target_object, source_object);
}
#endif
-
- public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- source.MutateHoistedGenericType (storey);
- target.MutateHoistedGenericType (storey);
- type = storey.MutateType (type);
- }
-
protected virtual Expression ResolveConversions (ResolveContext ec)
{
source = Convert.ImplicitConversionRequired (ec, source, target.Type, loc);
ExpressionStatement resolved;
IMemberContext rc;
- public FieldInitializer (FieldBuilder field, Expression expression, IMemberContext rc)
- : base (new FieldExpr (field, expression.Location), expression, expression.Location)
+ public FieldInitializer (FieldSpec spec, Expression expression, IMemberContext rc)
+ : base (new FieldExpr (spec, expression.Location), expression, expression.Location)
{
this.rc = rc;
- if (!field.IsStatic)
+ if (!spec.IsStatic)
((FieldExpr)target).InstanceExpression = CompilerGeneratedThis.Instance;
}
}
}
- class EventAddOrRemove : ExpressionStatement {
- EventExpr target;
- Binary.Operator op;
- Expression source;
-
- public EventAddOrRemove (Expression target, Binary.Operator op, Expression source, Location loc)
- {
- this.target = target as EventExpr;
- this.op = op;
- this.source = source;
- this.loc = loc;
- }
-
- public override Expression CreateExpressionTree (ResolveContext ec)
- {
- return new SimpleAssign (target, source).CreateExpressionTree (ec);
- }
-
- protected override Expression DoResolve (ResolveContext ec)
- {
- if (op != Binary.Operator.Addition && op != Binary.Operator.Subtraction)
- target.Error_AssignmentEventOnly (ec);
-
- source = source.Resolve (ec);
- if (source == null)
- return null;
-
- source = Convert.ImplicitConversionRequired (ec, source, target.Type, loc);
- if (source == null)
- return null;
-
- eclass = ExprClass.Value;
- type = TypeManager.void_type;
- return this;
- }
-
- public override void Emit (EmitContext ec)
- {
- if (RootContext.EvalMode)
- EmitStatement (ec);
- else
- throw new InternalErrorException ("don't know what to emit");
- }
-
- public override void EmitStatement (EmitContext ec)
- {
- target.EmitAddOrRemove (ec, op == Binary.Operator.Addition, source);
- }
- }
-
//
// This class is used for compound assignments.
//
Expression right;
Expression left;
- public CompoundAssign (Binary.Operator op, Expression target, Expression source)
- : base (target, source, target.Location)
+ public CompoundAssign (Binary.Operator op, Expression target, Expression source, Location loc)
+ : base (target, source, loc)
{
right = source;
this.op = op;
}
- public CompoundAssign (Binary.Operator op, Expression target, Expression source, Expression left)
- : this (op, target, source)
+ public CompoundAssign (Binary.Operator op, Expression target, Expression source, Expression left, Location loc)
+ : this (op, target, source, loc)
{
this.left = left;
}
return null;
}
- if (target is EventExpr)
- return new EventAddOrRemove (target, op, right, loc).Resolve (ec);
+ var event_expr = target as EventExpr;
+ if (event_expr != null) {
+ source = Convert.ImplicitConversionRequired (ec, right, target.Type, loc);
+ if (source == null)
+ return null;
+
+ Expression rside;
+ if (op == Binary.Operator.Addition)
+ rside = EmptyExpression.EventAddition;
+ else if (op == Binary.Operator.Subtraction)
+ rside = EmptyExpression.EventSubtraction;
+ else
+ rside = null;
+
+ target = target.ResolveLValue (ec, rside);
+ if (target == null)
+ return null;
+
+ eclass = ExprClass.Value;
+ type = event_expr.Operator.ReturnType;
+ return this;
+ }
//
// Only now we can decouple the original source/target
if (left == null)
left = new TargetExpression (target);
- source = new Binary (op, left, right, true);
+ source = new Binary (op, left, right, true, loc);
if (target is DynamicMemberBinder) {
Arguments targs = ((DynamicMemberBinder) target).Arguments;
protected override Expression ResolveConversions (ResolveContext ec)
{
- Type target_type = target.Type;
+ TypeSpec target_type = target.Type;
//
// 1. the return type is implicitly convertible to the type of target
}
}
- if (TypeManager.IsDynamicType (source.Type)) {
+ if (source.Type == InternalType.Dynamic) {
Arguments arg = new Arguments (1);
arg.Add (new Argument (source));
return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec);