Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / LoopExpression.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
6  * copy of the license can be found in the License.html file at the root of this distribution. If 
7  * you cannot locate the  Apache License, Version 2.0, please send an email to 
8  * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
9  * by the terms of the Apache License, Version 2.0.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15
16 using System;
17 using System.Diagnostics;
18 using System.Dynamic.Utils;
19
20 #if !FEATURE_CORE_DLR
21 namespace Microsoft.Scripting.Ast {
22 #else
23 namespace System.Linq.Expressions {
24 #endif
25     /// <summary>
26     /// Represents an infinite loop. It can be exited with "break".
27     /// </summary>
28     [DebuggerTypeProxy(typeof(Expression.LoopExpressionProxy))]
29     public sealed class LoopExpression : Expression {
30         private readonly Expression _body;
31         private readonly LabelTarget _break;
32         private readonly LabelTarget _continue;
33
34         internal LoopExpression(Expression body, LabelTarget @break, LabelTarget @continue) {
35             _body = body;
36             _break = @break;
37             _continue = @continue;
38         }
39
40         /// <summary>
41         /// Gets the static type of the expression that this <see cref="Expression" /> represents.
42         /// </summary>
43         /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
44         public sealed override Type Type {
45             get { return _break == null ? typeof(void) : _break.Type; }
46         }
47
48         /// <summary>
49         /// Returns the node type of this Expression. Extension nodes should return
50         /// ExpressionType.Extension when overriding this method.
51         /// </summary>
52         /// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
53         public sealed override ExpressionType NodeType {
54             get { return ExpressionType.Loop; }
55         }
56
57         /// <summary>
58         /// Gets the <see cref="Expression"/> that is the body of the loop.
59         /// </summary>
60         public Expression Body {
61             get { return _body; }
62         }
63
64         /// <summary>
65         /// Gets the <see cref="LabelTarget"/> that is used by the loop body as a break statement target.
66         /// </summary>
67         public LabelTarget BreakLabel {
68             get { return _break; }
69         }
70
71         /// <summary>
72         /// Gets the <see cref="LabelTarget"/> that is used by the loop body as a continue statement target.
73         /// </summary>
74         public LabelTarget ContinueLabel {
75             get { return _continue; }
76         }
77
78         /// <summary>
79         /// Dispatches to the specific visit method for this node type.
80         /// </summary>
81         protected internal override Expression Accept(ExpressionVisitor visitor) {
82             return visitor.VisitLoop(this);
83         }
84
85         /// <summary>
86         /// Creates a new expression that is like this one, but using the
87         /// supplied children. If all of the children are the same, it will
88         /// return this expression.
89         /// </summary>
90         /// <param name="breakLabel">The <see cref="BreakLabel" /> property of the result.</param>
91         /// <param name="continueLabel">The <see cref="ContinueLabel" /> property of the result.</param>
92         /// <param name="body">The <see cref="Body" /> property of the result.</param>
93         /// <returns>This expression if no children changed, or an expression with the updated children.</returns>
94         public LoopExpression Update(LabelTarget breakLabel, LabelTarget continueLabel, Expression body) {
95             if (breakLabel == BreakLabel && continueLabel == ContinueLabel && body == Body) {
96                 return this;
97             }
98             return Expression.Loop(body, breakLabel, continueLabel);
99         }
100     }
101
102     public partial class Expression {
103         /// <summary>
104         /// Creates a <see cref="LoopExpression"/> with the given body.
105         /// </summary>
106         /// <param name="body">The body of the loop.</param>
107         /// <returns>The created <see cref="LoopExpression"/>.</returns>
108         public static LoopExpression Loop(Expression body) {
109             return Loop(body, null);
110         }
111
112         /// <summary>
113         /// Creates a <see cref="LoopExpression"/> with the given body and break target.
114         /// </summary>
115         /// <param name="body">The body of the loop.</param>
116         /// <param name="break">The break target used by the loop body.</param>
117         /// <returns>The created <see cref="LoopExpression"/>.</returns>
118         public static LoopExpression Loop(Expression body, LabelTarget @break) {
119             return Loop(body, @break, null);
120         }
121
122         /// <summary>
123         /// Creates a <see cref="LoopExpression"/> with the given body.
124         /// </summary>
125         /// <param name="body">The body of the loop.</param>
126         /// <param name="break">The break target used by the loop body.</param>
127         /// <param name="continue">The continue target used by the loop body.</param>
128         /// <returns>The created <see cref="LoopExpression"/>.</returns>
129         public static LoopExpression Loop(Expression body, LabelTarget @break, LabelTarget @continue) {
130             RequiresCanRead(body, "body");
131             if (@continue != null && @continue.Type != typeof(void)) throw Error.LabelTypeMustBeVoid();
132             return new LoopExpression(body, @break, @continue);
133         }
134     }
135 }