//
using System;
-using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
+using System.Collections.Generic;
namespace Mono.CSharp
{
{
public enum AType : byte
{
- Ref = 1, // ref modifier used
- Out = 2, // out modifier used
- Default = 3 // argument created from default parameter value
+ None = 0,
+ Ref = 1, // ref modifier used
+ Out = 2, // out modifier used
+ Default = 3, // argument created from default parameter value
+ DynamicTypeName = 4 // System.Type argument for dynamic binding
}
public readonly AType ArgType;
this.Expr = expr;
}
- public Type Type {
+ public TypeSpec Type {
get { return Expr.Type; }
}
}
}
- public virtual Expression CreateExpressionTree (EmitContext ec)
+ public virtual Expression CreateExpressionTree (ResolveContext ec)
{
if (ArgType == AType.Default)
- Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter");
+ ec.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter");
return Expr.CreateExpressionTree (ec);
}
get { return ArgType == AType.Default; }
}
- public bool ResolveMethodGroup (EmitContext ec)
+ public bool ResolveMethodGroup (ResolveContext ec)
{
SimpleName sn = Expr as SimpleName;
if (sn != null)
return true;
}
- public void Resolve (EmitContext ec)
+ public void Resolve (ResolveContext ec)
{
if (Expr == EmptyExpression.Null)
return;
- using (ec.With (EmitContext.Flags.DoFlowAnalysis, true)) {
+ using (ec.With (ResolveContext.Options.DoFlowAnalysis, true)) {
// Verify that the argument is readable
if (ArgType != AType.Out)
Expr = Expr.Resolve (ec);
// Verify that the argument is writeable
if (Expr != null && IsByRef)
- Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess);
+ Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess.Instance);
if (Expr == null)
Expr = EmptyExpression.Null;
mode |= AddressOp.Load;
IMemoryLocation ml = (IMemoryLocation) Expr;
- ParameterReference pr = ml as ParameterReference;
-
- //
- // ParameterReferences might already be references, so we want
- // to pass just the value
- //
- if (pr != null && pr.IsRef)
- pr.EmitLoad (ec);
- else
- ml.AddressOf (ec, mode);
+ ml.AddressOf (ec, mode);
}
public Argument Clone (CloneContext clonectx)
public class NamedArgument : Argument
{
- public readonly LocatedToken Name;
+ public readonly string Name;
+ readonly Location loc;
LocalTemporary variable;
- public NamedArgument (LocatedToken name, Expression expr)
- : base (expr)
+ public NamedArgument (string name, Location loc, Expression expr)
+ : this (name, loc, expr, AType.None)
{
- Name = name;
}
- public override Expression CreateExpressionTree (EmitContext ec)
+ public NamedArgument (string name, Location loc, Expression expr, AType modifier)
+ : base (expr, modifier)
{
- Report.Error (853, Name.Location, "An expression tree cannot contain named argument");
+ this.Name = name;
+ this.loc = loc;
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext ec)
+ {
+ ec.Report.Error (853, loc, "An expression tree cannot contain named argument");
return base.CreateExpressionTree (ec);
}
public void EmitAssign (EmitContext ec)
{
- Expr.Emit (ec);
- variable = new LocalTemporary (Expr.Type);
+ var type = Expr.Type;
+ if (IsByRef) {
+ var ml = (IMemoryLocation) Expr;
+ ml.AddressOf (ec, AddressOp.Load);
+ type = ReferenceContainer.MakeType (type);
+ } else {
+ Expr.Emit (ec);
+ }
+
+ variable = new LocalTemporary (type);
variable.Store (ec);
Expr = variable;
}
- }
+ public Location Location {
+ get { return loc; }
+ }
+ }
+
public class Arguments
{
- ArrayList args; // TODO: This should really be linked list
- ArrayList reordered; // TODO: LinkedList
+ List<Argument> args;
+ List<NamedArgument> reordered;
public Arguments (int capacity)
{
- args = new ArrayList (capacity);
+ args = new List<Argument> (capacity);
}
- public int Add (Argument arg)
+ public void Add (Argument arg)
{
- return args.Add (arg);
+ args.Add (arg);
}
public void AddRange (Arguments args)
this.args.AddRange (args.args);
}
- public static Arguments CreateForExpressionTree (EmitContext ec, Arguments args, params Expression[] e)
+ public ArrayInitializer CreateDynamicBinderArguments (ResolveContext rc)
+ {
+ Location loc = Location.Null;
+ var all = new ArrayInitializer (args.Count, loc);
+
+ MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc);
+
+ foreach (Argument a in args) {
+ Arguments dargs = new Arguments (2);
+
+ // CSharpArgumentInfoFlags.None = 0
+ const string info_flags_enum = "CSharpArgumentInfoFlags";
+ Expression info_flags = new IntLiteral (0, loc);
+
+ var constant = a.Expr as Constant;
+ if (constant != null && constant.IsLiteral) {
+ info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags,
+ new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "Constant", loc), loc);
+ } else if (a.ArgType == Argument.AType.Ref) {
+ info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags,
+ new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsRef", loc), loc);
+ } else if (a.ArgType == Argument.AType.Out) {
+ info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags,
+ new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsOut", loc), loc);
+ } else if (a.ArgType == Argument.AType.DynamicTypeName) {
+ info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags,
+ new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsStaticType", loc), loc);
+ }
+
+ var arg_type = a.Expr.Type;
+
+ if (arg_type != InternalType.Dynamic) {
+ MethodGroupExpr mg = a.Expr as MethodGroupExpr;
+ if (mg != null) {
+ rc.Report.Error (1976, a.Expr.Location,
+ "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method",
+ mg.Name);
+ } else if (arg_type == InternalType.AnonymousMethod) {
+ rc.Report.Error (1977, a.Expr.Location,
+ "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast");
+ } else if (arg_type == TypeManager.void_type || arg_type == InternalType.Arglist || arg_type.IsPointer) {
+ rc.Report.Error (1978, a.Expr.Location,
+ "An expression of type `{0}' cannot be used as an argument of dynamic operation",
+ TypeManager.CSharpName (arg_type));
+ }
+
+ info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags,
+ new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc);
+ }
+
+ string named_value;
+ NamedArgument na = a as NamedArgument;
+ if (na != null) {
+ info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags,
+ new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "NamedArgument", loc), loc);
+
+ named_value = na.Name;
+ } else {
+ named_value = null;
+ }
+
+ dargs.Add (new Argument (info_flags));
+ dargs.Add (new Argument (new StringLiteral (named_value, loc)));
+ all.Add (new Invocation (new MemberAccess (new MemberAccess (binder, "CSharpArgumentInfo", loc), "Create", loc), dargs));
+ }
+
+ return all;
+ }
+
+ public static Arguments CreateForExpressionTree (ResolveContext ec, Arguments args, params Expression[] e)
{
Arguments all = new Arguments ((args == null ? 0 : args.Count) + e.Length);
for (int i = 0; i < e.Length; ++i) {
return all;
}
- public void CheckArrayAsAttribute ()
+ public void CheckArrayAsAttribute (CompilerContext ctx)
{
foreach (Argument arg in args) {
// Type is undefined (was error 246)
continue;
if (arg.Type.IsArray)
- Report.Warning (3016, 1, arg.Expr.Location, "Arrays as attribute arguments are not CLS-compliant");
+ ctx.Report.Warning (3016, 1, arg.Expr.Location, "Arrays as attribute arguments are not CLS-compliant");
}
}
foreach (Argument a in args) {
a.Emit (ec);
if (dup_args) {
- ec.ig.Emit (OpCodes.Dup);
+ ec.Emit (OpCodes.Dup);
(temps [i++] = new LocalTemporary (a.Type)).Store (ec);
}
}
}
}
- public bool GetAttributableValue (EmitContext ec, out object[] values)
+ public IEnumerator<Argument> GetEnumerator ()
{
- values = new object [args.Count];
- for (int j = 0; j < values.Length; ++j) {
- Argument a = this [j];
- if (!a.Expr.GetAttributableValue (ec, a.Type, out values[j]))
- return false;
- }
-
- return true;
+ return args.GetEnumerator ();
}
- public IEnumerator GetEnumerator ()
- {
- return args.GetEnumerator ();
+ //
+ // At least one argument is of dynamic type
+ //
+ public bool HasDynamic {
+ get {
+ foreach (Argument a in args) {
+ if (a.Type == InternalType.Dynamic)
+ return true;
+ }
+
+ return false;
+ }
}
public void Insert (int index, Argument arg)
args.Insert (index, arg);
}
+ public static System.Linq.Expressions.Expression[] MakeExpression (Arguments args, BuilderContext ctx)
+ {
+ if (args == null || args.Count == 0)
+ return null;
+
+ var exprs = new System.Linq.Expressions.Expression [args.Count];
+ for (int i = 0; i < exprs.Length; ++i) {
+ Argument a = (Argument) args.args [i];
+ exprs[i] = a.Expr.MakeExpression (ctx);
+ }
+
+ return exprs;
+ }
+
public void MarkReorderedArgument (NamedArgument a)
{
//
return;
if (reordered == null)
- reordered = new ArrayList ();
+ reordered = new List<NamedArgument> ();
reordered.Add (a);
}
- public void Resolve (EmitContext ec)
+ //
+ // Returns dynamic when at least one argument is of dynamic type
+ //
+ public void Resolve (ResolveContext ec, out bool dynamic)
{
- foreach (Argument a in args)
+ dynamic = false;
+ foreach (Argument a in args) {
a.Resolve (ec);
- }
-
- public void MutateHoistedGenericType (AnonymousMethodStorey storey)
- {
- foreach (Argument a in args)
- a.Expr.MutateHoistedGenericType (storey);
+ dynamic |= a.Type == InternalType.Dynamic;
+ }
}
public void RemoveAt (int index)
set { args [index] = value; }
}
}
-}
\ No newline at end of file
+}