2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[mono.git] / mcs / class / dlr / Runtime / Microsoft.Scripting.Core / Ast / DebugInfoExpression.cs
1 /* ****************************************************************************
2  *
3  * Copyright (c) Microsoft Corporation. 
4  *
5  * This source code is subject to terms and conditions of the Microsoft Public License. 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  Microsoft Public License, 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 Microsoft Public License.
10  *
11  * You must not remove this notice, or any other, from this software.
12  *
13  *
14  * ***************************************************************************/
15 using System; using Microsoft;
16
17
18 using System.Diagnostics;
19 #if CODEPLEX_40
20 using System.Dynamic.Utils;
21 #else
22 using Microsoft.Scripting.Utils;
23 #endif
24
25 #if CODEPLEX_40
26 namespace System.Linq.Expressions {
27 #else
28 namespace Microsoft.Linq.Expressions {
29 #endif
30     /// <summary>
31     /// Emits or clears a sequence point for debug information.
32     /// 
33     /// This allows the debugger to highlight the correct source code when
34     /// debugging.
35     /// </summary>
36 #if !SILVERLIGHT
37     [DebuggerTypeProxy(typeof(Expression.DebugInfoExpressionProxy))]
38 #endif
39     public class DebugInfoExpression : Expression {
40
41         private readonly SymbolDocumentInfo _document;
42
43         internal DebugInfoExpression(SymbolDocumentInfo document) {
44             _document = document;
45         }
46
47         /// <summary>
48         /// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
49         /// </summary>
50         /// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
51         public sealed override Type Type {
52             get { return typeof(void); }
53         }
54
55         /// <summary>
56         /// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
57         /// </summary>
58         /// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
59         public sealed override ExpressionType NodeType {
60             get { return ExpressionType.DebugInfo; }
61         }
62
63         /// <summary>
64         /// Gets the start line of this <see cref="DebugInfoExpression" />.
65         /// </summary>
66         public virtual int StartLine {
67             get { throw ContractUtils.Unreachable; }
68         }
69
70         /// <summary>
71         /// Gets the start column of this <see cref="DebugInfoExpression" />.
72         /// </summary>
73         public virtual int StartColumn {
74             get { throw ContractUtils.Unreachable; }
75         }
76
77         /// <summary>
78         /// Gets the end line of this <see cref="DebugInfoExpression" />.
79         /// </summary>
80         public virtual int EndLine {
81             get { throw ContractUtils.Unreachable; }
82         }
83
84         /// <summary>
85         /// Gets the end column of this <see cref="DebugInfoExpression" />.
86         /// </summary>
87         public virtual int EndColumn {
88             get { throw ContractUtils.Unreachable; }
89         }
90
91         /// <summary>
92         /// Gets the <see cref="SymbolDocumentInfo"/> that represents the source file.
93         /// </summary>
94         public SymbolDocumentInfo Document {
95             get { return _document; }
96         }
97
98         /// <summary>
99         /// Gets the value to indicate if the <see cref="DebugInfoExpression"/> is for clearing a sequence point.
100         /// </summary>
101         public virtual bool IsClear {
102             get { throw ContractUtils.Unreachable; }
103         }
104
105         internal override Expression Accept(ExpressionVisitor visitor) {
106             return visitor.VisitDebugInfo(this);
107         }
108     }
109
110     #region Specialized subclasses
111
112     internal sealed class SpanDebugInfoExpression : DebugInfoExpression {
113         private readonly int _startLine, _startColumn, _endLine, _endColumn;
114
115         internal SpanDebugInfoExpression(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn)
116             : base(document) {
117             _startLine = startLine;
118             _startColumn = startColumn;
119             _endLine = endLine;
120             _endColumn = endColumn;
121         }
122
123         public override int StartLine {
124             get {
125                 return _startLine;
126             }
127         }
128
129         public override int StartColumn {
130             get {
131                 return _startColumn;
132             }
133         }
134
135         public override int EndLine {
136             get {
137                 return _endLine;
138             }
139         }
140
141         public override int EndColumn {
142             get {
143                 return _endColumn;
144             }
145         }
146
147         public override bool IsClear {
148             get {
149                 return false;
150             }
151         }
152
153         internal override Expression Accept(ExpressionVisitor visitor) {
154             return visitor.VisitDebugInfo(this);
155         }
156     }
157
158     internal sealed class ClearDebugInfoExpression : DebugInfoExpression {
159         internal ClearDebugInfoExpression(SymbolDocumentInfo document)
160             : base(document) {
161         }
162
163         public override bool IsClear {
164             get {
165                 return true;
166             }
167         }
168
169         public override int StartLine {
170             get {
171                 return 0xfeefee;
172             }
173         }
174
175         public override int StartColumn {
176             get {
177                 return 0;
178             }
179         }
180
181         public override int EndLine {
182             get {
183                 return 0xfeefee;
184             }
185         }
186
187         public override int EndColumn {
188             get {
189                 return 0;
190             }
191         }
192     }
193     #endregion
194
195     public partial class Expression {
196         /// <summary>
197         /// Creates a <see cref="DebugInfoExpression"/> with the specified span.
198         /// </summary>
199         /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
200         /// <param name="startLine">The start line of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
201         /// <param name="startColumn">The start column of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
202         /// <param name="endLine">The end line of this <see cref="DebugInfoExpression" />. Must be greater or equal than the start line.</param>
203         /// <param name="endColumn">The end column of this <see cref="DebugInfoExpression" />. If the end line is the same as the start line, it must be greater or equal than the start column. In any case, must be greater than 0.</param>
204         /// <returns>An instance of <see cref="DebugInfoExpression"/>.</returns>
205         public static DebugInfoExpression DebugInfo(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn) {
206             ContractUtils.RequiresNotNull(document, "document");
207             if (startLine == 0xfeefee && startColumn == 0 && endLine == 0xfeefee && endColumn == 0) {
208                 return new ClearDebugInfoExpression(document);
209             }
210
211             ValidateSpan(startLine, startColumn, endLine, endColumn);
212             return new SpanDebugInfoExpression(document, startLine, startColumn, endLine, endColumn);
213         }
214
215         /// <summary>
216         /// Creates a <see cref="DebugInfoExpression"/> for clearing a sequence point.
217         /// </summary>
218         /// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
219         /// <returns>An instance of <see cref="DebugInfoExpression"/> for clearning a sequence point.</returns>
220         public static DebugInfoExpression ClearDebugInfo(SymbolDocumentInfo document) {
221             ContractUtils.RequiresNotNull(document, "document");
222
223             return new ClearDebugInfoExpression(document);
224         }
225
226         private static void ValidateSpan(int startLine, int startColumn, int endLine, int endColumn) {
227             if (startLine < 1) {
228                 throw Error.OutOfRange("startLine", 1);
229             }
230             if (startColumn < 1) {
231                 throw Error.OutOfRange("startColumn", 1);
232             }
233             if (endLine < 1) {
234                 throw Error.OutOfRange("endLine", 1);
235             }
236             if (endColumn < 1) {
237                 throw Error.OutOfRange("endColumn", 1);
238             }
239             if (startLine > endLine) {
240                 throw Error.StartEndMustBeOrdered();
241             }
242             if (startLine == endLine && startColumn > endColumn) {
243                 throw Error.StartEndMustBeOrdered();
244             }
245         }
246     }
247 }