using System;
using System.Reflection;
using System.Reflection.Emit;
-using System.Collections;
namespace Mono.CSharp {
/// Does not happen with a class because a class is a pointer -- so you always
/// get the indirection.
///
- /// The `is_address' stuff is really just a hack. We need to come up with a better
- /// way to handle it.
/// </remarks>
public class LocalTemporary : Expression, IMemoryLocation, IAssignMethod {
LocalBuilder builder;
- bool is_address;
- public LocalTemporary (Type t) : this (t, false) {}
-
- public LocalTemporary (Type t, bool is_address)
+ public LocalTemporary (Type t)
{
type = t;
eclass = ExprClass.Value;
- this.is_address = is_address;
}
public LocalTemporary (LocalBuilder b, Type t)
+ : this (t)
{
- type = t;
- eclass = ExprClass.Value;
- loc = Location.Null;
builder = b;
}
return CreateExpressionFactoryCall (ec, "Constant", args);
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
return this;
}
throw new InternalErrorException ("Emit without Store, or after Release");
ig.Emit (OpCodes.Ldloc, builder);
- // we need to copy from the pointer
- if (is_address)
- LoadFromPtr (ig, type);
}
#region IAssignMethod Members
get { return builder; }
}
- // NB: if you have `is_address' on the stack there must
- // be a managed pointer. Otherwise, it is the type from
- // the ctor.
public void Store (EmitContext ec)
{
ILGenerator ig = ec.ig;
if (builder == null)
- builder = ec.GetTemporaryLocal (is_address ? TypeManager.GetReferenceType (type): type);
+ builder = ec.GetTemporaryLocal (type);
ig.Emit (OpCodes.Stloc, builder);
}
public void AddressOf (EmitContext ec, AddressOp mode)
{
if (builder == null)
- builder = ec.GetTemporaryLocal (is_address ? TypeManager.GetReferenceType (type): type);
+ builder = ec.GetTemporaryLocal (type);
- // if is_address, than this is just the address anyways,
- // so we just return this.
ILGenerator ig = ec.ig;
- if (is_address)
+ if (builder.LocalType.IsByRef) {
+ //
+ // if is_address, than this is just the address anyways,
+ // so we just return this.
+ //
ig.Emit (OpCodes.Ldloc, builder);
- else
+ } else {
ig.Emit (OpCodes.Ldloca, builder);
+ }
}
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
type = storey.MutateType (type);
}
-
- public bool PointsToAddress {
- get {
- return is_address;
- }
- }
}
/// <summary>
get { return source; }
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
bool ok = true;
source = source.Resolve (ec);
return null;
}
- if ((RootContext.Version == LanguageVersion.ISO_1) &&
- (source is MethodGroupExpr)){
+ if ((RootContext.Version == LanguageVersion.ISO_1) && (source is MethodGroupExpr)){
((MethodGroupExpr) source).ReportUsageError (ec);
return null;
}
return this;
}
+#if NET_4_0
+ public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
+ {
+ var tassign = target as IDynamicAssign;
+ if (tassign == null)
+ throw new InternalErrorException (target.GetType () + " does not support dynamic assignment");
+
+ var target_object = tassign.MakeAssignExpression (ctx);
+
+ //
+ // Some hacking is needed as DLR does not support void type and requires
+ // always have object convertible return type to support caching and chaining
+ //
+ // We do this by introducing an explicit block which returns RHS value when
+ // available or null
+ //
+ if (target_object.NodeType == System.Linq.Expressions.ExpressionType.Block)
+ return target_object;
+
+ var source_object = System.Linq.Expressions.Expression.Convert (source.MakeExpression (ctx), target_object.Type);
+ return System.Linq.Expressions.Expression.Assign (target_object, source_object);
+ }
+#endif
+
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
{
source.MutateHoistedGenericType (storey);
}
}
- class SimpleAssign : Assign {
+ public class SimpleAssign : Assign {
public SimpleAssign (Expression target, Expression source)
: this (target, source, target.Location)
{
return t.Equals (source);
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
Expression e = base.DoResolve (ec);
if (e == null || e != this)
ExpressionStatement resolved;
IMemberContext rc;
- public FieldInitializer (FieldBuilder field, Expression expression, IMemberContext rc)
+ public FieldInitializer (FieldBase field, Expression expression, IMemberContext rc)
: base (new FieldExpr (field, expression.Location), expression, expression.Location)
{
this.rc = rc;
((FieldExpr)target).InstanceExpression = CompilerGeneratedThis.Instance;
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
// Field initializer can be resolved (fail) many times
if (source == null)
if (resolved == null) {
//
// Field initializers are tricky for partial classes. They have to
- // share same costructor (block) but they have they own resolve scope.
+ // share same constructor (block) but they have they own resolve scope.
//
IMemberContext old = ec.MemberContext;
return new SimpleAssign (target, source).CreateExpressionTree (ec);
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
if (op != Binary.Operator.Addition && op != Binary.Operator.Subtraction)
target.Error_AssignmentEventOnly (ec);
throw new NotSupportedException ("ET");
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
type = child.Type;
eclass = ExprClass.Value;
this.left = left;
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
right = right.Resolve (ec);
if (right == null)
}
if (target is EventExpr)
- return new EventAddOrRemove (target, op, right, loc).DoResolve (ec);
+ return new EventAddOrRemove (target, op, right, loc).Resolve (ec);
//
// Only now we can decouple the original source/target
source = new Binary (op, left, right, true);
- // TODO: TargetExpression breaks MemberAccess composition
if (target is DynamicMemberBinder) {
Arguments targs = ((DynamicMemberBinder) target).Arguments;
source = source.Resolve (ec);
Arguments args = new Arguments (2);
args.AddRange (targs);
args.Add (new Argument (source));
- source = new DynamicMemberBinder (true, ma.Name, args, loc).Resolve (ec);
+ source = new DynamicMemberBinder (ma.Name, args, loc).ResolveLValue (ec, right);
// Handles possible event addition/subtraction
if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) {
string method_prefix = op == Binary.Operator.Addition ?
Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix;
- Expression invoke = new DynamicInvocation (
+ var invoke = DynamicInvocation.CreateSpecialNameInvoke (
new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec);
args = new Arguments (1);
return base.DoResolve (ec);
}
-#if NET_4_0
- public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
- {
- var target_object = target.MakeExpression (ctx);
- var source_object = System.Linq.Expressions.Expression.Convert (source.MakeExpression (ctx), target_object.Type);
- return System.Linq.Expressions.Expression.Assign (target_object, source_object);
- }
-#endif
-
protected override Expression ResolveConversions (ResolveContext ec)
{
Type target_type = target.Type;
}
}
+ if (TypeManager.IsDynamicType (source.Type)) {
+ 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);
+ }
+
right.Error_ValueCannotBeConverted (ec, loc, target_type, false);
return null;
}