// The information about a user-perceived local variable
//
public class LocalInfo : IKnownVariable, ILocalVariable {
- public readonly Expression Type;
+ public readonly FullNamedExpression Type;
public Type VariableType;
public readonly string Name;
Flags flags;
ReadOnlyContext ro_context;
LocalBuilder builder;
-
- public LocalInfo (Expression type, string name, Block block, Location l)
+
+ public LocalInfo (FullNamedExpression type, string name, Block block, Location l)
{
Type = type;
Name = name;
// Variables in anonymous block are not resolved yet
//
if (VariableType == null)
- return new LocalInfo (Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
+ return new LocalInfo ((FullNamedExpression) Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
//
// Variables in method block are resolved
return null;
}
- LocalInfo vi = new LocalInfo (type, name, this, l);
+ LocalInfo vi = new LocalInfo ((FullNamedExpression) type, name, this, l);
AddVariable (vi);
if ((flags & Flags.VariablesInitialized) != 0)
{
Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
name, conflict);
- }
+ }
public bool AddConstant (Expression type, string name, Expression value, Location l)
{
public static void Reset ()
{
unique_counter = 0;
+ allowed_types = null;
}
public override bool Resolve (EmitContext ec)
#if GMCS_SOURCE
if ((new_expr == null) && TypeManager.IsNullableType (Expr.Type)) {
- unwrap = Nullable.Unwrap.Create (Expr, ec);
+ unwrap = Nullable.Unwrap.Create (Expr, false);
if (unwrap == null)
return false;
}
}
- class StringEmitter : Emitter {
- class StringPtr : Expression
- {
- LocalBuilder b;
-
- public StringPtr (LocalBuilder b, Location l)
- {
- this.b = b;
- eclass = ExprClass.Value;
- type = TypeManager.char_ptr_type;
- loc = l;
- }
-
- public override Expression CreateExpressionTree (EmitContext ec)
- {
- throw new NotSupportedException ("ET");
- }
-
- public override Expression DoResolve (EmitContext ec)
- {
- // This should never be invoked, we are born in fully
- // initialized state.
-
- return this;
- }
-
- public override void Emit (EmitContext ec)
- {
- if (TypeManager.int_get_offset_to_string_data == null) {
- // TODO: Move to resolve !!
- TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
- TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
- }
-
- ILGenerator ig = ec.ig;
-
- ig.Emit (OpCodes.Ldloc, b);
- ig.Emit (OpCodes.Conv_I);
- ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
- ig.Emit (OpCodes.Add);
- }
- }
-
- LocalBuilder pinned_string;
- Location loc;
+ class StringEmitter : Emitter
+ {
+ LocalInfo pinned_string;
public StringEmitter (Expression expr, LocalInfo li, Location loc):
base (expr, li)
{
- this.loc = loc;
+ pinned_string = new LocalInfo (new TypeExpression (TypeManager.string_type, loc), null, null, loc);
+ pinned_string.Pinned = true;
}
public override void Emit (EmitContext ec)
{
- ILGenerator ig = ec.ig;
- pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
-
+ pinned_string.Resolve (ec);
+ pinned_string.ResolveVariable (ec);
+
converted.Emit (ec);
- ig.Emit (OpCodes.Stloc, pinned_string);
+ pinned_string.EmitAssign (ec);
- Expression sptr = new StringPtr (pinned_string, loc);
- converted = Convert.ImplicitConversionRequired (
- ec, sptr, vi.VariableType, loc);
-
- if (converted == null)
- return;
+ PropertyInfo p = TypeManager.int_get_offset_to_string_data;
+ if (p == null) {
+ // TODO: Move to resolve
+ p = TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedProperty (
+ TypeManager.runtime_helpers_type, "OffsetToStringData", pinned_string.Location, TypeManager.int32_type);
- converted.Emit (ec);
+ if (p == null)
+ return;
+ }
+
+ // TODO: Should use Binary::Add
+ pinned_string.Emit (ec);
+ ec.ig.Emit (OpCodes.Conv_I);
+
+ PropertyExpr pe = new PropertyExpr (pinned_string.VariableType, p, pinned_string.Location);
+ //pe.InstanceExpression = pinned_string;
+ pe.Resolve (ec).Emit (ec);
+
+ ec.ig.Emit (OpCodes.Add);
vi.EmitAssign (ec);
}
public override void EmitExit (EmitContext ec)
{
ec.ig.Emit (OpCodes.Ldnull);
- ec.ig.Emit (OpCodes.Stloc, pinned_string);
+ pinned_string.EmitAssign (ec);
}
}
}
}
+ // FIXME: Why is it almost exact copy of Using ??
public class UsingTemporary : ExceptionStatement {
TemporaryVariable local_copy;
public Statement Statement;
Expression var;
Expression init;
- Expression converted_var;
ExpressionStatement assign;
public Using (Expression var, Expression init, Statement stmt, Location l)
loc = l;
}
- bool ResolveVariable (EmitContext ec)
- {
- ExpressionStatement a = new SimpleAssign (var, init, loc);
- a = a.ResolveStatement (ec);
- if (a == null)
- return false;
-
- assign = a;
-
- if (TypeManager.ImplementsInterface (a.Type, TypeManager.idisposable_type)) {
- converted_var = var;
- return true;
- }
-
- Expression e = Convert.ImplicitConversionStandard (ec, a, TypeManager.idisposable_type, var.Location);
- if (e == null) {
- Error_IsNotConvertibleToIDisposable (var);
- return false;
- }
-
- converted_var = e;
-
- return true;
- }
-
static public void Error_IsNotConvertibleToIDisposable (Expression expr)
{
Report.SymbolRelatedToPreviousError (expr.Type);
protected override void EmitFinallyBody (EmitContext ec)
{
ILGenerator ig = ec.ig;
+ Label skip = ig.DefineLabel ();
- if (!TypeManager.IsStruct (var.Type)) {
- Label skip = ig.DefineLabel ();
+ bool emit_null_check = !TypeManager.IsValueType (var.Type);
+ if (emit_null_check) {
var.Emit (ec);
ig.Emit (OpCodes.Brfalse, skip);
- converted_var.Emit (ec);
- ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
- ig.MarkLabel (skip);
- } else {
- Expression ml = Expression.MemberLookup(ec.ContainerType, TypeManager.idisposable_type, var.Type, "Dispose", Mono.CSharp.Location.Null);
-
- if (!(ml is MethodGroupExpr)) {
- var.Emit (ec);
- ig.Emit (OpCodes.Box, var.Type);
- ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
- } else {
- MethodInfo mi = null;
-
- foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
- if (TypeManager.GetParameterData (mk).Count == 0) {
- mi = mk;
- break;
- }
- }
-
- if (mi == null) {
- Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
- return;
- }
+ }
- IMemoryLocation mloc = (IMemoryLocation) var;
+ Invocation.EmitCall (ec, false, var, TypeManager.void_dispose_void, new ArrayList (0), loc);
- mloc.AddressOf (ec, AddressOp.Load);
- ig.Emit (OpCodes.Call, mi);
- }
- }
+ if (emit_null_check)
+ ig.MarkLabel (skip);
}
public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
return ok;
}
+ bool ResolveVariable (EmitContext ec)
+ {
+ assign = new SimpleAssign (var, init, loc);
+ assign = assign.ResolveStatement (ec);
+ if (assign == null)
+ return false;
+
+ if (assign.Type == TypeManager.idisposable_type ||
+ TypeManager.ImplementsInterface (assign.Type, TypeManager.idisposable_type)) {
+ return true;
+ }
+
+ Expression e = Convert.ImplicitConversionStandard (ec, assign, TypeManager.idisposable_type, var.Location);
+ if (e == null) {
+ Error_IsNotConvertibleToIDisposable (var);
+ return false;
+ }
+
+ throw new NotImplementedException ("covariance?");
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Using target = (Using) t;
protected override void EmitFinallyBody (EmitContext ec)
{
- ILGenerator ig = ec.ig;
-
Expression instance = parent.enumerator;
if (!TypeManager.IsValueType (parent.enumerator_type)) {
+ ILGenerator ig = ec.ig;
parent.enumerator.Emit (ec);