namespace Mono.CSharp {
using System;
using System.Collections;
- using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
Indirection, AddressOf, TOP
}
- Operator oper;
- Expression expr;
+ public Operator Oper;
+ public Expression Expr;
Location loc;
public Unary (Operator op, Expression expr, Location loc)
{
- this.oper = op;
- this.expr = expr;
+ this.Oper = op;
+ this.Expr = expr;
this.loc = loc;
}
- public Expression Expr {
- get {
- return expr;
- }
-
- set {
- expr = value;
- }
- }
-
- public Operator Oper {
- get {
- return oper;
- }
-
- set {
- oper = value;
- }
- }
-
/// <summary>
/// Returns a stringified representation of the Operator
/// </summary>
- string OperName ()
+ static public string OperName (Operator oper)
{
switch (oper){
case Operator.UnaryPlus:
oper_names [(int) Operator.AddressOf] = "op_AddressOf";
}
- void error23 (Type t)
+ void Error23 (Type t)
{
Report.Error (
- 23, loc, "Operator " + OperName () +
+ 23, loc, "Operator " + OperName (Oper) +
" cannot be applied to operand of type `" +
TypeManager.CSharpName (t) + "'");
}
if (expr is IntConstant)
e = new IntConstant (-((IntConstant) expr).Value);
- else if (expr is UIntConstant)
- e = new LongConstant (-((UIntConstant) expr).Value);
+ else if (expr is UIntConstant){
+ uint value = ((UIntConstant) expr).Value;
+
+ if (value < 2147483649)
+ return new IntConstant (-(int)value);
+ else
+ e = new LongConstant (value);
+ }
else if (expr is LongConstant)
e = new LongConstant (-((LongConstant) expr).Value);
+ else if (expr is ULongConstant){
+ ulong value = ((ULongConstant) expr).Value;
+
+ if (value < 9223372036854775809)
+ return new LongConstant(-(long)value);
+ }
else if (expr is FloatConstant)
e = new FloatConstant (-((FloatConstant) expr).Value);
else if (expr is DoubleConstant)
e = new IntConstant (-((ShortConstant) expr).Value);
else if (expr is UShortConstant)
e = new IntConstant (-((UShortConstant) expr).Value);
-
return e;
}
{
Type expr_type = e.Type;
- switch (oper){
+ switch (Oper){
case Operator.UnaryPlus:
return e;
case Operator.LogicalNot:
if (expr_type != TypeManager.bool_type) {
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
(expr_type == TypeManager.int64_type) ||
(expr_type == TypeManager.uint64_type) ||
(expr_type.IsSubclassOf (TypeManager.enum_type)))){
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
if (expr_type == TypeManager.uint64_type)
return new ULongConstant (~ ((ULongConstant) e).Value);
- throw new Exception (
- "FIXME: Implement constant OnesComplement of:" +
- expr_type);
+ Error23 (expr_type);
+ return null;
}
throw new Exception ("Can not constant fold");
}
Expression ResolveOperator (EmitContext ec)
{
- Type expr_type = expr.Type;
+ Type expr_type = Expr.Type;
//
// Step 1: Perform Operator Overload location
Expression mg;
string op_name;
- op_name = oper_names [(int) oper];
+ op_name = oper_names [(int) Oper];
mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
if (mg != null) {
Expression e = StaticCallExpr.MakeSimpleCall (
- ec, (MethodGroupExpr) mg, expr, loc);
+ ec, (MethodGroupExpr) mg, Expr, loc);
if (e == null){
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
//
// Step 2: Default operations on CLI native types.
//
- if (expr is Constant)
- return Reduce (ec, expr);
+ if (Expr is Constant)
+ return Reduce (ec, Expr);
- if (oper == Operator.LogicalNot){
+ if (Oper == Operator.LogicalNot){
if (expr_type != TypeManager.bool_type) {
- error23 (expr.Type);
+ Error23 (Expr.Type);
return null;
}
return this;
}
- if (oper == Operator.OnesComplement) {
+ if (Oper == Operator.OnesComplement) {
if (!((expr_type == TypeManager.int32_type) ||
(expr_type == TypeManager.uint32_type) ||
(expr_type == TypeManager.int64_type) ||
(expr_type == TypeManager.uint64_type) ||
(expr_type.IsSubclassOf (TypeManager.enum_type)))){
- error23 (expr.Type);
+ Expression e;
+
+ e = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc);
+ if (e != null){
+ type = TypeManager.int32_type;
+ return this;
+ }
+ e = ConvertImplicit (ec, Expr, TypeManager.uint32_type, loc);
+ if (e != null){
+ type = TypeManager.uint32_type;
+ return this;
+ }
+ e = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc);
+ if (e != null){
+ type = TypeManager.int64_type;
+ return this;
+ }
+ e = ConvertImplicit (ec, Expr, TypeManager.uint64_type, loc);
+ if (e != null){
+ type = TypeManager.uint64_type;
+ return this;
+ }
+ Error23 (expr_type);
return null;
}
type = expr_type;
return this;
}
- if (oper == Operator.UnaryPlus) {
+ if (Oper == Operator.UnaryPlus) {
//
// A plus in front of something is just a no-op, so return the child.
//
- return expr;
+ return Expr;
}
//
// double operator- (double d)
// decimal operator- (decimal d)
//
- if (oper == Operator.UnaryNegation){
+ if (Oper == Operator.UnaryNegation){
Expression e = null;
+ //
+ // transform - - expr into expr
+ //
+ if (Expr is Unary){
+ Unary unary = (Unary) Expr;
+
+ if (unary.Oper == Operator.UnaryNegation)
+ return unary.Expr;
+ }
+
//
// perform numeric promotions to int,
// long, double.
// bt wrote as a decimal interger literal
//
type = TypeManager.int64_type;
- expr = ConvertImplicit (ec, expr, type, loc);
+ Expr = ConvertImplicit (ec, Expr, type, loc);
return this;
}
// -92233720368547758087 (-2^63) to be wrote as
// decimal integer literal.
//
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
return this;
}
- e = ConvertImplicit (ec, expr, TypeManager.int32_type, loc);
+ e = ConvertImplicit (ec, Expr, TypeManager.int32_type, loc);
if (e != null){
- expr = e;
+ Expr = e;
type = e.Type;
return this;
}
- e = ConvertImplicit (ec, expr, TypeManager.int64_type, loc);
+ e = ConvertImplicit (ec, Expr, TypeManager.int64_type, loc);
if (e != null){
- expr = e;
+ Expr = e;
type = e.Type;
return this;
}
- e = ConvertImplicit (ec, expr, TypeManager.double_type, loc);
+ e = ConvertImplicit (ec, Expr, TypeManager.double_type, loc);
if (e != null){
- expr = e;
+ Expr = e;
type = e.Type;
return this;
}
- error23 (expr_type);
+ Error23 (expr_type);
return null;
}
- if (oper == Operator.AddressOf){
- if (expr.eclass != ExprClass.Variable){
+ if (Oper == Operator.AddressOf){
+ if (Expr.eclass != ExprClass.Variable){
Error (211, loc, "Cannot take the address of non-variables");
return null;
}
return null;
}
- if (!TypeManager.VerifyUnManaged (expr.Type, loc)){
+ if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){
return null;
}
- //
- // This construct is needed because dynamic types
- // are not known by Type.GetType, so we have to try then to use
- // ModuleBuilder.GetType.
- //
- string ptr_type_name = expr.Type.FullName + "*";
- type = Type.GetType (ptr_type_name);
- if (type == null)
- type = RootContext.ModuleBuilder.GetType (ptr_type_name);
+ string ptr_type_name = Expr.Type.FullName + "*";
+ type = TypeManager.LookupType (ptr_type_name);
return this;
}
- if (oper == Operator.Indirection){
+ if (Oper == Operator.Indirection){
if (!ec.InUnsafe){
UnsafeError (loc);
return null;
// We create an Indirection expression, because
// it can implement the IMemoryLocation.
//
- return new Indirection (expr);
+ return new Indirection (Expr);
}
- Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+ Error (187, loc, "No such operator '" + OperName (Oper) + "' defined for type '" +
TypeManager.CSharpName (expr_type) + "'");
return null;
}
public override Expression DoResolve (EmitContext ec)
{
- expr = expr.Resolve (ec);
+ Expr = Expr.Resolve (ec);
- if (expr == null)
+ if (Expr == null)
return null;
eclass = ExprClass.Value;
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
- Type expr_type = expr.Type;
+ Type expr_type = Expr.Type;
- switch (oper) {
+ switch (Oper) {
case Operator.UnaryPlus:
throw new Exception ("This should be caught by Resolve");
case Operator.UnaryNegation:
- expr.Emit (ec);
+ Expr.Emit (ec);
ig.Emit (OpCodes.Neg);
break;
case Operator.LogicalNot:
- expr.Emit (ec);
+ Expr.Emit (ec);
ig.Emit (OpCodes.Ldc_I4_0);
ig.Emit (OpCodes.Ceq);
break;
case Operator.OnesComplement:
- expr.Emit (ec);
+ Expr.Emit (ec);
ig.Emit (OpCodes.Not);
break;
case Operator.AddressOf:
- ((IMemoryLocation)expr).AddressOf (ec);
+ ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);
break;
default:
throw new Exception ("This should not happen: Operator = "
- + oper.ToString ());
+ + Oper.ToString ());
}
}
/// </summary>
public void EmitLogicalNot (EmitContext ec)
{
- if (oper != Operator.LogicalNot)
+ if (Oper != Operator.LogicalNot)
throw new Exception ("EmitLogicalNot can only be called with !expr");
- expr.Emit (ec);
+ Expr.Emit (ec);
}
public override string ToString ()
{
- return "Unary (" + oper + ", " + expr + ")";
+ return "Unary (" + Oper + ", " + Expr + ")";
}
}
//
public class Indirection : Expression, IMemoryLocation, IAssignMethod {
Expression expr;
+ LocalTemporary temporary;
+ bool have_temporary;
public Indirection (Expression expr)
{
eclass = ExprClass.Variable;
}
+ void LoadExprValue (EmitContext ec)
+ {
+ }
+
public override void Emit (EmitContext ec)
{
- expr.Emit (ec);
- LoadFromPtr (ec.ig, Type, false);
+ ILGenerator ig = ec.ig;
+
+ if (temporary != null){
+ if (have_temporary){
+ temporary.Emit (ec);
+ return;
+ }
+ expr.Emit (ec);
+ ec.ig.Emit (OpCodes.Dup);
+ temporary.Store (ec);
+ have_temporary = true;
+ } else
+ expr.Emit (ec);
+
+ LoadFromPtr (ig, Type);
}
public void EmitAssign (EmitContext ec, Expression source)
{
- expr.Emit (ec);
+ if (temporary != null){
+ if (have_temporary){
+ temporary.Emit (ec);
+ return;
+ }
+ expr.Emit (ec);
+ ec.ig.Emit (OpCodes.Dup);
+ temporary.Store (ec);
+ have_temporary = true;
+ } else
+ expr.Emit (ec);
+
source.Emit (ec);
StoreFromPtr (ec.ig, type);
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp Mode)
{
- expr.Emit (ec);
+ if (temporary != null){
+ if (have_temporary){
+ temporary.Emit (ec);
+ return;
+ }
+ expr.Emit (ec);
+ ec.ig.Emit (OpCodes.Dup);
+ temporary.Store (ec);
+ have_temporary = true;
+ } else
+ expr.Emit (ec);
}
public override Expression DoResolve (EmitContext ec)
//
return this;
}
+
+ public new void CacheTemporaries (EmitContext ec)
+ {
+ temporary = new LocalTemporary (ec, type);
+ }
}
/// <summary>
expr = e;
}
- string OperName ()
+ static string OperName (Mode mode)
{
return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
"++" : "--";
}
- void error23 (Type t)
+ void Error23 (Type t)
{
Report.Error (
- 23, loc, "Operator " + OperName () +
+ 23, loc, "Operator " + OperName (mode) +
" cannot be applied to operand of type `" +
TypeManager.CSharpName (t) + "'");
}
return null;
}
- Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
+ Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +
TypeManager.CSharpName (expr_type) + "'");
return null;
}
{
return GetTypeSize (t.GetElementType ());
}
-
+
+ //
+ // Loads the proper "1" into the stack based on the type
+ //
+ static void LoadOne (ILGenerator ig, Type t)
+ {
+ if (t == TypeManager.uint64_type || t == TypeManager.int64_type)
+ ig.Emit (OpCodes.Ldc_I8, 1L);
+ else if (t == TypeManager.double_type)
+ ig.Emit (OpCodes.Ldc_R8, 1.0);
+ else if (t == TypeManager.float_type)
+ ig.Emit (OpCodes.Ldc_R4, 1.0F);
+ else if (t.IsPointer){
+ int n = PtrTypeSize (t);
+
+ if (n == 0)
+ ig.Emit (OpCodes.Sizeof, t);
+ else
+ IntConstant.EmitInt (ig, n);
+ } else
+ ig.Emit (OpCodes.Ldc_I4_1);
+ }
+
//
// FIXME: We need some way of avoiding the use of temp_storage
if (temp_storage == null)
temp_storage = new LocalTemporary (ec, expr_type);
+ ia.CacheTemporaries (ec);
+ ig.Emit (OpCodes.Nop);
switch (mode){
case Mode.PreIncrement:
case Mode.PreDecrement:
if (method == null){
expr.Emit (ec);
- if (expr_type == TypeManager.uint64_type ||
- expr_type == TypeManager.int64_type)
- ig.Emit (OpCodes.Ldc_I8, 1L);
- else if (expr_type == TypeManager.double_type)
- ig.Emit (OpCodes.Ldc_R8, 1.0);
- else if (expr_type == TypeManager.float_type)
- ig.Emit (OpCodes.Ldc_R4, 1.0F);
- else if (expr_type.IsPointer){
- int n = PtrTypeSize (expr_type);
-
- if (n == 0)
- ig.Emit (OpCodes.Sizeof, expr_type);
+ LoadOne (ig, expr_type);
+
+ //
+ // Select the opcode based on the check state (then the type)
+ // and the actual operation
+ //
+ if (ec.CheckState){
+ if (expr_type == TypeManager.int32_type ||
+ expr_type == TypeManager.int64_type){
+ if (mode == Mode.PreDecrement)
+ ig.Emit (OpCodes.Sub_Ovf);
+ else
+ ig.Emit (OpCodes.Add_Ovf);
+ } else if (expr_type == TypeManager.uint32_type ||
+ expr_type == TypeManager.uint64_type){
+ if (mode == Mode.PreDecrement)
+ ig.Emit (OpCodes.Sub_Ovf_Un);
+ else
+ ig.Emit (OpCodes.Add_Ovf_Un);
+ } else {
+ if (mode == Mode.PreDecrement)
+ ig.Emit (OpCodes.Sub_Ovf);
+ else
+ ig.Emit (OpCodes.Add_Ovf);
+ }
+ } else {
+ if (mode == Mode.PreDecrement)
+ ig.Emit (OpCodes.Sub);
else
- IntConstant.EmitInt (ig, n);
- } else
- ig.Emit (OpCodes.Ldc_I4_1);
-
- if (mode == Mode.PreDecrement)
- ig.Emit (OpCodes.Sub);
- else
- ig.Emit (OpCodes.Add);
- } else
+ ig.Emit (OpCodes.Add);
+ }
+ } else
method.Emit (ec);
-
+
temp_storage.Store (ec);
ia.EmitAssign (ec, temp_storage);
if (is_expr)
else
ig.Emit (OpCodes.Dup);
- if (expr_type == TypeManager.uint64_type ||
- expr_type == TypeManager.int64_type)
- ig.Emit (OpCodes.Ldc_I8, 1L);
- else if (expr_type == TypeManager.double_type)
- ig.Emit (OpCodes.Ldc_R8, 1.0);
- else if (expr_type == TypeManager.float_type)
- ig.Emit (OpCodes.Ldc_R4, 1.0F);
- else if (expr_type.IsPointer){
- int n = PtrTypeSize (expr_type);
-
- if (n == 0)
- ig.Emit (OpCodes.Sizeof, expr_type);
+ LoadOne (ig, expr_type);
+
+ if (ec.CheckState){
+ if (expr_type == TypeManager.int32_type ||
+ expr_type == TypeManager.int64_type){
+ if (mode == Mode.PostDecrement)
+ ig.Emit (OpCodes.Sub_Ovf);
+ else
+ ig.Emit (OpCodes.Add_Ovf);
+ } else if (expr_type == TypeManager.uint32_type ||
+ expr_type == TypeManager.uint64_type){
+ if (mode == Mode.PostDecrement)
+ ig.Emit (OpCodes.Sub_Ovf_Un);
+ else
+ ig.Emit (OpCodes.Add_Ovf_Un);
+ } else {
+ if (mode == Mode.PostDecrement)
+ ig.Emit (OpCodes.Sub_Ovf);
+ else
+ ig.Emit (OpCodes.Add_Ovf);
+ }
+ } else {
+ if (mode == Mode.PostDecrement)
+ ig.Emit (OpCodes.Sub);
else
- IntConstant.EmitInt (ig, n);
- } else
- ig.Emit (OpCodes.Ldc_I4_1);
-
- if (mode == Mode.PostDecrement)
- ig.Emit (OpCodes.Sub);
- else
- ig.Emit (OpCodes.Add);
+ ig.Emit (OpCodes.Add);
+ }
} else {
method.Emit (ec);
}
public override Expression DoResolve (EmitContext ec)
{
- probe_type = RootContext.LookupType (ec.TypeContainer, ProbeType, false, loc);
+ probe_type = RootContext.LookupType (ec.DeclSpace, ProbeType, false, loc);
if (probe_type == null)
return null;
{
}
+ enum Action {
+ AlwaysTrue, AlwaysNull, AlwaysFalse, LeaveOnStack, Probe
+ }
+
+ Action action;
+
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
-
+
expr.Emit (ec);
-
- ig.Emit (OpCodes.Isinst, probe_type);
- ig.Emit (OpCodes.Ldnull);
- ig.Emit (OpCodes.Cgt_Un);
+
+ switch (action){
+ case Action.AlwaysFalse:
+ ig.Emit (OpCodes.Pop);
+ IntConstant.EmitInt (ig, 0);
+ return;
+ case Action.AlwaysTrue:
+ ig.Emit (OpCodes.Pop);
+ ig.Emit (OpCodes.Nop);
+ IntConstant.EmitInt (ig, 1);
+ return;
+ case Action.LeaveOnStack:
+ // the `e != null' rule.
+ return;
+ case Action.Probe:
+ ig.Emit (OpCodes.Isinst, probe_type);
+ ig.Emit (OpCodes.Ldnull);
+ ig.Emit (OpCodes.Cgt_Un);
+ return;
+ }
+ throw new Exception ("never reached");
}
public override Expression DoResolve (EmitContext ec)
if (e == null)
return null;
+ Type etype = expr.Type;
+ bool warning_always_matches = false;
+ bool warning_never_matches = false;
+
+ type = TypeManager.bool_type;
+ eclass = ExprClass.Value;
+
+ //
+ // First case, if at compile time, there is an implicit conversion
+ // then e != null (objects) or true (value types)
+ //
+ e = ConvertImplicitStandard (ec, expr, probe_type, loc);
+ if (e != null){
+ expr = e;
+ if (etype.IsValueType)
+ action = Action.AlwaysTrue;
+ else
+ action = Action.LeaveOnStack;
+
+ warning_always_matches = true;
+ } else if (ExplicitReferenceConversionExists (etype, probe_type)){
+ //
+ // Second case: explicit reference convresion
+ //
+ if (expr is NullLiteral)
+ action = Action.AlwaysFalse;
+ else
+ action = Action.Probe;
+ } else {
+ action = Action.AlwaysFalse;
+ warning_never_matches = true;
+ }
+
if (RootContext.WarningLevel >= 1){
- if (expr.Type == probe_type || expr.Type.IsSubclassOf (probe_type)){
+ if (warning_always_matches)
Report.Warning (
183, loc,
"The expression is always of type `" +
TypeManager.CSharpName (probe_type) + "'");
- }
-
- if (expr.Type != probe_type && !probe_type.IsSubclassOf (expr.Type)){
- if (!probe_type.IsInterface)
+ else if (warning_never_matches){
+ if (!(probe_type.IsInterface || expr.Type.IsInterface))
Report.Warning (
184, loc,
"The expression is never of type `" +
TypeManager.CSharpName (probe_type) + "'");
}
}
-
- type = TypeManager.bool_type;
- eclass = ExprClass.Value;
return this;
}
{
}
+ bool do_isinst = false;
+
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
expr.Emit (ec);
- ig.Emit (OpCodes.Isinst, probe_type);
+
+ if (do_isinst)
+ ig.Emit (OpCodes.Isinst, probe_type);
}
+ static void Error_CannotConvertType (Type source, Type target, Location loc)
+ {
+ Report.Error (
+ 39, loc, "as operator can not convert from `" +
+ TypeManager.CSharpName (source) + "' to `" +
+ TypeManager.CSharpName (target) + "'");
+ }
+
public override Expression DoResolve (EmitContext ec)
{
Expression e = base.DoResolve (ec);
type = probe_type;
eclass = ExprClass.Value;
+ Type etype = expr.Type;
+
+ e = ConvertImplicit (ec, expr, probe_type, loc);
+ if (e != null){
+ expr = e;
+ do_isinst = false;
+ return this;
+ }
- return this;
+ if (ExplicitReferenceConversionExists (etype, probe_type)){
+ do_isinst = true;
+ return this;
+ }
+
+ Error_CannotConvertType (etype, probe_type, loc);
+ return null;
}
}
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is SByteConstant){
sbyte v = ((SByteConstant) expr).Value;
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is ShortConstant){
short v = ((ShortConstant) expr).Value;
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is UShortConstant){
ushort v = ((UShortConstant) expr).Value;
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is IntConstant){
int v = ((IntConstant) expr).Value;
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is UIntConstant){
uint v = ((UIntConstant) expr).Value;
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is LongConstant){
long v = ((LongConstant) expr).Value;
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is ULongConstant){
ulong v = ((ULongConstant) expr).Value;
return new FloatConstant ((float) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is FloatConstant){
float v = ((FloatConstant) expr).Value;
return new ULongConstant ((ulong) v);
if (target_type == TypeManager.double_type)
return new DoubleConstant ((double) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
if (expr is DoubleConstant){
double v = ((DoubleConstant) expr).Value;
return new ULongConstant ((ulong) v);
if (target_type == TypeManager.float_type)
return new FloatConstant ((float) v);
+ if (target_type == TypeManager.char_type)
+ return new CharConstant ((char) v);
}
return null;
if (expr == null)
return null;
+ bool old_state = ec.OnlyLookupTypes;
+ ec.OnlyLookupTypes = true;
target_type = target_type.Resolve (ec);
- if (target_type == null)
+ ec.OnlyLookupTypes = old_state;
+
+ if (target_type == null){
+ Report.Error (-10, loc, "Can not resolve type");
return null;
+ }
if (target_type.eclass != ExprClass.Type){
report118 (loc, target_type, "class");
ExclusiveOr,
BitwiseOr,
LogicalAnd,
- LogicalOr
+ LogicalOr,
+ TOP
}
Operator oper;
Expression left, right;
- MethodBase method;
+
+ //
+ // After resolution, method might contain the operator overload
+ // method.
+ //
+ protected MethodBase method;
ArrayList Arguments;
+
Location loc;
bool DelegateOperation;
+ // This must be kept in sync with Operator!!!
+ static string [] oper_names;
+
+ static Binary ()
+ {
+ oper_names = new string [(int) Operator.TOP];
+
+ oper_names [(int) Operator.Multiply] = "op_Multiply";
+ oper_names [(int) Operator.Division] = "op_Division";
+ oper_names [(int) Operator.Modulus] = "op_Modulus";
+ oper_names [(int) Operator.Addition] = "op_Addition";
+ oper_names [(int) Operator.Subtraction] = "op_Subtraction";
+ oper_names [(int) Operator.LeftShift] = "op_LeftShift";
+ oper_names [(int) Operator.RightShift] = "op_RightShift";
+ oper_names [(int) Operator.LessThan] = "op_LessThan";
+ oper_names [(int) Operator.GreaterThan] = "op_GreaterThan";
+ oper_names [(int) Operator.LessThanOrEqual] = "op_LessThanOrEqual";
+ oper_names [(int) Operator.GreaterThanOrEqual] = "op_GreaterThanOrEqual";
+ oper_names [(int) Operator.Equality] = "op_Equality";
+ oper_names [(int) Operator.Inequality] = "op_Inequality";
+ oper_names [(int) Operator.BitwiseAnd] = "op_BitwiseAnd";
+ oper_names [(int) Operator.BitwiseOr] = "op_BitwiseOr";
+ oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr";
+ oper_names [(int) Operator.LogicalOr] = "op_LogicalOr";
+ oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
+ }
+
public Binary (Operator oper, Expression left, Expression right, Location loc)
{
this.oper = oper;
/// <summary>
/// Returns a stringified representation of the Operator
/// </summary>
- string OperName ()
+ static string OperName (Operator oper)
{
switch (oper){
case Operator.Multiply:
return oper.ToString ();
}
+ public override string ToString ()
+ {
+ return "operator " + OperName (oper) + "(" + left.ToString () + ", " +
+ right.ToString () + ")";
+ }
+
Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
{
if (expr.Type == target_type)
return ConvertImplicit (ec, expr, target_type, new Location (-1));
}
-
+
+ public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
+ {
+ Report.Error (
+ 34, loc, "Operator `" + OperName (oper)
+ + "' is ambiguous on operands of type `"
+ + TypeManager.CSharpName (l) + "' "
+ + "and `" + TypeManager.CSharpName (r)
+ + "'");
+ }
+
//
// Note that handling the case l == Decimal || r == Decimal
// is taken care of by the Step 1 Operator Overload resolution.
type = TypeManager.double_type;
} else if (l == TypeManager.float_type || r == TypeManager.float_type){
//
- // if either operand is of type float, th eother operand is
- // converd to type float.
+ // if either operand is of type float, the other operand is
+ // converted to type float.
//
if (r != TypeManager.double_type)
right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
if ((other == TypeManager.sbyte_type) ||
(other == TypeManager.short_type) ||
(other == TypeManager.int32_type) ||
- (other == TypeManager.int64_type)){
- string oper = OperName ();
-
- Error (34, loc, "Operator `" + OperName ()
- + "' is ambiguous on operands of type `"
- + TypeManager.CSharpName (l) + "' "
- + "and `" + TypeManager.CSharpName (r)
- + "'");
- }
+ (other == TypeManager.int64_type))
+ Error_OperatorAmbiguous (loc, oper, l, r);
type = TypeManager.uint64_type;
} else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
//
return true;
}
- void error19 ()
+ static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
{
Error (19, loc,
- "Operator " + OperName () + " cannot be applied to operands of type `" +
- TypeManager.CSharpName (left.Type) + "' and `" +
- TypeManager.CSharpName (right.Type) + "'");
-
+ "Operator " + name + " cannot be applied to operands of type `" +
+ TypeManager.CSharpName (l) + "' and `" +
+ TypeManager.CSharpName (r) + "'");
+ }
+
+ void Error_OperatorCannotBeApplied ()
+ {
+ Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
}
static bool is_32_or_64 (Type t)
e = ForceConversion (ec, right, TypeManager.int32_type);
if (e == null){
- error19 ();
+ Error_OperatorCannotBeApplied ();
return null;
}
right = e;
return this;
}
- error19 ();
+ Error_OperatorCannotBeApplied ();
return null;
}
-
+
Expression ResolveOperator (EmitContext ec)
{
Type l = left.Type;
Type r = right.Type;
+ bool overload_failed = false;
+
//
// Step 1: Perform Operator Overload location
//
Expression left_expr, right_expr;
-
- string op = "op_" + oper;
-
+
+ string op = oper_names [(int) oper];
+
MethodGroupExpr union;
left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
if (r != l){
right_expr = MemberLookup (
ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
- union = Invocation.MakeUnionSet (left_expr, right_expr);
+ union = Invocation.MakeUnionSet (left_expr, right_expr, loc);
} else
union = (MethodGroupExpr) left_expr;
-
+
if (union != null) {
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);
+
+ method = Invocation.OverloadResolve (ec, union, Arguments, Location.Null);
if (method != null) {
MethodInfo mi = (MethodInfo) method;
+
type = mi.ReturnType;
return this;
} else {
- error19 ();
- return null;
+ overload_failed = true;
}
}
-
+
//
// Step 2: Default operations on CLI native types.
//
- // Only perform numeric promotions on:
- // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
+ //
+ // Step 0: String concatenation (because overloading will get this wrong)
//
if (oper == Operator.Addition){
//
// If any of the arguments is a string, cast to string
//
+
if (l == TypeManager.string_type){
if (r == TypeManager.void_type) {
- error19 ();
+ Error_OperatorCannotBeApplied ();
return null;
}
// object + string
if (l == TypeManager.void_type) {
- error19 ();
+ Error_OperatorCannotBeApplied ();
return null;
}
return this;
}
+
+ //
+ // Transform a + ( - b) into a - b
+ //
+ if (right is Unary){
+ Unary right_unary = (Unary) right;
+
+ if (right_unary.Oper == Unary.Operator.UnaryNegation){
+ oper = Operator.Subtraction;
+ right = right_unary.Expr;
+ r = right.Type;
+ }
+ }
+ }
+
+ if (oper == Operator.Equality || oper == Operator.Inequality){
+ if (l == TypeManager.bool_type || r == TypeManager.bool_type){
+ if (r != TypeManager.bool_type || l != TypeManager.bool_type){
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ type = TypeManager.bool_type;
+ return this;
+ }
+
+ //
+ // operator != (object a, object b)
+ // operator == (object a, object b)
+ //
+ // For this to be used, both arguments have to be reference-types.
+ // Read the rationale on the spec (14.9.6)
+ //
+ // Also, if at compile time we know that the classes do not inherit
+ // one from the other, then we catch the error there.
+ //
+ if (!(l.IsValueType || r.IsValueType)){
+ type = TypeManager.bool_type;
+
+ if (l == r)
+ return this;
+
+ if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
+ return this;
+
+ //
+ // Also, a standard conversion must exist from either one
+ //
+ if (!(StandardConversionExists (left, r) ||
+ StandardConversionExists (right, l))){
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+ //
+ // We are going to have to convert to an object to compare
+ //
+ if (l != TypeManager.object_type)
+ left = new EmptyCast (left, TypeManager.object_type);
+ if (r != TypeManager.object_type)
+ right = new EmptyCast (right, TypeManager.object_type);
+
+ //
+ // FIXME: CSC here catches errors cs254 and cs252
+ //
+ return this;
+ }
}
+ // Only perform numeric promotions on:
+ // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
+ //
if (oper == Operator.Addition || oper == Operator.Subtraction) {
if (l.IsSubclassOf (TypeManager.delegate_type) &&
r.IsSubclassOf (TypeManager.delegate_type)) {
if (lie || rie){
Expression temp;
+ //
+ // operator + (E e, U x)
+ //
+ if (oper == Operator.Addition){
+ if (lie && rie){
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ Type enum_type = lie ? l : r;
+ Type other_type = lie ? r : l;
+ Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
+;
+
+ if (underlying_type != other_type){
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ type = enum_type;
+ return this;
+ }
+
if (!rie){
temp = ConvertImplicit (ec, right, l, loc);
if (temp != null)
l = r;
}
}
-
+
if (oper == Operator.Equality || oper == Operator.Inequality ||
oper == Operator.LessThanOrEqual || oper == Operator.LessThan ||
oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){
type = l;
return this;
}
+ return null;
}
if (oper == Operator.LeftShift || oper == Operator.RightShift)
if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
if (l != TypeManager.bool_type || r != TypeManager.bool_type){
- error19 ();
+ Error_OperatorCannotBeApplied ();
return null;
}
return this;
}
- if (oper == Operator.Equality || oper == Operator.Inequality){
- if (l == TypeManager.bool_type || r == TypeManager.bool_type){
- if (r != TypeManager.bool_type || l != TypeManager.bool_type){
- error19 ();
- return null;
- }
-
- type = TypeManager.bool_type;
- return this;
- }
-
- //
- // operator != (object a, object b)
- // operator == (object a, object b)
- //
- // For this to be used, both arguments have to be reference-types.
- // Read the rationale on the spec (14.9.6)
- //
- // Also, if at compile time we know that the classes do not inherit
- // one from the other, then we catch the error there.
- //
- if (!(l.IsValueType || r.IsValueType)){
- type = TypeManager.bool_type;
-
- if (l == r)
- return this;
-
- if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
- return this;
-
- //
- // We are going to have to convert to an object to compare
- //
- if (l != TypeManager.object_type)
- left = new EmptyCast (left, TypeManager.object_type);
- if (r != TypeManager.object_type)
- right = new EmptyCast (right, TypeManager.object_type);
-
+ //
+ // operator & (bool x, bool y)
+ // operator | (bool x, bool y)
+ // operator ^ (bool x, bool y)
+ //
+ if (l == TypeManager.bool_type && r == TypeManager.bool_type){
+ if (oper == Operator.BitwiseAnd ||
+ oper == Operator.BitwiseOr ||
+ oper == Operator.ExclusiveOr){
+ type = l;
return this;
}
}
-
+
//
// Pointer comparison
//
//
// We are dealing with numbers
//
+ if (overload_failed){
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
if (!DoNumericPromotions (ec, l, r)){
- error19 ();
+ Error_OperatorCannotBeApplied ();
return null;
}
(l == TypeManager.uint64_type)))
type = l;
} else {
- error19 ();
+ Error_OperatorCannotBeApplied ();
return null;
}
}
return this;
}
- /// <summary>
- /// Constant expression reducer for binary operations
- /// </summary>
- public Expression ConstantFold (EmitContext ec)
- {
- object l = ((Constant) left).GetValue ();
- object r = ((Constant) right).GetValue ();
-
- if (l is string && r is string)
- return new StringConstant ((string) l + (string) r);
-
- Type result_type = null;
-
- //
- // Enumerator folding
- //
- if (left.Type == right.Type && left is EnumConstant)
- result_type = left.Type;
-
- switch (oper){
- case Operator.BitwiseOr:
- if ((l is int) && (r is int)){
- IntConstant v;
- int res = (int)l | (int)r;
-
- v = new IntConstant (res);
- if (result_type == null)
- return v;
- else
- return new EnumConstant (v, result_type);
- }
- break;
-
- case Operator.BitwiseAnd:
- if ((l is int) && (r is int)){
- IntConstant v;
- int res = (int)l & (int)r;
-
- v = new IntConstant (res);
- if (result_type == null)
- return v;
- else
- return new EnumConstant (v, result_type);
- }
- break;
- }
-
- return null;
- }
-
public override Expression DoResolve (EmitContext ec)
{
left = left.Resolve (ec);
eclass = ExprClass.Value;
if (left is Constant && right is Constant){
- //
- // This is temporary until we do the full folding
- //
- Expression e = ConstantFold (ec);
+ Expression e = ConstantFold.BinaryFold (
+ ec, oper, (Constant) left, (Constant) right, loc);
if (e != null)
return e;
}
else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
opcode = OpCodes.Add_Ovf_Un;
else
- opcode = OpCodes.Mul;
+ opcode = OpCodes.Add;
} else
opcode = OpCodes.Add;
break;
break;
case Operator.RightShift:
- opcode = OpCodes.Shr;
+ if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
+ opcode = OpCodes.Shr_Un;
+ else
+ opcode = OpCodes.Shr;
break;
case Operator.LeftShift:
ig.Emit (opcode);
}
+
+ public bool IsBuiltinOperator {
+ get {
+ return method == null;
+ }
+ }
}
public class PointerArithmetic : Expression {
if (expr == null || trueExpr == null || falseExpr == null)
return null;
+ eclass = ExprClass.Value;
if (trueExpr.Type == falseExpr.Type)
type = trueExpr.Type;
else {
Expression conv;
+ Type true_type = trueExpr.Type;
+ Type false_type = falseExpr.Type;
+ if (trueExpr is NullLiteral){
+ type = false_type;
+ return this;
+ } else if (falseExpr is NullLiteral){
+ type = true_type;
+ return this;
+ }
+
//
// First, if an implicit conversion exists from trueExpr
// to falseExpr, then the result type is of type falseExpr.Type
//
- conv = ConvertImplicit (ec, trueExpr, falseExpr.Type, loc);
+ conv = ConvertImplicit (ec, trueExpr, false_type, loc);
if (conv != null){
//
// Check if both can convert implicitl to each other's type
//
- if (ConvertImplicit (ec, falseExpr, trueExpr.Type, loc) != null){
+ if (ConvertImplicit (ec, falseExpr, true_type, loc) != null){
Report.Error (
172, loc,
"Can not compute type of conditional expression " +
"' convert implicitly to each other");
return null;
}
- type = falseExpr.Type;
+ type = false_type;
trueExpr = conv;
- } else if ((conv = ConvertImplicit(ec, falseExpr,trueExpr.Type,loc))!= null){
- type = trueExpr.Type;
+ } else if ((conv = ConvertImplicit(ec, falseExpr, true_type,loc))!= null){
+ type = true_type;
falseExpr = conv;
} else {
Error (173, loc, "The type of the conditional expression can " +
return falseExpr;
}
- eclass = ExprClass.Value;
return this;
}
return null;
VariableInfo vi = VariableInfo;
-
+
+#if BROKEN
+ //
+ // Sigh: this breaks `using' and `fixed'. Need to review that
+ //
if (vi.ReadOnly){
- if (vi.Assigned){
- Report.Error (
- 1604, loc,
- "cannot assign to `" + Name + "' because it is readonly");
- return null;
- }
+ Report.Error (
+ 1604, loc,
+ "cannot assign to `" + Name + "' because it is readonly");
+ return null;
}
+#endif
return this;
}
{
VariableInfo vi = VariableInfo;
ILGenerator ig = ec.ig;
- int idx = vi.Idx;
+ ig.Emit (OpCodes.Ldloc, vi.LocalBuilder);
vi.Used = true;
-
- switch (idx){
- case 0:
- ig.Emit (OpCodes.Ldloc_0);
- break;
-
- case 1:
- ig.Emit (OpCodes.Ldloc_1);
- break;
-
- case 2:
- ig.Emit (OpCodes.Ldloc_2);
- break;
-
- case 3:
- ig.Emit (OpCodes.Ldloc_3);
- break;
-
- default:
- if (idx <= 255)
- ig.Emit (OpCodes.Ldloc_S, (byte) idx);
- else
- ig.Emit (OpCodes.Ldloc, idx);
- break;
- }
}
- public static void Store (ILGenerator ig, int idx)
- {
- switch (idx){
- case 0:
- ig.Emit (OpCodes.Stloc_0);
- break;
-
- case 1:
- ig.Emit (OpCodes.Stloc_1);
- break;
-
- case 2:
- ig.Emit (OpCodes.Stloc_2);
- break;
-
- case 3:
- ig.Emit (OpCodes.Stloc_3);
- break;
-
- default:
- if (idx <= 255)
- ig.Emit (OpCodes.Stloc_S, (byte) idx);
- else
- ig.Emit (OpCodes.Stloc, idx);
- break;
- }
- }
-
public void EmitAssign (EmitContext ec, Expression source)
{
ILGenerator ig = ec.ig;
source.Emit (ec);
- // Funny seems the code below generates optimal code for us, but
- // seems to take too long to generate what we need.
- // ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
-
- Store (ig, vi.Idx);
+ ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
VariableInfo vi = VariableInfo;
- int idx = vi.Idx;
- vi.Used = true;
- vi.Assigned = true;
-
- if (idx <= 255)
- ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
- else
- ec.ig.Emit (OpCodes.Ldloca, idx);
+ if ((mode & AddressOp.Load) != 0)
+ vi.Used = true;
+ if ((mode & AddressOp.Store) != 0)
+ vi.Assigned = true;
+
+ ec.ig.Emit (OpCodes.Ldloca, vi.LocalBuilder);
}
}
//
public override Expression DoResolve (EmitContext ec)
{
- type = pars.GetParameterInfo (ec.TypeContainer, idx, out is_ref);
+ type = pars.GetParameterInfo (ec.DeclSpace, idx, out is_ref);
eclass = ExprClass.Variable;
return this;
// If we are a reference, we loaded on the stack a pointer
// Now lets load the real value
//
- LoadFromPtr (ig, type, true);
+ LoadFromPtr (ig, type);
}
public void EmitAssign (EmitContext ec, Expression source)
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
int arg_idx = idx;
public Type Type {
get {
- return expr.Type;
+ if (ArgType == AType.Ref || ArgType == AType.Out)
+ return TypeManager.LookupType (expr.Type.ToString () + "&");
+ else
+ return expr.Type;
}
}
// to pass just the value
//
if (ArgType == AType.Ref || ArgType == AType.Out){
+ AddressOp mode = AddressOp.Store;
+
+ if (ArgType == AType.Ref)
+ mode |= AddressOp.Load;
+
if (expr is ParameterReference){
ParameterReference pr = (ParameterReference) expr;
if (pr.is_ref)
pr.EmitLoad (ec);
- else
- pr.AddressOf (ec);
+ else {
+
+ pr.AddressOf (ec, mode);
+ }
} else
- ((IMemoryLocation)expr).AddressOf (ec);
+ ((IMemoryLocation)expr).AddressOf (ec, mode);
} else
expr.Emit (ec);
}
}
if (q == null) {
- Expression tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);
+ Expression tmp = ConvertImplicit (ec, argument_expr, p, loc);
if (tmp != null)
return 1;
return 0;
}
- if (StandardConversionExists (p, q) == true &&
- StandardConversionExists (q, p) == false)
+ Expression p_tmp = new EmptyExpression (p);
+ Expression q_tmp = new EmptyExpression (q);
+
+ if (StandardConversionExists (p_tmp, q) == true &&
+ StandardConversionExists (q_tmp, p) == false)
return 1;
if (p == TypeManager.sbyte_type)
ParameterData best_pd;
int argument_count;
-
if (args == null)
argument_count = 0;
else
return sb.ToString ();
}
- public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2)
+ public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
{
MemberInfo [] miset;
MethodGroupExpr union;
+
+ if (mg1 == null){
+ if (mg2 == null)
+ return null;
+ return (MethodGroupExpr) mg2;
+ } else {
+ if (mg2 == null)
+ return (MethodGroupExpr) mg1;
+ }
- if (mg1 != null && mg2 != null) {
-
- MethodGroupExpr left_set = null, right_set = null;
- int length1 = 0, length2 = 0;
-
- left_set = (MethodGroupExpr) mg1;
- length1 = left_set.Methods.Length;
-
- right_set = (MethodGroupExpr) mg2;
- length2 = right_set.Methods.Length;
+ MethodGroupExpr left_set = null, right_set = null;
+ int length1 = 0, length2 = 0;
+
+ left_set = (MethodGroupExpr) mg1;
+ length1 = left_set.Methods.Length;
+
+ right_set = (MethodGroupExpr) mg2;
+ length2 = right_set.Methods.Length;
+
+ ArrayList common = new ArrayList ();
- ArrayList common = new ArrayList ();
-
- for (int i = 0; i < left_set.Methods.Length; i++) {
- for (int j = 0; j < right_set.Methods.Length; j++) {
- if (left_set.Methods [i] == right_set.Methods [j])
- common.Add (left_set.Methods [i]);
- }
+ foreach (MethodBase l in left_set.Methods){
+ foreach (MethodBase r in right_set.Methods){
+ if (l != r)
+ continue;
+ common.Add (r);
+ break;
}
-
- miset = new MemberInfo [length1 + length2 - common.Count];
-
- left_set.Methods.CopyTo (miset, 0);
-
- int k = 0;
-
- for (int j = 0; j < right_set.Methods.Length; j++)
- if (!common.Contains (right_set.Methods [j]))
- miset [length1 + k++] = right_set.Methods [j];
-
- union = new MethodGroupExpr (miset);
-
- return union;
-
- } else if (mg1 == null && mg2 != null) {
-
- MethodGroupExpr me = (MethodGroupExpr) mg2;
-
- miset = new MemberInfo [me.Methods.Length];
- me.Methods.CopyTo (miset, 0);
-
- union = new MethodGroupExpr (miset);
-
- return union;
-
- } else if (mg2 == null && mg1 != null) {
-
- MethodGroupExpr me = (MethodGroupExpr) mg1;
-
- miset = new MemberInfo [me.Methods.Length];
- me.Methods.CopyTo (miset, 0);
+ }
+
+ miset = new MemberInfo [length1 + length2 - common.Count];
+ left_set.Methods.CopyTo (miset, 0);
+
+ int k = length1;
- union = new MethodGroupExpr (miset);
-
- return union;
+ foreach (MemberInfo mi in right_set.Methods){
+ if (!common.Contains (mi))
+ miset [k++] = mi;
}
- return null;
+ union = new MethodGroupExpr (miset, loc);
+
+ 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 (ArrayList arguments, MethodBase candidate)
+ static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
{
int arg_count;
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 p_mod = pd.ParameterModifier (i);
if (a_mod == p_mod) {
-
+
if (a_mod == Parameter.Modifier.NONE)
- if (!StandardConversionExists (a.Type, pd.ParameterType (i)))
+ if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
return false;
if (a_mod == Parameter.Modifier.REF ||
- a_mod == Parameter.Modifier.OUT)
- if (pd.ParameterType (i) != a.Type)
+ a_mod == Parameter.Modifier.OUT) {
+ Type pt = pd.ParameterType (i);
+
+ if (!pt.IsByRef)
+ pt = TypeManager.LookupType (pt.FullName + "&");
+
+ if (pt != a.Type)
return false;
+ }
} else
return false;
for (int i = pd_count - 1; i < arg_count; i++) {
Argument a = (Argument) arguments [i];
- if (!StandardConversionExists (a.Type, element_type))
+ if (!StandardConversionExists (a.Expr, element_type))
return false;
}
/// Determines if the candidate method is applicable (section 14.4.2.1)
/// to the given set of arguments
/// </summary>
- static bool IsApplicable (ArrayList arguments, MethodBase candidate)
+ static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
{
int arg_count;
if (arg_count != pd.Count)
return false;
-
+
for (int i = arg_count; i > 0; ) {
i--;
Parameter.Modifier a_mod = a.GetParameterModifier ();
Parameter.Modifier p_mod = pd.ParameterModifier (i);
- if (a_mod == p_mod) {
-
+ if (a_mod == p_mod ||
+ (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
if (a_mod == Parameter.Modifier.NONE)
- if (!StandardConversionExists (a.Type, pd.ParameterType (i)))
+ if (!ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i)))
return false;
if (a_mod == Parameter.Modifier.REF ||
- a_mod == Parameter.Modifier.OUT)
- if (pd.ParameterType (i) != a.Type)
+ a_mod == Parameter.Modifier.OUT) {
+ Type pt = pd.ParameterType (i);
+
+ if (!pt.IsByRef)
+ pt = TypeManager.LookupType (pt.FullName + "&");
+
+ if (pt != a.Type)
return false;
+ }
} else
return false;
}
ArrayList Arguments, Location loc)
{
ArrayList afm = new ArrayList ();
- int best_match_idx = -1;
MethodBase method = null;
int argument_count;
ArrayList candidates = new ArrayList ();
- for (int i = me.Methods.Length; i > 0; ){
- i--;
- MethodBase candidate = me.Methods [i];
+
+ foreach (MethodBase candidate in me.Methods){
int x;
// Check if candidate is applicable (section 14.4.2.1)
- if (!IsApplicable (Arguments, candidate))
+ if (!IsApplicable (ec, Arguments, candidate))
continue;
candidates.Add (candidate);
-
x = BetterFunction (ec, Arguments, candidate, method, false, loc);
if (x == 0)
continue;
- else {
- best_match_idx = i;
- method = me.Methods [best_match_idx];
- }
+
+ method = candidate;
}
if (Arguments == null)
//
bool chose_params_expanded = false;
- if (best_match_idx == -1) {
-
+ if (method == null) {
candidates = new ArrayList ();
- for (int i = me.Methods.Length; i > 0; ) {
- i--;
- MethodBase candidate = me.Methods [i];
-
- if (!IsParamsMethodApplicable (Arguments, candidate))
+ foreach (MethodBase candidate in me.Methods){
+ if (!IsParamsMethodApplicable (ec, Arguments, candidate))
continue;
candidates.Add (candidate);
int x = BetterFunction (ec, Arguments, candidate, method, true, loc);
-
if (x == 0)
continue;
- else {
- best_match_idx = i;
- method = me.Methods [best_match_idx];
- chose_params_expanded = true;
- }
- }
- }
-
- //
- // Now we see if we can at least find a method with the same number of arguments
- //
- ParameterData pd;
- int method_count = 0;
- if (best_match_idx == -1) {
-
- for (int i = me.Methods.Length; i > 0;) {
- i--;
- MethodBase mb = me.Methods [i];
- pd = GetParameterData (mb);
-
- if (pd.Count == argument_count) {
- best_match_idx = i;
- method = me.Methods [best_match_idx];
- method_count++;
- } else
- continue;
+ method = candidate;
+ chose_params_expanded = true;
}
}
if (method == null)
return null;
-
//
// Now check that there are no ambiguities i.e the selected method
// should be better than all the others
//
- for (int i = 0; i < candidates.Count; ++i) {
- MethodBase candidate = (MethodBase) candidates [i];
-
+ foreach (MethodBase candidate in candidates){
if (candidate == method)
continue;
// number of arguments, then the expanded params method is never applicable
// so we debar the params method.
//
- if (IsParamsMethodApplicable (Arguments, candidate) &&
- IsApplicable (Arguments, method))
+ if (IsParamsMethodApplicable (ec, Arguments, candidate) &&
+ IsApplicable (ec, Arguments, method))
continue;
int x = BetterFunction (ec, Arguments, method, candidate,
chose_params_expanded, loc);
if (x != 1) {
- //Console.WriteLine ("Candidate : " + FullMethodDesc (candidate));
- //Console.WriteLine ("Best : " + FullMethodDesc (method));
Report.Error (
121, loc,
"Ambiguous call when selecting function due to implicit casts");
return null;
}
}
-
- // And now convert implicitly, each argument to the required type
-
- pd = GetParameterData (method);
- int pd_count = pd.Count;
+ //
+ // And now check if the arguments are all compatible, perform conversions
+ // if necessary etc. and return if everything is all right
+ //
+
+ if (VerifyArgumentsCompat (ec, Arguments, argument_count, method,
+ chose_params_expanded, null, loc))
+ return method;
+ else
+ return null;
+ }
+
+ public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
+ int argument_count,
+ MethodBase method,
+ bool chose_params_expanded,
+ Type delegate_type,
+ Location loc)
+ {
+ ParameterData pd = GetParameterData (method);
+ int pd_count = pd.Count;
+
for (int j = 0; j < argument_count; j++) {
Argument a = (Argument) Arguments [j];
Expression a_expr = a.Expr;
Type parameter_type = pd.ParameterType (j);
- if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS && chose_params_expanded)
+ if (pd.ParameterModifier (j) == Parameter.Modifier.PARAMS &&
+ chose_params_expanded)
parameter_type = parameter_type.GetElementType ();
if (a.Type != parameter_type){
Expression conv;
- conv = ConvertImplicitStandard (ec, a_expr, parameter_type, Location.Null);
+ conv = ConvertImplicit (ec, a_expr, parameter_type, loc);
if (conv == null) {
if (!Location.IsNull (loc)) {
- Error (1502, loc,
- "The best overloaded match for method '" +
- FullMethodDesc (method) +
- "' has some invalid arguments");
+ if (delegate_type == null)
+ Error (1502, loc,
+ "The best overloaded match for method '" +
+ FullMethodDesc (method) +
+ "' has some invalid arguments");
+ else
+ Report.Error (1594, loc,
+ "Delegate '" + delegate_type.ToString () +
+ "' has some invalid arguments.");
Error (1503, loc,
"Argument " + (j+1) +
": Cannot convert from '" + Argument.FullDesc (a)
+ "' to '" + pd.ParameterDesc (j) + "'");
}
- return null;
+
+ return false;
}
//
//
if (a_expr != conv)
a.Expr = conv;
-
- // FIXME : For the case of params methods, we need to actually instantiate
- // an array and initialize it with the argument values etc etc.
-
}
if (a.GetParameterModifier () != pd.ParameterModifier (j) &&
": Cannot convert from '" + Argument.FullDesc (a)
+ "' to '" + pd.ParameterDesc (j) + "'");
}
- return null;
+
+ return false;
}
}
-
- return method;
+
+ return true;
}
public override Expression DoResolve (EmitContext ec)
// Next, evaluate all the expressions in the argument list
//
if (Arguments != null){
- for (int i = Arguments.Count; i > 0;){
- --i;
- Argument a = (Argument) Arguments [i];
-
+ foreach (Argument a in Arguments){
if (!a.Resolve (ec, loc))
return null;
}
Type t = a.expr.Type;
string array_type = t.FullName + "[]";
LocalBuilder array;
-
+
array = ig.DeclareLocal (Type.GetType (array_type));
IntConstant.EmitInt (ig, count);
ig.Emit (OpCodes.Newarr, t);
/// 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
+ /// 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;
+ ParameterData pd;
+ if (mb != null)
+ pd = GetParameterData (mb);
else
- top = 0;
+ pd = null;
- if (mb != null)
- pd = GetParameterData (mb);
+ //
+ // If we are calling a params method with no arguments, special case it
+ //
+ if (arguments == null){
+ if (pd != null && pd.Count > 0 &&
+ pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){
+ ILGenerator ig = ec.ig;
+
+ IntConstant.EmitInt (ig, 0);
+ ig.Emit (OpCodes.Newarr, pd.ParameterType (0).GetElementType ());
+ }
+
+ return;
+ }
+
+ int top = arguments.Count;
for (int i = 0; i < top; i++){
Argument a = (Argument) arguments [i];
if (pd != null){
if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
- EmitParams (ec, i, arguments);
+ //
+ // Special case if we are passing the same data as the
+ // params argument, do not put it in an array.
+ //
+ if (pd.ParameterType (i) == a.Type)
+ a.Emit (ec);
+ else
+ EmitParams (ec, i, arguments);
return;
}
}
/// </remarks>
public static void EmitCall (EmitContext ec, bool is_base,
bool is_static, Expression instance_expr,
- MethodBase method, ArrayList Arguments)
+ MethodBase method, ArrayList Arguments, Location loc)
{
ILGenerator ig = ec.ig;
bool struct_call = false;
-
+
+ Type decl_type = method.DeclaringType;
+
+ if (!RootContext.StdLib) {
+ // Replace any calls to the system's System.Array type with calls to
+ // the newly created one.
+ if (method == TypeManager.system_int_array_get_length)
+ method = TypeManager.int_array_get_length;
+ else if (method == TypeManager.system_int_array_get_rank)
+ method = TypeManager.int_array_get_rank;
+ else if (method == TypeManager.system_object_array_clone)
+ method = TypeManager.object_array_clone;
+ else if (method == TypeManager.system_int_array_get_length_int)
+ method = TypeManager.int_array_get_length_int;
+ else if (method == TypeManager.system_int_array_get_lower_bound_int)
+ method = TypeManager.int_array_get_lower_bound_int;
+ else if (method == TypeManager.system_int_array_get_upper_bound_int)
+ method = TypeManager.int_array_get_upper_bound_int;
+ else if (method == TypeManager.system_void_array_copyto_array_int)
+ method = TypeManager.void_array_copyto_array_int;
+ }
+
+ //
+ // This checks the `ConditionalAttribute' on the method, and the
+ // ObsoleteAttribute
+ //
+ TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method);
+ if ((flags & TypeManager.MethodFlags.IsObsolete) != 0){
+ Report.Warning (
+ 612, loc, "`" + TypeManager.CSharpSignature (method)+
+ "' is obsolete");
+ }
+ if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+ return;
+
if (!is_static){
-
- if (method.DeclaringType.IsValueType)
+ if (decl_type.IsValueType)
struct_call = true;
//
// If this is ourselves, push "this"
// to have their value boxed.
struct_call = true;
- if (method.DeclaringType.IsValueType){
+ if (decl_type.IsValueType){
//
// If the expression implements IMemoryLocation, then
// we can optimize and use AddressOf on the
// it.
if (instance_expr is IMemoryLocation){
((IMemoryLocation)instance_expr).
- AddressOf (ec);
+ AddressOf (ec, AddressOp.LoadStore);
}
else {
Type t = instance_expr.Type;
}
}
- if (Arguments != null)
- EmitArguments (ec, method, Arguments);
+ EmitArguments (ec, method, Arguments);
if (is_static || struct_call || is_base){
if (method is MethodInfo)
{
MethodGroupExpr mg = (MethodGroupExpr) this.expr;
- EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments);
+ EmitCall (
+ ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
}
public override void EmitStatement (EmitContext ec)
}
}
+ //
+ // This class is used to "disable" the code generation for the
+ // temporary variable when initializing value types.
+ //
+ class EmptyAddressOf : EmptyExpression, IMemoryLocation {
+ public void AddressOf (EmitContext ec, AddressOp Mode)
+ {
+ // nothing
+ }
+ }
+
/// <summary>
/// Implements the new expression
/// </summary>
}
}
+ //
+ // This function is used to disable the following code sequence for
+ // value type initialization:
+ //
+ // AddressOf (temporary)
+ // Construct/Init
+ // LoadTemporary
+ //
+ // Instead the provide will have provided us with the address on the
+ // stack to store the results.
+ //
+ static Expression MyEmptyExpression;
+
+ public void DisableTemporaryValueType ()
+ {
+ if (MyEmptyExpression == null)
+ MyEmptyExpression = new EmptyAddressOf ();
+
+ //
+ // To enable this, look into:
+ // test-34 and test-89 and self bootstrapping.
+ //
+ // For instance, we can avoid a copy by using `newobj'
+ // instead of Call + Push-temp on value types.
+// value_target = MyEmptyExpression;
+ }
+
public override Expression DoResolve (EmitContext ec)
{
- type = RootContext.LookupType (ec.TypeContainer, RequestedType, false, loc);
+ type = RootContext.LookupType (ec.DeclSpace, RequestedType, false, loc);
if (type == null)
return null;
if (IsDelegate)
return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+
+ if (type.IsInterface || type.IsAbstract){
+ Report.Error (
+ 144, loc, "It is not possible to create instances of interfaces " +
+ "or abstract classes");
+ return null;
+ }
bool is_struct = false;
is_struct = type.IsSubclassOf (TypeManager.value_type);
return this;
Expression ml;
- ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor, AllBindingFlags, loc);
+ ml = MemberLookupFinal (ec, type, ".ctor",
+ MemberTypes.Constructor,
+ AllBindingFlags | BindingFlags.DeclaredOnly, loc);
+
+ if (ml == null)
+ return null;
if (! (ml is MethodGroupExpr)){
if (!is_struct){
return null;
}
}
-
+
if (ml != null) {
if (Arguments != null){
- for (int i = Arguments.Count; i > 0;){
- --i;
- Argument a = (Argument) Arguments [i];
-
+ foreach (Argument a in Arguments){
if (!a.Resolve (ec, loc))
return null;
}
Arguments, loc);
}
-
- if (method == null && !is_struct) {
- Error (-6, loc,
- "New invocation: Can not find a constructor for " +
- "this argument list");
- return null;
+
+ if (method == null) {
+ if (!is_struct || Arguments.Count > 0) {
+ Error (1501, loc,
+ "New invocation: Can not find a constructor for " +
+ "this argument list");
+ return null;
+ }
}
return this;
}
{
bool is_value_type = type.IsSubclassOf (TypeManager.value_type);
ILGenerator ig = ec.ig;
-
+
if (is_value_type){
IMemoryLocation ml;
if (value_target == null)
value_target = new LocalTemporary (ec, type);
-
+
ml = (IMemoryLocation) value_target;
- ml.AddressOf (ec);
+ ml.AddressOf (ec, AddressOp.Store);
}
if (method != null)
if (is_value_type){
if (method == null)
ig.Emit (OpCodes.Initobj, type);
- else
+ else
ig.Emit (OpCodes.Call, (ConstructorInfo) method);
-
- if (need_value_on_stack){
- value_target.Emit (ec);
- return true;
- }
- return false;
+ if (need_value_on_stack){
+ value_target.Emit (ec);
+ return true;
+ }
+ return false;
} else {
ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
return true;
}
/// <summary>
- /// Represents an array creation expression.
+ /// 14.5.10.2: Represents an array creation expression.
/// </summary>
///
/// <remarks>
/// specified but where initialization data is mandatory.
/// </remarks>
public class ArrayCreation : ExpressionStatement {
- string RequestedType;
- string Rank;
- ArrayList Initializers;
- Location loc;
- ArrayList Arguments;
+ string requested_type, rank;
+ ArrayList initializers;
+ Location loc;
+
+ //
+ // The list of Argument types.
+ // This is used to construct the `newarray' or constructor signature
+ //
+ ArrayList arguments;
+
+ //
+ // Method used to create the array object.
+ //
+ MethodBase new_method = null;
- MethodBase method = null;
Type array_element_type;
- bool IsOneDimensional = false;
- bool IsBuiltinType = false;
- bool ExpectInitializers = false;
-
- int dimensions = 0;
Type underlying_type;
+ bool is_one_dimensional = false;
+ bool is_builtin_type = false;
+ bool expect_initializers = false;
+ int dimensions = 0;
- ArrayList ArrayData;
+ ArrayList array_data;
- Hashtable Bounds;
+ Hashtable bounds;
//
// The number of array initializers that we can handle
//
int num_automatic_initializers;
- public ArrayCreation (string requested_type, ArrayList exprs,
- string rank, ArrayList initializers, Location l)
+ public ArrayCreation (string requested_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
{
- RequestedType = requested_type;
- Rank = rank;
- Initializers = initializers;
+ this.requested_type = requested_type;
+ this.initializers = initializers;
+ this.rank = rank;
loc = l;
- Arguments = new ArrayList ();
+ arguments = new ArrayList ();
foreach (Expression e in exprs)
- Arguments.Add (new Argument (e, Argument.AType.Expression));
+ arguments.Add (new Argument (e, Argument.AType.Expression));
}
public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
{
- RequestedType = requested_type;
- Initializers = initializers;
+ this.requested_type = requested_type;
+ this.initializers = initializers;
loc = l;
- Rank = rank.Substring (0, rank.LastIndexOf ("["));
+ this.rank = rank.Substring (0, rank.LastIndexOf ("["));
string tmp = rank.Substring (rank.LastIndexOf ("["));
dimensions = tmp.Length - 1;
- ExpectInitializers = true;
+ expect_initializers = true;
}
public static string FormArrayType (string base_type, int idx_count, string rank)
public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
{
if (specified_dims) {
- Argument a = (Argument) Arguments [idx];
+ Argument a = (Argument) arguments [idx];
if (!a.Resolve (ec, loc))
return false;
return false;
}
- Bounds [idx] = value;
+ bounds [idx] = value;
}
foreach (object o in probe) {
tmp = tmp.Resolve (ec);
if (tmp == null)
continue;
-
+
+ // Console.WriteLine ("I got: " + tmp);
// Handle initialization from vars, fields etc.
Expression conv = ConvertImplicitRequired (
return false;
if (conv is StringConstant)
- ArrayData.Add (conv);
+ array_data.Add (conv);
else if (conv is Constant) {
- ArrayData.Add (conv);
+ array_data.Add (conv);
num_automatic_initializers++;
} else
- ArrayData.Add (conv);
+ array_data.Add (conv);
}
}
public void UpdateIndices (EmitContext ec)
{
int i = 0;
- for (ArrayList probe = Initializers; probe != null;) {
+ for (ArrayList probe = initializers; probe != null;) {
if (probe.Count > 0 && probe [0] is ArrayList) {
Expression e = new IntConstant (probe.Count);
- Arguments.Add (new Argument (e, Argument.AType.Expression));
+ arguments.Add (new Argument (e, Argument.AType.Expression));
- Bounds [i++] = probe.Count;
+ bounds [i++] = probe.Count;
probe = (ArrayList) probe [0];
} else {
Expression e = new IntConstant (probe.Count);
- Arguments.Add (new Argument (e, Argument.AType.Expression));
+ arguments.Add (new Argument (e, Argument.AType.Expression));
- Bounds [i++] = probe.Count;
+ bounds [i++] = probe.Count;
probe = null;
}
}
public bool ValidateInitializers (EmitContext ec)
{
- if (Initializers == null) {
- if (ExpectInitializers)
+ if (initializers == null) {
+ if (expect_initializers)
return false;
else
return true;
}
underlying_type = RootContext.LookupType (
- ec.TypeContainer, RequestedType, false, loc);
+ ec.DeclSpace, requested_type, false, loc);
+
+ if (underlying_type == null)
+ return false;
//
// We use this to store all the date values in the order in which we
// will need to store them in the byte blob later
//
- ArrayData = new ArrayList ();
- Bounds = new Hashtable ();
+ array_data = new ArrayList ();
+ bounds = new Hashtable ();
bool ret;
- if (Arguments != null) {
- ret = CheckIndices (ec, Initializers, 0, true);
+ if (arguments != null) {
+ ret = CheckIndices (ec, initializers, 0, true);
return ret;
-
} else {
- Arguments = new ArrayList ();
+ arguments = new ArrayList ();
- ret = CheckIndices (ec, Initializers, 0, false);
+ ret = CheckIndices (ec, initializers, 0, false);
if (!ret)
return false;
UpdateIndices (ec);
- if (Arguments.Count != dimensions) {
+ if (arguments.Count != dimensions) {
error178 ();
return false;
}
return ret;
}
}
+
+ void Error_NegativeArrayIndex ()
+ {
+ Report.Error (284, loc, "Can not create array with a negative size");
+ }
+
+ //
+ // Converts `source' to an int, uint, long or ulong.
+ //
+ Expression ExpressionToArrayArgument (EmitContext ec, Expression source)
+ {
+ Expression target;
+
+ bool old_checked = ec.CheckState;
+ ec.CheckState = true;
+
+ target = ConvertImplicit (ec, source, TypeManager.int32_type, loc);
+ if (target == null){
+ target = ConvertImplicit (ec, source, TypeManager.uint32_type, loc);
+ if (target == null){
+ target = ConvertImplicit (ec, source, TypeManager.int64_type, loc);
+ if (target == null){
+ target = ConvertImplicit (ec, source, TypeManager.uint64_type, loc);
+ if (target == null)
+ Expression.Error_CannotConvertImplicit (loc, source.Type, TypeManager.int32_type);
+ }
+ }
+ }
+ ec.CheckState = old_checked;
+
+ //
+ // Only positive constants are allowed at compile time
+ //
+ if (target is Constant){
+ if (target is IntConstant){
+ if (((IntConstant) target).Value < 0){
+ Error_NegativeArrayIndex ();
+ return null;
+ }
+ }
+
+ if (target is LongConstant){
+ if (((LongConstant) target).Value < 0){
+ Error_NegativeArrayIndex ();
+ return null;
+ }
+ }
+
+ }
+
+ return target;
+ }
public override Expression DoResolve (EmitContext ec)
{
if (!ValidateInitializers (ec))
return null;
- if (Arguments == null)
+ if (arguments == null)
arg_count = 0;
else {
- arg_count = Arguments.Count;
- for (int i = arg_count; i > 0;){
- --i;
- Argument a = (Argument) Arguments [i];
-
+ arg_count = arguments.Count;
+ foreach (Argument a in arguments){
if (!a.Resolve (ec, loc))
return null;
+
+ Expression real_arg = ExpressionToArrayArgument (ec, a.expr);
+ if (real_arg == null)
+ return null;
+
+ a.expr = real_arg;
}
}
- string array_type = FormArrayType (RequestedType, arg_count, Rank);
- string element_type = FormElementType (RequestedType, arg_count, Rank);
+ string array_type = FormArrayType (requested_type, arg_count, rank);
+ string element_type = FormElementType (requested_type, arg_count, rank);
- type = RootContext.LookupType (ec.TypeContainer, array_type, false, loc);
+ type = RootContext.LookupType (ec.DeclSpace, array_type, false, loc);
array_element_type = RootContext.LookupType (
- ec.TypeContainer, element_type, false, loc);
+ ec.DeclSpace, element_type, false, loc);
if (type == null)
return null;
if (arg_count == 1) {
- IsOneDimensional = true;
+ is_one_dimensional = true;
eclass = ExprClass.Value;
return this;
}
- IsBuiltinType = TypeManager.IsBuiltinType (type);
+ is_builtin_type = TypeManager.IsBuiltinType (type);
- if (IsBuiltinType) {
-
+ if (is_builtin_type) {
Expression ml;
ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
AllBindingFlags, loc);
- if (!(ml is MethodGroupExpr)){
+ if (!(ml is MethodGroupExpr)) {
report118 (loc, ml, "method group");
return null;
}
return null;
}
- method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
+ new_method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, arguments, loc);
- if (method == null) {
+ if (new_method == null) {
Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
"this argument list");
return null;
eclass = ExprClass.Value;
return this;
-
} else {
-
- ModuleBuilder mb = RootContext.ModuleBuilder;
-
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
ArrayList args = new ArrayList ();
- if (Arguments != null){
- for (int i = arg_count; i > 0;){
- --i;
- Argument a = (Argument) Arguments [i];
-
- args.Add (a.Type);
- }
+
+ if (arguments != null) {
+ for (int i = 0; i < arg_count; i++)
+ args.Add (TypeManager.int32_type);
}
Type [] arg_types = null;
-
+
if (args.Count > 0)
arg_types = new Type [args.Count];
args.CopyTo (arg_types, 0);
- method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
+ new_method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
arg_types);
- if (method == null) {
+ if (new_method == null) {
Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
"this argument list");
return null;
eclass = ExprClass.Value;
return this;
-
}
}
- public static byte [] MakeByteBlob (ArrayList ArrayData, Type underlying_type, Location loc)
+ public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc)
{
int factor;
byte [] data;
-
- int count = ArrayData.Count;
+ byte [] element;
+ int count = array_data.Count;
factor = GetTypeSize (underlying_type);
if (factor == 0)
int idx = 0;
for (int i = 0; i < count; ++i) {
- object v = ArrayData [i];
+ object v = array_data [i];
if (v is EnumConstant)
v = ((EnumConstant) v).Child;
}
}
} else if (underlying_type == TypeManager.float_type) {
- unsafe {
- if (!(v is Expression)){
- float val = (float) v;
-
- byte *ptr = (byte *) &val;
+ if (!(v is Expression)){
+ element = BitConverter.GetBytes ((float) v);
- for (int j = 0; j < factor; ++j)
- data [idx + j] = (byte) ptr [j];
- }
+ for (int j = 0; j < factor; ++j)
+ data [idx + j] = element [j];
}
} else if (underlying_type == TypeManager.double_type) {
- unsafe {
- if (!(v is Expression)){
- double val = (double) v;
+ if (!(v is Expression)){
+ element = BitConverter.GetBytes ((double) v);
- byte *ptr = (byte *) &val;
-
- for (int j = 0; j < factor; ++j)
- data [idx + j] = (byte) ptr [j];
- }
+ for (int j = 0; j < factor; ++j)
+ data [idx + j] = element [j];
}
} else if (underlying_type == TypeManager.char_type){
-
if (!(v is Expression)){
int val = (int) ((char) v);
byte val = (byte) v;
data [idx] = (byte) val;
}
+ } else if (underlying_type == TypeManager.bool_type) {
+ if (!(v is Expression)){
+ bool val = (bool) v;
+ data [idx] = (byte) (val ? 1 : 0);
+ }
} else
throw new Exception ("Unrecognized type in MakeByteBlob");
FieldBuilder fb;
ILGenerator ig = ec.ig;
- byte [] data = MakeByteBlob (ArrayData, underlying_type, loc);
+ byte [] data = MakeByteBlob (array_data, underlying_type, loc);
if (data != null) {
fb = RootContext.MakeStaticData (data);
void EmitDynamicInitializers (EmitContext ec, bool is_expression)
{
ILGenerator ig = ec.ig;
- int dims = Bounds.Count;
+ int dims = bounds.Count;
int [] current_pos = new int [dims];
- int top = ArrayData.Count;
+ int top = array_data.Count;
LocalBuilder temp = ig.DeclareLocal (type);
ig.Emit (OpCodes.Stloc, temp);
if (dims != 1){
Type [] args;
ModuleBuilder mb = null;
- mb = RootContext.ModuleBuilder;
+ mb = CodeGen.ModuleBuilder;
args = new Type [dims + 1];
int j;
Expression e = null;
- if (ArrayData [i] is Expression)
- e = (Expression) ArrayData [i];
+ if (array_data [i] is Expression)
+ e = (Expression) array_data [i];
if (e != null) {
//
// Basically we do this for string literals and
// other non-literal expressions
//
- if (e is StringConstant || !(e is Constant) || num_automatic_initializers <= 2) {
-
+ if (e is StringConstant || !(e is Constant) ||
+ num_automatic_initializers <= 2) {
+ Type etype = e.Type;
+
ig.Emit (OpCodes.Ldloc, temp);
for (int idx = dims; idx > 0; ) {
IntConstant.EmitInt (ig, current_pos [idx]);
}
+ //
+ // If we are dealing with a struct, get the
+ // address of it, so we can store it.
+ //
+ if (etype.IsSubclassOf (TypeManager.value_type) &&
+ !TypeManager.IsBuiltinType (etype)){
+ if (e is New){
+ New n = (New) e;
+
+ //
+ // Let new know that we are providing
+ // the address where to store the results
+ //
+ n.DisableTemporaryValueType ();
+ }
+
+ ig.Emit (OpCodes.Ldelema, etype);
+ }
+
e.Emit (ec);
if (dims == 1)
ArrayAccess.EmitStoreOpcode (ig, array_element_type);
else
ig.Emit (OpCodes.Call, set);
-
}
}
//
for (int j = 0; j < dims; j++){
current_pos [j]++;
- if (current_pos [j] < (int) Bounds [j])
+ if (current_pos [j] < (int) bounds [j])
break;
current_pos [j] = 0;
}
ig.Emit (OpCodes.Ldloc, temp);
}
+ void EmitArrayArguments (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ foreach (Argument a in arguments) {
+ Type atype = a.Type;
+ a.Emit (ec);
+ if (atype == TypeManager.uint64_type || atype == TypeManager.int64_type)
+ ig.Emit (OpCodes.Conv_Ovf_U4);
+ }
+ }
+
void DoEmit (EmitContext ec, bool is_statement)
{
ILGenerator ig = ec.ig;
- if (IsOneDimensional) {
- Invocation.EmitArguments (ec, null, Arguments);
+ EmitArrayArguments (ec);
+ if (is_one_dimensional)
ig.Emit (OpCodes.Newarr, array_element_type);
-
- } else {
- Invocation.EmitArguments (ec, null, Arguments);
-
- if (IsBuiltinType)
- ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
+ else {
+ if (is_builtin_type)
+ ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method);
else
- ig.Emit (OpCodes.Newobj, (MethodInfo) method);
+ ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
}
- if (Initializers != null){
+ if (initializers != null){
//
// FIXME: Set this variable correctly.
//
public override Expression DoResolve (EmitContext ec)
{
eclass = ExprClass.Variable;
- type = ec.TypeContainer.TypeBuilder;
+ type = ec.ContainerType;
if (ec.IsStatic){
Report.Error (26, loc,
ec.ig.Emit (OpCodes.Starg, 0);
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
ec.ig.Emit (OpCodes.Ldarg_0);
public override Expression DoResolve (EmitContext ec)
{
typearg = RootContext.LookupType (
- ec.TypeContainer, QueriedType, false, loc);
+ ec.DeclSpace, QueriedType, false, loc);
if (typearg == null)
return null;
ec.ig.Emit (OpCodes.Ldtoken, typearg);
ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
}
+
+ public Type TypeArg {
+ get { return typearg; }
+ }
}
/// <summary>
public override Expression DoResolve (EmitContext ec)
{
type_queried = RootContext.LookupType (
- ec.TypeContainer, QueriedType, false, loc);
+ ec.DeclSpace, QueriedType, false, loc);
if (type_queried == null)
return null;
SimpleName sn = (SimpleName) left_original;
- Type t = RootContext.LookupType (ec.TypeContainer, sn.Name, true, loc);
+ Type t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
if (t != null)
return true;
if (member_lookup is FieldExpr){
FieldExpr fe = (FieldExpr) member_lookup;
FieldInfo fi = fe.FieldInfo;
-
+ Type decl_type = fi.DeclaringType;
+
if (fi is FieldBuilder) {
Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
if (fi.IsLiteral) {
Type t = fi.FieldType;
- Type decl_type = fi.DeclaringType;
+
object o;
if (fi is FieldBuilder)
//
Expression ml = MemberLookup (
- ec, ec.TypeContainer.TypeBuilder,
+ ec, ec.ContainerType,
ee.EventInfo.Name, MemberTypes.Event, AllBindingFlags, loc);
if (ml != null) {
{
//
// We are the sole users of ResolveWithSimpleName (ie, the only
- // ones that can cope with it
+ // ones that can cope with it)
//
Expression original = expr;
expr = expr.ResolveWithSimpleName (ec);
member_lookup = MemberLookup (ec, expr_type, Identifier, loc);
if (member_lookup == null){
- Report.Error (117, loc, "`" + expr_type + "' does not contain a " +
- "definition for `" + Identifier + "'");
+ //
+ // Try looking the member up from the same type, if we find
+ // it, we know that the error was due to limited visibility
+ //
+ object lookup = TypeManager.MemberLookup (
+ expr_type, expr_type, AllMemberTypes, AllBindingFlags, Identifier);
+ if (lookup == null)
+ Report.Error (117, loc, "`" + expr_type + "' does not contain a " +
+ "definition for `" + Identifier + "'");
+ else
+ Report.Error (122, loc, "`" + expr_type + "." + Identifier + "' " +
+ "is inaccessible because of its protection level");
return null;
}
public override Expression DoResolve (EmitContext ec)
{
- Expr = Expr.Resolve (ec);
+ bool last_const_check = ec.ConstantCheckState;
+ ec.ConstantCheckState = true;
+ Expr = Expr.Resolve (ec);
+ ec.ConstantCheckState = last_const_check;
+
if (Expr == null)
return null;
public override void Emit (EmitContext ec)
{
bool last_check = ec.CheckState;
+ bool last_const_check = ec.ConstantCheckState;
ec.CheckState = true;
+ ec.ConstantCheckState = true;
Expr.Emit (ec);
ec.CheckState = last_check;
+ ec.ConstantCheckState = last_const_check;
}
}
public override Expression DoResolve (EmitContext ec)
{
+ bool last_const_check = ec.ConstantCheckState;
+
+ ec.ConstantCheckState = false;
Expr = Expr.Resolve (ec);
+ ec.ConstantCheckState = last_const_check;
if (Expr == null)
return null;
public override void Emit (EmitContext ec)
{
bool last_check = ec.CheckState;
+ bool last_const_check = ec.ConstantCheckState;
ec.CheckState = false;
+ ec.ConstantCheckState = false;
Expr.Emit (ec);
ec.CheckState = last_check;
+ ec.ConstantCheckState = last_const_check;
}
}
if (Arguments == null)
return false;
- for (int i = Arguments.Count; i > 0;){
- --i;
- Argument a = (Argument) Arguments [i];
-
+ foreach (Argument a in Arguments){
if (!a.Resolve (ec, loc))
return false;
}
//
Type t = Expr.Type;
- if (t.IsSubclassOf (TypeManager.array_type))
+ if (t.IsArray)
return (new ArrayAccess (this)).Resolve (ec);
else if (t.IsPointer)
return MakePointerAccess ();
return null;
Type t = Expr.Type;
- if (t.IsSubclassOf (TypeManager.array_type))
+ if (t.IsArray)
return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
else if (t.IsPointer)
return MakePointerAccess ();
// Points to our "data" repository
//
ElementAccess ea;
+
+ LocalTemporary [] cached_locations;
public ArrayAccess (ElementAccess ea_data)
{
public override Expression DoResolve (EmitContext ec)
{
- if (ea.Expr.eclass != ExprClass.Variable) {
- report118 (ea.loc, ea.Expr, "variable");
+ ExprClass eclass = ea.Expr.eclass;
+
+#if false
+ // As long as the type is valid
+ if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
+ eclass == ExprClass.Value)) {
+ report118 (ea.loc, ea.Expr, "variable or value");
return null;
}
+#endif
Type t = ea.Expr.Type;
if (t.GetArrayRank () != ea.Arguments.Count){
ea.Arguments.Count);
return null;
}
- type = t.GetElementType ();
+ type = TypeManager.TypeToCoreType (t.GetElementType ());
if (type.IsPointer && !ec.InUnsafe){
UnsafeError (ea.loc);
return null;
MethodInfo FetchGetMethod ()
{
- ModuleBuilder mb = RootContext.ModuleBuilder;
- Type [] args = new Type [ea.Arguments.Count];
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
+ int arg_count = ea.Arguments.Count;
+ Type [] args = new Type [arg_count];
MethodInfo get;
- int i = 0;
-
- foreach (Argument a in ea.Arguments)
- args [i++] = a.Type;
+ for (int i = 0; i < arg_count; i++){
+ //args [i++] = a.Type;
+ args [i] = TypeManager.int32_type;
+ }
get = mb.GetArrayMethod (
ea.Expr.Type, "Get",
MethodInfo FetchAddressMethod ()
{
- ModuleBuilder mb = RootContext.ModuleBuilder;
- Type [] args = new Type [ea.Arguments.Count];
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
+ int arg_count = ea.Arguments.Count;
+ Type [] args = new Type [arg_count];
MethodInfo address;
string ptr_type_name;
Type ret_type;
- int i = 0;
ptr_type_name = type.FullName + "&";
ret_type = Type.GetType (ptr_type_name);
if (ret_type == null){
ret_type = mb.GetType (ptr_type_name);
}
-
- foreach (Argument a in ea.Arguments)
- args [i++] = a.Type;
+
+ for (int i = 0; i < arg_count; i++){
+ //args [i++] = a.Type;
+ args [i] = TypeManager.int32_type;
+ }
address = mb.GetArrayMethod (
ea.Expr.Type, "Address",
return address;
}
+
+ //
+ // Load the array arguments into the stack.
+ //
+ // If we have been requested to cache the values (cached_locations array
+ // initialized), then load the arguments the first time and store them
+ // in locals. otherwise load from local variables.
+ //
+ void LoadArrayAndArguments (EmitContext ec)
+ {
+ if (cached_locations == null){
+ ea.Expr.Emit (ec);
+ foreach (Argument a in ea.Arguments)
+ a.Expr.Emit (ec);
+ return;
+ }
+
+ ILGenerator ig = ec.ig;
+
+ if (cached_locations [0] == null){
+ cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type);
+ ea.Expr.Emit (ec);
+ ig.Emit (OpCodes.Dup);
+ cached_locations [0].Store (ec);
+
+ int j = 1;
+
+ foreach (Argument a in ea.Arguments){
+ cached_locations [j] = new LocalTemporary (ec, a.Expr.Type);
+ a.Expr.Emit (ec);
+ ig.Emit (OpCodes.Dup);
+ cached_locations [j].Store (ec);
+ j++;
+ }
+ return;
+ }
+
+ foreach (LocalTemporary lt in cached_locations)
+ lt.Emit (ec);
+ }
+
+ public new void CacheTemporaries (EmitContext ec)
+ {
+ cached_locations = new LocalTemporary [ea.Arguments.Count + 1];
+ }
public override void Emit (EmitContext ec)
{
int rank = ea.Expr.Type.GetArrayRank ();
ILGenerator ig = ec.ig;
- ea.Expr.Emit (ec);
-
- foreach (Argument a in ea.Arguments)
- a.Expr.Emit (ec);
-
+ LoadArrayAndArguments (ec);
+
if (rank == 1)
EmitLoadOpcode (ig, type);
else {
{
int rank = ea.Expr.Type.GetArrayRank ();
ILGenerator ig = ec.ig;
-
- ea.Expr.Emit (ec);
-
- foreach (Argument a in ea.Arguments)
- a.Expr.Emit (ec);
-
Type t = source.Type;
+ LoadArrayAndArguments (ec);
+
//
// The stobj opcode used by value types will need
// an address on the stack, not really an array/array
if (rank == 1)
EmitStoreOpcode (ig, t);
else {
- ModuleBuilder mb = RootContext.ModuleBuilder;
- Type [] args = new Type [ea.Arguments.Count + 1];
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
+ int arg_count = ea.Arguments.Count;
+ Type [] args = new Type [arg_count + 1];
MethodInfo set;
- int i = 0;
-
- foreach (Argument a in ea.Arguments)
- args [i++] = a.Type;
+ for (int i = 0; i < arg_count; i++){
+ //args [i++] = a.Type;
+ args [i] = TypeManager.int32_type;
+ }
- args [i] = type;
+ args [arg_count] = type;
set = mb.GetArrayMethod (
ea.Expr.Type, "Set",
}
}
- public void AddressOf (EmitContext ec)
+ public void AddressOf (EmitContext ec, AddressOp mode)
{
int rank = ea.Expr.Type.GetArrayRank ();
ILGenerator ig = ec.ig;
-
- ea.Expr.Emit (ec);
- foreach (Argument a in ea.Arguments)
- a.Expr.Emit (ec);
+ LoadArrayAndArguments (ec);
if (rank == 1){
ig.Emit (OpCodes.Ldelema, type);
}
}
}
-
- static public Indexers GetIndexersForType (Type t, TypeManager tm, Location loc)
+
+ static private Indexers GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
{
- Indexers ix = (Indexers) map [t];
- string p_name = TypeManager.IndexerPropertyName (t);
+ Indexers ix = (Indexers) map [lookup_type];
if (ix != null)
return ix;
- MemberInfo [] mi = tm.FindMembers (
- t, MemberTypes.Property,
- BindingFlags.Public | BindingFlags.Instance,
- Type.FilterName, p_name);
+ string p_name = TypeManager.IndexerPropertyName (lookup_type);
- if (mi == null || mi.Length == 0){
- Report.Error (21, loc,
- "Type `" + TypeManager.CSharpName (t) + "' does not have " +
- "any indexers defined");
+ MemberInfo [] mi = TypeManager.MemberLookup (
+ caller_type, lookup_type, MemberTypes.Property,
+ BindingFlags.Public | BindingFlags.Instance, p_name);
+
+ if (mi == null || mi.Length == 0)
return null;
- }
-
+
ix = new Indexers (mi);
- map [t] = ix;
+ map [lookup_type] = ix;
return ix;
}
+
+ static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc)
+ {
+ Indexers ix = (Indexers) map [lookup_type];
+
+ if (ix != null)
+ return ix;
+
+ ix = GetIndexersForTypeOrInterface (caller_type, lookup_type);
+ if (ix != null)
+ return ix;
+
+ Type [] ifaces = TypeManager.GetInterfaces (lookup_type);
+ if (ifaces != null) {
+ foreach (Type itype in ifaces) {
+ ix = GetIndexersForTypeOrInterface (caller_type, itype);
+ if (ix != null)
+ return ix;
+ }
+ }
+
+ Report.Error (21, loc,
+ "Type `" + TypeManager.CSharpName (lookup_type) +
+ "' does not have any indexers defined");
+ return null;
+ }
}
/// <summary>
if (ilist == null)
ilist = Indexers.GetIndexersForType (
- indexer_type, RootContext.TypeManager, ea.loc);
+ ec.ContainerType, indexer_type, ea.loc);
//
// Step 2: find the proper match
//
- if (ilist != null && ilist.getters != null && ilist.getters.Count > 0)
+ if (ilist != null && ilist.getters != null && ilist.getters.Count > 0){
+ Location loc = ea.loc;
+
get = (MethodInfo) Invocation.OverloadResolve (
- ec, new MethodGroupExpr (ilist.getters), ea.Arguments, ea.loc);
+ ec, new MethodGroupExpr (ilist.getters, loc), ea.Arguments, loc);
+ }
if (get == null){
Report.Error (154, ea.loc,
if (ilist == null)
ilist = Indexers.GetIndexersForType (
- indexer_type, RootContext.TypeManager, ea.loc);
+ ec.ContainerType, indexer_type, ea.loc);
if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
+ Location loc = ea.loc;
+
set_arguments = (ArrayList) ea.Arguments.Clone ();
set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
set = (MethodInfo) Invocation.OverloadResolve (
- ec, new MethodGroupExpr (ilist.setters), set_arguments, ea.loc);
+ ec, new MethodGroupExpr (ilist.setters, loc), set_arguments, loc);
}
if (set == null){
public override void Emit (EmitContext ec)
{
- Invocation.EmitCall (ec, false, false, ea.Expr, get, ea.Arguments);
+ Invocation.EmitCall (ec, false, false, ea.Expr, get, ea.Arguments, ea.loc);
}
//
//
public void EmitAssign (EmitContext ec, Expression source)
{
- Invocation.EmitCall (ec, false, false, ea.Expr, set, set_arguments);
+ Invocation.EmitCall (ec, false, false, ea.Expr, set, set_arguments, ea.loc);
}
}
public override Expression DoResolve (EmitContext ec)
{
Expression member_lookup;
- Type current_type = ec.TypeContainer.TypeBuilder;
+ Type current_type = ec.ContainerType;
Type base_type = current_type.BaseType;
Expression e;
public override Expression DoResolve (EmitContext ec)
{
- Type current_type = ec.TypeContainer.TypeBuilder;
+ Type current_type = ec.ContainerType;
Type base_type = current_type.BaseType;
Expression member_lookup;
/// foreach implementation to typecast the object return value from
/// get_Current into the proper type. All code has been generated and
/// we only care about the side effect conversions to be performed
+ ///
+ /// This is also now used as a placeholder where a no-action expression
+ /// is needed (the `New' class).
/// </summary>
public class EmptyExpression : Expression {
public EmptyExpression ()
}
type = RootContext.LookupType (
- ec.TypeContainer, left.Type.FullName + dim, false, loc);
+ ec.DeclSpace, left.Type.FullName + dim, false, loc);
if (type == null)
return null;
type = Type.GetType (array_ptr_type_name);
if (type == null){
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
type = mb.GetType (array_ptr_type_name);
}
return null;
}
- otype = RootContext.LookupType (ec.TypeContainer, t, false, loc);
+ otype = RootContext.LookupType (ec.DeclSpace, t, false, loc);
if (otype == null)
return null;
string ptr_name = otype.FullName + "*";
type = Type.GetType (ptr_name);
if (type == null){
- ModuleBuilder mb = RootContext.ModuleBuilder;
+ ModuleBuilder mb = CodeGen.ModuleBuilder;
type = mb.GetType (ptr_name);
}