// Author:
// Miguel de Icaza (miguel@ximian.com)
// Martin Baulig (martin@gnome.org)
+// Anirban Bhattacharjee (banirban@novell.com)
//
// (C) 2001, 2002 Ximian, Inc.
//
using System.Reflection.Emit;
using System.Diagnostics;
-namespace Mono.CSharp {
+namespace Mono.MonoBASIC {
using System.Collections;
} else {
if (Expr == null){
Report.Error (126, loc, "An object of type `" +
- TypeManager.CSharpName (ec.ReturnType) + "' is " +
+ TypeManager.MonoBASIC_Name (ec.ReturnType) + "' is " +
"expected for the return statement");
return true;
}
if ((t != TypeManager.exception_type) &&
!t.IsSubclassOf (TypeManager.exception_type) &&
!(expr is NullLiteral)) {
- Report.Error (155, loc,
+ Report.Error (30665, loc,
"The type caught or thrown must be derived " +
"from System.Exception");
return false;
{
ILGenerator ig = ec.ig;
- if (ec.InLoop == false && ec.Switch == null){
- Report.Error (139, loc, "No enclosing loop or switch to continue to");
- return false;
- }
+ if (type != ExitType.SUB && type != ExitType.FUNCTION &&
+ type != ExitType.PROPERTY && type != ExitType.TRY) {
+ if (ec.InLoop == false && ec.Switch == null){
+ if (type == ExitType.FOR)
+ Report.Error (30096, loc, "No enclosing FOR loop to exit from");
+ if (type == ExitType.WHILE) \r
+ Report.Error (30097, loc, "No enclosing WHILE loop to exit from");
+ if (type == ExitType.DO)
+ Report.Error (30089, loc, "No enclosing DO loop to exit from");
+ if (type == ExitType.SELECT)
+ Report.Error (30099, loc, "No enclosing SELECT to exit from");
- if (ec.InTry || ec.InCatch)
- ig.Emit (OpCodes.Leave, ec.LoopEnd);
- else
- ig.Emit (OpCodes.Br, ec.LoopEnd);
+ return false;
+ }
+ if (ec.InTry || ec.InCatch)
+ ig.Emit (OpCodes.Leave, ec.LoopEnd);
+ else
+ ig.Emit (OpCodes.Br, ec.LoopEnd);
+ } else {
+ if (ec.InFinally){
+ Report.Error (30393, loc,
+ "Control can not leave the body of the finally block");
+ return false;
+ }
+
+ if (ec.InTry || ec.InCatch) {
+ if (!ec.HasReturnLabel) {
+ ec.ReturnLabel = ec.ig.DefineLabel ();
+ ec.HasReturnLabel = true;
+ }
+ ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
+ } else
+ ec.ig.Emit (OpCodes.Ret);
+
+ return true;
+ }
+
return false;
}
}
FieldInfo field = struct_info [i];
Report.Error (171, loc,
- "Field `" + TypeManager.CSharpName (VariableType) +
+ "Field `" + TypeManager.MonoBASIC_Name (VariableType) +
"." + field.Name + "' must be fully initialized " +
"before control leaves the constructor");
return false;
if (converted != null){
Report.Error (-12, loc, "More than one conversion to an integral " +
" type exists for type `" +
- TypeManager.CSharpName (Expr.Type)+"'");
+ TypeManager.MonoBASIC_Name (Expr.Type)+"'");
return null;
} else
converted = e;
if (type.IsValueType){
Report.Error (185, loc, "lock statement requires the expression to be " +
" a reference type (type is: `" +
- TypeManager.CSharpName (type) + "'");
+ TypeManager.MonoBASIC_Name (type) + "'");
return false;
}
public class Catch {
public readonly string Name;
public readonly Block Block;
+ public Expression Clause;
public readonly Location Location;
Expression type_expr;
+ //Expression clus_expr;
Type type;
- public Catch (Expression type, string name, Block block, Location l)
+ public Catch (Expression type, string name, Block block, Expression clause, Location l)
{
type_expr = type;
Name = name;
Block = block;
+ Clause = clause;
Location = l;
}
return false;
if (type != TypeManager.exception_type && !type.IsSubclassOf (TypeManager.exception_type)){
- Report.Error (155, Location,
+ Report.Error (30665, Location,
"The type caught or thrown must be derived " +
"from System.Exception");
return false;
} else
type = null;
+ if (Clause != null) {
+ Clause = Statement.ResolveBoolean (ec, Clause, Location);
+ if (Clause == null) {
+ return false;
+ }
+ }
+
if (!Block.Resolve (ec))
return false;
ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
} else
ig.Emit (OpCodes.Pop);
-
- if (!c.Block.Emit (ec))
- returns = false;
+
+ //
+ // if when clause is there
+ //
+ if (c.Clause != null) {
+ if (c.Clause is BoolConstant) {
+ bool take = ((BoolConstant) c.Clause).Value;
+
+ if (take)
+ if (!c.Block.Emit (ec))
+ returns = false;
+ } else {
+ EmitBoolExpression (ec, c.Clause, finish, false);
+ if (!c.Block.Emit (ec))
+ returns = false;
+ }
+ } else
+ if (!c.Block.Emit (ec))
+ returns = false;
}
if (General != null){
ig.BeginCatchBlock (TypeManager.object_type);
ig.Emit (OpCodes.Pop);
- if (!General.Block.Emit (ec))
- returns = false;
+
+ if (General.Clause != null) {
+ if (General.Clause is BoolConstant) {
+ bool take = ((BoolConstant) General.Clause).Value;
+ if (take)
+ if (!General.Block.Emit (ec))
+ returns = false;
+ } else {
+ EmitBoolExpression (ec, General.Clause, finish, false);
+ if (!General.Block.Emit (ec))
+ returns = false;
+ }
+ } else
+ if (!General.Block.Emit (ec))
+ returns = false;
}
+
ec.InCatch = old_in_catch;
ig.MarkLabel (finish);
// Although it is not as important in this case, as the type
// will not likely be object (what the enumerator will return).
//
- conv = Expression.ConvertExplicit (ec, empty, var_type, loc);
+ conv = Expression.ConvertExplicit (ec, empty, var_type, false, loc);
if (conv == null)
return false;
public class AddHandler : Statement {
Expression EvtId;
Expression EvtHandler;
- Expression EvtTarget;
- public AddHandler (Expression evt_id, Expression evt_handler,
- Expression evt_target, Location l)
+ //
+ // keeps track whether EvtId is already resolved
+ //
+ bool resolved;
+
+ public AddHandler (Expression evt_id, Expression evt_handler, Location l)
{
EvtId = evt_id;
EvtHandler = evt_handler;
- EvtTarget = evt_target;
loc = l;
+ resolved = false;
//Console.WriteLine ("Adding handler '" + evt_handler + "' for Event '" + evt_id +"'");
}
public override bool Resolve (EmitContext ec)
{
+ //
+ // if EvetId is of EventExpr type that means
+ // this is already resolved
+ //
+ if (EvtId is EventExpr) {
+ resolved = true;
+ return true;
+ }
+
EvtId = EvtId.Resolve(ec);
EvtHandler = EvtHandler.Resolve(ec,ResolveFlags.MethodGroup);
- EvtTarget = EvtTarget.Resolve (ec,ResolveFlags.VariableOrValue);
if (EvtId == null || (!(EvtId is EventExpr))) {
- Report.Error (999, "'AddHandler' statement needs an event designator.");
+ Report.Error (30676, "Need an event designator.");
return false;
}
Report.Error (999, "'AddHandler' statement needs an event handler.");
return false;
}
- //EventExpr ee = (EventExpr) EvtId;
- //MethodGroupExpr me = (MethodGroupExpr) EvtHandler;
- //bool b = EvtId.Type.IsSubclassOf (TypeManager.delegate_type);
- //ee.EventInfo.AddEventHandler(EvtTarget, new System.Delegate())
+
return true;
}
protected override bool DoEmit (EmitContext ec)
{
+ //
+ // Already resolved and emitted don't do anything
+ //
+ if (resolved)
+ return true;
+
Expression e, d;
ArrayList args = new ArrayList();
Argument arg = new Argument (EvtHandler, Argument.AType.Expression);
args.Add (arg);
+
+
// The even type was already resolved to a delegate, so
// we must un-resolve its name to generate a type expression
string ts = (EvtId.Type.ToString()).Replace ('+','.');
return false;
}
- }
-
- public class ReDim : Statement {
- Expression RedimTarget;
- ArrayList NewIndexes;
- ArrayList Initializers;
- Type BaseType;
-
- private StatementExpression ReDimExpr;
-
- public ReDim (Expression expr, ArrayList args, bool opt_preserve, ArrayList inits, Location l)
+ }
+
+ /// <summary>
+ /// RemoveHandler statement
+ /// </summary>
+ public class RemoveHandler : Statement \r
+ {
+ Expression EvtId;
+ Expression EvtHandler;
+
+ public RemoveHandler (Expression evt_id, Expression evt_handler, Location l)
{
+ EvtId = evt_id;
+ EvtHandler = evt_handler;
loc = l;
- RedimTarget = expr;
- NewIndexes = args;
- Initializers = inits;
}
-
+
public override bool Resolve (EmitContext ec)
{
- RedimTarget = RedimTarget.Resolve (ec);
- if (!RedimTarget.Type.IsArray)
- Report.Error (49, "'ReDim' statement requires an array");
+ EvtId = EvtId.Resolve(ec);
+ EvtHandler = EvtHandler.Resolve(ec,ResolveFlags.MethodGroup);
+ if (EvtId == null || (!(EvtId is EventExpr))) \r
+ {
+ Report.Error (30676, "Need an event designator.");
+ return false;
+ }
- ArrayList args = new ArrayList();
- foreach (Argument a in NewIndexes) {
- if (a.Resolve(ec, loc))
- args.Add (a.Expr);
+ if (EvtHandler == null)
+ {
+ Report.Error (999, "'AddHandler' statement needs an event handler.");
+ return false;
}
+ return true;
+ }
+
+ protected override bool DoEmit (EmitContext ec)
+ {
+ Expression e, d;
+ ArrayList args = new ArrayList();
+ Argument arg = new Argument (EvtHandler, Argument.AType.Expression);
+ args.Add (arg);
- for (int x = 0; x < args.Count; x++) {
- args[x] = new Binary (Binary.Operator.Addition,
- (Expression) args[x], new IntLiteral (1), Location.Null);
+ // The even type was already resolved to a delegate, so
+ // we must un-resolve its name to generate a type expression
+ string ts = (EvtId.Type.ToString()).Replace ('+','.');
+ Expression dtype = Mono.MonoBASIC.Parser.DecomposeQI (ts, Location.Null);
+
+ // which we can use to declare a new event handler
+ // of the same type
+ d = new New (dtype, args, Location.Null);
+ d = d.Resolve(ec);
+ // detach the event
+ e = new CompoundAssign(Binary.Operator.Subtraction, EvtId, d, Location.Null);
+
+ // we resolve it all and emit the code
+ e = e.Resolve(ec);
+ if (e != null)
+ {
+ e.Emit(ec);
+ return true;
}
+ return false;
+ }
+ }
+
+ public class RedimClause {
+ public Expression Expr;
+ public ArrayList NewIndexes;
+
+ public RedimClause (Expression e, ArrayList args)
+ {
+ Expr = e;
NewIndexes = args;
- if (RedimTarget.Type.GetArrayRank() != args.Count)
- Report.Error (415, "'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, "", Initializers, Location.Null);
- ReDimExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (RedimTarget, acExpr, loc), loc);
- ReDimExpr.Resolve(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;
+ RedimTargets = targets;
+ Preserve = opt_preserve;
+ }
+
+ 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 (415, "'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;
}
}
}
+
+ public class Erase : Statement {
+ Expression EraseTarget;
+
+ private StatementExpression EraseExpr;
+
+ public Erase (Expression expr, Location l)
+ {
+ loc = l;
+ EraseTarget = expr;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ EraseTarget = EraseTarget.Resolve (ec);
+ if (!EraseTarget.Type.IsArray)
+ Report.Error (49, "'Erase' statement requires an array");
+
+ EraseExpr = (StatementExpression) new StatementExpression ((ExpressionStatement) new Assign (EraseTarget, NullLiteral.Null, loc), loc);
+ EraseExpr.Resolve(ec);
+
+ return true;
+ }
+
+ protected override bool DoEmit (EmitContext ec)
+ {
+ EraseExpr.Emit(ec);
+ return false;
+ }
+
+ }
+
+
}