public Return (Expression expr, Location l)
{
+ expr = Parser.SetValueRequiredFlag (expr);
Expr = expr;
loc = l;
}
if (ec.CurrentBranching.InTryBlock ())
ec.CurrentBranching.AddFinallyVector (vector);
- vector.Returns = FlowReturns.ALWAYS;
- vector.Breaks = FlowReturns.ALWAYS;
+ if (! ec.InTry && ! ec.InCatch) {
+ vector.Returns = FlowReturns.ALWAYS;
+ vector.Breaks = FlowReturns.ALWAYS;
+ }
return true;
}
public class LabeledStatement : Statement {
public readonly Location Location;
- //string label_name;
+ string label_name;
bool defined;
bool referenced;
Label label;
public LabeledStatement (string label_name, Location l)
{
- //this.label_name = label_name;
+ this.label_name = label_name;
this.Location = l;
}
+
+ public string LabelName {
+ get {
+ return label_name;
+ }
+ }
public Label LabelTarget (EmitContext ec)
{
}
if (ec.InTry || ec.InCatch) {
- if (!ec.HasReturnLabel) {
- ec.ReturnLabel = ec.ig.DefineLabel ();
- ec.HasReturnLabel = true;
- }
- ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+ if (ec.HasExitLabel)
+ ec.ig.Emit (OpCodes.Leave, ec.ExitLabel);
} else {
if(type == ExitType.SUB) {
ec.ig.Emit (OpCodes.Ret);
public LocalBuilder LocalBuilder;
public Type VariableType;
public string Alias;
-
- bool mod_static;
- public bool Static {
- get {
- return mod_static;
- }
- set {
- mod_static = value;
- }
- }
-
+ FieldBase FieldAlias;
public readonly string Name;
public readonly Location Location;
public readonly int Block;
ec.CurrentBranching.SetVariableAssigned (this, StructInfo [name]);
}
+ public FieldBase GetFieldAlias (EmitContext ec) {
+ if ( this.FieldAlias != null )
+ return this.FieldAlias;
+ else
+ {
+ ArrayList fields = ec.TypeContainer.Fields;
+ for (int i = 0; i < fields.Count; i++)
+ {
+ if (((Field) fields[i]).Name == this.Alias)
+ {
+ this.FieldAlias = (Field) fields[i];
+ break;
+ }
+ }
+ return this.FieldAlias;
+ }
+ }
+
public bool Resolve (DeclSpace decl)
{
if (struct_info != null)
bool isIndexerAccess;
string memberName;
Expression type_expr;
+ bool is_resolved = false;
public StatementSequence (Block parent, Location loc, Expression expr)
: this (parent, loc, expr, null)
public override Expression DoResolve (EmitContext ec)
{
+ if (is_resolved)
+ return this;
if (!stmtBlock.Resolve (ec))
return null;
eclass = ExprClass.Value;
type = TypeManager.object_type;
+ is_resolved = true;
return this;
}
protected override bool DoEmit (EmitContext ec)
{
ILGenerator ig = ec.ig;
- Label finish = ig.DefineLabel ();;
bool returns;
ec.TryCatchLevel++;
- ig.BeginExceptionBlock ();
+ Label finish = ig.BeginExceptionBlock ();
+ ec.HasExitLabel = true;
+ ec.ExitLabel = finish;
+
bool old_in_try = ec.InTry;
ec.InTry = true;
returns = Block.Emit (ec);
ec.InCatch = old_in_catch;
- ig.MarkLabel (finish);
if (Fini != null){
ig.BeginFinallyBlock ();
bool old_in_finally = ec.InFinally;
if (!returns || ec.InTry || ec.InCatch)
return returns;
+ return true;
+ }
+ }
+
+ public class Pending_Assign {
+ Statement assign;
+ Block block_to_be_inserted;
+ int statement_index;
+
+ public Pending_Assign (Block block, Statement assign, int index)
+ {
+ this.assign = assign;
+ this.block_to_be_inserted = block;
+ this.statement_index = index;
+ }
+
+ public void AddAssign()
+ {
+ block_to_be_inserted.statements.Insert( statement_index, assign );
+ }
+ }
+
+ public class On_Error : Statement {
+ public readonly Block method_block;
+ ArrayList targets;
+ LabeledStatement[] labeledstatements;
+
+ public On_Error (Block method_block, Location l)
+ {
+ //Goto
+ this.method_block = method_block;
+ base.loc = l;
+ targets = new ArrayList();
+ }
+
+ public int AddTarget ( string target )
+ {
+ int i = targets.IndexOf( target ) ;
+
+ if ( i == -1 )
+ return targets.Add ( target );
+ else
+ return i;
+ }
+
+ public ArrayList Targets {
+ get {
+ return targets;
+ }
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ this.labeledstatements = new LabeledStatement[targets.Count];
+
+ bool ok = true;
+
+ ec.StartFlowBranching (FlowBranchingType.EXCEPTION, method_block.StartLocation);
+
+ Report.Debug (1, "START OF TRY BLOCK", method_block.StartLocation);
+
+ bool old_in_try = ec.InTry;
+ ec.InTry = true;
+
+ if (!method_block.Resolve (ec))
+ ok = false;
+
+ ec.InTry = old_in_try;
+
+ FlowBranching.UsageVector vector = ec.CurrentBranching.CurrentUsageVector;
+
+ ec.EndFlowBranching ();
+
+ ec.CurrentBranching.CurrentUsageVector.Or (vector);
+
+ Report.Debug (1, "END OF TRY", ec.CurrentBranching);
+
+ //This statement has more than one label in cases of more than one 'on error goto' specification.
+ for ( int i = 0 ; i < targets.Count ; i++ )
+ {
+ labeledstatements[i] = method_block.Parent.LookupLabel ((string) targets[i]);
+
+ // If this is a forward goto.
+ if (!labeledstatements[i].IsDefined)
+ labeledstatements[i].AddUsageVector (ec.CurrentBranching.CurrentUsageVector);
+
+ labeledstatements[i].AddReference ();
+ }
+ ec.CurrentBranching.CurrentUsageVector.Breaks = FlowReturns.ALWAYS;
+
+ return ok;
+ }
+ protected override bool DoEmit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ //Try
+
+ bool returns;
+
+ ec.TryCatchLevel++;
+
+ Label finish = ig.BeginExceptionBlock ();
+ ec.HasExitLabel = true;
+ ec.ExitLabel = finish;
+
+ bool old_in_try = ec.InTry;
+ ec.InTry = true;
+ returns = method_block.Emit (ec);
+ ec.InTry = old_in_try;
+ bool old_in_catch = ec.InCatch;
+ ec.InCatch = true;
+
+ Label error = ig.DefineLabel();
+ Label endfilter = ig.DefineLabel();
+ Label verification = ig.DefineLabel();
+
+ ig.BeginExceptFilterBlock();
+ ig.Emit (OpCodes.Isinst, Type.GetType("System.Exception") );
+ ig.Emit (OpCodes.Brtrue_S, verification );
+
+ ig.Emit (OpCodes.Br_S, error);
+
+ ig.MarkLabel ( verification );
+ ig.Emit (OpCodes.Ldloc_0);
+ ig.Emit (OpCodes.Brfalse_S, error);
+
+ ig.Emit (OpCodes.Ldloc_1);
+ ig.Emit (OpCodes.Brtrue_S, error);
+
+ ig.Emit (OpCodes.Ldc_I4_1);
+ ig.Emit (OpCodes.Br_S, endfilter);
+
+ ig.MarkLabel (error);
+ ig.Emit (OpCodes.Ldc_I4_0);
+
+ ig.MarkLabel ( endfilter );
+
+
+ Label endcatch = ig.DefineLabel();
+ Label verification2 = ig.DefineLabel();
+
+ ig.BeginCatchBlock (null);
+ ig.Emit (OpCodes.Castclass, Type.GetType("System.Exception"));
+ ig.Emit (OpCodes.Dup);
+
+ Type t = typeof(Microsoft.VisualBasic.CompilerServices.ProjectData);
+ MethodInfo mi = t.GetMethod("SetProjectError", new Type[] { typeof(System.Exception) } );
+ ig.Emit (OpCodes.Call, mi);
+ ig.Emit (OpCodes.Stloc_3);
+ ig.Emit (OpCodes.Ldloc_1);
+ ig.Emit (OpCodes.Brfalse_S, verification2 );
+ ig.Emit (OpCodes.Leave_S, finish );
+ ig.MarkLabel ( verification2 );
+ ig.Emit (OpCodes.Ldc_I4_M1);
+ ig.Emit (OpCodes.Stloc_1);
+ ig.Emit (OpCodes.Ldloc_0);
+
+ Label[] lbswitch = new Label[targets.Count + 1];
+ for ( int i = 0; i <= targets.Count; i++ )
+ lbswitch[i] = ig.DefineLabel();
+
+ ig.Emit (OpCodes.Switch, lbswitch);
+ ig.MarkLabel ( lbswitch[0] ) ;
+ ig.Emit (OpCodes.Leave_S, endcatch);
+
+ Label[] labels = new Label[targets.Count];
+ for ( int i = 0; i < targets.Count; i++ )
+ {
+ labels[i] = labeledstatements[i].LabelTarget(ec);
+
+ ig.MarkLabel ( lbswitch[i+1] ) ;
+ ig.Emit ( OpCodes.Leave, labels[i] );
+ }
+
+ ig.MarkLabel ( endcatch );
+ ig.Emit ( OpCodes.Rethrow );
+
+ ec.InCatch = old_in_catch;
+
+ ig.EndExceptionBlock ();
+ ec.TryCatchLevel--;
+
+ Label end = ig.DefineLabel();
+ //ig.MarkLabel ( finish ) ;
+ ig.Emit (OpCodes.Ldloc_1);
+ ig.Emit (OpCodes.Brfalse_S, end );
+
+ mi = t.GetMethod("ClearProjectError");
+ ig.Emit (OpCodes.Call, mi);
+
+ ig.MarkLabel(end) ;
+
+ if (!returns)
+ return returns;
+
// Unfortunately, System.Reflection.Emit automatically emits a leave
// to the end of the finally block. This is a problem if 'returns'
// is true since we may jump to a point after the end of the method.
return true;
}
+
}
public class Using : Statement {
if (expr == null)
return false;
+ if ( variable.VariableInfo.Alias != null )
+ {
+ FieldBase fb = variable.VariableInfo.GetFieldAlias(ec);
+
+ if ( fb == null )
+ {
+ Report.Error (451, loc,"Name '" + variable.VariableInfo.Name + "' is not declared.");
+ return false;
+ }
+ else
+ type = fb.Type;
+ }
+
var_type = ec.DeclSpace.ResolveType (type, false, loc);
if (var_type == null)
return false;
ig.Emit (OpCodes.Ldloc, enumerator);
ig.Emit (OpCodes.Callvirt, hm.move_next);
ig.Emit (OpCodes.Brfalse, end_try);
+
+
+ FieldBase fb = null;
+ if ( variable.VariableInfo.Alias != null )
+ {
+ fb = variable.VariableInfo.GetFieldAlias(ec);
+
+ if( (fb.ModFlags & Modifiers.STATIC) == 0 )
+ ig.Emit (OpCodes.Ldarg_0);
+ }
+
ig.Emit (OpCodes.Ldloc, enumerator);
ig.Emit (OpCodes.Callvirt, hm.get_current);
- variable.EmitAssign (ec, conv);
+
+ if ( fb == null)
+ variable.EmitAssign (ec, conv);
+ else
+ variable.EmitAssign (ec, conv, fb);
+
statement.Emit (ec);
ig.Emit (OpCodes.Br, ec.LoopBegin);
ig.MarkLabel (end_try);
loop = ig.DefineLabel ();
ig.MarkLabel (loop);
+ FieldBase fb = null;
+ if ( variable.VariableInfo.Alias != null )
+ {
+ fb = variable.VariableInfo.GetFieldAlias(ec);
+
+ if( (fb.ModFlags & Modifiers.STATIC) == 0 )
+ ig.Emit (OpCodes.Ldarg_0);
+ }
+
ig.Emit (OpCodes.Ldloc, copy);
ig.Emit (OpCodes.Ldloc, counter);
ArrayAccess.EmitLoadOpcode (ig, var_type);
- variable.EmitAssign (ec, conv);
+ if ( fb == null)
+ variable.EmitAssign (ec, conv);
+ else
+ variable.EmitAssign (ec, conv, fb);
statement.Emit (ec);