// Miguel de Icaza (miguel@ximian.com)
// Martin Baulig (martin@gnome.org)
// Anirban Bhattacharjee (banirban@novell.com)
+// Manjula GHM (mmanjula@novell.com)
+// Satya Sudha K (ksathyasudha@novell.com)
//
// (C) 2001, 2002 Ximian, Inc.
//
if (e == null){
Report.Error (
- 31, loc, "Can not convert the expression to a boolean");
+ 30311, loc, "Can not convert the expression to a boolean");
}
ec.Mark (loc);
// Inform whether we are infinite or not
//
if (expr is BoolConstant){
- BoolConstant bc = (BoolConstant) expr;
-
ig.MarkLabel (ec.LoopBegin);
Statement.Emit (ec);
ig.Emit (OpCodes.Br, ec.LoopBegin);
}
public class For : Statement {
- Expression Test;
- readonly Statement InitStatement;
- readonly Statement Increment;
- readonly Statement Statement;
+ Expression LoopControlVar;
+ Expression Start;
+ Expression Limit;
+ Expression StepValue;
+ Statement statement, Increment;
bool may_return, infinite, empty;
+ private Statement InitStatement;
+ // required when loop control var is of type 'Object'
+ Expression Test, AddnTest;
+ LocalTemporary ltmp;
+ bool is_lcv_object;
- public For (Statement initStatement,
- Expression test,
- Statement increment,
+ public For (Expression loopVar,
+ Expression start,
+ Expression limit,
+ Expression stepVal,
Statement statement,
Location l)
{
- InitStatement = initStatement;
- Test = test;
- Increment = increment;
- Statement = statement;
+ LoopControlVar = loopVar;
+ Start = start;
+ Limit = limit;
+ StepValue = stepVal;
+ this.statement = statement;
loc = l;
+ ltmp = null;
+
+ InitStatement = new StatementExpression ((ExpressionStatement) (new Assign (LoopControlVar, Start, loc)), loc);
+ Increment = new StatementExpression (
+ (ExpressionStatement) (new CompoundAssign (Binary.Operator.Addition,
+ LoopControlVar, StepValue, loc)), loc);
+ AddnTest = null;
+ is_lcv_object = false;
}
-
public override bool Resolve (EmitContext ec)
{
bool ok = true;
+ LoopControlVar = LoopControlVar.Resolve (ec);
+ if (LoopControlVar == null)
+ return false;
+
+ Start = Start.Resolve (ec);
+ Limit = Limit.Resolve (ec);
+ StepValue = StepValue.Resolve (ec);
+ if (StepValue == null || Start == null || Limit == null)
+ return false;
+
+ double value = 0;
+ if (StepValue is Constant) {
+
+ value = GetValue (StepValue);
+ if (value > 0) // Positive Step value
+ Test = new Binary (Binary.Operator.LessThanOrEqual, LoopControlVar, Limit, loc);
+ else if (value < 0)
+ Test = new Binary (Binary.Operator.GreaterThanOrEqual, LoopControlVar, Limit, loc);
+ }
+
+ if (Start is Constant && Limit is Constant) {
+ if (value > 0)
+ AddnTest = ConstantFold.BinaryFold (ec, Binary.Operator.LessThanOrEqual,
+ (Constant) Start, (Constant) Limit, loc);
+ else if (value < 0)
+ AddnTest = ConstantFold.BinaryFold (ec, Binary.Operator.GreaterThanOrEqual,
+ (Constant) Start, (Constant) Limit, loc);
+ }
+
+
+ string method_to_call = null;
+ Binary left, right;
+ left = right = null;
+
+ switch (Type.GetTypeCode (LoopControlVar.Type)) {
+ case TypeCode.Boolean :
+ case TypeCode.Char :
+ case TypeCode.DateTime :
+ case TypeCode.String :
+ Report.Error (30337,loc,"'For' loop control variable cannot be of type '" + LoopControlVar.Type + "'");
+ return false;
+ case TypeCode.Byte :
+ if (Test == null)
+ Test = new Binary (Binary.Operator.LessThanOrEqual, LoopControlVar, Limit, loc);
+ break;
+ case TypeCode.Int16 :
+ if (Test == null) {
+ left = new Binary (Binary.Operator.ExclusiveOr,
+ new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (15), loc),
+ LoopControlVar,
+ loc);
+ right = new Binary (Binary.Operator.ExclusiveOr,
+ new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (15), loc),
+ Limit,
+ loc);
+ Test = new Binary (Binary.Operator.LessThanOrEqual, left, right, loc);
+ }
+ break;
+ case TypeCode.Int32 :
+ if (Test == null) {
+ left = new Binary (Binary.Operator.ExclusiveOr,
+ new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (31), loc),
+ LoopControlVar,
+ loc);
+ right = new Binary (Binary.Operator.ExclusiveOr,
+ new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (31), loc),
+ Limit,
+ loc);
+ Test = new Binary (Binary.Operator.LessThanOrEqual, left, right, loc);
+ }
+ break;
+ case TypeCode.Int64 :
+ if (Test == null) {
+ left = new Binary (Binary.Operator.ExclusiveOr,
+ new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (63), loc),
+ LoopControlVar,
+ loc);
+ right = new Binary (Binary.Operator.ExclusiveOr,
+ new Binary (Binary.Operator.RightShift, StepValue, new IntLiteral (63), loc),
+ Limit,
+ loc);
+ Test = new Binary (Binary.Operator.LessThanOrEqual, left, right, loc);
+ }
+ break;
+ case TypeCode.Decimal :
+ method_to_call = "Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckDec";
+ break;
+ case TypeCode.Single :
+ method_to_call = "Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckR4";
+ break;
+ case TypeCode.Double :
+ method_to_call = "Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckR8";
+ break;
+ case TypeCode.Object :
+ is_lcv_object = true;
+ ArrayList initArgs = new ArrayList ();
+ initArgs.Add (new Argument (LoopControlVar, Argument.AType.Expression));
+ initArgs.Add (new Argument (Start, Argument.AType.Expression));
+ initArgs.Add (new Argument (Limit, Argument.AType.Expression));
+ initArgs.Add (new Argument (StepValue, Argument.AType.Expression));
+ ltmp = new LocalTemporary (ec, TypeManager.object_type);
+ initArgs.Add (new Argument (ltmp, Argument.AType.Ref));
+ initArgs.Add (new Argument (LoopControlVar, Argument.AType.Ref));
+ Expression sname = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.FlowControl.ForLoopInitObj", loc);
+ AddnTest = new Invocation (sname, initArgs, loc);
+ //AddnTest = new Binary (Binary.Operator.Inequality, inv, new BoolLiteral (false), loc);
+ ArrayList args = new ArrayList ();
+ args.Add (new Argument (LoopControlVar, Argument.AType.Expression));
+ args.Add (new Argument (ltmp, Argument.AType.Expression));
+ args.Add (new Argument (LoopControlVar, Argument.AType.Ref));
+ sname = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.FlowControl.ForNextCheckObj", loc);
+ Test = new Invocation (sname, args, loc);
+ //Test = new Binary (Binary.Operator.Inequality, inv, new BoolLiteral (false), loc);
+ break;
+ }
+
+ if (method_to_call != null && !method_to_call.Equals ("")) {
+ ArrayList args = null;
+ args = new ArrayList ();
+ args.Add (new Argument (LoopControlVar, Argument.AType.Expression));
+ args.Add (new Argument (Limit, Argument.AType.Expression));
+ args.Add (new Argument (StepValue, Argument.AType.Expression));
+ Expression sname = Parser.DecomposeQI (method_to_call, loc);
+ Test = new Invocation (sname, args, loc);
+ //Test = new Binary (Binary.Operator.Inequality, invocation, new BoolLiteral (false), loc);
+ }
+
if (InitStatement != null){
if (!InitStatement.Resolve (ec))
ok = false;
}
+ if (AddnTest != null) {
+ AddnTest = ResolveBoolean (ec, AddnTest, loc);
+ if (AddnTest == null)
+ ok = false;
+ }
+
if (Test != null){
Test = ResolveBoolean (ec, Test, loc);
if (Test == null)
BoolConstant bc = (BoolConstant) Test;
if (bc.Value == false){
- Warning_DeadCodeFound (Statement.loc);
+ Warning_DeadCodeFound (statement.loc);
empty = true;
} else
infinite = true;
} else
infinite = true;
- if (Increment != null){
+ if (Increment != null) {
if (!Increment.Resolve (ec))
ok = false;
}
if (!infinite)
ec.CurrentBranching.CreateSibling ();
- if (!Statement.Resolve (ec))
+ if (!statement.Resolve (ec))
ok = false;
if (empty)
Label loop = ig.DefineLabel ();
Label test = ig.DefineLabel ();
- if (InitStatement != null)
+ if (!is_lcv_object && InitStatement != null)
if (! (InitStatement is EmptyStatement))
InitStatement.Emit (ec);
ec.InLoop = true;
ec.LoopBeginTryCatchLevel = ec.TryCatchLevel;
- ig.Emit (OpCodes.Br, test);
+ if (AddnTest != null) {
+ if (AddnTest is BoolConstant) {
+ if (!((BoolConstant) AddnTest).Value)
+ // We can actually branch to the end of the loop,
+ // but vbc does it this way
+ ig.Emit (OpCodes.Br, test);
+ } else if (is_lcv_object)
+ EmitBoolExpression (ec, AddnTest, ec.LoopEnd, false);
+ else
+ EmitBoolExpression (ec, AddnTest, test, false);
+ } else
+ ig.Emit (OpCodes.Br, test);
ig.MarkLabel (loop);
- Statement.Emit (ec);
+ statement.Emit (ec);
ig.MarkLabel (ec.LoopBegin);
- if (!(Increment is EmptyStatement))
+ if (!is_lcv_object && !(Increment is EmptyStatement))
Increment.Emit (ec);
ig.MarkLabel (test);
//
// Inform whether we are infinite or not
//
+
+ if (ltmp != null)
+ ltmp.Release (ec);
if (Test != null){
if (Test is BoolConstant){
BoolConstant bc = (BoolConstant) Test;
} else
return may_return == false;
}
+
+ private double GetValue (Expression e) {
+ if (e is DoubleConstant)
+ return ((DoubleConstant) e).Value;
+ if (e is FloatConstant)
+ return (double)((FloatConstant) e).Value;
+ if (e is IntConstant)
+ return (double)((IntConstant) e).Value;
+ if (e is LongConstant)
+ return (double)((LongConstant) e).Value;
+ if (e is DecimalConstant)
+ return (double)((DecimalConstant) e).Value;
+ return 0;
+ }
}
public class StatementExpression : Statement {
((ExpressionStatement) expr).EmitStatement (ec);
else {
expr.Emit (ec);
- ig.Emit (OpCodes.Pop);
+ if (! (expr is StatementSequence))
+ ig.Emit (OpCodes.Pop);
}
return false;
if (ec.CurrentBranching.InTryBlock ())
ec.CurrentBranching.AddFinallyVector (vector);
- else
- vector.CheckOutParameters (ec.CurrentBranching);
vector.Returns = FlowReturns.ALWAYS;
vector.Breaks = FlowReturns.ALWAYS;
label = block.LookupLabel (target);
if (label == null){
Report.Error (
- 159, loc,
+ 30132, loc,
"No such label `" + target + "' in this scope");
return false;
}
protected override bool DoEmit (EmitContext ec)
{
Label l = label.LabelTarget (ec);
- ec.ig.Emit (OpCodes.Br, l);
+ if (ec.InTry || ec.InCatch)
+ ec.ig.Emit (OpCodes.Leave, l);
+ else
+ ec.ig.Emit (OpCodes.Br, l);
return false;
}
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;
}
}
if (!ec.Switch.GotDefault){
- Report.Error (159, loc, "No default target on switch statement");
+ Report.Error (30132, loc, "No default target on switch statement");
return false;
}
ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
return false;
if (!(expr is Constant)){
- Report.Error (159, loc, "Target expression for goto case is not constant");
+ Report.Error (30132, loc, "Target expression for goto case is not constant");
return false;
}
if (sl == null){
Report.Error (
- 159, loc,
+ 30132, loc,
"No such label 'case " + val + "': for the goto case");
}
}
}
+ // Support 'End' Statement which terminates execution immediately
+
+ public class End : Statement {
+
+ public End (Location l)
+ {
+ loc = l;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ return true;
+ }
+
+ protected override bool DoEmit (EmitContext ec)
+ {
+ Expression e = null;
+ Expression tmp = Mono.MonoBASIC.Parser.DecomposeQI (
+ "Microsoft.VisualBasic.CompilerServices.ProjectData.EndApp",
+ Location.Null);
+
+ e = new Invocation (tmp, null, loc);
+ e.Resolve (ec);
+
+ if (e == null)
+ return false;
+ e.Emit (ec);
+
+ return true;
+ }
+ }
+
+
public class Break : Statement {
public Break (Location l)
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
+ if (type == ExitType.WHILE)
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");
ec.HasReturnLabel = true;
}
ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
- } else
- ec.ig.Emit (OpCodes.Ret);
+ } else {
+ if(type == ExitType.SUB) {
+ ec.ig.Emit (OpCodes.Ret);
+ } else {
+ ec.ig.Emit (OpCodes.Ldloc_0);
+ ec.ig.Emit (OpCodes.Ret);
+ }
+
+ }
return true;
}
Report.Debug (1, "MERGING FINALLY ORIGIN DONE", this);
}
-
- public void CheckOutParameters (FlowBranching branching)
- {
- if (parameters != null)
- branching.CheckOutParameters (parameters, branching.Location);
- }
-
// <summary>
// Performs an `or' operation on the locals and the parameters.
// </summary>
num_params = 0;
for (int i = 0; i < count; i++) {
- Parameter.Modifier mod = param_info.ParameterModifier (i);
+ //Parameter.Modifier mod = param_info.ParameterModifier (i);
- if ((mod & Parameter.Modifier.OUT) == 0)
- continue;
+ // if ((mod & Parameter.Modifier.OUT) == 0)
+ // continue;
param_map [i] = ++num_params;
CurrentUsageVector.MergeFinallyOrigins (finally_vectors);
}
- // <summary>
- // Check whether all `out' parameters have been assigned.
- // </summary>
- public void CheckOutParameters (MyBitVector parameters, Location loc)
- {
- if (InTryBlock ())
- return;
-
- for (int i = 0; i < param_map.Length; i++) {
- int index = param_map [i];
-
- if (index == 0)
- continue;
-
- if (parameters [index - 1])
- continue;
-
- // If it's a struct, we must ensure that all its fields have
- // been assigned. If the struct has any non-public fields, this
- // can only be done by assigning the whole struct.
-
- MyStructInfo struct_info = struct_params [index - 1];
- if ((struct_info == null) || struct_info.HasNonPublicFields) {
- Report.Error (
- 177, loc, "The out parameter `" +
- param_info.ParameterName (i) + "' must be " +
- "assigned before control leave the current method.");
- param_map [i] = 0;
- continue;
- }
-
-
- for (int j = 0; j < struct_info.Count; j++) {
- if (!parameters [index + j]) {
- Report.Error (
- 177, loc, "The out parameter `" +
- param_info.ParameterName (i) + "' must be " +
- "assigned before control leave the current method.");
- param_map [i] = 0;
- break;
- }
- }
- }
- }
// <summary>
// Merge a child branching.
Report.Debug (1, "MERGING TOP BLOCK DONE", Location, vector);
if (vector.Breaks != FlowReturns.EXCEPTION) {
- if (!vector.AlwaysBreaks)
- CheckOutParameters (CurrentUsageVector.Parameters, Location);
return vector.AlwaysBreaks ? FlowReturns.ALWAYS : vector.Returns;
} else
return FlowReturns.EXCEPTION;
//
// Maps variable names to ILGenerator.LocalBuilders
//
- CaseInsensitiveHashtable local_builders;
+ //CaseInsensitiveHashtable local_builders;
+
+ // to hold names of variables required for late binding
+ public const string lateBindingArgs = "1_LBArgs";
+ public const string lateBindingArgNames = "1_LBArgsNames";
+ public const string lateBindingCopyBack = "1_LBCopyBack";
+
+ bool isLateBindingRequired = false;
bool used = false;
{
if (parent != null)
parent.AddChild (this);
+ else {
+ // Top block
+ // Add variables that may be required for late binding
+ variables = new CaseInsensitiveHashtable ();
+ ArrayList rank_specifier = new ArrayList ();
+ ArrayList element = new ArrayList ();
+ element.Add (new EmptyExpression ());
+ rank_specifier.Add (element);
+ Expression e = Mono.MonoBASIC.Parser.DecomposeQI ("System.Object[]", start);
+ AddVariable (e, Block.lateBindingArgs, null, start);
+ e = Mono.MonoBASIC.Parser.DecomposeQI ("System.String[]", start);
+ AddVariable (e, Block.lateBindingArgNames, null, start);
+ e = Mono.MonoBASIC.Parser.DecomposeQI ("System.Boolean[]", start);
+ AddVariable (e, Block.lateBindingCopyBack, null, start);
+ }
this.Parent = parent;
this.Implicit = implicit_block;
statements = new ArrayList ();
}
+ public bool IsLateBindingRequired {
+ get {
+ return isLateBindingRequired;
+ }
+ set {
+ isLateBindingRequired = value;
+ }
+ }
+
public int ID {
get {
return this_id;
VariableInfo vi = GetVariableInfo (name);
if (vi != null) {
if (vi.Block != ID)
- Report.Error (136, l, "A local variable named `" + name + "' " +
+ Report.Error (30616, l, "A local variable named `" + name + "' " +
"cannot be declared in this scope since it would " +
"give a different meaning to `" + name + "', which " +
"is already used in a `parent or current' scope to " +
"denote something else");
else
- Report.Error (128, l, "A local variable `" + name + "' is already " +
+ Report.Error (30290, l, "A local variable `" + name + "' is already " +
"defined in this scope");
return null;
}
int idx = 0;
Parameter p = pars.GetParameterByName (name, out idx);
if (p != null) {
- Report.Error (136, l, "A local variable named `" + name + "' " +
+ Report.Error (30616, l, "A local variable named `" + name + "' " +
"cannot be declared in this scope since it would " +
"give a different meaning to `" + name + "', which " +
"is already used in a `parent or current' scope to " +
/// </remarks>
public void EmitMeta (EmitContext ec, Block toplevel)
{
- DeclSpace ds = ec.DeclSpace;
+ //DeclSpace ds = ec.DeclSpace;
ILGenerator ig = ec.ig;
if (!variables_initialized)
// Process this block variables
//
if (variables != null){
- local_builders = new CaseInsensitiveHashtable ();
+ //local_builders = new CaseInsensitiveHashtable ();
foreach (DictionaryEntry de in variables){
string name = (string) de.Key;
+ /*
+ if (!isLateBindingRequired) {
+ if (name.Equals (Block.lateBindingArgs) ||
+ name.Equals (Block.lateBindingArgNames) ||
+ name.Equals (Block.lateBindingCopyBack))
+ continue;
+ }
+ */
VariableInfo vi = (VariableInfo) de.Value;
if (vi.VariableType == null)
bool ok = true;
ec.CurrentBlock = this;
- ec.StartFlowBranching (this);
-
- Report.Debug (1, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
if (!variables_initialized)
UpdateVariableInfo (ec);
+ ec.StartFlowBranching (this);
+
+ Report.Debug (1, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);
+
ArrayList new_statements = new ArrayList ();
bool unreachable = false, warning_shown = false;
warning_shown = true;
Warning_DeadCodeFound (s.loc);
}
-
continue;
}
}
}
+ public class StatementSequence : Expression {
+ Block stmtBlock;
+ ArrayList args, originalArgs;
+ Expression expr;
+ bool isRetValRequired;
+ bool isLeftHandSide;
+ bool isIndexerAccess;
+ string memberName;
+ Expression type_expr;
+
+ public StatementSequence (Block parent, Location loc, Expression expr)
+ : this (parent, loc, expr, null)
+ { }
+
+ public StatementSequence (Block parent, Location loc, Expression expr, string name,
+ Expression type_expr, ArrayList a, bool isRetValRequired,
+ bool isLeftHandSide)
+ : this (parent, loc, expr, a)
+ {
+ this.memberName = name;
+ this.type_expr = type_expr;
+ this.isRetValRequired = isRetValRequired;
+ this.isLeftHandSide = isLeftHandSide;
+ }
+
+ public StatementSequence (Block parent, Location loc, Expression expr, ArrayList a,
+ bool isRetValRequired, bool isLeftHandSide)
+ : this (parent, loc, expr, a)
+ {
+ this.isRetValRequired = isRetValRequired;
+ this.isLeftHandSide = isLeftHandSide;
+ if (expr is MemberAccess) {
+ this.expr = ((MemberAccess)expr).Expr;
+ this.memberName = ((MemberAccess)expr).Identifier;
+ this.isIndexerAccess = false;
+ } else if (expr is IndexerAccess) {
+ this.expr = ((IndexerAccess) expr).Instance;
+ this.memberName = "";
+ this.isIndexerAccess = true;
+ }
+ }
+
+ public StatementSequence (Block parent, Location loc, Expression expr, ArrayList a)
+ {
+ stmtBlock = new Block (parent);
+ args = a;
+ originalArgs = new ArrayList ();
+ if (args != null) {
+ for (int index = 0; index < a.Count; index ++) {
+ Argument argument = (Argument) args [index];
+ originalArgs.Add (new Argument (argument.Expr, argument.ArgType));
+ }
+ }
+
+ this.expr = expr;
+ stmtBlock.IsLateBindingRequired = true;
+ this.loc = loc;
+ this.isRetValRequired = this.isLeftHandSide = false;
+ this.memberName = "";
+ this.type_expr = null;
+ }
+
+ public ArrayList Arguments {
+ get {
+ return args;
+ }
+ set {
+ args = value;
+ }
+ }
+
+ public bool IsLeftHandSide {
+ set {
+ isLeftHandSide = value;
+ }
+ }
+
+ public Block StmtBlock {
+ get {
+ return stmtBlock;
+ }
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (!stmtBlock.Resolve (ec))
+ return null;
+ eclass = ExprClass.Value;
+ type = TypeManager.object_type;
+ return this;
+ }
+
+ public bool ResolveArguments (EmitContext ec) {
+
+ bool argNamesFound = false;
+ if (Arguments != null)
+ {
+ for (int index = 0; index < Arguments.Count; index ++)
+ {
+ Argument a = (Argument) Arguments [index];
+ if (a.ParamName == null || a.ParamName == "") {
+ if (argNamesFound) {
+ Report.Error (30241, loc, "Named Argument expected");
+ return false;
+ }
+ } else
+ argNamesFound = true;
+ if (a.ArgType == Argument.AType.NoArg)
+ a = new Argument (Parser.DecomposeQI ("System.Reflection.Missing.Value", loc), Argument.AType.Expression);
+ if (!a.Resolve (ec, loc))
+ return false;
+ Arguments [index] = a;
+ }
+ }
+ return true;
+ }
+
+ public void GenerateLateBindingStatements ()
+ {
+ int argCount = 0;
+ ArrayList arrayInitializers = new ArrayList ();
+ ArrayList ArgumentNames = null;
+ if (args != null) {
+ //arrayInitializers = new ArrayList ();
+ argCount = args.Count;
+ for (int index = 0; index < args.Count; index ++) {
+ Argument a = (Argument) args [index];
+ Expression argument = a.Expr;
+ arrayInitializers.Add (argument);
+ if (a.ParamName != null && a.ParamName != "") {
+ if (ArgumentNames == null)
+ ArgumentNames = new ArrayList ();
+ ArgumentNames.Add (new StringLiteral (a.ParamName));
+ }
+ }
+ }
+
+ // __LateBindingArgs = new Object () {arg1, arg2 ...}
+ ArrayCreation new_expr = new ArrayCreation (Parser.DecomposeQI ("System.Object", loc), "[]", arrayInitializers, loc);
+ Assign assign_stmt = null;
+
+ LocalVariableReference v1 = new LocalVariableReference (stmtBlock, Block.lateBindingArgs, loc);
+ assign_stmt = new Assign (v1, new_expr, loc);
+ stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+ // __LateBindingArgNames = new string () { argument names}
+ LocalVariableReference v2 = null;
+ if (ArgumentNames != null && ArgumentNames.Count > 0) {
+ new_expr = new ArrayCreation (Parser.DecomposeQI ("System.String", loc), "[]", ArgumentNames, loc);
+ v2 = new LocalVariableReference (stmtBlock, Block.lateBindingArgNames, loc);
+ assign_stmt = new Assign (v2, new_expr, loc);
+ stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+ }
+
+ //string memName = "";
+ //bool isIndexerAccess = true;
+
+ ArrayList invocationArgs = new ArrayList ();
+ if (isIndexerAccess || memberName == "") {
+ invocationArgs.Add (new Argument (expr, Argument.AType.Expression));
+ invocationArgs.Add (new Argument (v1, Argument.AType.Expression));
+ invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+ Expression tmp = null;
+ if (!isLeftHandSide)
+ tmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexGet", loc);
+ else
+ tmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateIndexSet", loc);
+ Invocation invStmt = new Invocation (tmp, invocationArgs, Location.Null);
+ invStmt.IsLateBinding = true;
+ stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) invStmt, loc));
+ return;
+ }
+
+ if (expr != null)
+ invocationArgs.Add (new Argument (expr, Argument.AType.Expression));
+ else
+ invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+ if (type_expr != null)
+ invocationArgs.Add (new Argument (type_expr, Argument.AType.Expression));
+ else
+ invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+ invocationArgs.Add (new Argument (new StringLiteral (memberName), Argument.AType.Expression));
+ invocationArgs.Add (new Argument (v1, Argument.AType.Expression));
+ if (ArgumentNames != null && ArgumentNames.Count > 0)
+ invocationArgs.Add (new Argument (v2, Argument.AType.Expression));
+ else
+ invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+
+ // __LateBindingCopyBack = new Boolean (no_of_args) {}
+ bool isCopyBackRequired = false;
+ if (!isLeftHandSide) {
+ for (int i = 0; i < argCount; i++) {
+ Argument origArg = (Argument) Arguments [i];
+ Expression origExpr = origArg.Expr;
+ if (!(origExpr is Constant || origArg.ArgType == Argument.AType.NoArg))
+ isCopyBackRequired = true;
+ }
+ }
+
+ LocalVariableReference v3 = new LocalVariableReference (stmtBlock, Block.lateBindingCopyBack, loc);
+ if (isCopyBackRequired) {
+ ArrayList rank_specifier = new ArrayList ();
+ rank_specifier.Add (new IntLiteral (argCount));
+ arrayInitializers = new ArrayList ();
+ for (int i = 0; i < argCount; i++) {
+ Argument a = (Argument) Arguments [i];
+ Expression origExpr = a.Expr;
+ if (origExpr is Constant || a.ArgType == Argument.AType.NoArg || origExpr is New)
+ arrayInitializers.Add (new BoolLiteral (false));
+ else
+ arrayInitializers.Add (new BoolLiteral (true));
+ }
+
+ new_expr = new ArrayCreation (Parser.DecomposeQI ("System.Boolean", loc), "[]", arrayInitializers, loc);
+ assign_stmt = new Assign (v3, new_expr, loc);
+ stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+ invocationArgs.Add (new Argument (v3, Argument.AType.Expression));
+ } else if (! isLeftHandSide) {
+ invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+ }
+
+ Expression etmp = null;
+ if (isLeftHandSide) {
+ // LateSet
+ etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateSet", loc);
+ } else if (isRetValRequired) {
+ // Late Get
+ etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateGet", loc);
+ } else {
+ etmp = Parser.DecomposeQI ("Microsoft.VisualBasic.CompilerServices.LateBinding.LateCall", loc);
+ }
+
+ Invocation inv_stmt = new Invocation (etmp, invocationArgs, Location.Null);
+ inv_stmt.IsLateBinding = true;
+ stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) inv_stmt, loc));
+
+ if (! isCopyBackRequired)
+ return;
+
+ for (int i = argCount - 1; i >= 0; i --) {
+ Argument arg = (Argument) originalArgs [i];
+ Expression origExpr = (Expression) arg.Expr;
+ if (arg.ArgType == Argument.AType.NoArg)
+ continue;
+ if (origExpr is Constant)
+ continue;
+ if (origExpr is New)
+ continue;
+
+ Expression intExpr = new IntLiteral (i);
+ ArrayList argsLocal = new ArrayList ();
+ argsLocal.Add (new Argument (intExpr, Argument.AType.Expression));
+ Expression indexExpr = new Invocation (new SimpleName (Block.lateBindingCopyBack, loc), argsLocal, loc);
+ Expression value = new Invocation (new SimpleName (Block.lateBindingArgs, loc), argsLocal, loc);
+ assign_stmt = new Assign (origExpr, value, loc);
+ Expression boolExpr = new Binary (Binary.Operator.Inequality, indexExpr, new BoolLiteral (false), loc);
+ Statement ifStmt = new If (boolExpr, new StatementExpression ((ExpressionStatement) assign_stmt, loc), loc);
+ stmtBlock.AddStatement (ifStmt);
+ }
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ stmtBlock.Emit (ec);
+ }
+ }
+
public class SwitchLabel {
- Expression label;
- object converted;
+ public enum LabelType : byte {
+ Operator, Range, Label, Else
+ }
+
+ Expression label, start, end;
+ LabelType label_type;
+ Expression label_condition, start_condition, end_condition;
+ Binary.Operator oper;
public Location loc;
public Label ILLabel;
public Label ILLabelCode;
//
// if expr == null, then it is the default case.
//
- public SwitchLabel (Expression expr, Location l)
+ public SwitchLabel (Expression start, Expression end, LabelType ltype, Binary.Operator oper, Location l) {
+ this.start = start;
+ this.end = end;
+ this.label_type = ltype;
+ this.oper = oper;
+ this.loc = l;
+ label_condition = start_condition = end_condition = null;
+ }
+
+ public SwitchLabel (Expression expr, LabelType ltype, Binary.Operator oper, Location l)
{
label = expr;
+ start = end = null;
+ label_condition = start_condition = end_condition = null;
loc = l;
+ this.label_type = ltype;
+ this.oper = oper;
}
public Expression Label {
}
}
- public object Converted {
+ public LabelType Type {
+ get {
+ return label_type;
+ }
+ }
+
+ public Expression ConditionStart {
+ get {
+ return start_condition;
+ }
+ }
+
+ public Expression ConditionEnd {
get {
- return converted;
+ return end_condition;
+ }
+ }
+
+ public Expression ConditionLabel {
+ get {
+ return label_condition;
}
}
// Resolves the expression, reduces it to a literal if possible
// and then converts it to the requested type.
//
- public bool ResolveAndReduce (EmitContext ec, Type required_type)
+ public bool ResolveAndReduce (EmitContext ec, Expression expr)
{
ILLabel = ec.ig.DefineLabel ();
ILLabelCode = ec.ig.DefineLabel ();
- if (label == null)
+ Expression e = null;
+ switch (label_type) {
+ case LabelType.Label :
+ if (label == null)
+ return false;
+ e = label.Resolve (ec);
+ if (e != null)
+ e = Expression.ConvertImplicit (ec, e, expr.Type, loc);
+ if (e == null)
+ return false;
+ label_condition = new Binary (Binary.Operator.Equality, expr, e, loc);
+ if ((label_condition = label_condition.DoResolve (ec)) == null)
+ return false;
+ return true;
+ case LabelType.Operator :
+ e = label.Resolve (ec);
+ label_condition = new Binary (oper, expr, e, loc);
+ if ((label_condition = label_condition.DoResolve (ec)) == null)
+ return false;
+ return true;
+ case LabelType.Range :
+ if (start == null || end == null)
+ return false;
+ e = start.Resolve (ec);
+ if (e != null)
+ e = Expression.ConvertImplicit (ec, e, expr.Type, loc);
+ if (e == null)
+ return false;
+ start_condition = new Binary (Binary.Operator.GreaterThanOrEqual, expr, e, loc);
+ start_condition = start_condition.Resolve (ec);
+ e = end.Resolve (ec);
+ if (e != null)
+ e = Expression.ConvertImplicit (ec, e, expr.Type, loc);
+ if (e == null)
+ return false;
+ end_condition = new Binary (Binary.Operator.LessThanOrEqual, expr, e, loc);
+ end_condition = end_condition.Resolve (ec);
+ if (start_condition == null || end_condition == null)
+ return false;
return true;
-
- Expression e = label.Resolve (ec);
-
- if (e == null)
- return false;
-
- if (!(e is Constant)){
- Console.WriteLine ("Value is: " + label);
- Report.Error (150, loc, "A constant value is expected");
- return false;
- }
- if (e is StringConstant || e is NullLiteral){
- if (required_type == TypeManager.string_type){
- converted = e;
- ILLabel = ec.ig.DefineLabel ();
- return true;
- }
+ case LabelType.Else :
+ break;
}
-
- converted = Expression.ConvertIntLiteral ((Constant) e, required_type, loc);
- if (converted == null)
- return false;
-
return true;
}
}
// The types allowed to be implicitly cast from
// on the governing type
//
- static Type [] allowed_types;
+ //static Type [] allowed_types;
public Switch (Expression e, ArrayList sects, Location l)
{
//
Expression SwitchGoverningType (EmitContext ec, Type t)
{
- if (t == TypeManager.int32_type ||
- t == TypeManager.uint32_type ||
- t == TypeManager.char_type ||
- t == TypeManager.byte_type ||
- t == TypeManager.sbyte_type ||
- t == TypeManager.ushort_type ||
+ if (t == TypeManager.byte_type ||
t == TypeManager.short_type ||
- t == TypeManager.uint64_type ||
+ t == TypeManager.int32_type ||
t == TypeManager.int64_type ||
+ t == TypeManager.decimal_type ||
+ t == TypeManager.float_type ||
+ t == TypeManager.double_type ||
+ t == TypeManager.date_type ||
+ t == TypeManager.char_type ||
+ t == TypeManager.object_type ||
t == TypeManager.string_type ||
t == TypeManager.bool_type ||
t.IsSubclassOf (TypeManager.enum_type))
return Expr;
-
+/*
if (allowed_types == null){
allowed_types = new Type [] {
TypeManager.sbyte_type,
converted = e;
}
return converted;
+*/
+ return null;
}
void error152 (string n)
//
bool CheckSwitch (EmitContext ec)
{
- Type compare_type;
+ //Type compare_type;
bool error = false;
Elements = new CaseInsensitiveHashtable ();
got_default = false;
+/*
if (TypeManager.IsEnumType (SwitchType)){
compare_type = TypeManager.EnumToUnderlying (SwitchType);
} else
compare_type = SwitchType;
+*/
- foreach (SwitchSection ss in Sections){
- foreach (SwitchLabel sl in ss.Labels){
- if (!sl.ResolveAndReduce (ec, SwitchType)){
+ for (int secIndex = 0; secIndex < Sections.Count; secIndex ++) {
+ SwitchSection ss = (SwitchSection) Sections [secIndex];
+ for (int labelIndex = 0; labelIndex < ss.Labels.Count; labelIndex ++) {
+ SwitchLabel sl = (SwitchLabel) ss.Labels [labelIndex];
+ if (!sl.ResolveAndReduce (ec, Expr)){
error = true;
continue;
}
- if (sl.Label == null){
+ if (sl.Type == SwitchLabel.LabelType.Else){
if (got_default){
error152 ("default");
error = true;
got_default = true;
continue;
}
-
- object key = sl.Converted;
-
- if (key is Constant)
- key = ((Constant) key).GetValue ();
-
- if (key == null)
- key = NullLiteral.Null;
-
- string lname = null;
- if (compare_type == TypeManager.uint64_type){
- ulong v = (ulong) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.int64_type){
- long v = (long) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.uint32_type){
- uint v = (uint) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.char_type){
- char v = (char) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.byte_type){
- byte v = (byte) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.sbyte_type){
- sbyte v = (sbyte) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.short_type){
- short v = (short) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.ushort_type){
- ushort v = (ushort) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.string_type){
- if (key is NullLiteral){
- if (Elements.Contains (NullLiteral.Null))
- lname = "null";
- else
- Elements.Add (NullLiteral.Null, null);
- } else {
- string s = (string) key;
-
- if (Elements.Contains (s))
- lname = s;
- else
- Elements.Add (s, sl);
- }
- } else if (compare_type == TypeManager.int32_type) {
- int v = (int) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- } else if (compare_type == TypeManager.bool_type) {
- bool v = (bool) key;
-
- if (Elements.Contains (v))
- lname = v.ToString ();
- else
- Elements.Add (v, sl);
- }
- else
- {
- throw new Exception ("Unknown switch type!" +
- SwitchType + " " + compare_type);
- }
-
- if (lname != null){
- error152 ("case + " + lname);
- error = true;
- }
}
}
if (error)
}
}
+/*
/// <summary>
/// This method emits code for a lookup-based switch statement (non-string)
/// Basically it groups the cases into blocks that are at least half full,
return all_return;
}
+*/
public override bool Resolve (EmitContext ec)
{
new_expr = SwitchGoverningType (ec, Expr.Type);
if (new_expr == null){
- Report.Error (151, loc, "An integer type or string was expected for switch");
+ Report.Error (30338, loc, "'Select' expression cannot be of type '" + Expr.Type +"'");
return false;
}
protected override bool DoEmit (EmitContext ec)
{
- // Store variable for comparission purposes
- LocalBuilder value = ec.ig.DeclareLocal (SwitchType);
- new_expr.Emit (ec);
- ec.ig.Emit (OpCodes.Stloc, value);
-
ILGenerator ig = ec.ig;
-
- default_target = ig.DefineLabel ();
-
//
// Setup the codegen context
//
ec.LoopEnd = ig.DefineLabel ();
ec.Switch = this;
- // Emit Code.
- bool all_return;
- if (SwitchType == TypeManager.string_type)
- all_return = SimpleSwitchEmit (ec, value);
- else
- all_return = TableSwitchEmit (ec, value);
+ for (int secIndex = 0; secIndex < Sections.Count; secIndex ++) {
+ SwitchSection section = (SwitchSection) Sections [secIndex];
+ Label sLabel = ig.DefineLabel ();
+ Label lLabel = ig.DefineLabel ();
+ ArrayList Labels = section.Labels;
+ for (int labelIndex = 0; labelIndex < Labels.Count; labelIndex ++) {
+ SwitchLabel sl = (SwitchLabel) Labels [labelIndex];
+ switch (sl.Type) {
+ case SwitchLabel.LabelType.Range :
+ if (labelIndex + 1 == Labels.Count) {
+ EmitBoolExpression (ec, sl.ConditionStart, sLabel, false);
+ EmitBoolExpression (ec, sl.ConditionEnd, sLabel, false);
+ ig.Emit (OpCodes.Br, lLabel);
+ } else {
+ Label newLabel = ig.DefineLabel ();
+ EmitBoolExpression (ec, sl.ConditionStart, newLabel, false);
+ EmitBoolExpression (ec, sl.ConditionEnd, newLabel, false);
+ ig.Emit (OpCodes.Br, lLabel);
+ ig.MarkLabel (newLabel);
+ }
+ break;
+ case SwitchLabel.LabelType.Else :
+ // Nothing to be done here
+ break;
+ case SwitchLabel.LabelType.Operator :
+ EmitBoolExpression (ec, sl.ConditionLabel, lLabel, true);
+ if (labelIndex + 1 == Labels.Count)
+ ig.Emit (OpCodes.Br, sLabel);
+ break;
+ case SwitchLabel.LabelType.Label :
+ EmitBoolExpression (ec, sl.ConditionLabel, lLabel, true);
+ if (labelIndex + 1 == Labels.Count)
+ ig.Emit (OpCodes.Br, sLabel);
+ break;
+ }
+
+ }
+ ig.MarkLabel (lLabel);
+ section.Block.Emit (ec);
+ ig.MarkLabel (sLabel);
+ }
// Restore context state.
ig.MarkLabel (ec.LoopEnd);
//
ec.LoopEnd = old_end;
ec.Switch = old_switch;
-
- return all_return;
+ return true;
}
}
bool val;
if (type.IsValueType){
- Report.Error (185, loc, "lock statement requires the expression to be " +
+ Report.Error (30582, loc, "lock statement requires the expression to be " +
" a reference type (type is: `" +
TypeManager.MonoBASIC_Name (type) + "'");
return false;
ig.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
// try
- Label end = ig.BeginExceptionBlock ();
+ ig.BeginExceptionBlock ();
bool old_in_try = ec.InTry;
ec.InTry = true;
Label finish = ig.DefineLabel ();
FlowBranching.UsageVector f_vector = ec.CurrentBranching.CurrentUsageVector;
Report.Debug (1, "END OF FINALLY", ec.CurrentBranching, returns, vector, f_vector);
-
- if ((returns == FlowReturns.SOMETIMES) || (returns == FlowReturns.ALWAYS)) {
- ec.CurrentBranching.CheckOutParameters (f_vector.Parameters, loc);
- }
-
ec.CurrentBranching.CurrentUsageVector.Or (vector);
Report.Debug (1, "END OF TRY", ec.CurrentBranching);
protected override bool DoEmit (EmitContext ec)
{
ILGenerator ig = ec.ig;
- Label end;
Label finish = ig.DefineLabel ();;
bool returns;
ec.TryCatchLevel++;
- end = ig.BeginExceptionBlock ();
+ ig.BeginExceptionBlock ();
bool old_in_try = ec.InTry;
ec.InTry = true;
returns = Block.Emit (ec);
bool old_in_catch = ec.InCatch;
ec.InCatch = true;
- DeclSpace ds = ec.DeclSpace;
+ //DeclSpace ds = ec.DeclSpace;
foreach (Catch c in Specific){
VariableInfo vi;
}
/// <summary>
- /// Implementation of the foreach C# statement
+ /// Implementation of the for each statement
/// </summary>
public class Foreach : Statement {
Expression type;
if (!statement.Resolve (ec))
return false;
- FlowReturns returns = ec.EndFlowBranching ();
-
+ //FlowReturns returns = ec.EndFlowBranching ();
+ ec.EndFlowBranching ();
return true;
}
// Protect the code in a try/finalize block, so that
// if the beast implement IDisposable, we get rid of it
//
- Label l;
bool old_in_try = ec.InTry;
if (hm.is_disposable) {
- l = ig.BeginExceptionBlock ();
+ ig.BeginExceptionBlock ();
ec.InTry = true;
}
NewIndexes = args;
if (RedimTarget.Type.GetArrayRank() != args.Count)
- Report.Error (415, "'ReDim' cannot change the number of dimensions of an array.");
+ 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);