return this;
}
+ if (expr_type == TypeManager.object_type) {
+ Expression etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.ObjectType.NotObj", Location.Null);
+ ArrayList arguments = new ArrayList ();
+ arguments.Add (new Argument (Expr, Argument.AType.Expression));
+ Expression e = new Invocation (etmp, arguments, loc);
+ return e.Resolve (ec);
+ }
+
break;
case Operator.AddressOf:
// Not required in VB ??
loc = l;
}
+/*
void LoadExprValue (EmitContext ec)
{
}
+*/
public override void Emit (EmitContext ec)
{
"++" : "--";
}
- void Error23 (Type t)
- {
- Error (
- 30311, "Operator " + OperName (mode) +
- " cannot be applied to operand of type '" +
- TypeManager.MonoBASIC_Name (t) + "'");
- }
-
/// <summary>
/// Returns whether an object of type 't' can be incremented
/// or decremented with add/sub (ie, basically whether we can
}
}
- public class Exponentiation : Expression {
-
- Expression left, right;
- ArrayList Arguments;
- protected MethodBase method;
-
- public Exponentiation(Location loc, Expression left, Expression right) {
- this.left = left;
- this.right = right;
- this.loc = loc;
- }
-
- public override Expression DoResolve (EmitContext ec)
- {
- left = left.Resolve (ec);
- right = right.Resolve (ec);
-
- if (left == null || right == null)
- return null;
-
- if (left.Type == null)
- throw new Exception (
- "Resolve returned non null, but did not set the type! (" +
- left + ") at Line: " + loc.Row);
- if (right.Type == null)
- throw new Exception (
- "Resolve returned non null, but did not set the type! (" +
- right + ") at Line: "+ loc.Row);
-
- eclass = ExprClass.Value;
- Expression e = null;
-
- if (left is EnumConstant) {
- left = ((EnumConstant) left).WidenToCompilerConstant();
- }
-
- if (right is EnumConstant) {
- right = ((EnumConstant) right).WidenToCompilerConstant();
- }
-
- if (left is Constant && right is Constant){
- e = ConstantFold.BinaryFold (
- ec, Binary.Operator.Exponentiation, (Constant) left, (Constant) right, loc);
- if (e != null)
- return e;
- }
-
- Type l = left.Type;
- Type r = right.Type;
-
- if (left is NullLiteral && right is NullLiteral) {
- Error_OperatorCannotBeApplied (loc, "^", l, r);
- return null;
- }
- if (left is NullLiteral)
- l = r;
- if (right is NullLiteral)
- r = l;
-
- if (l == TypeManager.object_type || r == TypeManager.object_type) {
- if (r.IsValueType)
- right = ConvertImplicit (ec, right, TypeManager.object_type, loc);
- if (l.IsValueType)
- left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
- if (left == null || right == null) {
- Error_OperatorCannotBeApplied (loc, "^", l, r);
- return null;
- }
-
- l = left.Type;
- r = right.Type;
-
- Expression tmp = Mono.MonoBASIC.Parser.DecomposeQI (
- "Microsoft.VisualBasic.CompilerServices.ObjectType.PowObj",
- Location.Null);
-
- ArrayList arguments = new ArrayList ();
- arguments.Add (new Argument (left, Argument.AType.Expression));
- arguments.Add (new Argument (right, Argument.AType.Expression));
- e = new Invocation (tmp, arguments, loc);
- return e.Resolve (ec);
- }
-
- if (l == TypeManager.date_type || r == TypeManager.date_type ||
- l == TypeManager.char_type || r == TypeManager.char_type ||
- ! l.IsValueType || ! r.IsValueType) {
- Error_OperatorCannotBeApplied (loc, "^", l, r);
- return null;
- }
-
- if (l != TypeManager.double_type) {
- left = ConvertImplicit (ec, left, TypeManager.double_type, loc);
- if (left == null){
- Error_OperatorCannotBeApplied (loc, "&", l, r);
- return null;
- }
- type = TypeManager.double_type;
- }
-
- if (r != TypeManager.double_type) {
- right = ConvertImplicit (ec, right, TypeManager.double_type, loc);
- if (right == null){
- Error_OperatorCannotBeApplied (loc, "^", l, r);
- return null;
- }
-
- type = TypeManager.double_type;
- }
-
- Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI("System.Math.Pow", loc);
- ArrayList args = new ArrayList();
- args.Add (new Argument (left, Argument.AType.Expression));
- args.Add (new Argument (right, Argument.AType.Expression));
- e = (Expression) new Invocation (etmp, args, loc);
- return e.Resolve(ec);
- }
-
- public override void Emit (EmitContext ec)
- {
- throw new Exception ("Should not happen");
- }
-
- static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
- {
- Report.Error (19, loc,
- "Operator " + name + " cannot be applied to operands of type '" +
- TypeManager.MonoBASIC_Name (l) + "' and '" +
- TypeManager.MonoBASIC_Name (r) + "'");
- }
-
- }
public class StringConcat : Expression {
Expression left, right;
public enum Operator : byte {
Exponentiation,
Multiply, Division, IntDivision, Modulus,
- Addition, Subtraction,
+ Addition, Subtraction, Concat,
LeftShift, RightShift,
LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual,
Equality, Inequality,
public Binary (Operator oper, Expression left, Expression right, Location loc)
{
+ left = Parser.SetValueRequiredFlag (left);
+ right = Parser.SetValueRequiredFlag (right);
this.oper = oper;
this.left = left;
this.right = right;
else if (r == TypeManager.decimal_type)
conv_right_as = TypeManager.bool_type;
} else if ((l == TypeManager.double_type || r == TypeManager.double_type) ||
- (oper == Operator.Division &&
- !(l == TypeManager.decimal_type || r == TypeManager.decimal_type))) {
+ (oper == Operator.Exponentiation) ||
+ (oper == Operator.Division &&
+ !(l == TypeManager.decimal_type || r == TypeManager.decimal_type))) {
//
// If either operand is of type double, the other operand is
// conveted to type double.
oper == Operator.ExclusiveOr);
}
- bool IsNumericType (Type type) {
- return (type == TypeManager.byte_type ||
- type == TypeManager.sbyte_type ||
- type == TypeManager.short_type ||
- type == TypeManager.int32_type ||
- type == TypeManager.int64_type ||
- type == TypeManager.decimal_type ||
- type == TypeManager.double_type ||
- type == TypeManager.float_type);
- }
-
Expression ResolveOperator (EmitContext ec)
{
Type l = left.Type;
Type conv_left_as = null;
Type conv_right_as = null;
- if (left is NullLiteral && (r.IsValueType || r == TypeManager.string_type)) {
+ if ((left is NullLiteral ||(Type.GetTypeCode(l)==TypeCode.DBNull)) && (r.IsValueType || r == TypeManager.string_type)) {
// Just treat nothing as the other type, implicit conversion
// will return the default value
conv_left_as = r;
l = r;
+ //incase of DBNull set to NullLiteral
+ left = NullLiteral.Null;
}
- if (right is NullLiteral && (l.IsValueType || l == TypeManager.string_type)) {
+ if ((right is NullLiteral ||(Type.GetTypeCode(r)==TypeCode.DBNull)) && (l.IsValueType || l == TypeManager.string_type)) {
// Just treat nothing as the other type, implicit conversion
// will return the default value
conv_right_as = l;
r = l;
+ right = NullLiteral.Null;
}
// deal with objects and reference types first
// one from the other, then we catch the error there.
// If other type is a value type, convert it to object
- if (l.IsValueType && r == TypeManager.object_type)
+ if (r == TypeManager.object_type &&
+ (l.IsValueType || l == TypeManager.string_type))
left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
- if (r.IsValueType && l == TypeManager.object_type)
+ if (l == TypeManager.object_type &&
+ (r.IsValueType || r == TypeManager.string_type))
right = ConvertImplicit (ec, right, TypeManager.object_type, loc);
if (left == null || right == null) {
Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
conv_left_as = conv_right_as = TypeManager.int64_type;
type = TypeManager.int64_type;
}
+ } else if (oper == Operator.Exponentiation) {
+ conv_left_as = conv_right_as = TypeManager.double_type;
} else if (oper == Operator.IntDivision) {
conv_left_as = conv_right_as = TypeManager.int64_type;
} else {
// Required conversions done by 'DoNumericPromotions' method
// So Reset 'conv_left_as', 'conv_right_as'
conv_left_as = conv_right_as = null;
+
if (l == TypeManager.decimal_type && r == TypeManager.decimal_type) {
if (IsRelationalOperator (oper)) {
Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI ("System.Decimal.Compare", Location.Null);
if (conv_done)
return ResolveOperator (ec);
+
+ if (oper == Operator.Exponentiation) {
+ Expression etmp = Mono.MonoBASIC.Parser.DecomposeQI("System.Math.Pow", loc);
+ ArrayList args = new ArrayList();
+ args.Add (new Argument (left, Argument.AType.Expression));
+ args.Add (new Argument (right, Argument.AType.Expression));
+ Expression e = (Expression) new Invocation (etmp, args, loc);
+ return e.Resolve(ec);
+ }
+
bool overload_failed = false;
string op = oper_names [(int) oper];
MethodGroupExpr union = null;
public override Expression DoResolve (EmitContext ec)
{
+ if (oper == Operator.Concat) {
+ Expression e = new StringConcat (loc, left, right);
+ return e.Resolve (ec);
+ }
left = left.Resolve (ec);
right = right.Resolve (ec);
right + ") at Line: "+ loc.Row);
eclass = ExprClass.Value;
+
+ // To support 'Or' argument of AttributeTargets in AttributeUsage
- if (left is EnumConstant) {
+ if (left is EnumConstant && oper != Operator.BitwiseOr) {
left = ((EnumConstant) left).WidenToCompilerConstant();
}
- if (right is EnumConstant) {
+ if (right is EnumConstant && oper != Operator.BitwiseOr) {
right = ((EnumConstant) right).WidenToCompilerConstant();
}
{
VariableInfo vi = VariableInfo;
- if (ec.DoFlowAnalysis)
+ if (ec.DoFlowAnalysis) {
ec.SetVariableAssigned (vi);
+ }
Expression e = DoResolve (ec);
VariableInfo vi = VariableInfo;
ILGenerator ig = ec.ig;
- ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
+ if (vi.Alias != null && vi.Static) {
+ ArrayList fields = ec.TypeContainer.Fields;
+ FieldBase fb = null;
+ for (int i = 0; i < fields.Count; i++) {
+ if (((Field) fields[i]).Name == vi.Alias) {
+ fb = (Field) fields[i];
+ break;
+ }
+ }
+ if ((fb.ModFlags & Modifiers.STATIC) != 0)
+ ig.Emit (OpCodes.Ldsfld, fb.FieldBuilder);
+ else {
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, fb.FieldBuilder);
+ }
+ } else
+ ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
+
vi.Used = true;
}
vi.Assigned = true;
- source.Emit (ec);
-
- ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ if (vi.Alias != null && vi.Static) {
+ ArrayList fields = ec.TypeContainer.Fields;
+ FieldBase fb = null;
+ for (int i = 0; i < fields.Count; i++) {
+ if (((Field) fields[i]).Name == vi.Alias) {
+ fb = (Field) fields[i];
+ break;
+ }
+ }
+ if ((fb.ModFlags & Modifiers.STATIC) != 0) {
+ source.Emit (ec);
+ ig.Emit (OpCodes.Stsfld, fb.FieldBuilder);
+ }
+ else {
+ ig.Emit (OpCodes.Ldarg_0);
+ source.Emit (ec);
+ ig.Emit (OpCodes.Stfld, fb.FieldBuilder);
+ }
+ }
+ else {
+ source.Emit (ec);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
+ }
}
public void AddressOf (EmitContext ec, AddressOp mode)
{
VariableInfo vi = VariableInfo;
- ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder);
+ if (vi.Alias != null && vi.Static) {
+ ArrayList fields = ec.TypeContainer.Fields;
+ FieldBase fb = null;
+ for (int i = 0; i < fields.Count; i++) {
+ if (((Field) fields[i]).Name == vi.Alias) {
+ fb = (Field) fields[i];
+ break;
+ }
+ }
+ if ((fb.ModFlags & Modifiers.STATIC) != 0)
+ ec.ig.Emit (OpCodes.Ldsflda, fb.FieldBuilder);
+ else {
+ ec.ig.Emit (OpCodes.Ldarg_0);
+ ec.ig.Emit (OpCodes.Ldflda, fb.FieldBuilder);
+ }
+ } else
+ ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder);
}
}
{
type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
- is_out = (mod & Parameter.Modifier.OUT) != 0;
+ // is_out = (mod & Parameter.Modifier.OUT) != 0;
eclass = ExprClass.Variable;
- if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
+ /* if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
return null;
-
+ */
return this;
}
{
type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
- is_out = (mod & Parameter.Modifier.OUT) != 0;
+ // is_out = (mod & Parameter.Modifier.OUT) != 0;
eclass = ExprClass.Variable;
-
+ /*
if (is_out && ec.DoFlowAnalysis)
ec.SetParameterAssigned (idx);
-
+ */
return this;
}
public Expression expr;
MethodBase method = null;
bool is_base;
+ bool is_latebinding;
bool is_left_hand; // Needed for late bound calls
+ bool is_retval_required; // Needed for late bound calls
static Hashtable method_parameter_cache;
- static MemberFilter CompareName;
+ //static MemberFilter CompareName;
+
+ static ArrayList tempvars; // For ByRef - different parameter and argument type
+ static bool is_byref_conversion = false; //For ByRef when it is converted
+ static string errorMsg = "";
static Invocation ()
{
public Invocation (Expression expr, ArrayList arguments, Location l)
{
this.expr = expr;
+ if (this.expr is MemberAccess)
+ ((MemberAccess) this.expr).IsInvocation = true;
+ if (this.expr is SimpleName)
+ ((SimpleName) this.expr).IsInvocation = true;
+ this.is_retval_required = false;
+ this.is_left_hand = false;
Arguments = arguments;
loc = l;
- CompareName = new MemberFilter (compare_name_filter);
+ //CompareName = new MemberFilter (compare_name_filter);
}
public Expression Expr {
}
}
+ public bool IsLeftHand {
+ get {
+ return is_left_hand;
+ }
+ set {
+ is_left_hand = value;
+ }
+ }
+
+ public bool IsRetvalRequired {
+ get {
+ return is_retval_required;
+ }
+ set {
+ is_retval_required = value;
+ }
+ }
+
+ public bool IsLateBinding {
+ get {
+ return is_latebinding;
+ }
+ set {
+ is_latebinding = value;
+ }
+ }
+
/// <summary>
/// Returns the Parameters (a ParameterData interface) for the
/// Method 'mb'
return union;
}
- /// <summary>
- /// Determines is the candidate method, if a params method, is applicable
- /// in its expanded form to the given set of arguments
- /// </summary>
- static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
- {
- int arg_count;
-
- if (arguments == null)
- arg_count = 0;
- else
- arg_count = arguments.Count;
-
- ParameterData pd = GetParameterData (candidate);
-
- int pd_count = pd.Count;
-
- if (pd_count == 0)
- return false;
-
- if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
- return false;
-
- if (pd_count - 1 > arg_count)
- return false;
-
- if (pd_count == 1 && arg_count == 0)
- return true;
-
- //
- // If we have come this far, the case which remains is when the number of parameters
- // is less than or equal to the argument count.
- //
- for (int i = 0; i < pd_count - 1; ++i) {
-
- Argument a = (Argument) arguments [i];
-
- Parameter.Modifier a_mod = a.GetParameterModifier () &
- ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
- Parameter.Modifier p_mod = pd.ParameterModifier (i) &
- ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
-
- if (a_mod == p_mod) {
-
- if (a_mod == Parameter.Modifier.NONE)
- if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
- return false;
-
- if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
- Type pt = pd.ParameterType (i);
-
- if (!pt.IsByRef)
- pt = TypeManager.LookupType (pt.FullName + "&");
-
- if (pt != a.Type)
- return false;
- }
- } else
- return false;
-
- }
-
- Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
-
- for (int i = pd_count - 1; i < arg_count; i++) {
- Argument a = (Argument) arguments [i];
-
- if (!StandardConversionExists (a.Expr, element_type))
- return false;
- }
-
- return true;
- }
-
protected enum ConversionType { None, Widening, Narrowing };
static ConversionType CheckParameterAgainstArgument (EmitContext ec, ParameterData pd, int i, Argument a, Type ptype)
{
+ if (a.ArgType == Argument.AType.NoArg) {
+ return ConversionType.Widening;
+ }
+
Parameter.Modifier a_mod = a.GetParameterModifier () &
- ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+ ~(Parameter.Modifier.REF);
Parameter.Modifier p_mod = pd.ParameterModifier (i) &
- ~(Parameter.Modifier.OUT | Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
+ ~(Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
if (a_mod == p_mod ||
(a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
- if (a_mod == Parameter.Modifier.NONE) {
+ // if (a_mod == Parameter.Modifier.NONE) {
if (! WideningConversionExists (a.Expr, ptype) ) {
+
if (! NarrowingConversionExists (ec, a.Expr, ptype) )
return ConversionType.None;
else
return ConversionType.Narrowing;
} else
- return ConversionType.Widening;
- }
+ return ConversionType.Widening;
+ // }
+/*
if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
Type pt = pd.ParameterType (i);
return ConversionType.None;
}
return ConversionType.Widening;
+*/
} else
return ConversionType.None;
}
return count;
}
+ static ConversionType IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate,
+ out bool expanded)
+ {
+ bool objectArgsPresent;
+ return IsApplicable (ec, arguments, candidate, out expanded, out objectArgsPresent);
+ }
+
/// <summary>
/// Determines if the candidate method is applicable (section 14.4.2.1)
/// to the given set of arguments
/// </summary>
- static ConversionType IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate, out bool expanded)
+ static ConversionType IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate,
+ out bool expanded, out bool objectArgsPresent)
{
int arg_count;
Type param_type;
- expanded = false;
+ expanded = objectArgsPresent = false;
+ int num_narr_conv = 0; // Count the narrowing conversion not involving object
+ // arguments
if (arguments == null)
arg_count = 0;
if (!HasArrayParameter (pd) && arg_count > pd_count)
return ConversionType.None;
}
+
ConversionType result = ConversionType.Widening;
- ArrayList newarglist = new ArrayList();
if (arg_count > 0) {
result = ConversionType.None;
int array_param_index = -1;
return ConversionType.None;
}
- if ((mod & Parameter.Modifier.REF) != 0) {
+ if (a.ArgType != Argument.AType.NoArg && (mod & Parameter.Modifier.REF) != 0) {
a = new Argument (a.Expr, Argument.AType.Ref);
if (!a.Resolve(ec,Location.Null))
return ConversionType.None;
}
if (match == ConversionType.None)
match = CheckParameterAgainstArgument (ec, pd, i, a, param_type);
- newarglist.Add (a);
if (match == ConversionType.None)
return ConversionType.None;
- if (result == ConversionType.None)
+
+ if (match == ConversionType.Narrowing) {
+ result = match;
+ if (a.Expr.Type == TypeManager.object_type)
+ objectArgsPresent = true;
+ else {
+ objectArgsPresent = false;
+ num_narr_conv ++;
+ }
+ } else if (result == ConversionType.None)
result = match;
- else if (match == ConversionType.Narrowing)
- result = ConversionType.Narrowing;
}
}
-#if false
- // We've found a candidate, so we exchange the dummy NoArg arguments
- // with new arguments containing the default value for that parameter
-
- ArrayList newarglist = new ArrayList();
- for (int i = 0; i < arg_count; i++) {
- Argument a = (Argument) arguments [i];
- Parameter p = null;
-
- if (ps != null)
- p = (Parameter) ps.FixedParameters[i];
-
- if (a.ArgType == Argument.AType.NoArg){
- a = new Argument (p.ParameterInitializer, Argument.AType.Expression);
- a.Resolve(ec, Location.Null);
- }
+ if (num_narr_conv > 0) // There were narrowing conversions other than those for object arguments
+ objectArgsPresent = false;
- // ToDo - This part is getting resolved second time within this function
- // This is a costly operation
- // The earlier resoved result should be used here.
- // Has to be done during compiler optimization.
- if (a.ArgType == Argument.AType.AddressOf) {
- param_type = pd.ParameterType (i);
- bool IsDelegate = TypeManager.IsDelegateType (param_type);
-
- a = new Argument ((Expression) a.Expr, Argument.AType.Expression);
- ArrayList args = new ArrayList();
- args.Add (a);
- string param_name = pd.ParameterDesc(i).Replace('+', '.');
- Expression pname = MonoBASIC.Parser.DecomposeQI (param_name, Location.Null);
-
- New temp_new = new New ((Expression)pname, args, Location.Null);
- Expression del_temp = temp_new.DoResolve(ec);
-
- if (del_temp == null)
- return ConversionType.None;
+ return result;
+ }
- a = new Argument (del_temp, Argument.AType.Expression);
- if (!a.Resolve(ec, Location.Null))
- return ConversionType.None;
+ internal static ArrayList ReorderArguments (MethodBase mb,
+ ArrayList Arguments,
+ CaseInsensitiveHashtable namedArgs,
+ ref string ErrMsg,
+ Location loc)
+ {
+ ArrayList orderedArgs = new ArrayList ();
+ ParameterData pd = GetParameterData (mb);
+ bool error = false;
+ for (int index = 0; index < pd.Count; index ++) {
+ string paramName = pd.ParameterName (index);
+ if (namedArgs.Contains (paramName)) {
+ if ((pd.ParameterModifier (index) & Parameter.Modifier.PARAMS) == Parameter.Modifier.PARAMS) {
+ error = true;
+ ErrMsg += "\n\t'" + FullMethodDesc (mb) + "': Named argument cannot match a ParamArray parameter";
+ continue;
+ }
+ int argIndex = (int) namedArgs [paramName];
+ orderedArgs.Add (Arguments [argIndex]);
+ } else {
+ Parameter.Modifier p_mod = pd.ParameterModifier (index) & Parameter.Modifier.OPTIONAL;
+ if (p_mod == Parameter.Modifier.OPTIONAL)
+ orderedArgs.Add (new Argument (pd.ParameterName (index), new EmptyExpression (), Argument.AType.NoArg));
+ else {
+ error = true;
+ ErrMsg += "\n\t'" + FullMethodDesc (mb) + "': Argument not specified for parameter '" + paramName + "'";
+ }
}
+ }
- if ((p != null) && ((p.ModFlags & Parameter.Modifier.REF) != 0)) {
- a.ArgType = Argument.AType.Ref;
- a.Resolve(ec, Location.Null);
- } else if ((pd.ParameterModifier (i) & Parameter.Modifier.REF) != 0) {
- a.ArgType = Argument.AType.Ref;
- a.Resolve(ec, Location.Null);
- }
- newarglist.Add(a);
- int n = pd_count - arg_count;
- if (n > 0) {
- for (int x = 0; x < n; x++) {
- Parameter op = (Parameter) ps.FixedParameters[x + arg_count];
- Argument b = new Argument (op.ParameterInitializer, Argument.AType.Expression);
- b.Resolve(ec, Location.Null);
- newarglist.Add (b);
+ if (Arguments.Count > orderedArgs.Count) {
+ for (int argIndex = 0; argIndex < Arguments.Count; argIndex ++) {
+ string argName = ((Argument) Arguments [argIndex]).ParamName;
+ bool found = false;
+ for (int paramIndex = 0; paramIndex < pd.Count; paramIndex ++) {
+ string paramName = pd.ParameterName (paramIndex);
+ if (String.Compare (argName, paramName, true) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ error = true;
+ ErrMsg += "\n\t'" + FullMethodDesc (mb) + "': '" + argName + "' is not a parameter";
}
}
}
-#endif
- return result;
+ if (error)
+ return null;
+ return orderedArgs;
}
+/*
static bool compare_name_filter (MemberInfo m, object filterCriteria)
{
return (m.Name == ((string) filterCriteria));
}
+*/
+
+ public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
+ ref ArrayList Arguments, Location loc)
+ {
+ bool isLateBindingRequired;
+ return OverloadResolve (ec, me, ref Arguments, loc, out isLateBindingRequired);
+ }
// We need an overload for OverloadResolve because Invocation.DoResolve
// must pass Arguments by reference, since a later call to IsApplicable
return OverloadResolve (ec, me, ref a, loc);
}
+/*
static string ToString(MethodBase mbase)
{
if (mbase == null)
return mbase.ToString();
}
+*/
/// <summary>
/// Find the Applicable Function Members (7.4.2.1)
/// loc: The location if we want an error to be reported, or a Null
/// location for "probing" purposes.
///
+ /// isLateBindingRequired : Flag to indicate that this method call is
+ /// is a candidate for late binding. Set to true if
+ /// there is atleast one object argument and we get
+ /// * Two or more candidates that require widening conv
+ /// * Two or more candidates require narrowing conversions
+ /// (for object arguments **only**)
/// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
/// that is the best match of me on Arguments.
///
/// </summary>
public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
- ref ArrayList Arguments, Location loc)
+ ref ArrayList Arguments, Location loc,
+ out bool isLateBindingRequired)
{
MethodBase method = null;
int argument_count;
ArrayList candidates = new ArrayList ();
+ ArrayList lateBindingCandidates = new ArrayList ();
Hashtable expanded_candidates = new Hashtable();
int narrow_count = 0;
bool narrowing_candidate = false;
+ errorMsg = "";
+ isLateBindingRequired = false;
+ CaseInsensitiveHashtable namedArgs = new CaseInsensitiveHashtable ();
+ if (Arguments == null)
+ argument_count = 0;
+ else
+ argument_count = Arguments.Count;
+
+ if (!CheckNamedArguments (Arguments, loc))
+ return null;
+
+ if (!GetNamedArgPos (Arguments, ref namedArgs, loc))
+ return null;
+
+ ArrayList newarglist = Arguments;
foreach (MethodBase candidate in me.Methods){
- bool candidate_expanded;
- ConversionType m = IsApplicable (ec, Arguments, candidate, out candidate_expanded);
+ bool candidate_expanded, object_args_present;
+ newarglist = Arguments;
+ if (argument_count > 0 && namedArgs.Count != 0) {
+ newarglist = ReorderArguments (candidate, Arguments, namedArgs, ref errorMsg, loc);
+ if (newarglist == null)
+ continue;
+ }
+
+ ConversionType m = IsApplicable (ec, newarglist, candidate, out candidate_expanded, out object_args_present);
if (candidate_expanded)
expanded_candidates [candidate] = candidate;
if (m == ConversionType.None)
continue;
else if (m == ConversionType.Narrowing) {
+ if (object_args_present) // if the narrowing conversion was due
+ // to the argument being an object
+ lateBindingCandidates.Add (candidate);
if (method == null) {
method = candidate;
narrowing_candidate = true;
}
if (candidates.Count == 0) {
- if (narrow_count > 1)
- method = null;
- else if (narrow_count == 1)
+ if (lateBindingCandidates.Count > 1) {
+ isLateBindingRequired = true;
+ return null;
+ }
+
+ if (narrow_count > 1) {
+ if (lateBindingCandidates.Count == 1)
+ method = (MethodBase) lateBindingCandidates [0];
+ else
+ method = null;
+ } else if (narrow_count == 1)
candidates = null;
} else if (candidates.Count == 1) {
method = (MethodBase)candidates [0];
candidates = null;
} else
- narrow_count = 0;
-
- if (Arguments == null)
- argument_count = 0;
- else
- argument_count = Arguments.Count;
+ narrow_count = 0;
-
if (method == null) {
//
// Okay so we have failed to find anything so we
bool dummy;
if (narrow_count != 0) {
- if (IsApplicable (ec, Arguments, c, out dummy) == ConversionType.None)
+ if (IsApplicable (ec, Arguments, c, out dummy) == ConversionType.None)
continue;
Report.Error (1502, loc,
"Overloaded match for method '" +
if (candidates != null) {
foreach (MethodBase candidate in candidates){
- if (candidate == method)
- continue;
+ if (candidate == method)
+ continue;
+
if (BetterFunction (ec, Arguments, candidate, method,
false, loc) == Applicability.Better) {
- Report.Error (
- 121, loc,
- "Ambiguous call of '" + me.Name + "' when selecting function due to implicit casts");
+ Report.Error (
+ 121, loc,
+ "Ambiguous call of '" + me.Name + "' when selecting function due to implicit casts");
return null;
- }
+ }
}
}
bool chose_params_expanded = expanded_candidates.Contains (method);
- Arguments = ConstructArgumentList(ec, Arguments, method);
+ newarglist = Arguments;
+ if (argument_count > 0 && namedArgs.Count != 0) {
+ string err = "";
+ newarglist = ReorderArguments (method, Arguments, namedArgs, ref err, loc);
+ if (newarglist == null)
+ return null;
+ }
+ Arguments = ConstructArgumentList(ec, newarglist, namedArgs, method);
if (VerifyArgumentsCompat (ec, Arguments, argument_count, method,
chose_params_expanded, null, loc))
{
return null;
}
- public static ArrayList ConstructArgumentList (EmitContext ec, ArrayList Arguments, MethodBase method)
+ internal static bool CheckNamedArguments (ArrayList Arguments, Location loc)
+ {
+ if (Arguments == null || Arguments.Count == 0)
+ return true;
+
+ bool namedArgFound = false;
+ for (int index = 0; index < Arguments.Count; index ++) {
+ Argument a = (Argument) Arguments [index];
+ if (a.ParamName == null || a.ParamName == "") {
+ if (namedArgFound) {
+ Report.Error (30241, loc,
+ "Named argument expected");
+ return false;
+ }
+ } else
+ namedArgFound = true;
+ }
+
+ return true;
+ }
+
+ internal static bool GetNamedArgPos (ArrayList Arguments, ref CaseInsensitiveHashtable namedArgs, Location loc)
+ {
+ namedArgs.Clear ();
+ if (Arguments == null || Arguments.Count == 0)
+ return true;
+ for (int index = 0; index < Arguments.Count; index ++) {
+ Argument a = (Argument) Arguments [index];
+ if (a.ParamName == null || a.ParamName == "")
+ // none of the args are named
+ return true;
+ if (namedArgs.Contains (a.ParamName)) {
+ Report.Error (30274, loc, "Parameter '" + a.ParamName +"'already has a matching argument");
+ return false;
+ }
+ namedArgs.Add (a.ParamName, index);
+ }
+ return true;
+ }
+
+ public static ArrayList ConstructArgumentList (EmitContext ec, ArrayList Arguments, CaseInsensitiveHashtable namedArgs, MethodBase method)
{
ArrayList newarglist = new ArrayList();
int arg_count = Arguments == null ? 0 : Arguments.Count;
ParameterData pd = GetParameterData (method);
-
-
+ bool argNamesGiven = (namedArgs.Count > 0);
for (int i = 0; i < arg_count; i++) {
Argument a = (Argument) Arguments [i];
Type param_type = pd.ParameterType (i);
bool IsDelegate = TypeManager.IsDelegateType (param_type);
+ if (a.ArgType == Argument.AType.NoArg) {
+ Expression pdvalue = pd.DefaultValue (i);
+ pdvalue.Resolve (ec);
+ if (pdvalue != NullLiteral.Null)
+ pdvalue = ConvertImplicit (ec, pdvalue, param_type, Location.Null);;
+ if (argNamesGiven)
+ a = new Argument (pd.ParameterName (i), pdvalue, Argument.AType.Expression);
+ else
+ a = new Argument (pdvalue, Argument.AType.Expression);
+ a.Resolve (ec, Location.Null);
+ }
+
if (IsDelegate) {
if (a.ArgType == Argument.AType.AddressOf) {
a = new Argument ((Expression) a.Expr, Argument.AType.Expression);
return newarglist;
for (int i = arg_count; i < pd.Count; i++) {
+ Type param_type = pd.ParameterType (i);
Expression e = pd.DefaultValue (i);
- Argument a = new Argument (e, Argument.AType.Expression);
+ e.Resolve (ec);
+ if (e != NullLiteral.Null)
+ e = ConvertImplicit (ec, e, param_type, Location.Null);
+ Argument a = null;
+ if (argNamesGiven)
+ a = new Argument (e, Argument.AType.Expression);
+ else
+ a = new Argument (pd.ParameterName (i), e, Argument.AType.Expression);
if ((pd.ParameterModifier (i) & Parameter.Modifier.REF) != 0)
a.ArgType = Argument.AType.Ref;
- e.Resolve (ec);
a.Resolve (ec, Location.Null);
newarglist.Add (a);
}
return false;
}
if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS &&
- chose_params_expanded)
+ chose_params_expanded)
parameter_type = TypeManager.TypeToCoreType (parameter_type.GetElementType ());
- if (a.Type != parameter_type){
+ // By pass conversion for foll. case and handle it in EmitArguments()
+
+ if (a.ArgType != Argument.AType.Ref && a.Type != parameter_type){
Expression conv;
conv = ConvertImplicit (ec, a_expr, parameter_type, loc);
}
Parameter.Modifier a_mod = a.GetParameterModifier () &
- ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
+ ~(Parameter.Modifier.REF);
Parameter.Modifier p_mod = pd.ParameterModifier (j) &
- ~(Parameter.Modifier.OUT | Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
+ ~(Parameter.Modifier.REF | Parameter.Modifier.OPTIONAL);
if (a_mod != p_mod &&
pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
return true;
}
-
+
public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
this.is_left_hand = true;
Expression expr_to_return = DoResolve (ec);
+ if (expr_to_return is PropertyGroupExpr) {
+ PropertyGroupExpr pe = expr_to_return as PropertyGroupExpr;
+ pe = (PropertyGroupExpr) pe.ResolveLValue (ec, right_side);
+ if (pe == null)
+ return null;
+ if (pe.IndexerAccessRequired) {
+ if (pe.Type.IsArray) {
+ // If we are here, expr must be an ArrayAccess
+ ArrayList idxs = new ArrayList();
+ foreach (Argument a in Arguments)
+ {
+ idxs.Add (a.Expr);
+ }
+ ElementAccess ea = new ElementAccess (expr_to_return, idxs, expr.Location);
+ ArrayAccess aa = new ArrayAccess (ea, expr_to_return.Location);
+ expr_to_return = aa.DoResolve(ec);
+ expr_to_return.eclass = ExprClass.Variable;
+ } else {
+ //
+ // check whether this is a indexer
+ //
+ ArrayList idxs = new ArrayList();
+ foreach (Argument a in Arguments) {
+ idxs.Add (a.Expr);
+ }
+ ElementAccess ea = new ElementAccess (expr_to_return, idxs, expr.Location);
+ IndexerAccess ia = new IndexerAccess (ea, expr_to_return.Location);
+ if (is_left_hand)
+ expr_to_return = ia.DoResolveLValue (ec, right_side);
+ else
+ expr_to_return = ia.DoResolve(ec);
+ }
+ return expr_to_return;
+ }
+ }
- if (expr_to_return is IndexerAccess) {
+ if (expr_to_return is IndexerAccess && is_left_hand) {
IndexerAccess ia = expr_to_return as IndexerAccess;
expr_to_return = ia.DoResolveLValue (ec, right_side);
}
// trigger the invocation
//
Expression expr_to_return = null;
+ Expression temp = null;
if (expr is BaseAccess)
is_base = true;
+ ResolveFlags flags;
if ((ec.ReturnType != null) && (expr.ToString() == ec.BlockName)) {
ec.InvokingOwnOverload = true;
- expr = expr.Resolve (ec, ResolveFlags.MethodGroup);
+ flags = ResolveFlags.MethodGroup;
+ temp = expr.Resolve (ec, flags);
ec.InvokingOwnOverload = false;
}
else
{
ec.InvokingOwnOverload = false;
- expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
- }
- if (expr == null)
+ flags = ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup;
+ temp = expr.Resolve (ec, flags);
+ }
+
+ if (temp == null) {
+ if (is_left_hand)
+ return null;
+
+ if (expr is MemberAccess) {
+ MemberAccess m = expr as MemberAccess;
+ if (m.Expr.Type == TypeManager.object_type) {
+ StatementSequence etmp = new StatementSequence (ec.CurrentBlock,
+ loc, expr, Arguments,
+ is_retval_required, is_left_hand);
+ if (!etmp.ResolveArguments (ec))
+ return null;
+ etmp.GenerateLateBindingStatements();
+ this.is_latebinding = true;
+ return etmp.Resolve (ec);
+ }
+ }
return null;
+ }
+
+ expr = temp;
if (expr is Invocation) {
// FIXME Calls which return an Array are not resolved (here or in the grammar)
expr = expr.Resolve(ec);
}
- if (!(expr is MethodGroupExpr))
+ if (!(expr is MethodGroupExpr || expr is PropertyGroupExpr))
{
Type expr_type = expr.Type;
if (expr is MethodGroupExpr)
{
MethodGroupExpr mg = (MethodGroupExpr) expr;
- method = OverloadResolve (ec, mg, ref Arguments, loc);
-
+ bool isLateBindingRequired = false;
+ method = OverloadResolve (ec, mg, ref Arguments, loc, out isLateBindingRequired);
if (method == null)
{
+ if (isLateBindingRequired) {
+ Expression type_expr = new TypeOf (Parser.DecomposeQI (mg.DeclaringType.Name, loc), loc);
+ StatementSequence etmp = new StatementSequence (ec.CurrentBlock,
+ loc, null, mg.Name, type_expr,
+ Arguments, is_retval_required, is_left_hand);
+ if (! etmp.ResolveArguments (ec))
+ return null;
+ etmp.GenerateLateBindingStatements ();
+ return etmp.Resolve (ec);
+ }
Error (30455,
- "Could not find any applicable function to invoke for this argument list");
+ "Could not find any applicable function to invoke for this argument list" + errorMsg);
return null;
}
return expr_to_return;
}
- if (expr is PropertyExpr)
+ if (expr is PropertyGroupExpr)
{
- PropertyExpr pe = ((PropertyExpr) expr);
- if (pe.PropertyArgs != null)
+ PropertyGroupExpr pe = ((PropertyGroupExpr) expr);
+ if (pe.Arguments != null)
goto skip_already_resolved_property;
- pe.PropertyArgs = (ArrayList) Arguments;
- MethodBase mi = pe.PropertyInfo.GetGetMethod(true);
-
- bool expanded = false;
- if (IsApplicable(ec, pe.PropertyArgs, mi, out expanded) != ConversionType.None) {
- if(VerifyArgumentsCompat (ec, pe.PropertyArgs,
- pe.PropertyArgs.Count, mi, expanded, null, loc, pe.Name))
- {
- expr_to_return = pe.DoResolve (ec);
- expr_to_return.eclass = ExprClass.PropertyAccess;
- Arguments = new ArrayList ();
- return expr_to_return;
- }
- else
- {
- throw new Exception("Error resolving Property Access expression\n" + pe.ToString());
- }
- } else {
- pe.PropertyArgs = new ArrayList ();
- if (VerifyArgumentsCompat (ec, pe.PropertyArgs,
- 0, mi, false, null, loc, pe.Name)) {
- expr = pe.DoResolve (ec);
- expr.eclass = ExprClass.PropertyAccess;
- } else {
- throw new Exception("Error resolving Property Access expression\n" + pe.ToString());
- }
+ if (Arguments != null)
+ pe.Arguments = (ArrayList) Arguments.Clone ();
+ if (is_left_hand)
+ return pe;
+ string name = pe.Name;
+ pe = (PropertyGroupExpr) pe.Resolve (ec);
+ if (pe == null) {
+ Error (30057, "Property '" + name + "' cannot be invoked with given arguments");
+ return null;
}
+
+ if (!pe.IndexerAccessRequired)
+ return pe;
+ expr = pe;
}
skip_already_resolved_property:
// We can't resolve now, but we
// have to try to access the array with a call
// to LateIndexGet/Set in the runtime
- Expression lig_call_expr;
-
- if (!is_left_hand)
- lig_call_expr = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexGet", Location.Null);
- else
- lig_call_expr = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexSet", Location.Null);
- Expression obj_type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", Location.Null);
- ArrayList adims = new ArrayList();
-
- ArrayList ainit = new ArrayList();
- foreach (Argument a in Arguments)
- ainit.Add ((Expression) a.Expr);
-
- adims.Add ((Expression) new IntLiteral (Arguments.Count));
-
- Expression oace = new ArrayCreation (obj_type, adims, "", ainit, Location.Null);
-
- ArrayList args = new ArrayList();
- args.Add (new Argument(expr, Argument.AType.Expression));
- args.Add (new Argument(oace, Argument.AType.Expression));
- args.Add (new Argument(NullLiteral.Null, Argument.AType.Expression));
-
- Expression lig_call = new Invocation (lig_call_expr, args, Location.Null);
- expr_to_return = lig_call.Resolve(ec);
- expr_to_return.eclass = ExprClass.Variable;
+ if (! is_left_hand) {
+ StatementSequence etmp = new StatementSequence (ec.CurrentBlock,
+ loc, ia, Arguments,
+ true, false);
+ if (!etmp.ResolveArguments (ec))
+ return null;
+ etmp.GenerateLateBindingStatements();
+ return etmp.Resolve (ec);
+ }
+ return null;
}
}
return expr_to_return;
}
- static void Error_WrongNumArguments (Location loc, String name, int arg_count)
- {
- Report.Error (1501, loc, "No overload for method `" + name + "' takes `" +
+ static void Error_WrongNumArguments (Location loc, String name, int arg_count)
+ {
+ Report.Error (1501, loc, "No overload for method `" + name + "' takes `" +
arg_count + "' arguments");
- }
+ }
// <summary>
// Emits the list of arguments as an array
public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
{
ParameterData pd = GetParameterData (mb);
-
//
// If we are calling a params method with no arguments, special case it
//
for (int i = 0; i < top; i++){
Argument a = (Argument) arguments [i];
+ Type parameter_type = pd.ParameterType(i);
+ Type argtype = a.Type;
+ Type arg_expr_type = a.Expr.Type;
if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
//
EmitParams (ec, i, arguments);
return;
}
-
- if ((a.ArgType == Argument.AType.Ref || a.ArgType == Argument.AType.Out) &&
- !(a.Expr is IMemoryLocation)) {
- LocalTemporary tmp = new LocalTemporary (ec, pd.ParameterType (i));
+ if ((a.ArgType == Argument.AType.Ref ) &&
+ (parameter_type != arg_expr_type ||
+ ! (a.Expr is IMemoryLocation))) {
- a.Expr.Emit (ec);
- tmp.Store (ec);
- a = new Argument (tmp, a.ArgType);
+ LocalTemporary localtmp = new LocalTemporary (ec, parameter_type );
+
+ if((arg_expr_type != parameter_type) && (a.ArgType == Argument.AType.Ref)) {
+ Expression e = ConvertImplicit (ec, a.Expr, parameter_type, Location.Null);
+ is_byref_conversion = true;
+ e.Emit (ec);
+ } else
+ a.Expr.Emit (ec);
+
+
+
+ if (tempvars == null)
+ tempvars = new ArrayList ();
+ if (a.Expr is IMemoryLocation && is_byref_conversion ) {
+ Expression conv;
+ if(argtype.IsByRef)
+ argtype = argtype.GetElementType();
+ conv = ConvertImplicit (ec, localtmp, argtype, Location.Null);
+ tempvars.Add (new Assign (a.Expr, conv, Location.Null));
+
+ } else if (a.Expr is PropertyGroupExpr) {
+ // FIXME: We shouldnt be doing Resolve from inside 'Emit'.
+ // Have to find a way to push this up to 'Resolve'
+ Expression conv;
+ if(argtype.IsByRef)
+ argtype = argtype.GetElementType();
+ conv = ConvertImplicit (ec, localtmp, argtype, Location.Null);
+ Assign assgn = new Assign (a.Expr, conv, Location.Null);
+ Expression e = assgn.Resolve (ec);
+ tempvars.Add (e);
+ }
+ localtmp.Store (ec);
+ a = new Argument (localtmp, a.ArgType);
}
-
- a.Emit (ec);
- }
+ a.Emit (ec);
+ }
+
+
if (pd.Count > top &&
pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
{
ILGenerator ig = ec.ig;
bool struct_call = false;
+ bool is_myclass = false;
+
+ if (instance_expr is This && ((This) instance_expr).AccessType == This.TypeOfAccess.MyClass)
+ is_myclass = true;
Type decl_type = method.DeclaringType;
EmitArguments (ec, method, Arguments);
- if (is_static || struct_call || is_base)
+ if (is_static || struct_call || is_base || is_myclass)
{
if (method is MethodInfo)
{
}
}
+/*
static void EmitPropertyArgs (EmitContext ec, ArrayList prop_args)
{
int top = prop_args.Count;
a.Emit (ec);
}
}
+*/
public override void Emit (EmitContext ec)
{
MethodGroupExpr mg = (MethodGroupExpr) this.expr;
-
+
EmitCall (
ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
}
//
if (method is MethodInfo){
Type ret = ((MethodInfo)method).ReturnType;
- if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
+ if ((TypeManager.TypeToCoreType (ret) != TypeManager.void_type) && !this.is_latebinding) {
ec.ig.Emit (OpCodes.Pop);
+
+ if (tempvars != null) {
+ foreach (Expression s in tempvars) {
+ if (s is ExpressionStatement)
+ ((ExpressionStatement) s).EmitStatement (ec);
+ else
+ s.Emit (ec);
+ }
+ tempvars.Clear ();
+ }
+ }
+
}
}
}
}
}
+/*
void Error_NegativeArrayIndex ()
{
Error (284, "Can not create array with a negative size");
return target;
}
+*/
//
// Creates the type of the array
/// </summary>
public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
+ public enum TypeOfAccess : byte {
+ Me, MyClass
+ }
+
Block block;
VariableInfo vi;
+ TypeOfAccess access_type;
+ public This (TypeOfAccess access_type, Block block, Location loc)
+ {
+ this.loc = loc;
+ this.block = block;
+ this.access_type = access_type;
+ }
+
public This (Block block, Location loc)
{
this.loc = loc;
this.block = block;
+ this.access_type = TypeOfAccess.Me;
}
public This (Location loc)
{
this.loc = loc;
+ this.access_type = TypeOfAccess.Me;
+ }
+
+ public TypeOfAccess AccessType {
+ get { return access_type; }
}
public bool IsAssigned (EmitContext ec, Location loc)
public readonly string Identifier;
Expression expr;
Expression member_lookup;
+ bool is_invocation = false;
+ bool is_left_hand;
+ bool is_addressof = false;
public MemberAccess (Expression expr, string id, Location l)
{
loc = l;
}
+ public MemberAccess (Expression expr, string id, Location l, bool isInvocation)
+ {
+ this.expr = expr;
+ Identifier = id;
+ loc = l;
+ is_invocation = isInvocation;
+ }
+
+ public bool IsInvocation {
+ get {
+ return is_invocation;
+ }
+ set {
+ is_invocation = value;
+ }
+ }
+
+ public bool IsAddressOf {
+ set {
+ is_addressof = value;
+ }
+ }
+
+ public bool IsLeftHand {
+ get {
+ return is_left_hand;
+ }
+ set {
+ is_left_hand = value;
+ }
+ }
+
public Expression Expr {
get {
return expr;
Expression left, Location loc,
Expression left_original)
{
- bool left_is_type, left_is_explicit;
+ bool left_is_type, left_is_explicit;
+
// If 'left' is null, then we're called from SimpleNameResolve and this is
// a member in the currently defining class.
if (fi is FieldBuilder) {
Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
-
if (c != null) {
- //object o = c.LookupConstantValue (ec);
+ object o;
+ if (!c.LookupConstantValue (out o, ec))
+ return null;
+
object real_value = ((Constant) c.Expr).GetValue ();
+ Expression exp = Constantify (real_value, fi.FieldType);
- return Constantify (real_value, fi.FieldType);
- }
+ return exp;
+ }
}
+
+ // IsInitOnly is because of MS compatibility, I don't know why but they emit decimal constant as InitOnly
+
+ if (fi.IsInitOnly && !(fi is FieldBuilder) && fi.FieldType == TypeManager.decimal_type) {
+ object[] attrs = fi.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false);
+ if (attrs.Length == 1)
+ return new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value);
+ }
+
+
if (fi.IsLiteral) {
Type t = fi.FieldType;
if (member_lookup is IMemberExpr) {
IMemberExpr me = (IMemberExpr) member_lookup;
- if (left_is_type){
- MethodGroupExpr mg = me as MethodGroupExpr;
- if ((mg != null) && left_is_explicit && left.Type.IsInterface)
- mg.IsExplicitImpl = left_is_explicit;
-
- if (!me.IsStatic){
- if (IdenticalNameAndTypeName (ec, left_original, loc))
- return member_lookup;
-
- SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
- return null;
+ if (left_is_type) {
+ if (me is PropertyGroupExpr) {
+ PropertyGroupExpr mg = me as PropertyGroupExpr;
+ if ((mg != null) && left_is_explicit && left.Type.IsInterface)
+ mg.IsExplicitImpl = left_is_explicit;
+
+ if (!me.IsStatic){
+ if (IdenticalNameAndTypeName (ec, left_original, loc))
+ return member_lookup;
+
+ SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
+ return null;
+ }
+ } else {
+ MethodGroupExpr mg = me as MethodGroupExpr;
+ if ((mg != null) && left_is_explicit && left.Type.IsInterface)
+ mg.IsExplicitImpl = left_is_explicit;
+
+ if (!me.IsStatic){
+ if (IdenticalNameAndTypeName (ec, left_original, loc))
+ return member_lookup;
+
+ SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
+ return null;
+ }
}
} else {
SimpleName child_expr = (SimpleName) expr;
Expression new_expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
+ ((SimpleName) new_expr).IsInvocation = is_invocation;
if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
return new_expr.Resolve (ec, flags);
}
member_lookup = MemberLookup (ec, expr_type, Identifier, loc);
-
if (member_lookup == null)
{
// Error has already been reported.
expr_type, expr_type, AllMemberTypes, AllBindingFlags |
BindingFlags.NonPublic, Identifier);
- if (lookup == null)
- Error (30456, "'" + expr_type + "' does not contain a definition for '" + Identifier + "'");
+ if (lookup == null) {
+ if (expr_type != TypeManager.object_type)
+ Error (30456, "'" + expr_type + "' does not contain a definition for '" + Identifier + "'");
+ // If this came as a part of Invocation,
+ // Since argumets are not known, return null,
+ // let Invocation's Resolve take care
+ if (is_invocation)
+ return null;
+
+ else if (! is_left_hand) {
+ StatementSequence etmp = new StatementSequence (ec.CurrentBlock,
+ loc, this, null,
+ true, is_left_hand);
+ etmp.GenerateLateBindingStatements();
+ return etmp.Resolve (ec);
+ }
+
+ // if the expression is a left hand side of an assignment,
+ // return null, as we dont know the RHS
+ // Let assign take care of Late Binding
+ return null;
+ }
else
{
if ((expr_type != ec.ContainerType) &&
if (member_lookup == null)
return null;
+ if ((member_lookup is MethodGroupExpr) && ! is_invocation && !is_addressof) {
+ Expression inv = new Invocation (this, new ArrayList (), loc);
+ return inv.Resolve (ec);
+ }
+
+ if (member_lookup is PropertyGroupExpr && is_invocation) // As we dont know the arguments yet
+ return member_lookup;
+
// The following DoResolve/DoResolveLValue will do the definite assignment
// check.
if (right_side != null)
else
member_lookup = member_lookup.DoResolve (ec);
+
return member_lookup;
}
return ix;
}
}
-
- Report.Error (21, loc,
- "Type '" + TypeManager.MonoBASIC_Name (lookup_type) +
- "' does not have any indexers defined");
return null;
}
}
MethodInfo get, set;
Indexers ilist;
ArrayList set_arguments;
- bool is_base_indexer;
+ //bool is_base_indexer;
protected Type indexer_type;
protected Type current_type;
Location loc)
{
this.instance_expr = instance_expr;
- this.is_base_indexer = is_base_indexer;
+ //this.is_base_indexer = is_base_indexer;
this.eclass = ExprClass.Value;
this.loc = loc;
}
+ public Expression Instance {
+ get {
+ return instance_expr;
+ }
+ }
+
+ public ArrayList Arguments {
+ get {
+ return arguments;
+ }
+ }
+
protected virtual bool CommonResolve (EmitContext ec)
{
indexer_type = instance_expr.Type;
//
// This is a group of properties, piles of them.
- if (ilist == null)
+ if (ilist == null) {
ilist = Indexers.GetIndexersForType (
current_type, indexer_type, loc);
+ if (ilist == null && indexer_type != TypeManager.object_type) {
+ Report.Error (21, loc,
+ "Type '" + TypeManager.MonoBASIC_Name (indexer_type) +
+ "' does not have any indexers defined");
+ return null;
+ }
+ }
+
//
// Step 2: find the proper match
//
ec, new MethodGroupExpr (ilist.getters, loc), arguments, loc);
if (get == null){
- Error (30524, "indexer can not be used in this context, because " +
- "it lacks a 'get' accessor");
+ if (instance_expr.Type != TypeManager.object_type)
+ Error (30524, "indexer can not be used in this context, because " +
+ "it lacks a 'get' accessor");
return null;
}
Type right_type = right_side.Type;
- if (ilist == null)
+ if (ilist == null) {
ilist = Indexers.GetIndexersForType (
current_type, indexer_type, loc);
+ if (ilist == null && indexer_type != TypeManager.object_type) {
+ Report.Error (21, loc,
+ "Type '" + TypeManager.MonoBASIC_Name (indexer_type) +
+ "' does not have any indexers defined");
+ return null;
+ }
+ }
if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
set_arguments = (ArrayList) arguments.Clone ();