Expression ResolveAddressOf (ResolveContext ec)
{
- if (!ec.IsUnsafe)
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, loc);
+ } else if (!ec.IsUnsafe) {
UnsafeError (ec, loc);
+ }
Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
if (Expr == null || Expr.eclass != ExprClass.Variable) {
is_fixed = vr.IsFixed;
vr.SetHasAddressTaken ();
- if (vr.IsHoisted) {
+ if (vr.IsHoisted && ec.CurrentIterator == null) {
AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, vr, loc);
}
} else {
if (expr == null)
return null;
- if (!ec.IsUnsafe)
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, loc);
+ } else if (!ec.IsUnsafe) {
UnsafeError (ec, loc);
+ }
var pc = expr.Type as PointerContainer;
expr.EmitSideEffect (ec);
}
+ public override void EmitPrepare (EmitContext ec)
+ {
+ expr.EmitPrepare (ec);
+ }
+
public override void FlowAnalysis (FlowAnalysisContext fc)
{
expr.FlowAnalysis (fc);
public override Expression CreateExpressionTree (ResolveContext ec)
{
if (Variable != null)
- throw new NotSupportedException ();
+ ec.Report.Error (8122, loc, "An expression tree cannot contain a pattern matching operator");
Arguments args = Arguments.CreateForExpressionTree (ec, null,
expr.CreateExpressionTree (ec),
ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
}
+ public override void EmitPrepare (EmitContext ec)
+ {
+ base.EmitPrepare (ec);
+
+ if (Variable != null)
+ Variable.CreateBuilder (ec);
+ }
+
void EmitPatternMatch (EmitContext ec)
{
var no_match = ec.DefineLabel ();
ec.Emit (OpCodes.Dup);
no_value_label = ec.DefineLabel ();
ec.Emit (OpCodes.Brfalse_S, no_value_label);
+
+ if (Variable.HoistedVariant != null)
+ ec.EmitThis ();
+
expr_unwrap.Emit (ec);
} else {
+ if (Variable?.HoistedVariant != null)
+ ec.EmitThis ();
+
expr.Emit (ec);
// Only to make verifier happy
value_on_stack = false;
}
- Variable.CreateBuilder (ec);
- Variable.EmitAssign (ec);
+ if (Variable.HoistedVariant != null) {
+ Variable.HoistedVariant.EmitAssignFromStack (ec);
+
+ if (expr_unwrap != null) {
+ ec.MarkLabel (no_value_label);
+ } else if (!value_on_stack) {
+ Variable.HoistedVariant.Emit (ec);
+ }
+ } else {
+ //
+ // It's ok to have variable builder created out of order. It simplifies emit
+ // of statements like while (condition) { }
+ //
+ if (!Variable.Created)
+ Variable.CreateBuilder (ec);
+
+ Variable.EmitAssign (ec);
- if (expr_unwrap != null) {
- ec.MarkLabel (no_value_label);
- } else if (!value_on_stack) {
- Variable.Emit (ec);
+ if (expr_unwrap != null) {
+ ec.MarkLabel (no_value_label);
+ } else if (!value_on_stack) {
+ Variable.Emit (ec);
+ }
}
}
}
fc.SetVariableAssigned (Variable.VariableInfo, true);
}
+ public override void FlowAnalysisConditional (FlowAnalysisContext fc)
+ {
+ if (Variable == null) {
+ base.FlowAnalysisConditional (fc);
+ return;
+ }
+
+ expr.FlowAnalysis (fc);
+
+ fc.DefiniteAssignmentOnTrue = fc.BranchDefiniteAssignment ();
+ fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+
+ fc.SetVariableAssigned (Variable.VariableInfo, fc.DefiniteAssignmentOnTrue);
+ }
+
protected override void ResolveProbeType (ResolveContext rc)
{
if (!(ProbeType is TypeExpr) && rc.Module.Compiler.Settings.Version == LanguageVersion.Experimental) {
Expression ResolveResultExpression (ResolveContext ec)
{
+ if (Variable != null) {
+ if (expr is NullLiteral) {
+ ec.Report.Error (8117, loc, "Cannot use null as pattern matching operand");
+ return this;
+ }
+
+ CheckExpressionVariable (ec);
+ }
+
TypeSpec d = expr.Type;
bool d_is_nullable = false;
// If E is a method group or the null literal, or if the type of E is a reference
// type or a nullable type and the value of E is null, the result is false
//
- if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
+ if (expr.IsNull)
return CreateConstantResult (ec, false);
if (d.IsNullableType) {
TypeSpec t = probe_type_expr;
bool t_is_nullable = false;
if (t.IsNullableType) {
+ if (Variable != null) {
+ ec.Report.Error (8116, loc, "The nullable type `{0}' pattern matching is not allowed. Consider using underlying type `{1}'",
+ t.GetSignatureForError (), Nullable.NullableInfo.GetUnderlyingType (t).GetSignatureForError ());
+ }
+
var ut = Nullable.NullableInfo.GetUnderlyingType (t);
if (!ut.IsGenericParameter) {
t = ut;
return ResolveGenericParameter (ec, d, tps);
if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
- ec.Report.Warning (1981, 3, loc,
- "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
- OperatorName, t.GetSignatureForError ());
+ if (Variable != null) {
+ ec.Report.Error (8208, loc, "The type `{0}' pattern matching is not allowed", t.GetSignatureForError ());
+ } else {
+ ec.Report.Warning (1981, 3, loc,
+ "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
+ OperatorName, t.GetSignatureForError ());
+ }
}
if (TypeManager.IsGenericParameter (d))
eclass = ExprClass.Value;
TypeSpec etype = expr.Type;
+ if (expr is TupleLiteral && TupleLiteral.ContainsNoTypeElement (etype)) {
+ ec.Report.Error (8307, expr.Location, "The first operand of an `as' operator may not be a tuple literal without a natural type");
+ type = InternalType.ErrorType;
+ return this;
+ }
+
+ if (type == null) {
+ type = InternalType.ErrorType;
+ return this;
+ }
+
if (!TypeSpec.IsReferenceType (type) && !type.IsNullableType) {
if (TypeManager.IsGenericParameter (type)) {
ec.Report.Error (413, loc,
return null;
}
- if (type.IsPointer && !ec.IsUnsafe) {
- UnsafeError (ec, loc);
+ if (type.IsPointer) {
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, loc);
+ } else if (!ec.IsUnsafe) {
+ UnsafeError (ec, loc);
+ }
}
eclass = ExprClass.Value;
public void AddressOf (EmitContext ec, AddressOp mode)
{
- Variable.CreateBuilder (ec);
+ if (!Variable.Created)
+ Variable.CreateBuilder (ec);
if (Initializer != null) {
lvr.EmitAssign (ec, Initializer, false, false);
public override Expression CreateExpressionTree (ResolveContext rc)
{
- rc.Report.Error (8046, loc, "An expression tree cannot contain a declaration expression");
+ rc.Report.Error (8198, loc, "An expression tree cannot contain out variable declaration");
return null;
}
bool DoResolveCommon (ResolveContext rc)
{
+ CheckExpressionVariable (rc);
+
var var_expr = VariableType as VarExpr;
if (var_expr != null) {
type = InternalType.VarOutType;
{
throw new NotImplementedException ();
}
+
+ public override void EmitPrepare (EmitContext ec)
+ {
+ Variable.CreateBuilder (ec);
+ }
}
//
public override Expression ConvertResult (ResolveContext ec, Binary b)
{
if (left != null) {
- b.left = EmptyCast.Create (b.left, left);
+ b.left = Convert.UserDefinedConversion (ec, b.left, left, Convert.UserConversionRestriction.ImplicitOnly, b.loc) ?? EmptyCast.Create (b.left, left);
} else if (right != null) {
- b.right = EmptyCast.Create (b.right, right);
+ b.right = Convert.UserDefinedConversion (ec, b.right, right, Convert.UserConversionRestriction.ImplicitOnly, b.loc) ?? EmptyCast.Create (b.right, right);
}
TypeSpec r_type = ReturnType;
}
}
- static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op)
+ public static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op)
{
switch (op) {
case Operator.Addition:
return;
}
+ bool dereference = IsRef && !(source is ReferenceExpression);
New n_source = source as New;
if (n_source != null && n_source.CanEmitOptimizedLocalTarget (ec)) {
if (!n_source.Emit (ec, this)) {
if (leave_copy) {
EmitLoad (ec);
- if (IsRef)
+ if (dereference)
ec.EmitLoadFromPtr (type);
}
return;
}
} else {
- if (IsRef)
+ if (dereference)
EmitLoad (ec);
source.Emit (ec);
if (leave_copy) {
ec.Emit (OpCodes.Dup);
- if (IsRef) {
+ if (dereference) {
temp = new LocalTemporary (Type);
temp.Store (ec);
}
}
- if (IsRef)
+ if (dereference)
ec.EmitStoreFromPtr (type);
else
Variable.EmitAssign (ec);
}
public override bool IsRef {
- get { return false; }
+ get { return local_info.IsByRef; }
}
public override string Name {
AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc);
} else if (local_info.IsFixed) {
ec.Report.Error (1764, loc,
- "Cannot use fixed local `{0}' inside an anonymous method, lambda expression or query expression",
+ "Cannot use fixed variable `{0}' inside an anonymous method, lambda expression or query expression",
+ GetSignatureForError ());
+ } else if (local_info.IsByRef) {
+ ec.Report.Error (8175, loc,
+ "Cannot use by-reference variable `{0}' inside an anonymous method, lambda expression, or query expression",
GetSignatureForError ());
}
protected override Expression DoResolve (ResolveContext rc)
{
ResolveConditionalAccessReceiver (rc);
- return DoResolveInvocation (rc);
+ return DoResolveInvocation (rc, null);
+ }
+
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+ {
+ var sn = expr as SimpleName;
+ if (sn != null && sn.Name == "var" && sn.Arity == 0 && arguments?.Count > 1) {
+ var targets = new List<Expression> (arguments.Count);
+ var variables = new List<LocalVariable> (arguments.Count);
+ foreach (var arg in arguments) {
+ var arg_sn = arg.Expr as SimpleName;
+ if (arg_sn == null || arg_sn.Arity != 0) {
+ rc.Report.Error (8199, loc, "The syntax `var (...)' as an lvalue is reserved");
+ return ErrorExpression.Instance;
+ }
+
+ var lv = new LocalVariable (rc.CurrentBlock, arg_sn.Name, arg.Expr.Location);
+ rc.CurrentBlock.AddLocalName (lv);
+ variables.Add (lv);
+
+ targets.Add (new LocalVariableReference (lv, arg_sn.Location));
+ }
+
+ var res = new TupleDeconstruct (targets, variables, right_side, loc);
+ return res.Resolve (rc);
+ }
+
+ if (right_side != null) {
+ if (eclass != ExprClass.Unresolved)
+ return this;
+
+ var res = DoResolveInvocation (rc, right_side);
+ if (res == null)
+ return null;
+
+ return res;
+ }
+
+ return base.DoResolveLValue (rc, right_side);
}
- Expression DoResolveInvocation (ResolveContext ec)
+ Expression DoResolveInvocation (ResolveContext ec, Expression rhs)
{
Expression member_expr;
var atn = expr as ATypeNameExpression;
IsSpecialMethodInvocation (ec, method, loc);
eclass = ExprClass.Value;
+
+ if (type.Kind == MemberKind.ByRef) {
+ if (rhs == null && arguments?.ContainsEmitWithAwait () == true) {
+ ec.Report.Error (8178, loc, "`await' cannot be used in an expression containing a call to `{0}' because it returns by reference",
+ GetSignatureForError ());
+ }
+
+ if (rhs != EmptyExpression.OutAccess)
+ return ByRefDereference.Create (this).Resolve (ec);
+ }
+
return this;
}
else
mg.EmitCall (ec, arguments, false);
}
-
+
+ public override void EmitPrepare (EmitContext ec)
+ {
+ mg.EmitPrepare (ec);
+
+ arguments?.EmitPrepare (ec);
+ }
+
public override void EmitStatement (EmitContext ec)
{
if (mg.IsConditionallyExcluded)
protected override Expression DoResolve (ResolveContext ec)
{
+ if (RequestedType is TupleTypeExpr) {
+ ec.Report.Error (8181, loc, "Tuple type cannot be used in an object creation expression. Use a tuple literal expression instead.");
+ }
+
type = RequestedType.ResolveAsType (ec);
if (type == null)
return null;
bool is_value_type = type.IsStructOrEnum;
VariableReference vr = target as VariableReference;
+ bool prepare_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments?.ContainsEmitWithAwait () == true;
+
if (target != null && is_value_type && (vr != null || method == null)) {
+ if (prepare_await) {
+ arguments = arguments.Emit (ec, false, true);
+ prepare_await = false;
+ }
+
target.AddressOf (ec, AddressOp.Store);
} else if (vr != null && vr.IsRef) {
vr.EmitLoad (ec);
}
if (arguments != null) {
- if (ec.HasSet (BuilderContext.Options.AsyncBody) && (arguments.Count > (this is NewInitialize ? 0 : 1)) && arguments.ContainsEmitWithAwait ())
+ if (prepare_await)
arguments = arguments.Emit (ec, false, true);
arguments.Emit (ec);
array_element_type = best_type_inference.InferredTypeArguments[0];
best_type_inference = null;
- if (array_element_type == null ||
- array_element_type == InternalType.NullLiteral || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
- arguments.Count != rank.Dimension) {
+ if (array_element_type == null || InternalType.HasNoType (array_element_type) || arguments.Count != rank.Dimension) {
ec.Report.Error (826, loc,
"The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
return null;
TypeSpec nested = null;
while (expr_type != null) {
- nested = MemberCache.FindNestedType (expr_type, Name, Arity);
+ nested = MemberCache.FindNestedType (expr_type, Name, Arity, false);
if (nested == null) {
if (expr_type == tnew_expr) {
Error_IdentifierNotFound (rc, expr_type);
}
expr_type = tnew_expr;
- nested = MemberCache.FindNestedType (expr_type, Name, Arity);
+ nested = MemberCache.FindNestedType (expr_type, Name, Arity, false);
ErrorIsInaccesible (rc, nested.GetSignatureForError (), loc);
break;
}
public void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type)
{
- var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity));
+ var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity), false);
if (nested != null) {
Error_TypeArgumentsCannotBeUsed (rc, nested, expr.Location);
}
type = ac.Element;
- if (type.IsPointer && !ec.IsUnsafe) {
- UnsafeError (ec, ea.Location);
+ if (type.IsPointer) {
+ if (ec.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec, ea.Location);
+ } else if (!ec.IsUnsafe) {
+ UnsafeError (ec, ea.Location);
+ }
}
if (conditional_access_receiver)
#region IBaseMembersProvider Members
- IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec baseType)
+ IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec type)
{
- return baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
+ var baseType = type.BaseType;
+ var members = baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
+
+ if (members == null && !type.IsInterface) {
+ var tps = queried_type as TypeParameterSpec;
+ if (tps != null)
+ members = MemberCache.FindInterfaceMembers (tps, MemberCache.IndexerNameAlias);
+ }
+
+ return members;
}
IParametersMember OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters (MemberSpec member)
if (!(ec.CurrentMemberDefinition is Field) && !TypeManager.VerifyUnmanaged (ec.Module, type, loc))
return null;
- if (!ec.IsUnsafe) {
+ var rc = ec as ResolveContext;
+ if (rc?.CurrentIterator != null) {
+ UnsafeInsideIteratorError (ec.Module.Compiler.Report, loc);
+ } else if (!ec.IsUnsafe) {
UnsafeError (ec.Module.Compiler.Report, loc);
}
}
}
+ class ReferenceTypeExpr : TypeExpr
+ {
+ FullNamedExpression element;
+
+ public ReferenceTypeExpr (FullNamedExpression element, Location loc)
+ {
+ this.element = element;
+ this.loc = loc;
+ }
+
+ public override TypeSpec ResolveAsType (IMemberContext mc, bool allowUnboundTypeArguments = false)
+ {
+ type = element.ResolveAsType (mc);
+ if (type == null)
+ return null;
+
+ eclass = ExprClass.Type;
+ type = ReferenceContainer.MakeType (mc.Module, type);
+
+ return type;
+ }
+
+ public override string GetSignatureForError ()
+ {
+ return "ref " + element.GetSignatureForError ();
+ }
+
+ public override object Accept (StructuralVisitor visitor)
+ {
+ return visitor.Visit (this);
+ }
+ }
+
class FixedBufferPtr : Expression
{
readonly Expression array;
args);
}
- protected override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext rc)
{
- Expression e = base.DoResolve (ec);
+ Expression e = base.DoResolve (rc);
if (type == null)
return null;
if (type.IsDelegate) {
- ec.Report.Error (1958, Initializers.Location,
+ rc.Report.Error (1958, Initializers.Location,
"Object and collection initializers cannot be used to instantiate a delegate");
}
- Expression previous = ec.CurrentInitializerVariable;
- ec.CurrentInitializerVariable = new InitializerTargetExpression (this);
- initializers.Resolve (ec);
- ec.CurrentInitializerVariable = previous;
+ Expression previous = rc.CurrentInitializerVariable;
+ rc.CurrentInitializerVariable = new InitializerTargetExpression (this);
+ using (rc.With (ResolveContext.Options.DontSetConditionalAccessReceiver, false)) {
+ initializers.Resolve (rc);
+ }
+ rc.CurrentInitializerVariable = previous;
dynamic = e as DynamicExpressionStatement;
if (dynamic != null)
throw new NotImplementedException ();
sf = ec.GetTemporaryField (type);
+ sf.AutomaticallyReuse = false;
sf.EmitAssign (ec, temp, false, false);
temp_target = sf;
temp.Release (ec);
temp.Release (ec);
if (sf != null)
- sf.IsAvailableForReuse = true;
-
+ sf.PrepareCleanup (ec);
+
return true;
}
int errors = ec.Report.Errors;
type.CreateContainer ();
type.DefineContainer ();
+ type.ExpandBaseInterfaces ();
type.Define ();
if ((ec.Report.Errors - errors) == 0) {
parent.Module.AddAnonymousType (type);
}
type = e.Type;
- if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
+ if (type.Kind == MemberKind.Void || InternalType.HasNoType (type) || type.IsPointer || (e is TupleLiteral && TupleLiteral.ContainsNoTypeElement (type))) {
Error_InvalidInitializer (ec, type.GetSignatureForError ());
return null;
}
return value;
}
}
+
+ class ThrowExpression : ExpressionStatement
+ {
+ Expression expr;
+
+ public ThrowExpression (Expression expr, Location loc)
+ {
+ this.expr = expr;
+ this.loc = loc;
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ var target = (ThrowExpression)t;
+ target.expr = expr.Clone (clonectx);
+ }
+
+ public override bool ContainsEmitWithAwait ()
+ {
+ return expr.ContainsEmitWithAwait ();
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext rc)
+ {
+ rc.Report.Error (8188, loc, "An expression tree cannot not contain a throw expression");
+ return expr;
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ expr = expr.Resolve (rc, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+
+ if (expr == null)
+ return null;
+
+ expr = Throw.ConvertType (rc, expr);
+
+ eclass = ExprClass.Value;
+ type = InternalType.ThrowExpr;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ EmitStatement (ec);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ expr.Emit (ec);
+
+ ec.Emit (OpCodes.Throw);
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return Reachability.CreateUnreachable ();
+ }
+ }
+
+ class ReferenceExpression : CompositeExpression
+ {
+ public ReferenceExpression (Expression expr, Location loc)
+ : base (expr)
+ {
+ this.loc = loc;
+ }
+
+ static bool CanBeByRef (Expression expr)
+ {
+ if (expr is IAssignMethod)
+ return true;
+
+ var invocation = expr as Invocation;
+ if (invocation?.Type.Kind == MemberKind.ByRef)
+ return true;
+
+ return false;
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext rc)
+ {
+ throw new NotSupportedException ("ET");
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ var res = expr.DoResolveLValue (rc, EmptyExpression.OutAccess);
+ if (res == null || !CanBeByRef (res)) {
+ if (res?.Type != InternalType.ErrorType)
+ rc.Report.Error (8156, expr.Location, "An expression cannot be used in this context because it may not be returned by reference");
+ return ErrorExpression.Instance;
+ }
+
+ type = res.Type;
+ var type_container = type as ReferenceContainer;
+ if (type_container != null)
+ type = type_container.Element;
+
+ expr = res;
+ eclass = ExprClass.Value;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ var ml = expr as IMemoryLocation;
+ if (ml != null)
+ ml.AddressOf (ec, AddressOp.LoadStore);
+ else
+ expr.Emit (ec);
+ }
+
+ public override void Error_ValueCannotBeConverted (ResolveContext rc, TypeSpec target, bool expl)
+ {
+ rc.Report.Error (8173, loc, "The expression must be of type `{0}' because it is being assigned by reference", target.GetSignatureForError ());
+ }
+ }
+
+ class ByRefDereference : CompositeExpression, IMemoryLocation, IAssignMethod
+ {
+ bool prepared;
+ LocalTemporary temporary;
+
+ private ByRefDereference (Expression expr)
+ : base (expr)
+ {
+ }
+
+ public static Expression Create (Expression expr)
+ {
+ var rc = expr.Type as ReferenceContainer;
+ if (rc == null)
+ return expr;
+
+ return new ByRefDereference (expr) {
+ type = rc.Element
+ };
+ }
+
+ public void AddressOf (EmitContext ec, AddressOp mode)
+ {
+ expr.Emit (ec);
+ }
+
+ public void Emit (EmitContext ec, bool leave_copy)
+ {
+ Emit (ec);
+ if (leave_copy) {
+ ec.Emit (OpCodes.Dup);
+ temporary = new LocalTemporary (type);
+ temporary.Store (ec);
+ }
+ }
+
+ public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound)
+ {
+ prepared = isCompound;
+
+ expr.Emit (ec);
+
+ if (isCompound)
+ ec.Emit (OpCodes.Dup);
+
+ source.Emit (ec);
+ if (leave_copy) {
+ throw new NotImplementedException ("leave_copy");
+ }
+
+ ec.EmitStoreFromPtr (type);
+
+ if (temporary != null) {
+ temporary.Emit (ec);
+ temporary.Release (ec);
+ }
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ eclass = ExprClass.Variable;
+ return this;
+ }
+
+ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+ {
+ return DoResolve (rc);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ if (!prepared)
+ base.Emit(ec);
+
+ ec.EmitLoadFromPtr (type);
+ }
+
+ public override object Accept (StructuralVisitor visitor)
+ {
+ return visitor.Visit (this);
+ }
+ }
}