// end of the code generated for EmitAssign
//
void Emit (EmitContext ec, bool leave_copy);
// end of the code generated for EmitAssign
//
void Emit (EmitContext ec, bool leave_copy);
// for expressions like a [f ()] ++, where you can't call `f ()' twice.
//
void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load);
// for expressions like a [f ()] ++, where you can't call `f ()' twice.
//
void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load);
/*
For simple assignments, this interface is very simple, EmitAssign is called with source
as the source expression and leave_copy and prepare_for_load false.
/*
For simple assignments, this interface is very simple, EmitAssign is called with source
as the source expression and leave_copy and prepare_for_load false.
EmitAssign will be called as before, however, prepare_for_load will be
true. The @source expression will contain an expression
which calls Emit. So, the calls look like:
EmitAssign will be called as before, however, prepare_for_load will be
true. The @source expression will contain an expression
which calls Emit. So, the calls look like:
this.EmitAssign (ec, source, false, true) ->
source.Emit (ec); ->
[...] ->
this.EmitAssign (ec, source, false, true) ->
source.Emit (ec); ->
[...] ->
end [...]
end source.Emit (ec);
end this.EmitAssign (ec, source, false, true)
end [...]
end source.Emit (ec);
end this.EmitAssign (ec, source, false, true)
When prepare_for_load is true, EmitAssign emits a `token' on the stack that
Emit will use for its state.
When prepare_for_load is true, EmitAssign emits a `token' on the stack that
Emit will use for its state.
this.EmitAssign (ec, source, false, true)
call f
dup
this.EmitAssign (ec, source, false, true)
call f
dup
stfld
end this.EmitAssign (ec, source, false, true)
stfld
end this.EmitAssign (ec, source, false, true)
leave_copy (in both EmitAssign and Emit) tells the compiler to leave a copy
of the expression at that point in evaluation. This is used for pre/post inc/dec
and for a = x += y. Let's do the above example with leave_copy true in EmitAssign
leave_copy (in both EmitAssign and Emit) tells the compiler to leave a copy
of the expression at that point in evaluation. This is used for pre/post inc/dec
and for a = x += y. Let's do the above example with leave_copy true in EmitAssign
this.EmitAssign (ec, source, true, true)
call f
dup
this.EmitAssign (ec, source, true, true)
call f
dup
dup
stloc temp
stfld
ldloc temp
end this.EmitAssign (ec, source, true, true)
dup
stloc temp
stfld
ldloc temp
end this.EmitAssign (ec, source, true, true)
this.EmitAssign (ec, source, false, true)
call f
dup
this.EmitAssign (ec, source, false, true)
call f
dup
stfld
ldloc temp
end this.EmitAssign (ec, source, false, true)
stfld
ldloc temp
end this.EmitAssign (ec, source, false, true)
/// code to access this value, return its address or save its value.
///
/// If `is_address' is true, then the value that we store is the address to the
/// code to access this value, return its address or save its value.
///
/// If `is_address' is true, then the value that we store is the address to the
///
/// This is needed for a value type, because otherwise you just end up making a
/// copy of the value on the stack and modifying it. You really need a pointer
///
/// This is needed for a value type, because otherwise you just end up making a
/// copy of the value on the stack and modifying it. You really need a pointer
-
- public LocalTemporary (EmitContext ec, Type t) : this (ec, t, false) {}
-
- public LocalTemporary (EmitContext ec, Type t, bool is_address)
+
+ public LocalTemporary (Type t) : this (t, false) {}
+
+ public LocalTemporary (Type t, bool is_address)
ig.Emit (OpCodes.Ldloc, builder);
// we need to copy from the pointer
if (is_address)
ig.Emit (OpCodes.Ldloc, builder);
// we need to copy from the pointer
if (is_address)
ig.Emit (OpCodes.Stloc, builder);
}
public void AddressOf (EmitContext ec, AddressOp mode)
{
ig.Emit (OpCodes.Stloc, builder);
}
public void AddressOf (EmitContext ec, AddressOp mode)
{
// if is_address, than this is just the address anyways,
// so we just return this.
ILGenerator ig = ec.ig;
// if is_address, than this is just the address anyways,
// so we just return this.
ILGenerator ig = ec.ig;
/// </summary>
public class Assign : ExpressionStatement {
protected Expression target, source, real_source;
/// </summary>
public class Assign : ExpressionStatement {
protected Expression target, source, real_source;
Report.Warning (1717, 3, loc, "Assignment made to same variable; did you mean to assign something else?");
}
Report.Warning (1717, 3, loc, "Assignment made to same variable; did you mean to assign something else?");
}
// to this Type and so, according to the spec
// is allowed to only appear on the left hand of
// the += and -= operators
// to this Type and so, according to the spec
// is allowed to only appear on the left hand of
// the += and -= operators
// in the case it is being referenced within the same type container;
// it will appear as a FieldExpr in that case.
//
// in the case it is being referenced within the same type container;
// it will appear as a FieldExpr in that case.
//
if (!(target is IAssignMethod) && (target.eclass != ExprClass.EventAccess)) {
Report.Error (131, loc,
"Left hand of an assignment must be a variable, " +
if (!(target is IAssignMethod) && (target.eclass != ExprClass.EventAccess)) {
Report.Error (131, loc,
"Left hand of an assignment must be a variable, " +
if (source is New && target_type.IsValueType &&
(target.eclass != ExprClass.IndexerAccess) && (target.eclass != ExprClass.PropertyAccess)){
New n = (New) source;
if (source is New && target_type.IsValueType &&
(target.eclass != ExprClass.IndexerAccess) && (target.eclass != ExprClass.PropertyAccess)){
New n = (New) source;
//
// If this assignment/operator was part of a compound binary
// operator, then we allow an explicit conversion, as detailed
//
// If this assignment/operator was part of a compound binary
// operator, then we allow an explicit conversion, as detailed
source = Convert.ExplicitConversion (ec, source, target_type, loc);
if (source == null){
a.original_source.Error_ValueCannotBeConverted (loc, target_type, true);
return null;
}
source = Convert.ExplicitConversion (ec, source, target_type, loc);
if (source == null){
a.original_source.Error_ValueCannotBeConverted (loc, target_type, true);
return null;
}
}
source = Convert.ImplicitConversionRequired (ec, source, target_type, loc);
}
source = Convert.ImplicitConversionRequired (ec, source, target_type, loc);
temp_source = source;
am.EmitAssign (ec, temp_source, !is_statement, this is CompoundAssign);
temp_source = source;
am.EmitAssign (ec, temp_source, !is_statement, this is CompoundAssign);
public CompoundAssign (Binary.Operator op, Expression target, Expression source)
: base (target, source, target.Location)
{
public CompoundAssign (Binary.Operator op, Expression target, Expression source)
: base (target, source, target.Location)
{
//
// Only now we can decouple the original source/target
// into a tree, to guarantee that we do not have side
//
// Only now we can decouple the original source/target
// into a tree, to guarantee that we do not have side