//
protected virtual void CloneTo (CloneContext clonectx, Statement target)
{
- throw new Exception (String.Format ("Statement.CloneTo not implemented for {0}", this.GetType ()));
+ throw new InternalErrorException ("{0} does not implement Statement.CloneTo", this.GetType ());
}
-
+
public Statement Clone (CloneContext clonectx)
{
Statement s = (Statement) this.MemberwiseClone ();
return result;
}
+ ///
+ /// Remaps block to cloned copy if one exists.
+ ///
+ public Block RemapBlockCopy (Block from)
+ {
+ Block mapped_to = (Block)block_map[from];
+ if (mapped_to == null)
+ return from;
+
+ return mapped_to;
+ }
+
public void AddVariableMap (LocalInfo from, LocalInfo to)
{
if (variable_map == null)
protected override void DoEmit (EmitContext ec)
{
}
+
+ protected override void CloneTo (CloneContext clonectx, Statement target)
+ {
+ // nothing needed.
+ }
}
public class If : Statement {
bool is_true_ret;
- public If (Expression expr, Statement trueStatement, Location l)
+ public If (Expression expr, Statement true_statement, Location l)
{
this.expr = expr;
- TrueStatement = trueStatement;
+ TrueStatement = true_statement;
loc = l;
}
public If (Expression expr,
- Statement trueStatement,
- Statement falseStatement,
+ Statement true_statement,
+ Statement false_statement,
Location l)
{
this.expr = expr;
- TrueStatement = trueStatement;
- FalseStatement = falseStatement;
+ TrueStatement = true_statement;
+ FalseStatement = false_statement;
loc = l;
}
public Statement EmbeddedStatement;
bool infinite;
- public Do (Statement statement, Expression boolExpr, Location l)
+ public Do (Statement statement, Expression bool_expr, Location l)
{
- expr = boolExpr;
+ expr = bool_expr;
EmbeddedStatement = statement;
loc = l;
}
public Statement Statement;
bool infinite, empty;
- public While (Expression boolExpr, Statement statement, Location l)
+ public While (Expression bool_expr, Statement statement, Location l)
{
- this.expr = boolExpr;
+ this.expr = bool_expr;
Statement = statement;
loc = l;
}
public Statement Statement;
bool infinite, empty;
- public For (Statement initStatement,
+ public For (Statement init_statement,
Expression test,
Statement increment,
Statement statement,
Location l)
{
- InitStatement = initStatement;
+ InitStatement = init_statement;
Test = test;
Increment = increment;
Statement = statement;
/// Implements the return statement
/// </summary>
public class Return : Statement {
- public Expression Expr;
+ Expression Expr;
+ bool unwind_protect;
public Return (Expression expr, Location l)
{
Expr = expr;
loc = l;
}
-
- bool unwind_protect;
-
- public override bool Resolve (EmitContext ec)
+
+ bool DoResolve (EmitContext ec)
{
+ if (Expr == null) {
+ if (ec.ReturnType == TypeManager.void_type)
+ return true;
+
+ Error (126, "An object of a type convertible to `{0}' is required " +
+ "for the return statement",
+ TypeManager.CSharpName (ec.ReturnType));
+ return false;
+ }
+
AnonymousContainer am = ec.CurrentAnonymousMethod;
if ((am != null) && am.IsIterator && ec.InIterator) {
Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " +
- "statement to return a value, or yield break to end the iteration");
- return false;
+ "statement to return a value, or yield break to end the iteration");
}
- if (ec.ReturnType == null){
- if (Expr != null){
- if (am != null){
- Report.Error (1662, loc,
- "Cannot convert anonymous method block to delegate type `{0}' because some of the return types in the block are not implicitly convertible to the delegate return type",
- am.GetSignatureForError ());
- }
- Error (127, "A return keyword must not be followed by any expression when method returns void");
- return false;
- }
- } else {
- if (Expr == null){
- Error (126, "An object of a type convertible to `{0}' is required " +
- "for the return statement",
- TypeManager.CSharpName (ec.ReturnType));
- return false;
- }
+ if (am == null && ec.ReturnType == TypeManager.void_type) {
+ MemberCore mc = ec.ResolveContext as MemberCore;
+ Report.Error (127, loc, "`{0}': A return keyword must not be followed by any expression when method returns void",
+ mc.GetSignatureForError ());
+ }
- Expr = Expr.Resolve (ec);
- if (Expr == null)
- return false;
+ Expr = Expr.Resolve (ec);
+ if (Expr == null)
+ return false;
- if (Expr.Type != ec.ReturnType) {
- if (ec.InferReturnType) {
- ec.ReturnType = Expr.Type;
- } else {
- Expr = Convert.ImplicitConversionRequired (
- ec, Expr, ec.ReturnType, loc);
- if (Expr == null)
- return false;
+ if (Expr.Type != ec.ReturnType) {
+ if (ec.InferReturnType) {
+ ec.ReturnType = Expr.Type;
+ } else {
+ Expr = Convert.ImplicitConversionRequired (
+ ec, Expr, ec.ReturnType, loc);
+
+ if (Expr == null) {
+ if (am != null) {
+ Report.Error (1662, loc,
+ "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type",
+ am.ContainerType, am.GetSignatureForError ());
+ }
+ return false;
}
}
}
- int errors = Report.Errors;
+ return true;
+ }
+
+ public override bool Resolve (EmitContext ec)
+ {
+ if (!DoResolve (ec))
+ return false;
+
unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
if (unwind_protect)
ec.NeedReturnLabel ();
ec.CurrentBranching.CurrentUsageVector.Goto ();
- return errors == Report.Errors;
+ return true;
}
protected override void DoEmit (EmitContext ec)
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Return target = (Return) t;
-
- target.Expr = Expr.Clone (clonectx);
+ // It's null for simple return;
+ if (Expr != null)
+ target.Expr = Expr.Clone (clonectx);
}
}
{
ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
}
+
+ protected override void CloneTo (CloneContext clonectx, Statement t)
+ {
+ // nothing needed
+ }
}
public class Continue : Statement {
{
ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
}
+
+ protected override void CloneTo (CloneContext clonectx, Statement t)
+ {
+ // nothing needed.
+ }
}
public abstract class Variable
public bool Resolve (EmitContext ec)
{
if (VariableType == null) {
- TypeExpr texpr = Type.ResolveAsTypeTerminal (ec, false);
+ TypeExpr texpr = Type.ResolveAsContextualType (ec, false);
if (texpr == null)
return false;
public LocalInfo Clone (CloneContext clonectx)
{
- // Only this kind is created by the parser.
- return new LocalInfo (Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
+ //
+ // Variables in anonymous block are not resolved yet
+ //
+ if (VariableType == null)
+ return new LocalInfo (Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
+
+ //
+ // Variables in method block are resolved
+ //
+ LocalInfo li = new LocalInfo (null, Name, clonectx.LookupBlock (Block), Location);
+ li.VariableType = VariableType;
+ return li;
}
}
// The statements in this block
//
protected ArrayList statements;
- protected int current_statement;
int num_statements;
//
protected static int id;
int this_id;
+
+ int assignable_slots;
+ protected ScopeInfo scope_info;
+ bool unreachable_shown;
+ bool unreachable;
public Block (Block parent)
: this (parent, (Flags) 0, Location.Null, Location.Null)
if (vi != null) {
Report.SymbolRelatedToPreviousError (vi.Location, name);
if (Explicit == vi.Block.Explicit)
- Report.Error (128, l,
- "A local variable named `{0}' is already defined in this scope", name);
+ Error_AlreadyDeclared (l, name, null);
else
Error_AlreadyDeclared (l, name, "parent");
return null;
Report.SymbolRelatedToPreviousError (pi.Location, name);
Error_AlreadyDeclared (loc, name,
pi.Block == Toplevel ? "method argument" : "parent or current");
+ return null;
}
+
+ if (Toplevel.GenericMethod != null) {
+ foreach (TypeParameter tp in Toplevel.GenericMethod.CurrentTypeParameters) {
+ if (tp.Name == name) {
+ Report.SymbolRelatedToPreviousError (tp);
+ Error_AlreadyDeclaredTypeParameter (loc, name);
+ return null;
+ }
+ }
+ }
IKnownVariable kvi = Explicit.GetKnownVariable (name);
if (kvi != null) {
}
vi = new LocalInfo (type, name, this, l);
- Variables.Add (name, vi);
- Explicit.AddKnownVariable (name, vi);
+ AddVariable (vi);
if ((flags & Flags.VariablesInitialized) != 0)
throw new InternalErrorException ("block has already been resolved");
return vi;
}
+
+ protected virtual void AddVariable (LocalInfo li)
+ {
+ Variables.Add (li.Name, li);
+ Explicit.AddKnownVariable (li.Name, li);
+ }
- protected static void Error_AlreadyDeclared (Location loc, string var, string reason)
+ protected virtual void Error_AlreadyDeclared (Location loc, string var, string reason)
{
+ if (reason == null) {
+ Error_AlreadyDeclared (loc, var);
+ return;
+ }
+
Report.Error (136, loc, "A local variable named `{0}' cannot be declared " +
"in this scope because it would give a different meaning " +
"to `{0}', which is already used in a `{1}' scope " +
"to denote something else", var, reason);
}
+ protected virtual void Error_AlreadyDeclared (Location loc, string name)
+ {
+ Report.Error (128, loc,
+ "A local variable named `{0}' is already defined in this scope", name);
+ }
+
+ protected virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name)
+ {
+ GenericMethod.Error_ParameterNameCollision (loc, name, "local variable");
+ }
+
public bool AddConstant (Expression type, string name, Expression value, Location l)
{
if (AddVariable (type, name, l) == null)
statements.Add (s);
flags |= Flags.BlockUsed;
}
-
- public void InsertStatementAfterCurrent (Statement statement)
- {
- statements.Insert (current_statement + 1, statement);
- flags |= Flags.BlockUsed;
- }
public bool Used {
get { return (flags & Flags.BlockUsed) != 0; }
flags |= Flags.IsDestructor;
}
- int assignable_slots;
public int AssignableSlots {
get {
if ((flags & Flags.VariablesInitialized) == 0)
}
}
- protected ScopeInfo scope_info;
-
public ScopeInfo ScopeInfo {
get { return scope_info; }
}
{
string name;
- if ((variables != null) && (RootContext.WarningLevel >= 3)) {
+ if ((variables != null) && (Report.WarningLevel >= 3)) {
foreach (DictionaryEntry de in variables){
LocalInfo vi = (LocalInfo) de.Value;
}
}
- bool unreachable_shown;
- bool unreachable;
-
private void CheckPossibleMistakenEmptyStatement (Statement s)
{
Statement body;
// from the beginning of the function. The outer Resolve() that detected the unreachability is
// responsible for handling the situation.
//
- for (current_statement = 0; current_statement < statements.Count; current_statement++) {
- Statement s = (Statement) statements [current_statement];
+ int statement_count = statements.Count;
+ for (int ix = 0; ix < statement_count; ix++){
+ Statement s = (Statement) statements [ix];
// Check possible empty statement (CS0642)
- if (RootContext.WarningLevel >= 3 &&
- current_statement + 1 < statements.Count &&
- statements [current_statement + 1] is Block)
+ if (Report.WarningLevel >= 3 &&
+ ix + 1 < statement_count &&
+ statements [ix + 1] is Block)
CheckPossibleMistakenEmptyStatement (s);
//
//
if (!s.Resolve (ec)) {
+ if (ec.IsInProbingMode)
+ return false;
+
ok = false;
- statements [current_statement] = EmptyStatement.Value;
+ statements [ix] = EmptyStatement.Value;
continue;
}
if (unreachable && !(s is LabeledStatement) && !(s is Block))
- statements [current_statement] = EmptyStatement.Value;
+ statements [ix] = EmptyStatement.Value;
- num_statements = current_statement + 1;
+ num_statements = ix + 1;
unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
if (unreachable && s is LabeledStatement)
}
Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,
- ec.CurrentBranching, statements.Count, num_statements);
+ ec.CurrentBranching, statement_count, num_statements);
if (!ok)
return false;
if (this == Toplevel && !Toplevel.IsThisAssigned (ec) && !vector.IsUnreachable)
ok = false;
- if ((labels != null) && (RootContext.WarningLevel >= 2)) {
+ if ((labels != null) && (Report.WarningLevel >= 2)) {
foreach (LabeledStatement label in labels.Values)
if (!label.HasBeenReferenced)
Report.Warning (164, 2, label.loc,
flags |= Flags.HasRet;
if (ok && (errors == Report.Errors)) {
- if (RootContext.WarningLevel >= 3)
- UsageWarning (vector);
+ UsageWarning (vector);
}
return ok;
clonectx.AddBlockMap (this, target);
- target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
+ //target.Toplevel = (ToplevelBlock) clonectx.LookupBlock (Toplevel);
target.Explicit = (ExplicitBlock) clonectx.LookupBlock (Explicit);
if (Parent != null)
- target.Parent = clonectx.LookupBlock (Parent);
-
- target.statements = new ArrayList ();
- if (target.children != null){
- target.children = new ArrayList ();
- foreach (Block b in children){
- Block newblock = (Block) b.Clone (clonectx);
-
- target.children.Add (newblock);
- }
-
- }
-
- foreach (Statement s in statements)
- target.statements.Add (s.Clone (clonectx));
+ target.Parent = clonectx.RemapBlockCopy (Parent);
if (variables != null){
target.variables = new Hashtable ();
}
}
+ target.statements = new ArrayList (statements.Count);
+ foreach (Statement s in statements)
+ target.statements.Add (s.Clone (clonectx));
+
+ if (target.children != null){
+ target.children = new ArrayList (children.Count);
+ foreach (Block b in children){
+ target.children.Add (clonectx.LookupBlock (b));
+ }
+ }
+
//
// TODO: labels, switch_block, constants (?), anonymous_children
//
FlowBranchingToplevel top_level_branching;
AnonymousContainer anonymous_container;
RootScopeInfo root_scope;
+ Parameters parameters;
+ ToplevelParameterInfo[] parameter_info;
public bool HasVarargs {
get { return (flags & Flags.HasVarargs) != 0; }
//
// The parameters for the block.
//
- Parameters parameters;
public Parameters Parameters {
get { return parameters; }
}
return true;
}
- ToplevelParameterInfo [] parameter_info;
+ public virtual Expression GetTransparentIdentifier (string name)
+ {
+ return null;
+ }
+
void ProcessParameters ()
{
int n = parameters.Count;
for (int i = 0; i < n; ++i) {
parameter_info [i] = new ToplevelParameterInfo (this, i);
- string name = parameters [i].Name;
+ Parameter p = parameters [i];
+ if (p == null)
+ continue;
+ string name = p.Name;
LocalInfo vi = GetLocalInfo (name);
if (vi != null) {
Report.SymbolRelatedToPreviousError (vi.Location, name);
return null;
}
- //
- // Whether the parameter named `name' is local to this block,
- // or false, if the parameter belongs to an encompassing block.
- //
- public bool IsLocalParameter (string name)
- {
- return Parameters.GetParameterByName (name) != null;
- }
-
- //
- // Whether the `name' is a parameter reference
- //
- public bool IsParameterReference (string name)
- {
- for (ToplevelBlock t = this; t != null; t = t.Container) {
- if (t.IsLocalParameter (name))
- return true;
- }
- return false;
- }
-
LocalInfo this_variable = null;
// <summary>
Block block = new ExplicitBlock (this, StartLocation, EndLocation);
foreach (Statement stmt in statements)
block.AddStatement (stmt);
- statements = new ArrayList ();
+ statements.Clear ();
statements.Add (new MoveNextStatement (iterator, block));
}
return true;
}
- public void Erorr_AlreadyOccurs (Type switchType, SwitchLabel collisionWith)
+ public void Erorr_AlreadyOccurs (Type switch_type, SwitchLabel collision_with)
{
string label;
if (converted == null)
label = "default";
else if (converted == NullStringCase)
label = "null";
- else if (TypeManager.IsEnumType (switchType))
- label = TypeManager.CSharpEnumValue (switchType, converted);
+ else if (TypeManager.IsEnumType (switch_type))
+ label = TypeManager.CSharpEnumValue (switch_type, converted);
else
label = converted.ToString ();
- Report.SymbolRelatedToPreviousError (collisionWith.loc, null);
+ Report.SymbolRelatedToPreviousError (collision_with.loc, null);
Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
}
// structure used to hold blocks of keys while calculating table switch
class KeyBlock : IComparable
{
- public KeyBlock (long _nFirst)
+ public KeyBlock (long _first)
{
- nFirst = nLast = _nFirst;
+ first = last = _first;
}
- public long nFirst;
- public long nLast;
- public ArrayList rgKeys = null;
+ public long first;
+ public long last;
+ public ArrayList element_keys = null;
// how many items are in the bucket
public int Size = 1;
public int Length
{
- get { return (int) (nLast - nFirst + 1); }
+ get { return (int) (last - first + 1); }
}
- public static long TotalLength (KeyBlock kbFirst, KeyBlock kbLast)
+ public static long TotalLength (KeyBlock kb_first, KeyBlock kb_last)
{
- return kbLast.nLast - kbFirst.nFirst + 1;
+ return kb_last.last - kb_first.first + 1;
}
public int CompareTo (object obj)
{
int nLength = Length;
int nLengthOther = kb.Length;
if (nLengthOther == nLength)
- return (int) (kb.nFirst - nFirst);
+ return (int) (kb.first - first);
return nLength - nLengthOther;
}
}
/// <returns></returns>
void TableSwitchEmit (EmitContext ec, LocalBuilder val)
{
- int cElements = Elements.Count;
- object [] rgKeys = new object [cElements];
- Elements.Keys.CopyTo (rgKeys, 0);
- Array.Sort (rgKeys);
+ int element_count = Elements.Count;
+ object [] element_keys = new object [element_count];
+ Elements.Keys.CopyTo (element_keys, 0);
+ Array.Sort (element_keys);
// initialize the block list with one element per key
- ArrayList rgKeyBlocks = new ArrayList ();
- foreach (object key in rgKeys)
- rgKeyBlocks.Add (new KeyBlock (System.Convert.ToInt64 (key)));
+ ArrayList key_blocks = new ArrayList ();
+ foreach (object key in element_keys)
+ key_blocks.Add (new KeyBlock (System.Convert.ToInt64 (key)));
- KeyBlock kbCurr;
+ KeyBlock current_kb;
// iteratively merge the blocks while they are at least half full
// there's probably a really cool way to do this with a tree...
- while (rgKeyBlocks.Count > 1)
+ while (key_blocks.Count > 1)
{
- ArrayList rgKeyBlocksNew = new ArrayList ();
- kbCurr = (KeyBlock) rgKeyBlocks [0];
- for (int ikb = 1; ikb < rgKeyBlocks.Count; ikb++)
+ ArrayList key_blocks_new = new ArrayList ();
+ current_kb = (KeyBlock) key_blocks [0];
+ for (int ikb = 1; ikb < key_blocks.Count; ikb++)
{
- KeyBlock kb = (KeyBlock) rgKeyBlocks [ikb];
- if ((kbCurr.Size + kb.Size) * 2 >= KeyBlock.TotalLength (kbCurr, kb))
+ KeyBlock kb = (KeyBlock) key_blocks [ikb];
+ if ((current_kb.Size + kb.Size) * 2 >= KeyBlock.TotalLength (current_kb, kb))
{
// merge blocks
- kbCurr.nLast = kb.nLast;
- kbCurr.Size += kb.Size;
+ current_kb.last = kb.last;
+ current_kb.Size += kb.Size;
}
else
{
// start a new block
- rgKeyBlocksNew.Add (kbCurr);
- kbCurr = kb;
+ key_blocks_new.Add (current_kb);
+ current_kb = kb;
}
}
- rgKeyBlocksNew.Add (kbCurr);
- if (rgKeyBlocks.Count == rgKeyBlocksNew.Count)
+ key_blocks_new.Add (current_kb);
+ if (key_blocks.Count == key_blocks_new.Count)
break;
- rgKeyBlocks = rgKeyBlocksNew;
+ key_blocks = key_blocks_new;
}
// initialize the key lists
- foreach (KeyBlock kb in rgKeyBlocks)
- kb.rgKeys = new ArrayList ();
+ foreach (KeyBlock kb in key_blocks)
+ kb.element_keys = new ArrayList ();
// fill the key lists
int iBlockCurr = 0;
- if (rgKeyBlocks.Count > 0) {
- kbCurr = (KeyBlock) rgKeyBlocks [0];
- foreach (object key in rgKeys)
+ if (key_blocks.Count > 0) {
+ current_kb = (KeyBlock) key_blocks [0];
+ foreach (object key in element_keys)
{
- bool fNextBlock = (key is UInt64) ? (ulong) key > (ulong) kbCurr.nLast :
- System.Convert.ToInt64 (key) > kbCurr.nLast;
- if (fNextBlock)
- kbCurr = (KeyBlock) rgKeyBlocks [++iBlockCurr];
- kbCurr.rgKeys.Add (key);
+ bool next_block = (key is UInt64) ? (ulong) key > (ulong) current_kb.last :
+ System.Convert.ToInt64 (key) > current_kb.last;
+ if (next_block)
+ current_kb = (KeyBlock) key_blocks [++iBlockCurr];
+ current_kb.element_keys.Add (key);
}
}
// sort the blocks so we can tackle the largest ones first
- rgKeyBlocks.Sort ();
+ key_blocks.Sort ();
// okay now we can start...
ILGenerator ig = ec.ig;
- Label lblEnd = ig.DefineLabel (); // at the end ;-)
- Label lblDefault = ig.DefineLabel ();
+ Label lbl_end = ig.DefineLabel (); // at the end ;-)
+ Label lbl_default = ig.DefineLabel ();
- Type typeKeys = null;
- if (rgKeys.Length > 0)
- typeKeys = rgKeys [0].GetType (); // used for conversions
+ Type type_keys = null;
+ if (element_keys.Length > 0)
+ type_keys = element_keys [0].GetType (); // used for conversions
Type compare_type;
else
compare_type = SwitchType;
- for (int iBlock = rgKeyBlocks.Count - 1; iBlock >= 0; --iBlock)
+ for (int iBlock = key_blocks.Count - 1; iBlock >= 0; --iBlock)
{
- KeyBlock kb = ((KeyBlock) rgKeyBlocks [iBlock]);
- lblDefault = (iBlock == 0) ? DefaultTarget : ig.DefineLabel ();
+ KeyBlock kb = ((KeyBlock) key_blocks [iBlock]);
+ lbl_default = (iBlock == 0) ? DefaultTarget : ig.DefineLabel ();
if (kb.Length <= 2)
{
- foreach (object key in kb.rgKeys)
+ foreach (object key in kb.element_keys)
{
ig.Emit (OpCodes.Ldloc, val);
EmitObjectInteger (ig, key);
// check block range (could be > 2^31)
ig.Emit (OpCodes.Ldloc, val);
- EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys));
- ig.Emit (OpCodes.Blt, lblDefault);
+ EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys));
+ ig.Emit (OpCodes.Blt, lbl_default);
ig.Emit (OpCodes.Ldloc, val);
- EmitObjectInteger (ig, System.Convert.ChangeType (kb.nLast, typeKeys));
- ig.Emit (OpCodes.Bgt, lblDefault);
+ EmitObjectInteger (ig, System.Convert.ChangeType (kb.last, type_keys));
+ ig.Emit (OpCodes.Bgt, lbl_default);
// normalize range
ig.Emit (OpCodes.Ldloc, val);
- if (kb.nFirst != 0)
+ if (kb.first != 0)
{
- EmitObjectInteger (ig, System.Convert.ChangeType (kb.nFirst, typeKeys));
+ EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys));
ig.Emit (OpCodes.Sub);
}
ig.Emit (OpCodes.Conv_I4); // assumes < 2^31 labels!
{
// normalize range
ig.Emit (OpCodes.Ldloc, val);
- int nFirst = (int) kb.nFirst;
- if (nFirst > 0)
+ int first = (int) kb.first;
+ if (first > 0)
{
- IntConstant.EmitInt (ig, nFirst);
+ IntConstant.EmitInt (ig, first);
ig.Emit (OpCodes.Sub);
}
- else if (nFirst < 0)
+ else if (first < 0)
{
- IntConstant.EmitInt (ig, -nFirst);
+ IntConstant.EmitInt (ig, -first);
ig.Emit (OpCodes.Add);
}
}
// first, build the list of labels for the switch
int iKey = 0;
int cJumps = kb.Length;
- Label [] rgLabels = new Label [cJumps];
+ Label [] switch_labels = new Label [cJumps];
for (int iJump = 0; iJump < cJumps; iJump++)
{
- object key = kb.rgKeys [iKey];
- if (System.Convert.ToInt64 (key) == kb.nFirst + iJump)
+ object key = kb.element_keys [iKey];
+ if (System.Convert.ToInt64 (key) == kb.first + iJump)
{
SwitchLabel sl = (SwitchLabel) Elements [key];
- rgLabels [iJump] = sl.GetILLabel (ec);
+ switch_labels [iJump] = sl.GetILLabel (ec);
iKey++;
}
else
- rgLabels [iJump] = lblDefault;
+ switch_labels [iJump] = lbl_default;
}
// emit the switch opcode
- ig.Emit (OpCodes.Switch, rgLabels);
+ ig.Emit (OpCodes.Switch, switch_labels);
}
// mark the default for this block
if (iBlock != 0)
- ig.MarkLabel (lblDefault);
+ ig.MarkLabel (lbl_default);
}
// TODO: find the default case and emit it here,
// make sure to mark other labels in the default section
// the last default just goes to the end
- ig.Emit (OpCodes.Br, lblDefault);
+ ig.Emit (OpCodes.Br, lbl_default);
// now emit the code for the sections
- bool fFoundDefault = false;
- bool fFoundNull = false;
+ bool found_default = false;
+ bool found_null = false;
foreach (SwitchSection ss in Sections)
{
foreach (SwitchLabel sl in ss.Labels)
if (sl.Converted == SwitchLabel.NullStringCase)
- fFoundNull = true;
+ found_null = true;
}
foreach (SwitchSection ss in Sections)
if (sl.Converted == SwitchLabel.NullStringCase)
ig.MarkLabel (null_target);
else if (sl.Label == null) {
- ig.MarkLabel (lblDefault);
- fFoundDefault = true;
- if (!fFoundNull)
+ ig.MarkLabel (lbl_default);
+ found_default = true;
+ if (!found_null)
ig.MarkLabel (null_target);
}
}
ss.Block.Emit (ec);
}
- if (!fFoundDefault) {
- ig.MarkLabel (lblDefault);
- if (HaveUnwrap && !fFoundNull) {
+ if (!found_default) {
+ ig.MarkLabel (lbl_default);
+ if (HaveUnwrap && !found_null) {
ig.MarkLabel (null_target);
}
}
- ig.MarkLabel (lblEnd);
+ ig.MarkLabel (lbl_end);
}
//
// This simple emit switch works, but does not take advantage of the
SwitchType = new_expr.Type;
if (RootContext.Version == LanguageVersion.ISO_1 && SwitchType == TypeManager.bool_type) {
- Report.FeatureIsNotISO1 (loc, "switch expression of boolean type");
+ Report.FeatureIsNotAvailable (loc, "switch expression of boolean type");
return false;
}
ec, array_ptr, vi.VariableType, loc);
if (converted == null)
return false;
+
+ //
+ // fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0])
+ //
+ converted = new Conditional (new Binary (Binary.Operator.LogicalOr,
+ new Binary (Binary.Operator.Equality, e, new NullConstant (loc)),
+ new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc))),
+ NullPointer.Null,
+ converted);
+
+ converted = converted.Resolve (ec);
data [i] = new ExpressionEmitter (converted, vi);
i++;
}
// Case 4: fixed buffer
- FieldExpr fe = e as FieldExpr;
- if (fe != null) {
- IFixedBuffer ff = AttributeTester.GetFixedBuffer (fe.FieldInfo);
- if (ff != null) {
- Expression fixed_buffer_ptr = new FixedBufferPtr (fe, ff.ElementType, loc);
-
- Expression converted = Convert.ImplicitConversionRequired (
- ec, fixed_buffer_ptr, vi.VariableType, loc);
- if (converted == null)
- return false;
-
- data [i] = new ExpressionEmitter (converted, vi);
- i++;
-
- continue;
- }
+ FixedBufferPtr fixed_buffer_ptr = e as FixedBufferPtr;
+ if (fixed_buffer_ptr != null) {
+ data [i++] = new ExpressionEmitter (fixed_buffer_ptr, vi);
+ continue;
}
//
Fixed target = (Fixed) t;
target.type = type.Clone (clonectx);
- target.declarators = new ArrayList ();
- foreach (LocalInfo var in declarators)
- target.declarators.Add (clonectx.LookupVariable (var));
+ target.declarators = new ArrayList (declarators.Count);
+ foreach (Pair p in declarators) {
+ LocalInfo vi = (LocalInfo) p.First;
+ Expression e = (Expression) p.Second;
+
+ target.declarators.Add (
+ new Pair (clonectx.LookupVariable (vi), e.Clone (clonectx)));
+ }
+
target.statement = statement.Clone (clonectx);
}
}
{
Catch target = (Catch) t;
- target.type_expr = type_expr.Clone (clonectx);
+ if (type_expr != null)
+ target.type_expr = type_expr.Clone (clonectx);
+ if (VarBlock != null)
+ target.VarBlock = clonectx.LookupBlock (VarBlock);
target.Block = clonectx.LookupBlock (Block);
- target.VarBlock = clonectx.LookupBlock (VarBlock);
}
}
Report.Debug (1, "START OF CATCH BLOCKS", vector);
- Type[] prevCatches = new Type [Specific.Count];
+ Type[] prev_catches = new Type [Specific.Count];
int last_index = 0;
foreach (Catch c in Specific){
ec.CurrentBranching.CreateSibling (
if (!c.Resolve (ec))
return false;
- Type resolvedType = c.CatchType;
+ Type resolved_type = c.CatchType;
for (int ii = 0; ii < last_index; ++ii) {
- if (resolvedType == prevCatches [ii] || resolvedType.IsSubclassOf (prevCatches [ii])) {
- Report.Error (160, c.loc, "A previous catch clause already catches all exceptions of this or a super type `{0}'", prevCatches [ii].FullName);
+ if (resolved_type == prev_catches [ii] || resolved_type.IsSubclassOf (prev_catches [ii])) {
+ Report.Error (160, c.loc, "A previous catch clause already catches all exceptions of this or a super type `{0}'", prev_catches [ii].FullName);
return false;
}
}
- prevCatches [last_index++] = resolvedType;
+ prev_catches [last_index++] = resolved_type;
need_exc_block = true;
}
Type expr_type;
Expression [] resolved_vars;
Expression [] converted_vars;
- ExpressionStatement [] assign;
+ Expression [] assign;
TemporaryVariable local_copy;
public Using (object expression_or_block, Statement stmt, Location l)
//
bool ResolveLocalVariableDecls (EmitContext ec)
{
- int i = 0;
-
- TypeExpr texpr = null;
-
- if (expr is VarExpr) {
- Expression e = ((Expression)((DictionaryEntry)var_list[0]).Value).Resolve (ec);
- if (e == null || e.Type == null)
- return false;
- texpr = new TypeExpression (e.Type, loc);
- }
- else
- texpr = expr.ResolveAsTypeTerminal (ec, false);
-
- if (texpr == null)
- return false;
-
- expr_type = texpr.Type;
-
- //
- // The type must be an IDisposable or an implicit conversion
- // must exist.
- //
- converted_vars = new Expression [var_list.Count];
- resolved_vars = new Expression [var_list.Count];
- assign = new ExpressionStatement [var_list.Count];
+ resolved_vars = new Expression[var_list.Count];
+ assign = new Expression [var_list.Count];
+ converted_vars = new Expression[var_list.Count];
- bool need_conv = !TypeManager.ImplementsInterface (
- expr_type, TypeManager.idisposable_type);
-
- foreach (DictionaryEntry e in var_list){
+ for (int i = 0; i < assign.Length; ++i) {
+ DictionaryEntry e = (DictionaryEntry) var_list [i];
Expression var = (Expression) e.Key;
-
- if (expr is VarExpr) {
- LocalVariableReference l = var as LocalVariableReference;
- ((LocalInfo)l.Block.Variables[l.Name]).VariableType = expr_type;
- ((VarExpr)expr).Handled = true;
- }
+ Expression new_expr = (Expression) e.Value;
- var = var.ResolveLValue (ec, new EmptyExpression (), loc);
- if (var == null)
+ Expression a = new Assign (var, new_expr, loc);
+ a = a.Resolve (ec);
+ if (a == null)
return false;
resolved_vars [i] = var;
+ assign [i] = a;
- if (!need_conv) {
- i++;
+ if (TypeManager.ImplementsInterface (a.Type, TypeManager.idisposable_type)) {
+ converted_vars [i] = var;
continue;
}
- converted_vars [i] = Convert.ImplicitConversion (
- ec, var, TypeManager.idisposable_type, loc);
-
- if (converted_vars [i] == null) {
- Error_IsNotConvertibleToIDisposable ();
+ a = Convert.ImplicitConversionStandard (ec, a, TypeManager.idisposable_type, var.Location);
+ if (a == null) {
+ Error_IsNotConvertibleToIDisposable (var);
return false;
}
- i++;
- }
-
- i = 0;
- foreach (DictionaryEntry e in var_list){
- Expression var = resolved_vars [i];
- Expression new_expr = (Expression) e.Value;
- Expression a;
-
- a = new Assign (var, new_expr, loc);
- a = a.Resolve (ec);
- if (a == null)
- return false;
-
- if (!need_conv)
- converted_vars [i] = var;
- assign [i] = (ExpressionStatement) a;
- i++;
+ converted_vars [i] = a;
}
return true;
}
- void Error_IsNotConvertibleToIDisposable ()
+ static void Error_IsNotConvertibleToIDisposable (Expression expr)
{
- Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
- TypeManager.CSharpName (expr_type));
+ Report.SymbolRelatedToPreviousError (expr.Type);
+ Report.Error (1674, expr.Location, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
+ expr.GetSignatureForError ());
}
bool ResolveExpression (EmitContext ec)
{
if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
if (Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
- Error_IsNotConvertibleToIDisposable ();
+ Error_IsNotConvertibleToIDisposable (expr);
return false;
}
}
int i = 0;
for (i = 0; i < assign.Length; i++) {
- assign [i].EmitStatement (ec);
+ ExpressionStatement es = assign [i] as ExpressionStatement;
+
+ if (es != null)
+ es.EmitStatement (ec);
+ else {
+ assign [i].Emit (ec);
+ ig.Emit (OpCodes.Pop);
+ }
if (emit_finally)
ig.BeginExceptionBlock ();
if (expr == null)
return false;
- if (type is VarExpr) {
- Type element_type = null;
- if (TypeManager.HasElementType (expr.Type))
- element_type = TypeManager.GetElementType (expr.Type);
- else {
- MethodGroupExpr mg = Expression.MemberLookup (
- ec.ContainerType, expr.Type, "GetEnumerator", MemberTypes.Method,
- Expression.AllBindingFlags, loc) as MethodGroupExpr;
-
- if (mg == null)
- return false;
-
- MethodInfo get_enumerator = null;
- foreach (MethodInfo mi in mg.Methods) {
- if (TypeManager.GetParameterData (mi).Count != 0)
- continue;
- if ((mi.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
- continue;
- if (CollectionForeach.IsOverride (mi))
- continue;
- get_enumerator = mi;
- }
-
- if (get_enumerator == null)
- return false;
-
- PropertyInfo pi = TypeManager.GetProperty (get_enumerator.ReturnType, "Current");
-
- if (pi == null)
- return false;
-
- element_type = pi.PropertyType;
- }
-
- type = new TypeLookupExpression (element_type.AssemblyQualifiedName);
-
- LocalVariableReference lv = variable as LocalVariableReference;
- ((LocalInfo)lv.Block.Variables[lv.Name]).VariableType = element_type;
- }
-
- Constant c = expr as Constant;
- if (c != null && c.GetValue () == null) {
+ if (expr.Type == TypeManager.null_type) {
Report.Error (186, loc, "Use of null is not valid in this context");
return false;
}
- TypeExpr texpr = type.ResolveAsTypeTerminal (ec, false);
- if (texpr == null)
- return false;
-
- Type var_type = texpr.Type;
-
if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
expr.ExprClassName);
}
if (expr.Type.IsArray) {
- array = new ArrayForeach (var_type, variable, expr, statement, loc);
+ array = new ArrayForeach (type, variable, expr, statement, loc);
return array.Resolve (ec);
- } else {
- collection = new CollectionForeach (
- var_type, variable, expr, statement, loc);
- return collection.Resolve (ec);
}
+
+ collection = new CollectionForeach (type, variable, expr, statement, loc);
+ return collection.Resolve (ec);
}
protected override void DoEmit (EmitContext ec)
Expression variable, expr, conv;
Statement statement;
Type array_type;
- Type var_type;
+ Expression var_type;
TemporaryVariable[] lengths;
ArrayCounter[] counter;
int rank;
TemporaryVariable copy;
Expression access;
- public ArrayForeach (Type var_type, Expression var,
+ public ArrayForeach (Expression var_type, Expression var,
Expression expr, Statement stmt, Location l)
{
this.var_type = var_type;
if (access == null)
return false;
- conv = Convert.ExplicitConversion (ec, access, var_type, loc);
+ VarExpr ve = var_type as VarExpr;
+ if (ve != null) {
+ // Infer implicitly typed local variable from foreach array type
+ var_type = new TypeExpression (access.Type, ve.Location);
+ }
+
+ var_type = var_type.ResolveAsTypeTerminal (ec, false);
+ if (var_type == null)
+ return false;
+
+ conv = Convert.ExplicitConversion (ec, access, var_type.Type, loc);
if (conv == null)
return false;
MethodGroupExpr get_enumerator;
PropertyExpr get_current;
MethodInfo move_next;
- Type var_type, enumerator_type;
+ Expression var_type;
+ Type enumerator_type;
bool is_disposable;
bool enumerator_found;
- public CollectionForeach (Type var_type, Expression var,
+ public CollectionForeach (Expression var_type, Expression var,
Expression expr, Statement stmt, Location l)
{
this.var_type = var_type;
TypeManager.CSharpName (expr.Type));
}
- public static bool IsOverride (MethodInfo m)
+ bool IsOverride (MethodInfo m)
{
m = (MethodInfo) TypeManager.DropGenericMethodArguments (m);
get_current = tmp_get_cur;
enumerator_type = tmp_enumerator_type;
MethodInfo[] mi = new MethodInfo[] { (MethodInfo) result };
- get_enumerator = new MethodGroupExpr (mi, loc);
+ get_enumerator = new MethodGroupExpr (mi, enumerator_type, loc);
if (t != expr.Type) {
expr = Convert.ExplicitConversion (
return false;
}
+ VarExpr ve = var_type as VarExpr;
+ if (ve != null) {
+ // Infer implicitly typed local variable from foreach enumerable type
+ var_type = new TypeExpression (get_current.PropertyInfo.PropertyType, var_type.Location);
+ }
+
+ var_type = var_type.ResolveAsTypeTerminal (ec, false);
+ if (var_type == null)
+ return false;
+
enumerator = new TemporaryVariable (enumerator_type, loc);
enumerator.Resolve (ec);
- init = new Invocation (get_enumerator, new ArrayList ());
+ init = new Invocation (get_enumerator, null);
init = init.Resolve (ec);
if (init == null)
return false;
Expression move_next_expr;
{
MemberInfo[] mi = new MemberInfo[] { move_next };
- MethodGroupExpr mg = new MethodGroupExpr (mi, loc);
+ MethodGroupExpr mg = new MethodGroupExpr (mi, var_type.Type, loc);
mg.InstanceExpression = enumerator;
- move_next_expr = new Invocation (mg, new ArrayList ());
+ move_next_expr = new Invocation (mg, null);
}
get_current.InstanceExpression = enumerator;
Statement block = new CollectionForeachStatement (
- var_type, variable, get_current, statement, loc);
+ var_type.Type, variable, get_current, statement, loc);
loop = new While (move_next_expr, block, loc);