}
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 {
if (ec.CurrentBranching.InTryBlock ())
ec.CurrentBranching.AddFinallyVector (vector);
- else
- vector.CheckOutParameters (ec.CurrentBranching);
vector.Returns = FlowReturns.ALWAYS;
vector.Breaks = FlowReturns.ALWAYS;
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;
}
}
ec.ig.Emit (OpCodes.Leave, ec.ReturnLabel);
} else {
- ec.ig.Emit (OpCodes.Ldloc_0);
- ec.ig.Emit (OpCodes.Ret);
+ if(type == ExitType.SUB) {
+ ec.ig.Emit (OpCodes.Ret);
+ } else {
+ ec.ig.Emit (OpCodes.Ldloc_0);
+ ec.ig.Emit (OpCodes.Ret);
+ }
}
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";
return isLateBindingRequired;
}
set {
- isLateBindingRequired = true;
+ isLateBindingRequired = value;
}
}
// 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;
public class StatementSequence : Expression {
Block stmtBlock;
- ArrayList args;
+ 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 {
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;
- // Arguments for call Microsoft.VisualBasic.CompilerServices.LateBinding.LateCall
- ArrayList invocationArgs = new ArrayList ();
- invocationArgs.Add (new Argument (((MemberAccess)expr).Expr, Argument.AType.Expression));
- invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
- invocationArgs.Add (new Argument (new StringLiteral (((MemberAccess)expr).Identifier), Argument.AType.Expression));
- // __LateBindingArgs = new Object () {arg1, arg2 ...}
ArrayList arrayInitializers = new ArrayList ();
- ArrayList originalArgs = new ArrayList ();
+ ArrayList ArgumentNames = null;
if (args != null) {
//arrayInitializers = new ArrayList ();
argCount = args.Count;
- foreach (Argument a in args) {
- arrayInitializers.Add (a.Expr);
- originalArgs.Add (a.Expr);
+ 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));
- invocationArgs.Add (new Argument (v1, Argument.AType.Expression));
+ // __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));
+ }
- // __LateBindingArgNames = nothing
- //LocalVariableReference v2 = new LocalVariableReference (stmtBlock, Block.lateBindingArgNames, loc);
- //assign_stmt = new Assign (v2, NullLiteral.Null, loc);
- //stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) assign_stmt, loc));
+ //string memName = "";
+ //bool isIndexerAccess = true;
- invocationArgs.Add (new Argument (NullLiteral.Null, Argument.AType.Expression));
+ 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;
- for (int i = 0; i < argCount; i++) {
- if (!(((Argument)args[i]).Expr is Constant))
- isCopyBackRequired = true;
+ 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);
rank_specifier.Add (new IntLiteral (argCount));
arrayInitializers = new ArrayList ();
for (int i = 0; i < argCount; i++) {
- if (((Argument)args[i]).Expr is Constant)
+ 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));
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 {
+ } 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);
inv_stmt.IsLateBinding = true;
stmtBlock.AddStatement (new StatementExpression ((ExpressionStatement) inv_stmt, loc));
- for (int i = 0; i< argCount; i ++) {
- Expression thisArg = (Expression) originalArgs [i];
- if (thisArg is Constant)
+ 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 varRef = (Expression) (originalArgs [i]);
Expression value = new Invocation (new SimpleName (Block.lateBindingArgs, loc), argsLocal, loc);
- assign_stmt = new Assign (varRef, value, 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);
- //ec.ig.Emit (OpCodes.Ldloc_0);
}
}
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 converted;
+ return start_condition;
+ }
+ }
+
+ public Expression ConditionEnd {
+ get {
+ 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;
}
}
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);
}
/// <summary>
- /// Implementation of the foreach C# statement
+ /// Implementation of the for each statement
/// </summary>
public class Foreach : Statement {
Expression type;
return false;
//FlowReturns returns = ec.EndFlowBranching ();
-
+ ec.EndFlowBranching ();
return true;
}
//
bool old_in_try = ec.InTry;
- if (hm.is_disposable)
+ if (hm.is_disposable) {
+ ig.BeginExceptionBlock ();
ec.InTry = true;
+ }
Label end_try = ig.DefineLabel ();