// 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;
}
}
set {
initialize_vector ();
- for (int i = 0; i < Math.Min (vector.Count, value.Count); i++)
+ for (int i = 0; i < System.Math.Min (vector.Count, value.Count); i++)
vector [i] = value [i];
}
}
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;
//
// Labels. (label, block) pairs.
//
- Hashtable labels;
+ CaseInsensitiveHashtable labels;
//
// Keeps track of (name, type) pairs
//
- Hashtable variables;
+ CaseInsensitiveHashtable variables;
//
// Keeps track of constants
- Hashtable constants;
+ CaseInsensitiveHashtable constants;
//
// Maps variable names to ILGenerator.LocalBuilders
//
- Hashtable local_builders;
+ CaseInsensitiveHashtable local_builders;
bool used = false;
public bool AddLabel (string name, LabeledStatement target)
{
if (labels == null)
- labels = new Hashtable ();
+ labels = new CaseInsensitiveHashtable ();
if (labels.Contains (name))
return false;
public void AddChildVariableName (string name)
{
if (child_variable_names == null)
- child_variable_names = new Hashtable ();
+ child_variable_names = new CaseInsensitiveHashtable ();
if (!child_variable_names.Contains (name))
child_variable_names.Add (name, true);
this_variable = new VariableInfo (tc, ID, l);
if (variables == null)
- variables = new Hashtable ();
+ variables = new CaseInsensitiveHashtable ();
variables.Add ("this", this_variable);
return this_variable;
public VariableInfo AddVariable (Expression type, string name, Parameters pars, Location l)
{
if (variables == null)
- variables = new Hashtable ();
+ variables = new CaseInsensitiveHashtable ();
VariableInfo vi = GetVariableInfo (name);
if (vi != null) {
return false;
if (constants == null)
- constants = new Hashtable ();
+ constants = new CaseInsensitiveHashtable ();
constants.Add (name, value);
return true;
// Process this block variables
//
if (variables != null){
- local_builders = new Hashtable ();
+ local_builders = new CaseInsensitiveHashtable ();
foreach (DictionaryEntry de in variables){
string name = (string) de.Key;
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;
{
Type compare_type;
bool error = false;
- Elements = new Hashtable ();
+ Elements = new CaseInsensitiveHashtable ();
got_default = false;
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;
}
- }
+ }
+
+ /// <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;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ 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;
+ }
+
+ 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);
+
+ // 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;
+ }
+ }
+
+ 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;
+ }
+
+ protected override bool DoEmit (EmitContext ec)
+ {
+ ReDimExpr.Emit(ec);
+ return false;
+ }
+
+ }
+
+ 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;
+ }
+
+ }
+
+
}