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 Expression Type;
public LocalBuilder LocalBuilder;
public Type VariableType;
+ public string Alias;
+ FieldBase FieldAlias;
public readonly string Name;
public readonly Location Location;
public readonly int Block;
-
+
public int Number;
public bool Used;
public bool Assigned;
public bool ReadOnly;
+ public VariableInfo (Expression type, string name, int block, Location l, string Alias)
+ : this (type, name, block, l)
+ {
+ this.Alias = Alias;
+ }
+
public VariableInfo (Expression type, string name, int block, Location l)
{
Type = type;
Location = l;
}
+ public VariableInfo (TypeContainer tc, int block, Location l, string Alias)
+ : this (tc, block, l)
+ {
+ this.Alias = Alias;
+ }
+
public VariableInfo (TypeContainer tc, int block, Location l)
{
VariableType = tc.TypeBuilder;
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)
return "VariableInfo (" + Number + "," + Type + "," + Location + ")";
}
}
-
+
public class StatementSequence : Expression {
Block stmtBlock;
ArrayList args, originalArgs;
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);
public AddHandler (Expression evt_id, Expression evt_handler, Location l)
{
EvtId = evt_id;
- EvtHandler = evt_handler;
+ EvtHandler = Parser.SetAddressOf (evt_handler);
loc = l;
resolved = false;
//Console.WriteLine ("Adding handler '" + evt_handler + "' for Event '" + evt_id +"'");
public RemoveHandler (Expression evt_id, Expression evt_handler, Location l)
{
EvtId = evt_id;
- EvtHandler = evt_handler;
+ EvtHandler = Parser.SetAddressOf (evt_handler);
loc = l;
}
}
public class RedimClause {
- public Expression Expr;
- public ArrayList NewIndexes;
+ private Expression RedimTarget;
+ private ArrayList NewIndexes;
+ private Expression AsType;
- public RedimClause (Expression e, ArrayList args)
+ private LocalTemporary localTmp = null;
+ private Expression origRedimTarget = null;
+ private StatementExpression ReDimExpr;
+
+ public RedimClause (Expression e, ArrayList args, Expression e_as)
{
- Expr = e;
+ if (e is SimpleName)
+ ((SimpleName) e).IsInvocation = false;
+ if (e is MemberAccess)
+ ((MemberAccess) e).IsInvocation = false;
+
+ RedimTarget = e;
NewIndexes = args;
+ AsType = e_as;
}
+
+ public bool Resolve (EmitContext ec, bool Preserve, Location loc)
+ {
+ RedimTarget = RedimTarget.Resolve (ec);
+
+ if (AsType != null) {
+ Report.Error (30811, loc, "'ReDim' statements can no longer be used to declare array variables");
+ return false;
+ }
+
+ if (!RedimTarget.Type.IsArray) {
+ Report.Error (49, loc, "'ReDim' statement requires an array");
+ return false;
+ }
+
+ ArrayList args = new ArrayList();
+ foreach (Argument a in NewIndexes) {
+ if (a.Resolve(ec, loc))
+ args.Add (a.Expr);
+ }
+
+ for (int x = 0; x < args.Count; x++) {
+ args[x] = new Binary (Binary.Operator.Addition,
+ (Expression) args[x], new IntLiteral (1), Location.Null);
+ }
+
+ NewIndexes = args;
+ if (RedimTarget.Type.GetArrayRank() != NewIndexes.Count) {
+ Report.Error (30415, loc, "'ReDim' cannot change the number of dimensions of an array.");
+ return false;
+ }
+
+ Type BaseType = RedimTarget.Type.GetElementType();
+ Expression BaseTypeExpr = MonoBASIC.Parser.DecomposeQI(BaseType.FullName.ToString(), Location.Null);
+ ArrayCreation acExpr = new ArrayCreation (BaseTypeExpr, NewIndexes, "", null, Location.Null);
+ if (Preserve)
+ {
+ ExpressionStatement PreserveExpr = null;
+ if (RedimTarget is PropertyGroupExpr) {
+ localTmp = new LocalTemporary (ec, RedimTarget.Type);
+ PropertyGroupExpr pe = RedimTarget as PropertyGroupExpr;
+ origRedimTarget = new PropertyGroupExpr (pe.Properties, pe.Arguments, pe.InstanceExpression, loc);
+ if ((origRedimTarget = origRedimTarget.Resolve (ec)) == null) {
+ Report.Error (-1, loc, "'ReDim' vs PropertyGroup");
+ return false;
+ }
+ PreserveExpr = (ExpressionStatement) new Preserve(localTmp, acExpr, loc);
+ } else
+ PreserveExpr = (ExpressionStatement) new Preserve(RedimTarget, acExpr, loc);
+ ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, PreserveExpr, loc), loc);
+ }
+ else
+ ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, acExpr, loc), loc);
+ ReDimExpr.Resolve(ec);
+ return true;
+ }
+
+ public void DoEmit (EmitContext ec)
+ {
+ if (ReDimExpr == null)
+ return;
+
+ if (localTmp != null && origRedimTarget != null) {
+ origRedimTarget.Emit (ec);
+ localTmp.Store (ec);
+ }
+ ReDimExpr.Emit(ec);
+ }
+
}
public class ReDim : Statement {
ArrayList RedimTargets;
- Type BaseType;
bool Preserve;
- private StatementExpression ReDimExpr;
-
public ReDim (ArrayList targets, bool opt_preserve, Location l)
{
loc = l;
public override bool Resolve (EmitContext ec)
{
- Expression RedimTarget;
- ArrayList NewIndexes;
-
- foreach (RedimClause rc in RedimTargets) {
- RedimTarget = rc.Expr;
- NewIndexes = rc.NewIndexes;
-
- RedimTarget = RedimTarget.Resolve (ec);
- if (!RedimTarget.Type.IsArray)
- Report.Error (49, "'ReDim' statement requires an array");
-
- ArrayList args = new ArrayList();
- foreach (Argument a in NewIndexes) {
- if (a.Resolve(ec, loc))
- args.Add (a.Expr);
- }
-
- for (int x = 0; x < args.Count; x++) {
- args[x] = new Binary (Binary.Operator.Addition,
- (Expression) args[x], new IntLiteral (1), Location.Null);
- }
-
- NewIndexes = args;
- if (RedimTarget.Type.GetArrayRank() != args.Count)
- Report.Error (30415, "'ReDim' cannot change the number of dimensions of an array.");
-
- BaseType = RedimTarget.Type.GetElementType();
- Expression BaseTypeExpr = MonoBASIC.Parser.DecomposeQI(BaseType.FullName.ToString(), Location.Null);
- ArrayCreation acExpr = new ArrayCreation (BaseTypeExpr, NewIndexes, "", null, Location.Null);
- // TODO: we are in a foreach we probably can't reuse ReDimExpr, must turn it into an array(list)
- if (Preserve)
- {
- ExpressionStatement PreserveExpr = (ExpressionStatement) new Preserve(RedimTarget, acExpr, loc);
- ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, PreserveExpr, loc), loc);
- }
- else
- ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, acExpr, loc), loc);
- ReDimExpr.Resolve(ec);
- }
- return true;
+ bool result = true;
+ foreach (RedimClause rc in RedimTargets)
+ result = rc.Resolve(ec, Preserve, loc) && result;
+ return result;
}
protected override bool DoEmit (EmitContext ec)
{
- ReDimExpr.Emit(ec);
+ foreach (RedimClause rc in RedimTargets)
+ rc.DoEmit(ec);
return false;
}