public override void Emit (EmitContext ec)
{
if (args != null)
- Invocation.EmitArguments (ec, args);
+ Invocation.EmitArguments (ec, mi, args);
ec.ig.Emit (OpCodes.Call, mi);
return;
public UnaryMutator (Mode m, Expression e, Location l)
{
- if (e == null)
- throw new Exception ("oops");
-
mode = m;
loc = l;
expr = e;
Arguments = new ArrayList ();
Arguments.Add (new Argument (left, Argument.AType.Expression));
Arguments.Add (new Argument (right, Argument.AType.Expression));
-
+
method = Invocation.OverloadResolve (ec, union, Arguments, loc);
if (method != null) {
MethodInfo mi = (MethodInfo) method;
// Note that operators are static anyway
if (Arguments != null)
- Invocation.EmitArguments (ec, Arguments);
+ Invocation.EmitArguments (ec, method, Arguments);
if (method is MethodInfo)
ig.Emit (OpCodes.Call, (MethodInfo) method);
public readonly AType ArgType;
public Expression expr;
-
+
public Argument (Expression expr, AType type)
{
this.expr = expr;
public static string FullDesc (Argument a)
{
- StringBuilder sb = new StringBuilder ();
-
- if (a.ArgType == AType.Ref)
- sb.Append ("ref ");
-
- if (a.ArgType == AType.Out)
- sb.Append ("out ");
-
- sb.Append (TypeManager.CSharpName (a.Expr.Type));
-
- return sb.ToString ();
+ return (a.ArgType == AType.Ref ? "ref " :
+ (a.ArgType == AType.Out ? "out " : "")) +
+ TypeManager.CSharpName (a.Expr.Type);
}
- public bool Resolve (EmitContext ec)
+ public bool Resolve (EmitContext ec, Location loc)
{
expr = expr.Resolve (ec);
+ if (ArgType == AType.Expression)
+ return expr != null;
+
+ if (expr.ExprClass != ExprClass.Variable){
+ Report.Error (206, loc,
+ "A property or indexer can not be passed as an out or ref " +
+ "parameter");
+ return false;
+ }
+
return expr != null;
}
public void Emit (EmitContext ec)
{
- expr.Emit (ec);
+ if (ArgType == AType.Ref || ArgType == AType.Out)
+ ((IMemoryLocation)expr).AddressOf (ec);
+ else
+ expr.Emit (ec);
}
}
// </summary>
public class Invocation : ExpressionStatement {
public readonly ArrayList Arguments;
- public readonly Location Location;
+ Location loc;
Expression expr;
MethodBase method = null;
{
this.expr = expr;
Arguments = arguments;
- Location = l;
+ loc = l;
}
public Expression Expr {
argument_count = 0;
else
argument_count = Arguments.Count;
-
+
//
// Now we see if we can find params functions, applicable in their expanded form
// since if they were applicable in their normal form, they would have been selected
Expression conv;
if (use_standard)
- conv = ConvertImplicitStandard (ec, a_expr, parameter_type,
- Location.Null);
+ conv = ConvertImplicitStandard (ec, a_expr, parameter_type, Location.Null);
else
- conv = ConvertImplicit (ec, a_expr, parameter_type,
- Location.Null);
+ conv = ConvertImplicit (ec, a_expr, parameter_type, Location.Null);
if (conv == null) {
if (!Location.IsNull (loc)) {
bool IsDelegate = TypeManager.IsDelegateType (expr_type);
if (IsDelegate)
return (new DelegateInvocation (
- this.expr, Arguments, Location)).Resolve (ec);
+ this.expr, Arguments, loc)).Resolve (ec);
}
}
if (!(expr is MethodGroupExpr)){
- report118 (Location, this.expr, "method group");
+ report118 (loc, this.expr, "method group");
return null;
}
--i;
Argument a = (Argument) Arguments [i];
- if (!a.Resolve (ec))
+ if (!a.Resolve (ec, loc))
return null;
}
}
- method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments,
- Location);
+ method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments, loc);
if (method == null){
- Error (-6, Location,
+ Error (-6, loc,
"Could not find any applicable function for this argument list");
return null;
}
return this;
}
- public static void EmitArguments (EmitContext ec, ArrayList Arguments)
+ // <summary>
+ // Emits the list of arguments as an array
+ // </summary>
+ static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
+ {
+ ILGenerator ig = ec.ig;
+ int count = arguments.Count - idx;
+ Argument a = (Argument) arguments [idx];
+ Type t = a.expr.Type;
+ string array_type = t.FullName + "[]";
+ LocalBuilder array;
+
+ array = ig.DeclareLocal (Type.GetType (array_type));
+ IntLiteral.EmitInt (ig, count);
+ ig.Emit (OpCodes.Newarr, t);
+ ig.Emit (OpCodes.Stloc, array);
+
+ int top = arguments.Count;
+ for (int j = idx; j < top; j++){
+ a = (Argument) arguments [j];
+
+ ig.Emit (OpCodes.Ldloc, array);
+ IntLiteral.EmitInt (ig, j - idx);
+ a.Emit (ec);
+
+ ArrayAccess.EmitStoreOpcode (ig, t);
+ }
+ ig.Emit (OpCodes.Ldloc, array);
+ }
+
+ // <summary>
+ // Emits a list of resolved Arguments that are in the arguments
+ // ArrayList.
+ //
+ // The MethodBase argument might be null if the
+ // emission of the arguments is known not to contain
+ // a `params' field (for example in constructors or other routines
+ // that keep their arguments in this structure
+ // </summary>
+
+ public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
{
+ ParameterData pd = null;
int top;
- if (Arguments != null)
- top = Arguments.Count;
+ if (arguments != null)
+ top = arguments.Count;
else
top = 0;
+ if (mb != null)
+ pd = GetParameterData (mb);
+
for (int i = 0; i < top; i++){
- Argument a = (Argument) Arguments [i];
+ Argument a = (Argument) arguments [i];
+ if (pd != null){
+ if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
+ EmitParams (ec, i, arguments);
+ return;
+ }
+ }
+
a.Emit (ec);
}
}
Type t = instance_expr.Type;
instance_expr.Emit (ec);
- LocalBuilder temp = ec.GetTemporaryStorage (t);
+ LocalBuilder temp = ig.DeclareLocal (t);
ig.Emit (OpCodes.Stloc, temp);
ig.Emit (OpCodes.Ldloca, temp);
}
}
if (Arguments != null)
- EmitArguments (ec, Arguments);
+ EmitArguments (ec, method, Arguments);
if (is_static || struct_call){
if (method is MethodInfo)
public readonly ArrayList Arguments;
public readonly string RequestedType;
- Location Location;
+ Location loc;
MethodBase method = null;
//
//
Expression value_target;
- public New (string requested_type, ArrayList arguments, Location loc)
+ public New (string requested_type, ArrayList arguments, Location l)
{
RequestedType = requested_type;
Arguments = arguments;
- Location = loc;
+ loc = l;
}
public Expression ValueTypeVariable {
bool IsDelegate = TypeManager.IsDelegateType (type);
if (IsDelegate)
- return (new NewDelegate (type, Arguments, Location)).Resolve (ec);
+ return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
Expression ml;
ml = MemberLookup (ec, type, ".ctor", false,
- MemberTypes.Constructor, AllBindingsFlags, Location);
+ MemberTypes.Constructor, AllBindingsFlags, loc);
bool is_struct = false;
is_struct = type.IsSubclassOf (TypeManager.value_type);
if (! (ml is MethodGroupExpr)){
if (!is_struct){
- report118 (Location, ml, "method group");
+ report118 (loc, ml, "method group");
return null;
}
}
--i;
Argument a = (Argument) Arguments [i];
- if (!a.Resolve (ec))
+ if (!a.Resolve (ec, loc))
return null;
}
}
method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
- Arguments, Location);
+ Arguments, loc);
}
if (method == null && !is_struct) {
- Error (-6, Location,
+ Error (-6, loc,
"New invocation: Can not find a constructor for " +
"this argument list");
return null;
ml.AddressOf (ec);
} else {
- Invocation.EmitArguments (ec, Arguments);
+ Invocation.EmitArguments (ec, method, Arguments);
ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
return true;
}
string RequestedType;
string Rank;
ArrayList Initializers;
- Location Location;
+ Location loc;
ArrayList Arguments;
MethodBase method = null;
bool IsBuiltinType = false;
+ int dimensions = 0;
+
public ArrayCreation (string requested_type, ArrayList exprs,
string rank, ArrayList initializers, Location l)
{
RequestedType = requested_type;
Rank = rank;
Initializers = initializers;
- Location = l;
+ loc = l;
Arguments = new ArrayList ();
public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
{
RequestedType = requested_type;
- Rank = rank;
Initializers = initializers;
- Location = l;
+ loc = l;
+
+ Rank = rank.Substring (0, rank.LastIndexOf ("["));
+
+ string tmp = rank.Substring (rank.LastIndexOf ("["));
+
+ dimensions = tmp.Length - 1;
}
public static string FormArrayType (string base_type, int idx_count, string rank)
return val.Substring (0, val.LastIndexOf ("["));
}
+
+ void error178 ()
+ {
+ Report.Error (178, loc, "Incorrectly structured array initializer");
+ }
+
+ bool ValidateInitializers (EmitContext ec)
+ {
+ if (Initializers == null)
+ return true;
+
+ Type underlying_type = ec.TypeContainer.LookupType (RequestedType, false);
+
+ ArrayList probe = Initializers;
+
+ if (Arguments != null) {
+ for (int i = 0; i < Arguments.Count; i++) {
+ Argument a = (Argument) Arguments [i];
+
+ Expression e = Expression.Reduce (ec, a.Expr);
+
+ if (!(e is Literal)) {
+ Report.Error (150, loc, "A constant value is expected");
+ return false;
+ }
+
+ int value = (int) ((Literal) e).GetValue ();
+ if (probe == null) {
+ error178 ();
+ return false;
+ }
+
+ if (value != probe.Count) {
+ error178 ();
+ return false;
+ }
+
+ if (probe [0] is ArrayList)
+ probe = (ArrayList) probe [0];
+ else {
+ for (int j = 0; j < probe.Count; ++j) {
+ Expression tmp = (Expression) probe [j];
+
+ tmp = tmp.Resolve (ec);
+
+ Expression conv = ConvertImplicitRequired (ec, tmp,
+ underlying_type, loc);
+
+ if (conv == null)
+ return false;
+ }
+
+ probe = null;
+ }
+ }
+
+ } else {
+ //
+ // Here is where we update dimension info in the case
+ // that the user skips doing that
+ //
+
+ Arguments = new ArrayList ();
+
+ for (probe = Initializers; probe != null; ) {
+ Expression e = new IntLiteral (probe.Count);
+
+ Arguments.Add (new Argument (e, Argument.AType.Expression));
+
+ if (probe [0] is ArrayList)
+ probe = (ArrayList) probe [0];
+ else {
+ for (int j = 0; j < probe.Count; ++j) {
+ Expression tmp = (Expression) probe [j];
+
+ tmp = tmp.Resolve (ec);
+
+ Expression conv = ConvertImplicitRequired (ec, tmp,
+ underlying_type, loc);
+
+ if (conv == null)
+ return false;
+ }
+
+ probe = null;
+ }
+ }
+
+ if (Arguments.Count != dimensions) {
+ error178 ();
+ return false;
+ }
+ }
+ return true;
+ }
+
public override Expression DoResolve (EmitContext ec)
{
int arg_count;
-
+
+ if (!ValidateInitializers (ec))
+ return null;
+
if (Arguments == null)
arg_count = 0;
else
Expression ml;
ml = MemberLookup (ec, type, ".ctor", false, MemberTypes.Constructor,
- AllBindingsFlags, Location);
+ AllBindingsFlags, loc);
if (!(ml is MethodGroupExpr)){
- report118 (Location, ml, "method group");
+ report118 (loc, ml, "method group");
return null;
}
if (ml == null) {
- Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
+ Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
"this argument list");
return null;
}
--i;
Argument a = (Argument) Arguments [i];
- if (!a.Resolve (ec))
+ if (!a.Resolve (ec, loc))
return null;
}
}
- method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, Location);
+ method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
if (method == null) {
- Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
+ Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
"this argument list");
return null;
}
--i;
Argument a = (Argument) Arguments [i];
- if (!a.Resolve (ec))
+ if (!a.Resolve (ec, loc))
return null;
args.Add (a.Type);
arg_types);
if (method == null) {
- Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
+ Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
"this argument list");
return null;
}
ILGenerator ig = ec.ig;
if (IsOneDimensional) {
- Invocation.EmitArguments (ec, Arguments);
+ Invocation.EmitArguments (ec, null, Arguments);
ig.Emit (OpCodes.Newarr, array_element_type);
} else {
- Invocation.EmitArguments (ec, Arguments);
+ Invocation.EmitArguments (ec, null, Arguments);
if (IsBuiltinType)
ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
--i;
Argument a = (Argument) Arguments [i];
- if (!a.Resolve (ec))
+ if (!a.Resolve (ec, loc))
return false;
}
return this;
}
+ // <summary>
+ // Emits the right opcode to load an object of Type `t'
+ // from an array of T
+ // </summary>
+ static public void EmitLoadOpcode (ILGenerator ig, Type type)
+ {
+ if (type == TypeManager.byte_type)
+ ig.Emit (OpCodes.Ldelem_I1);
+ else if (type == TypeManager.sbyte_type)
+ ig.Emit (OpCodes.Ldelem_U1);
+ else if (type == TypeManager.short_type)
+ ig.Emit (OpCodes.Ldelem_I2);
+ else if (type == TypeManager.ushort_type)
+ ig.Emit (OpCodes.Ldelem_U2);
+ else if (type == TypeManager.int32_type)
+ ig.Emit (OpCodes.Ldelem_I4);
+ else if (type == TypeManager.uint32_type)
+ ig.Emit (OpCodes.Ldelem_U4);
+ else if (type == TypeManager.uint64_type)
+ ig.Emit (OpCodes.Ldelem_I8);
+ else if (type == TypeManager.int64_type)
+ ig.Emit (OpCodes.Ldelem_I8);
+ else if (type == TypeManager.float_type)
+ ig.Emit (OpCodes.Ldelem_R4);
+ else if (type == TypeManager.double_type)
+ ig.Emit (OpCodes.Ldelem_R8);
+ else if (type == TypeManager.intptr_type)
+ ig.Emit (OpCodes.Ldelem_I);
+ else
+ ig.Emit (OpCodes.Ldelem_Ref);
+ }
+
+ // <summary>
+ // Emits the right opcode to store an object of Type `t'
+ // from an array of T.
+ // </summary>
+ static public void EmitStoreOpcode (ILGenerator ig, Type t)
+ {
+ if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
+ ig.Emit (OpCodes.Stelem_I1);
+ else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
+ ig.Emit (OpCodes.Stelem_I2);
+ else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
+ ig.Emit (OpCodes.Stelem_I4);
+ else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
+ ig.Emit (OpCodes.Stelem_I8);
+ else if (t == TypeManager.float_type)
+ ig.Emit (OpCodes.Stelem_R4);
+ else if (t == TypeManager.double_type)
+ ig.Emit (OpCodes.Stelem_R8);
+ else if (t == TypeManager.intptr_type)
+ ig.Emit (OpCodes.Stelem_I);
+ else
+ ig.Emit (OpCodes.Stelem_Ref);
+ }
+
public override void Emit (EmitContext ec)
{
int rank = ea.Expr.Type.GetArrayRank ();
foreach (Argument a in ea.Arguments)
a.Expr.Emit (ec);
- if (rank == 1){
- if (type == TypeManager.byte_type)
- ig.Emit (OpCodes.Ldelem_I1);
- else if (type == TypeManager.sbyte_type)
- ig.Emit (OpCodes.Ldelem_U1);
- else if (type == TypeManager.short_type)
- ig.Emit (OpCodes.Ldelem_I2);
- else if (type == TypeManager.ushort_type)
- ig.Emit (OpCodes.Ldelem_U2);
- else if (type == TypeManager.int32_type)
- ig.Emit (OpCodes.Ldelem_I4);
- else if (type == TypeManager.uint32_type)
- ig.Emit (OpCodes.Ldelem_U4);
- else if (type == TypeManager.uint64_type)
- ig.Emit (OpCodes.Ldelem_I8);
- else if (type == TypeManager.int64_type)
- ig.Emit (OpCodes.Ldelem_I8);
- else if (type == TypeManager.float_type)
- ig.Emit (OpCodes.Ldelem_R4);
- else if (type == TypeManager.double_type)
- ig.Emit (OpCodes.Ldelem_R8);
- else if (type == TypeManager.intptr_type)
- ig.Emit (OpCodes.Ldelem_I);
- else
- ig.Emit (OpCodes.Ldelem_Ref);
- } else {
+ if (rank == 1)
+ EmitLoadOpcode (ig, type);
+ else {
ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
Type [] args = new Type [ea.Arguments.Count];
MethodInfo get;
source.Emit (ec);
Type t = source.Type;
- if (rank == 1){
- if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
- ig.Emit (OpCodes.Stelem_I1);
- else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
- ig.Emit (OpCodes.Stelem_I2);
- else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
- ig.Emit (OpCodes.Stelem_I4);
- else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
- ig.Emit (OpCodes.Stelem_I8);
- else if (t == TypeManager.float_type)
- ig.Emit (OpCodes.Stelem_R4);
- else if (t == TypeManager.double_type)
- ig.Emit (OpCodes.Stelem_R8);
- else if (t == TypeManager.intptr_type)
- ig.Emit (OpCodes.Stelem_I);
- else
- ig.Emit (OpCodes.Stelem_Ref);
- } else {
+ if (rank == 1)
+ EmitStoreOpcode (ig, t);
+ else {
ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
Type [] args = new Type [ea.Arguments.Count + 1];
MethodInfo set;
eclass = ExprClass.Value;
}
+ public EmptyExpression (Type t)
+ {
+ type = t;
+ eclass = ExprClass.Value;
+ }
+
public override Expression DoResolve (EmitContext ec)
{
return this;