Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@@ -0,0 +1 @@
b8dcd61a298655cfc35b4937de6457d5432afb35

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,178 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Diagnostics;
using System.Dynamic.Utils;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents a catch statement in a try block.
/// This must have the same return type (i.e., the type of <see cref="P:CatchBlock.Body"/>) as the try block it is associated with.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.CatchBlockProxy))]
#endif
public sealed class CatchBlock {
private readonly Type _test;
private readonly ParameterExpression _var;
private readonly Expression _body;
private readonly Expression _filter;
internal CatchBlock(Type test, ParameterExpression variable, Expression body, Expression filter) {
_test = test;
_var = variable;
_body = body;
_filter = filter;
}
/// <summary>
/// Gets a reference to the <see cref="Exception"/> object caught by this handler.
/// </summary>
public ParameterExpression Variable {
get { return _var; }
}
/// <summary>
/// Gets the type of <see cref="Exception"/> this handler catches.
/// </summary>
public Type Test {
get { return _test; }
}
/// <summary>
/// Gets the body of the catch block.
/// </summary>
public Expression Body {
get { return _body; }
}
/// <summary>
/// Gets the body of the <see cref="CatchBlock"/>'s filter.
/// </summary>
public Expression Filter {
get {
return _filter;
}
}
/// <summary>
/// Returns a <see cref="String"/> that represents the current <see cref="Object"/>.
/// </summary>
/// <returns>A <see cref="String"/> that represents the current <see cref="Object"/>. </returns>
public override string ToString() {
return ExpressionStringBuilder.CatchBlockToString(this);
}
/// <summary>
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
/// </summary>
/// <param name="variable">The <see cref="Variable" /> property of the result.</param>
/// <param name="filter">The <see cref="Filter" /> property of the result.</param>
/// <param name="body">The <see cref="Body" /> property of the result.</param>
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public CatchBlock Update(ParameterExpression variable, Expression filter, Expression body) {
if (variable == Variable && filter == Filter && body == Body) {
return this;
}
return Expression.MakeCatchBlock(Test, variable, body, filter);
}
}
public partial class Expression {
/// <summary>
/// Creates a <see cref="CatchBlock"/> representing a catch statement.
/// The <see cref="Type"/> of object to be caught can be specified but no reference to the object
/// will be available for use in the <see cref="CatchBlock"/>.
/// </summary>
/// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
/// <param name="body">The body of the catch statement.</param>
/// <returns>The created <see cref="CatchBlock"/>.</returns>
public static CatchBlock Catch(Type type, Expression body) {
return MakeCatchBlock(type, null, body, null);
}
/// <summary>
/// Creates a <see cref="CatchBlock"/> representing a catch statement with a reference to the caught object for use in the handler body.
/// </summary>
/// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
/// <param name="body">The body of the catch statement.</param>
/// <returns>The created <see cref="CatchBlock"/>.</returns>
public static CatchBlock Catch(ParameterExpression variable, Expression body) {
ContractUtils.RequiresNotNull(variable, "variable");
return MakeCatchBlock(variable.Type, variable, body, null);
}
/// <summary>
/// Creates a <see cref="CatchBlock"/> representing a catch statement with
/// an <see cref="Exception"/> filter but no reference to the caught <see cref="Exception"/> object.
/// </summary>
/// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
/// <param name="body">The body of the catch statement.</param>
/// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
/// <returns>The created <see cref="CatchBlock"/>.</returns>
public static CatchBlock Catch(Type type, Expression body, Expression filter) {
return MakeCatchBlock(type, null, body, filter);
}
/// <summary>
/// Creates a <see cref="CatchBlock"/> representing a catch statement with
/// an <see cref="Exception"/> filter and a reference to the caught <see cref="Exception"/> object.
/// </summary>
/// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
/// <param name="body">The body of the catch statement.</param>
/// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
/// <returns>The created <see cref="CatchBlock"/>.</returns>
public static CatchBlock Catch(ParameterExpression variable, Expression body, Expression filter) {
ContractUtils.RequiresNotNull(variable, "variable");
return MakeCatchBlock(variable.Type, variable, body, filter);
}
/// <summary>
/// Creates a <see cref="CatchBlock"/> representing a catch statement with the specified elements.
/// </summary>
/// <param name="type">The <see cref="Type"/> of <see cref="Exception"/> this <see cref="CatchBlock"/> will handle.</param>
/// <param name="variable">A <see cref="ParameterExpression"/> representing a reference to the <see cref="Exception"/> object caught by this handler.</param>
/// <param name="body">The body of the catch statement.</param>
/// <param name="filter">The body of the <see cref="Exception"/> filter.</param>
/// <returns>The created <see cref="CatchBlock"/>.</returns>
/// <remarks><paramref name="type"/> must be non-null and match the type of <paramref name="variable"/> (if it is supplied).</remarks>
public static CatchBlock MakeCatchBlock(Type type, ParameterExpression variable, Expression body, Expression filter) {
ContractUtils.RequiresNotNull(type, "type");
ContractUtils.Requires(variable == null || TypeUtils.AreEquivalent(variable.Type, type), "variable");
if (variable != null && variable.IsByRef) {
throw Error.VariableMustNotBeByRef(variable, variable.Type);
}
RequiresCanRead(body, "body");
if (filter != null) {
RequiresCanRead(filter, "filter");
if (filter.Type != typeof(bool)) throw Error.ArgumentMustBeBoolean();
}
return new CatchBlock(type, variable, body, filter);
}
}
}

View File

@@ -0,0 +1,232 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Dynamic.Utils;
using System.Diagnostics;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents an expression that has a conditional operator.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.ConditionalExpressionProxy))]
#endif
public class ConditionalExpression : Expression {
private readonly Expression _test;
private readonly Expression _true;
internal ConditionalExpression(Expression test, Expression ifTrue) {
_test = test;
_true = ifTrue;
}
internal static ConditionalExpression Make(Expression test, Expression ifTrue, Expression ifFalse, Type type) {
if (ifTrue.Type != type || ifFalse.Type != type) {
return new FullConditionalExpressionWithType(test, ifTrue, ifFalse, type);
} if (ifFalse is DefaultExpression && ifFalse.Type == typeof(void)) {
return new ConditionalExpression(test, ifTrue);
} else {
return new FullConditionalExpression(test, ifTrue, ifFalse);
}
}
/// <summary>
/// Returns the node type of this Expression. Extension nodes should return
/// ExpressionType.Extension when overriding this method.
/// </summary>
/// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.Conditional; }
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents.
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public override Type Type {
get { return IfTrue.Type; }
}
/// <summary>
/// Gets the test of the conditional operation.
/// </summary>
public Expression Test {
get { return _test; }
}
/// <summary>
/// Gets the expression to execute if the test evaluates to true.
/// </summary>
public Expression IfTrue {
get { return _true; }
}
/// <summary>
/// Gets the expression to execute if the test evaluates to false.
/// </summary>
public Expression IfFalse {
get { return GetFalse(); }
}
internal virtual Expression GetFalse() {
return Expression.Empty();
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitConditional(this);
}
/// <summary>
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
/// </summary>
/// <param name="test">The <see cref="Test" /> property of the result.</param>
/// <param name="ifTrue">The <see cref="IfTrue" /> property of the result.</param>
/// <param name="ifFalse">The <see cref="IfFalse" /> property of the result.</param>
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public ConditionalExpression Update(Expression test, Expression ifTrue, Expression ifFalse) {
if (test == Test && ifTrue == IfTrue && ifFalse == IfFalse) {
return this;
}
return Expression.Condition(test, ifTrue, ifFalse, Type);
}
}
internal class FullConditionalExpression : ConditionalExpression {
private readonly Expression _false;
internal FullConditionalExpression(Expression test, Expression ifTrue, Expression ifFalse)
: base(test, ifTrue) {
_false = ifFalse;
}
internal override Expression GetFalse() {
return _false;
}
}
internal class FullConditionalExpressionWithType : FullConditionalExpression {
private readonly Type _type;
internal FullConditionalExpressionWithType(Expression test, Expression ifTrue, Expression ifFalse, Type type)
: base(test, ifTrue, ifFalse) {
_type = type;
}
public sealed override Type Type {
get { return _type; }
}
}
public partial class Expression {
/// <summary>
/// Creates a <see cref="ConditionalExpression"/>.
/// </summary>
/// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
/// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
/// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param>
/// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
/// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values.</returns>
public static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse) {
RequiresCanRead(test, "test");
RequiresCanRead(ifTrue, "ifTrue");
RequiresCanRead(ifFalse, "ifFalse");
if (test.Type != typeof(bool)) {
throw Error.ArgumentMustBeBoolean();
}
if (!TypeUtils.AreEquivalent(ifTrue.Type, ifFalse.Type)) {
throw Error.ArgumentTypesMustMatch();
}
return ConditionalExpression.Make(test, ifTrue, ifFalse, ifTrue.Type);
}
/// <summary>
/// Creates a <see cref="ConditionalExpression"/>.
/// </summary>
/// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
/// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
/// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param>
/// <param name="type">A <see cref="Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
/// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values.</returns>
/// <remarks>This method allows explicitly unifying the result type of the conditional expression in cases where the types of <paramref name="ifTrue"/>
/// and <paramref name="ifFalse"/> expressions are not equal. Types of both <paramref name="ifTrue"/> and <paramref name="ifFalse"/> must be implicitly
/// reference assignable to the result type. The <paramref name="type"/> is allowed to be <see cref="System.Void"/>.</remarks>
public static ConditionalExpression Condition(Expression test, Expression ifTrue, Expression ifFalse, Type type) {
RequiresCanRead(test, "test");
RequiresCanRead(ifTrue, "ifTrue");
RequiresCanRead(ifFalse, "ifFalse");
ContractUtils.RequiresNotNull(type, "type");
if (test.Type != typeof(bool)) {
throw Error.ArgumentMustBeBoolean();
}
if (type != typeof(void)) {
if (!TypeUtils.AreReferenceAssignable(type, ifTrue.Type) ||
!TypeUtils.AreReferenceAssignable(type, ifFalse.Type)) {
throw Error.ArgumentTypesMustMatch();
}
}
return ConditionalExpression.Make(test, ifTrue, ifFalse, type);
}
/// <summary>
/// Creates a <see cref="ConditionalExpression"/>.
/// </summary>
/// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
/// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
/// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
/// properties set to the specified values. The <see cref="P:ConditionalExpression.IfFalse"/> property is set to default expression and
/// the type of the resulting <see cref="ConditionalExpression"/> returned by this method is <see cref="System.Void"/>.</returns>
public static ConditionalExpression IfThen(Expression test, Expression ifTrue) {
return Condition(test, ifTrue, Expression.Empty(), typeof(void));
}
/// <summary>
/// Creates a <see cref="ConditionalExpression"/>.
/// </summary>
/// <param name="test">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.Test"/> property equal to.</param>
/// <param name="ifTrue">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfTrue"/> property equal to.</param>
/// <param name="ifFalse">An <see cref="Expression"/> to set the <see cref="P:ConditionalExpression.IfFalse"/> property equal to.</param>
/// <returns>A <see cref="ConditionalExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Conditional"/> and the <see cref="P:ConditionalExpression.Test"/>, <see cref="P:ConditionalExpression.IfTrue"/>,
/// and <see cref="P:ConditionalExpression.IfFalse"/> properties set to the specified values. The type of the resulting <see cref="ConditionalExpression"/>
/// returned by this method is <see cref="System.Void"/>.</returns>
public static ConditionalExpression IfThenElse(Expression test, Expression ifTrue, Expression ifFalse) {
return Condition(test, ifTrue, ifFalse, typeof(void));
}
}
}

View File

@@ -0,0 +1,138 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Diagnostics;
using System.Dynamic.Utils;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents an expression that has a constant value.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.ConstantExpressionProxy))]
#endif
public class ConstantExpression : Expression {
// Possible optimization: we could have a Constant<T> subclass that
// stores the unboxed value.
private readonly object _value;
internal ConstantExpression(object value) {
_value = value;
}
internal static ConstantExpression Make(object value, Type type) {
if ((value == null && type == typeof(object)) || (value != null && value.GetType() == type)) {
return new ConstantExpression(value);
} else {
return new TypedConstantExpression(value, type);
}
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents.
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public override Type Type {
get {
if (_value == null) {
return typeof(object);
}
return _value.GetType();
}
}
/// <summary>
/// Returns the node type of this Expression. Extension nodes should return
/// ExpressionType.Extension when overriding this method.
/// </summary>
/// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.Constant; }
}
/// <summary>
/// Gets the value of the constant expression.
/// </summary>
public object Value {
get { return _value; }
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitConstant(this);
}
}
internal class TypedConstantExpression : ConstantExpression {
private readonly Type _type;
internal TypedConstantExpression(object value, Type type)
: base(value) {
_type = type;
}
public sealed override Type Type {
get { return _type; }
}
}
public partial class Expression {
/// <summary>
/// Creates a <see cref="ConstantExpression"/> that has the <see cref="P:ConstantExpression.Value"/> property set to the specified value. .
/// </summary>
/// <param name="value">An <see cref="System.Object"/> to set the <see cref="P:ConstantExpression.Value"/> property equal to.</param>
/// <returns>
/// A <see cref="ConstantExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Constant"/> and the <see cref="P:Expression.Value"/> property set to the specified value.
/// </returns>
public static ConstantExpression Constant(object value) {
return ConstantExpression.Make(value, value == null ? typeof(object) : value.GetType());
}
/// <summary>
/// Creates a <see cref="ConstantExpression"/> that has the <see cref="P:ConstantExpression.Value"/>
/// and <see cref="P:ConstantExpression.Type"/> properties set to the specified values. .
/// </summary>
/// <param name="value">An <see cref="System.Object"/> to set the <see cref="P:ConstantExpression.Value"/> property equal to.</param>
/// <param name="type">A <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="ConstantExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Constant"/> and the <see cref="P:ConstantExpression.Value"/> and
/// <see cref="P:Expression.Type"/> properties set to the specified values.
/// </returns>
public static ConstantExpression Constant(object value, Type type) {
ContractUtils.RequiresNotNull(type, "type");
if (value == null && type.IsValueType && !TypeUtils.IsNullableType(type)) {
throw Error.ArgumentTypesMustMatch();
}
if (value != null && !type.IsAssignableFrom(value.GetType())) {
throw Error.ArgumentTypesMustMatch();
}
return ConstantExpression.Make(value, type);
}
}
}

View File

@@ -0,0 +1,249 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Diagnostics;
using System.Dynamic.Utils;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Emits or clears a sequence point for debug information.
///
/// This allows the debugger to highlight the correct source code when
/// debugging.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.DebugInfoExpressionProxy))]
#endif
public class DebugInfoExpression : Expression {
private readonly SymbolDocumentInfo _document;
internal DebugInfoExpression(SymbolDocumentInfo document) {
_document = document;
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public sealed override Type Type {
get { return typeof(void); }
}
/// <summary>
/// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
/// </summary>
/// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.DebugInfo; }
}
/// <summary>
/// Gets the start line of this <see cref="DebugInfoExpression" />.
/// </summary>
public virtual int StartLine {
get { throw ContractUtils.Unreachable; }
}
/// <summary>
/// Gets the start column of this <see cref="DebugInfoExpression" />.
/// </summary>
public virtual int StartColumn {
get { throw ContractUtils.Unreachable; }
}
/// <summary>
/// Gets the end line of this <see cref="DebugInfoExpression" />.
/// </summary>
public virtual int EndLine {
get { throw ContractUtils.Unreachable; }
}
/// <summary>
/// Gets the end column of this <see cref="DebugInfoExpression" />.
/// </summary>
public virtual int EndColumn {
get { throw ContractUtils.Unreachable; }
}
/// <summary>
/// Gets the <see cref="SymbolDocumentInfo"/> that represents the source file.
/// </summary>
public SymbolDocumentInfo Document {
get { return _document; }
}
/// <summary>
/// Gets the value to indicate if the <see cref="DebugInfoExpression"/> is for clearing a sequence point.
/// </summary>
public virtual bool IsClear {
get { throw ContractUtils.Unreachable; }
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitDebugInfo(this);
}
}
#region Specialized subclasses
internal sealed class SpanDebugInfoExpression : DebugInfoExpression {
private readonly int _startLine, _startColumn, _endLine, _endColumn;
internal SpanDebugInfoExpression(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn)
: base(document) {
_startLine = startLine;
_startColumn = startColumn;
_endLine = endLine;
_endColumn = endColumn;
}
public override int StartLine {
get {
return _startLine;
}
}
public override int StartColumn {
get {
return _startColumn;
}
}
public override int EndLine {
get {
return _endLine;
}
}
public override int EndColumn {
get {
return _endColumn;
}
}
public override bool IsClear {
get {
return false;
}
}
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitDebugInfo(this);
}
}
internal sealed class ClearDebugInfoExpression : DebugInfoExpression {
internal ClearDebugInfoExpression(SymbolDocumentInfo document)
: base(document) {
}
public override bool IsClear {
get {
return true;
}
}
public override int StartLine {
get {
return 0xfeefee;
}
}
public override int StartColumn {
get {
return 0;
}
}
public override int EndLine {
get {
return 0xfeefee;
}
}
public override int EndColumn {
get {
return 0;
}
}
}
#endregion
public partial class Expression {
/// <summary>
/// Creates a <see cref="DebugInfoExpression"/> with the specified span.
/// </summary>
/// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
/// <param name="startLine">The start line of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
/// <param name="startColumn">The start column of this <see cref="DebugInfoExpression" />. Must be greater than 0.</param>
/// <param name="endLine">The end line of this <see cref="DebugInfoExpression" />. Must be greater or equal than the start line.</param>
/// <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>
/// <returns>An instance of <see cref="DebugInfoExpression"/>.</returns>
public static DebugInfoExpression DebugInfo(SymbolDocumentInfo document, int startLine, int startColumn, int endLine, int endColumn) {
ContractUtils.RequiresNotNull(document, "document");
if (startLine == 0xfeefee && startColumn == 0 && endLine == 0xfeefee && endColumn == 0) {
return new ClearDebugInfoExpression(document);
}
ValidateSpan(startLine, startColumn, endLine, endColumn);
return new SpanDebugInfoExpression(document, startLine, startColumn, endLine, endColumn);
}
/// <summary>
/// Creates a <see cref="DebugInfoExpression"/> for clearing a sequence point.
/// </summary>
/// <param name="document">The <see cref="SymbolDocumentInfo"/> that represents the source file.</param>
/// <returns>An instance of <see cref="DebugInfoExpression"/> for clearning a sequence point.</returns>
public static DebugInfoExpression ClearDebugInfo(SymbolDocumentInfo document) {
ContractUtils.RequiresNotNull(document, "document");
return new ClearDebugInfoExpression(document);
}
private static void ValidateSpan(int startLine, int startColumn, int endLine, int endColumn) {
if (startLine < 1) {
throw Error.OutOfRange("startLine", 1);
}
if (startColumn < 1) {
throw Error.OutOfRange("startColumn", 1);
}
if (endLine < 1) {
throw Error.OutOfRange("endLine", 1);
}
if (endColumn < 1) {
throw Error.OutOfRange("endColumn", 1);
}
if (startLine > endLine) {
throw Error.StartEndMustBeOrdered();
}
if (startLine == endLine && startColumn > endColumn) {
throw Error.StartEndMustBeOrdered();
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,89 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Diagnostics;
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents the default value of a type or an empty expression.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.DefaultExpressionProxy))]
#endif
public sealed class DefaultExpression : Expression {
private readonly Type _type;
internal DefaultExpression(Type type) {
_type = type;
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents.
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public sealed override Type Type {
get { return _type; }
}
/// <summary>
/// Returns the node type of this Expression. Extension nodes should return
/// ExpressionType.Extension when overriding this method.
/// </summary>
/// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.Default; }
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitDefault(this);
}
}
public partial class Expression {
/// <summary>
/// Creates an empty expression that has <see cref="System.Void"/> type.
/// </summary>
/// <returns>
/// A <see cref="DefaultExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Default"/> and the <see cref="P:Expression.Type"/> property set to <see cref="System.Void"/>.
/// </returns>
public static DefaultExpression Empty() {
return new DefaultExpression(typeof(void));
}
/// <summary>
/// Creates a <see cref="DefaultExpression"/> that has the <see cref="P:Expression.Type"/> property set to the specified type.
/// </summary>
/// <param name="type">A <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="DefaultExpression"/> that has the <see cref="P:Expression.NodeType"/> property equal to
/// <see cref="F:ExpressionType.Default"/> and the <see cref="P:Expression.Type"/> property set to the specified type.
/// </returns>
public static DefaultExpression Default(Type type) {
if (type == typeof(void)) {
return Empty();
}
return new DefaultExpression(type);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Text;
using System.Dynamic.Utils;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents the initialization of a list.
/// </summary>
public sealed class ElementInit : IArgumentProvider {
private MethodInfo _addMethod;
private ReadOnlyCollection<Expression> _arguments;
internal ElementInit(MethodInfo addMethod, ReadOnlyCollection<Expression> arguments) {
_addMethod = addMethod;
_arguments = arguments;
}
/// <summary>
/// Gets the <see cref="MethodInfo"/> used to add elements to the object.
/// </summary>
public MethodInfo AddMethod {
get { return _addMethod; }
}
/// <summary>
/// Gets the list of elements to be added to the object.
/// </summary>
public ReadOnlyCollection<Expression> Arguments {
get { return _arguments; }
}
Expression IArgumentProvider.GetArgument(int index) {
return _arguments[index];
}
int IArgumentProvider.ArgumentCount {
get {
return _arguments.Count;
}
}
/// <summary>
/// Creates a <see cref="String"/> representation of the node.
/// </summary>
/// <returns>A <see cref="String"/> representation of the node.</returns>
public override string ToString() {
return ExpressionStringBuilder.ElementInitBindingToString(this);
}
/// <summary>
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
/// </summary>
/// <param name="arguments">The <see cref="Arguments" /> property of the result.</param>
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public ElementInit Update(IEnumerable<Expression> arguments) {
if (arguments == Arguments) {
return this;
}
return Expression.ElementInit(AddMethod, arguments);
}
}
public partial class Expression {
/// <summary>
/// Creates an <see cref="T:ElementInit">ElementInit</see> expression that represents the initialization of a list.
/// </summary>
/// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
/// <param name="arguments">An array containing the Expressions to be used to initialize the list.</param>
/// <returns>The created <see cref="T:ElementInit">ElementInit</see> expression.</returns>
public static ElementInit ElementInit(MethodInfo addMethod, params Expression[] arguments) {
return ElementInit(addMethod, arguments as IEnumerable<Expression>);
}
/// <summary>
/// Creates an <see cref="T:ElementInit">ElementInit</see> expression that represents the initialization of a list.
/// </summary>
/// <param name="addMethod">The <see cref="MethodInfo"/> for the list's Add method.</param>
/// <param name="arguments">An <see cref="IEnumerable{T}"/> containing <see cref="Expression"/> elements to initialize the list.</param>
/// <returns>The created <see cref="T:ElementInit">ElementInit</see> expression.</returns>
public static ElementInit ElementInit(MethodInfo addMethod, IEnumerable<Expression> arguments) {
ContractUtils.RequiresNotNull(addMethod, "addMethod");
ContractUtils.RequiresNotNull(arguments, "arguments");
var argumentsRO = arguments.ToReadOnly();
RequiresCanRead(argumentsRO, "arguments");
ValidateElementInitAddMethodInfo(addMethod);
ValidateArgumentTypes(addMethod, ExpressionType.Call, ref argumentsRO);
return new ElementInit(addMethod, argumentsRO);
}
private static void ValidateElementInitAddMethodInfo(MethodInfo addMethod) {
ValidateMethodInfo(addMethod);
ParameterInfo[] pis = addMethod.GetParametersCached();
if (pis.Length == 0) {
throw Error.ElementInitializerMethodWithZeroArgs();
}
if (!addMethod.Name.Equals("Add", StringComparison.OrdinalIgnoreCase)) {
throw Error.ElementInitializerMethodNotAdd();
}
if (addMethod.IsStatic) {
throw Error.ElementInitializerMethodStatic();
}
foreach (ParameterInfo pi in pis) {
if (pi.ParameterType.IsByRef) {
throw Error.ElementInitializerMethodNoRefOutParam(pi.Name, addMethod.Name);
}
}
}
}
}

View File

@@ -0,0 +1,457 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.ObjectModel;
using System.Reflection;
using System.Runtime.CompilerServices;
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
#if !SILVERLIGHT
public partial class Expression {
#region Generated Expression Debugger Proxies
// *** BEGIN GENERATED CODE ***
// generated by function: gen_debug_proxies from: generate_tree.py
internal class BinaryExpressionProxy {
private readonly BinaryExpression _node;
public BinaryExpressionProxy(BinaryExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public LambdaExpression Conversion { get { return _node.Conversion; } }
public String DebugView { get { return _node.DebugView; } }
public Boolean IsLifted { get { return _node.IsLifted; } }
public Boolean IsLiftedToNull { get { return _node.IsLiftedToNull; } }
public Expression Left { get { return _node.Left; } }
public MethodInfo Method { get { return _node.Method; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Expression Right { get { return _node.Right; } }
public Type Type { get { return _node.Type; } }
}
internal class BlockExpressionProxy {
private readonly BlockExpression _node;
public BlockExpressionProxy(BlockExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public ReadOnlyCollection<Expression> Expressions { get { return _node.Expressions; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Expression Result { get { return _node.Result; } }
public Type Type { get { return _node.Type; } }
public ReadOnlyCollection<ParameterExpression> Variables { get { return _node.Variables; } }
}
internal class CatchBlockProxy {
private readonly CatchBlock _node;
public CatchBlockProxy(CatchBlock node) {
_node = node;
}
public Expression Body { get { return _node.Body; } }
public Expression Filter { get { return _node.Filter; } }
public Type Test { get { return _node.Test; } }
public ParameterExpression Variable { get { return _node.Variable; } }
}
internal class ConditionalExpressionProxy {
private readonly ConditionalExpression _node;
public ConditionalExpressionProxy(ConditionalExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Expression IfFalse { get { return _node.IfFalse; } }
public Expression IfTrue { get { return _node.IfTrue; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Expression Test { get { return _node.Test; } }
public Type Type { get { return _node.Type; } }
}
internal class ConstantExpressionProxy {
private readonly ConstantExpression _node;
public ConstantExpressionProxy(ConstantExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
public Object Value { get { return _node.Value; } }
}
internal class DebugInfoExpressionProxy {
private readonly DebugInfoExpression _node;
public DebugInfoExpressionProxy(DebugInfoExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public SymbolDocumentInfo Document { get { return _node.Document; } }
public Int32 EndColumn { get { return _node.EndColumn; } }
public Int32 EndLine { get { return _node.EndLine; } }
public Boolean IsClear { get { return _node.IsClear; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Int32 StartColumn { get { return _node.StartColumn; } }
public Int32 StartLine { get { return _node.StartLine; } }
public Type Type { get { return _node.Type; } }
}
internal class DefaultExpressionProxy {
private readonly DefaultExpression _node;
public DefaultExpressionProxy(DefaultExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class DynamicExpressionProxy {
private readonly DynamicExpression _node;
public DynamicExpressionProxy(DynamicExpression node) {
_node = node;
}
public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
public CallSiteBinder Binder { get { return _node.Binder; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Type DelegateType { get { return _node.DelegateType; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class GotoExpressionProxy {
private readonly GotoExpression _node;
public GotoExpressionProxy(GotoExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public GotoExpressionKind Kind { get { return _node.Kind; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public LabelTarget Target { get { return _node.Target; } }
public Type Type { get { return _node.Type; } }
public Expression Value { get { return _node.Value; } }
}
internal class IndexExpressionProxy {
private readonly IndexExpression _node;
public IndexExpressionProxy(IndexExpression node) {
_node = node;
}
public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public PropertyInfo Indexer { get { return _node.Indexer; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Expression Object { get { return _node.Object; } }
public Type Type { get { return _node.Type; } }
}
internal class InvocationExpressionProxy {
private readonly InvocationExpression _node;
public InvocationExpressionProxy(InvocationExpression node) {
_node = node;
}
public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Expression Expression { get { return _node.Expression; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class LabelExpressionProxy {
private readonly LabelExpression _node;
public LabelExpressionProxy(LabelExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Expression DefaultValue { get { return _node.DefaultValue; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public LabelTarget Target { get { return _node.Target; } }
public Type Type { get { return _node.Type; } }
}
internal class LambdaExpressionProxy {
private readonly LambdaExpression _node;
public LambdaExpressionProxy(LambdaExpression node) {
_node = node;
}
public Expression Body { get { return _node.Body; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public String Name { get { return _node.Name; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public ReadOnlyCollection<ParameterExpression> Parameters { get { return _node.Parameters; } }
public Type ReturnType { get { return _node.ReturnType; } }
public Boolean TailCall { get { return _node.TailCall; } }
public Type Type { get { return _node.Type; } }
}
internal class ListInitExpressionProxy {
private readonly ListInitExpression _node;
public ListInitExpressionProxy(ListInitExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public ReadOnlyCollection<ElementInit> Initializers { get { return _node.Initializers; } }
public NewExpression NewExpression { get { return _node.NewExpression; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class LoopExpressionProxy {
private readonly LoopExpression _node;
public LoopExpressionProxy(LoopExpression node) {
_node = node;
}
public Expression Body { get { return _node.Body; } }
public LabelTarget BreakLabel { get { return _node.BreakLabel; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public LabelTarget ContinueLabel { get { return _node.ContinueLabel; } }
public String DebugView { get { return _node.DebugView; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class MemberExpressionProxy {
private readonly MemberExpression _node;
public MemberExpressionProxy(MemberExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Expression Expression { get { return _node.Expression; } }
public MemberInfo Member { get { return _node.Member; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class MemberInitExpressionProxy {
private readonly MemberInitExpression _node;
public MemberInitExpressionProxy(MemberInitExpression node) {
_node = node;
}
public ReadOnlyCollection<MemberBinding> Bindings { get { return _node.Bindings; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public NewExpression NewExpression { get { return _node.NewExpression; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class MethodCallExpressionProxy {
private readonly MethodCallExpression _node;
public MethodCallExpressionProxy(MethodCallExpression node) {
_node = node;
}
public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public MethodInfo Method { get { return _node.Method; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Expression Object { get { return _node.Object; } }
public Type Type { get { return _node.Type; } }
}
internal class NewArrayExpressionProxy {
private readonly NewArrayExpression _node;
public NewArrayExpressionProxy(NewArrayExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public ReadOnlyCollection<Expression> Expressions { get { return _node.Expressions; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class NewExpressionProxy {
private readonly NewExpression _node;
public NewExpressionProxy(NewExpression node) {
_node = node;
}
public ReadOnlyCollection<Expression> Arguments { get { return _node.Arguments; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public ConstructorInfo Constructor { get { return _node.Constructor; } }
public String DebugView { get { return _node.DebugView; } }
public ReadOnlyCollection<MemberInfo> Members { get { return _node.Members; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class ParameterExpressionProxy {
private readonly ParameterExpression _node;
public ParameterExpressionProxy(ParameterExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Boolean IsByRef { get { return _node.IsByRef; } }
public String Name { get { return _node.Name; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class RuntimeVariablesExpressionProxy {
private readonly RuntimeVariablesExpression _node;
public RuntimeVariablesExpressionProxy(RuntimeVariablesExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
public ReadOnlyCollection<ParameterExpression> Variables { get { return _node.Variables; } }
}
internal class SwitchCaseProxy {
private readonly SwitchCase _node;
public SwitchCaseProxy(SwitchCase node) {
_node = node;
}
public Expression Body { get { return _node.Body; } }
public ReadOnlyCollection<Expression> TestValues { get { return _node.TestValues; } }
}
internal class SwitchExpressionProxy {
private readonly SwitchExpression _node;
public SwitchExpressionProxy(SwitchExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public ReadOnlyCollection<SwitchCase> Cases { get { return _node.Cases; } }
public MethodInfo Comparison { get { return _node.Comparison; } }
public String DebugView { get { return _node.DebugView; } }
public Expression DefaultBody { get { return _node.DefaultBody; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Expression SwitchValue { get { return _node.SwitchValue; } }
public Type Type { get { return _node.Type; } }
}
internal class TryExpressionProxy {
private readonly TryExpression _node;
public TryExpressionProxy(TryExpression node) {
_node = node;
}
public Expression Body { get { return _node.Body; } }
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Expression Fault { get { return _node.Fault; } }
public Expression Finally { get { return _node.Finally; } }
public ReadOnlyCollection<CatchBlock> Handlers { get { return _node.Handlers; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
}
internal class TypeBinaryExpressionProxy {
private readonly TypeBinaryExpression _node;
public TypeBinaryExpressionProxy(TypeBinaryExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Expression Expression { get { return _node.Expression; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Type Type { get { return _node.Type; } }
public Type TypeOperand { get { return _node.TypeOperand; } }
}
internal class UnaryExpressionProxy {
private readonly UnaryExpression _node;
public UnaryExpressionProxy(UnaryExpression node) {
_node = node;
}
public Boolean CanReduce { get { return _node.CanReduce; } }
public String DebugView { get { return _node.DebugView; } }
public Boolean IsLifted { get { return _node.IsLifted; } }
public Boolean IsLiftedToNull { get { return _node.IsLiftedToNull; } }
public MethodInfo Method { get { return _node.Method; } }
public ExpressionType NodeType { get { return _node.NodeType; } }
public Expression Operand { get { return _node.Operand; } }
public Type Type { get { return _node.Type; } }
}
// *** END GENERATED CODE ***
#endregion
}
#endif
}

View File

@@ -0,0 +1,418 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic.Utils;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
using Microsoft.Scripting.Utils;
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// The base type for all nodes in Expression Trees.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
public abstract partial class Expression {
private delegate LambdaExpression LambdaFactory(Expression body, string name, bool tailCall, ReadOnlyCollection<ParameterExpression> parameters);
private static readonly CacheDict<Type, MethodInfo> _LambdaDelegateCache = new CacheDict<Type, MethodInfo>(40);
private static volatile CacheDict<Type, LambdaFactory> _LambdaFactories;
// LINQ protected ctor from 3.5
#if !CLR2 // needs ConditionWeakTable in 4.0
// For 4.0, many frequently used Expression nodes have had their memory
// footprint reduced by removing the Type and NodeType fields. This has
// large performance benefits to all users of Expression Trees.
//
// To support the 3.5 protected constructor, we store the fields that
// used to be here in a ConditionalWeakTable.
private class ExtensionInfo {
public ExtensionInfo(ExpressionType nodeType, Type type) {
NodeType = nodeType;
Type = type;
}
internal readonly ExpressionType NodeType;
internal readonly Type Type;
}
private static ConditionalWeakTable<Expression, ExtensionInfo> _legacyCtorSupportTable;
/// <summary>
/// Constructs a new instance of <see cref="Expression"/>.
/// </summary>
/// <param name="nodeType">The <see ctype="ExpressionType"/> of the <see cref="Expression"/>.</param>
/// <param name="type">The <see cref="Type"/> of the <see cref="Expression"/>.</param>
[Obsolete("use a different constructor that does not take ExpressionType. Then override NodeType and Type properties to provide the values that would be specified to this constructor.")]
protected Expression(ExpressionType nodeType, Type type) {
// Can't enforce anything that V1 didn't
if (_legacyCtorSupportTable == null) {
Interlocked.CompareExchange(
ref _legacyCtorSupportTable,
new ConditionalWeakTable<Expression, ExtensionInfo>(),
null
);
}
_legacyCtorSupportTable.Add(this, new ExtensionInfo(nodeType, type));
}
#endif
/// <summary>
/// Constructs a new instance of <see cref="Expression"/>.
/// </summary>
protected Expression() {
}
/// <summary>
/// The <see cref="ExpressionType"/> of the <see cref="Expression"/>.
/// </summary>
public virtual ExpressionType NodeType {
get {
#if !CLR2
ExtensionInfo extInfo;
if (_legacyCtorSupportTable != null && _legacyCtorSupportTable.TryGetValue(this, out extInfo)) {
return extInfo.NodeType;
}
#endif
// the extension expression failed to override NodeType
throw Error.ExtensionNodeMustOverrideProperty("Expression.NodeType");
}
}
/// <summary>
/// The <see cref="Type"/> of the value represented by this <see cref="Expression"/>.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
public virtual Type Type {
get {
#if !CLR2
ExtensionInfo extInfo;
if (_legacyCtorSupportTable != null && _legacyCtorSupportTable.TryGetValue(this, out extInfo)) {
return extInfo.Type;
}
#endif
// the extension expression failed to override Type
throw Error.ExtensionNodeMustOverrideProperty("Expression.Type");
}
}
/// <summary>
/// Indicates that the node can be reduced to a simpler node. If this
/// returns true, Reduce() can be called to produce the reduced form.
/// </summary>
public virtual bool CanReduce {
get { return false; }
}
/// <summary>
/// Reduces this node to a simpler expression. If CanReduce returns
/// true, this should return a valid expression. This method is
/// allowed to return another node which itself must be reduced.
/// </summary>
/// <returns>The reduced expression.</returns>
public virtual Expression Reduce() {
if (CanReduce) throw Error.ReducibleMustOverrideReduce();
return this;
}
/// <summary>
/// Reduces the node and then calls the visitor delegate on the reduced expression.
/// Throws an exception if the node isn't reducible.
/// </summary>
/// <param name="visitor">An instance of <see cref="Func{Expression, Expression}"/>.</param>
/// <returns>The expression being visited, or an expression which should replace it in the tree.</returns>
/// <remarks>
/// Override this method to provide logic to walk the node's children.
/// A typical implementation will call visitor.Visit on each of its
/// children, and if any of them change, should return a new copy of
/// itself with the modified children.
/// </remarks>
protected internal virtual Expression VisitChildren(ExpressionVisitor visitor) {
if (!CanReduce) throw Error.MustBeReducible();
return visitor.Visit(ReduceAndCheck());
}
/// <summary>
/// Dispatches to the specific visit method for this node type. For
/// example, <see cref="MethodCallExpression" /> will call into
/// <see cref="ExpressionVisitor.VisitMethodCall" />.
/// </summary>
/// <param name="visitor">The visitor to visit this node with.</param>
/// <returns>The result of visiting this node.</returns>
/// <remarks>
/// This default implementation for <see cref="ExpressionType.Extension" />
/// nodes will call <see cref="ExpressionVisitor.VisitExtension" />.
/// Override this method to call into a more specific method on a derived
/// visitor class of ExprressionVisitor. However, it should still
/// support unknown visitors by calling VisitExtension.
/// </remarks>
protected internal virtual Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitExtension(this);
}
/// <summary>
/// Reduces this node to a simpler expression. If CanReduce returns
/// true, this should return a valid expression. This method is
/// allowed to return another node which itself must be reduced.
/// </summary>
/// <returns>The reduced expression.</returns>
/// <remarks >
/// Unlike Reduce, this method checks that the reduced node satisfies
/// certain invariants.
/// </remarks>
public Expression ReduceAndCheck() {
if (!CanReduce) throw Error.MustBeReducible();
var newNode = Reduce();
// 1. Reduction must return a new, non-null node
// 2. Reduction must return a new node whose result type can be assigned to the type of the original node
if (newNode == null || newNode == this) throw Error.MustReduceToDifferent();
if (!TypeUtils.AreReferenceAssignable(Type, newNode.Type)) throw Error.ReducedNotCompatible();
return newNode;
}
/// <summary>
/// Reduces the expression to a known node type (i.e. not an Extension node)
/// or simply returns the expression if it is already a known type.
/// </summary>
/// <returns>The reduced expression.</returns>
public Expression ReduceExtensions() {
var node = this;
while (node.NodeType == ExpressionType.Extension) {
node = node.ReduceAndCheck();
}
return node;
}
/// <summary>
/// Creates a <see cref="String"/> representation of the Expression.
/// </summary>
/// <returns>A <see cref="String"/> representation of the Expression.</returns>
public override string ToString() {
return ExpressionStringBuilder.ExpressionToString(this);
}
#if CLR2
/// <summary>
/// Writes a <see cref="String"/> representation of the <see cref="Expression"/> to a <see cref="TextWriter"/>.
/// </summary>
/// <param name="writer">A <see cref="TextWriter"/> that will be used to build the string representation.</param>
public void DumpExpression(TextWriter writer) {
DebugViewWriter.WriteTo(this, writer);
}
/// <summary>
/// Creates a <see cref="String"/> representation of the Expression.
/// </summary>
/// <returns>A <see cref="String"/> representation of the Expression.</returns>
public string DebugView {
#else
private string DebugView {
#endif
get {
using (System.IO.StringWriter writer = new System.IO.StringWriter(CultureInfo.CurrentCulture)) {
DebugViewWriter.WriteTo(this, writer);
return writer.ToString();
}
}
}
/// <summary>
/// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T.
///
/// This is called from various methods where we internally hold onto an IList of T
/// or a readonly collection of T. We check to see if we've already returned a
/// readonly collection of T and if so simply return the other one. Otherwise we do
/// a thread-safe replacement of the list w/ a readonly collection which wraps it.
///
/// Ultimately this saves us from having to allocate a ReadOnlyCollection for our
/// data types because the compiler is capable of going directly to the IList of T.
/// </summary>
internal static ReadOnlyCollection<T> ReturnReadOnly<T>(ref IList<T> collection) {
IList<T> value = collection;
// if it's already read-only just return it.
ReadOnlyCollection<T> res = value as ReadOnlyCollection<T>;
if (res != null) {
return res;
}
// otherwise make sure only readonly collection every gets exposed
Interlocked.CompareExchange<IList<T>>(
ref collection,
value.ToReadOnly(),
value
);
// and return it
return (ReadOnlyCollection<T>)collection;
}
/// <summary>
/// Helper used for ensuring we only return 1 instance of a ReadOnlyCollection of T.
///
/// This is similar to the ReturnReadOnly of T. This version supports nodes which hold
/// onto multiple Expressions where one is typed to object. That object field holds either
/// an expression or a ReadOnlyCollection of Expressions. When it holds a ReadOnlyCollection
/// the IList which backs it is a ListArgumentProvider which uses the Expression which
/// implements IArgumentProvider to get 2nd and additional values. The ListArgumentProvider
/// continues to hold onto the 1st expression.
///
/// This enables users to get the ReadOnlyCollection w/o it consuming more memory than if
/// it was just an array. Meanwhile The DLR internally avoids accessing which would force
/// the readonly collection to be created resulting in a typical memory savings.
/// </summary>
internal static ReadOnlyCollection<Expression> ReturnReadOnly(IArgumentProvider provider, ref object collection) {
Expression tObj = collection as Expression;
if (tObj != null) {
// otherwise make sure only one readonly collection ever gets exposed
Interlocked.CompareExchange(
ref collection,
new ReadOnlyCollection<Expression>(new ListArgumentProvider(provider, tObj)),
tObj
);
}
// and return what is not guaranteed to be a readonly collection
return (ReadOnlyCollection<Expression>)collection;
}
/// <summary>
/// Helper which is used for specialized subtypes which use ReturnReadOnly(ref object, ...).
/// This is the reverse version of ReturnReadOnly which takes an IArgumentProvider.
///
/// This is used to return the 1st argument. The 1st argument is typed as object and either
/// contains a ReadOnlyCollection or the Expression. We check for the Expression and if it's
/// present we return that, otherwise we return the 1st element of the ReadOnlyCollection.
/// </summary>
internal static T ReturnObject<T>(object collectionOrT) where T : class {
T t = collectionOrT as T;
if (t != null) {
return t;
}
return ((ReadOnlyCollection<T>)collectionOrT)[0];
}
#if SILVERLIGHT
#if !CLR2
// Quirks mode for Expression Trees as they existed in Silverlight 2 and 3
internal readonly static bool SilverlightQuirks = System.CompatibilitySwitches.IsAppEarlierThanSilverlight4;
#else
internal readonly static bool SilverlightQuirks = true;
#endif
#endif
private static void RequiresCanRead(Expression expression, string paramName) {
if (expression == null) {
throw new ArgumentNullException(paramName);
}
// validate that we can read the node
switch (expression.NodeType) {
case ExpressionType.Index:
IndexExpression index = (IndexExpression)expression;
if (index.Indexer != null && !index.Indexer.CanRead) {
throw new ArgumentException(Strings.ExpressionMustBeReadable, paramName);
}
break;
case ExpressionType.MemberAccess:
MemberExpression member = (MemberExpression)expression;
MemberInfo memberInfo = member.Member;
if (memberInfo.MemberType == MemberTypes.Property) {
PropertyInfo prop = (PropertyInfo)memberInfo;
if (!prop.CanRead) {
throw new ArgumentException(Strings.ExpressionMustBeReadable, paramName);
}
}
break;
}
}
private static void RequiresCanRead(IEnumerable<Expression> items, string paramName) {
if (items != null) {
// this is called a lot, avoid allocating an enumerator if we can...
IList<Expression> listItems = items as IList<Expression>;
if (listItems != null) {
for (int i = 0; i < listItems.Count; i++) {
RequiresCanRead(listItems[i], paramName);
}
return;
}
foreach (var i in items) {
RequiresCanRead(i, paramName);
}
}
}
private static void RequiresCanWrite(Expression expression, string paramName) {
if (expression == null) {
throw new ArgumentNullException(paramName);
}
bool canWrite = false;
switch (expression.NodeType) {
case ExpressionType.Index:
IndexExpression index = (IndexExpression)expression;
if (index.Indexer != null) {
canWrite = index.Indexer.CanWrite;
} else {
canWrite = true;
}
break;
case ExpressionType.MemberAccess:
MemberExpression member = (MemberExpression)expression;
switch (member.Member.MemberType) {
case MemberTypes.Property:
PropertyInfo prop = (PropertyInfo)member.Member;
canWrite = prop.CanWrite;
break;
case MemberTypes.Field:
FieldInfo field = (FieldInfo)member.Member;
canWrite = !(field.IsInitOnly || field.IsLiteral);
break;
}
break;
case ExpressionType.Parameter:
canWrite = true;
break;
}
if (!canWrite) {
throw new ArgumentException(Strings.ExpressionMustBeWriteable, paramName);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,377 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Describes the node types for the nodes of an expression tree.
/// </summary>
public enum ExpressionType {
#region Generated Expression Tree Node Types
// *** BEGIN GENERATED CODE ***
// generated by function: gen_tree_nodes from: generate_tree.py
/// <summary>
/// A node that represents arithmetic addition without overflow checking.
/// </summary>
Add,
/// <summary>
/// A node that represents arithmetic addition with overflow checking.
/// </summary>
AddChecked,
/// <summary>
/// A node that represents a bitwise AND operation.
/// </summary>
And,
/// <summary>
/// A node that represents a short-circuiting conditional AND operation.
/// </summary>
AndAlso,
/// <summary>
/// A node that represents getting the length of a one-dimensional array.
/// </summary>
ArrayLength,
/// <summary>
/// A node that represents indexing into a one-dimensional array.
/// </summary>
ArrayIndex,
/// <summary>
/// A node that represents represents a method call.
/// </summary>
Call,
/// <summary>
/// A node that represents a null coalescing operation.
/// </summary>
Coalesce,
/// <summary>
/// A node that represents a conditional operation.
/// </summary>
Conditional,
/// <summary>
/// A node that represents an expression that has a constant value.
/// </summary>
Constant,
/// <summary>
/// A node that represents a cast or conversion operation. If the operation is a numeric conversion, it overflows silently if the converted value does not fit the target type.
/// </summary>
Convert,
/// <summary>
/// A node that represents a cast or conversion operation. If the operation is a numeric conversion, an exception is thrown if the converted value does not fit the target type.
/// </summary>
ConvertChecked,
/// <summary>
/// A node that represents arithmetic division.
/// </summary>
Divide,
/// <summary>
/// A node that represents an equality comparison.
/// </summary>
Equal,
/// <summary>
/// A node that represents a bitwise XOR operation.
/// </summary>
ExclusiveOr,
/// <summary>
/// A node that represents a "greater than" numeric comparison.
/// </summary>
GreaterThan,
/// <summary>
/// A node that represents a "greater than or equal" numeric comparison.
/// </summary>
GreaterThanOrEqual,
/// <summary>
/// A node that represents applying a delegate or lambda expression to a list of argument expressions.
/// </summary>
Invoke,
/// <summary>
/// A node that represents a lambda expression.
/// </summary>
Lambda,
/// <summary>
/// A node that represents a bitwise left-shift operation.
/// </summary>
LeftShift,
/// <summary>
/// A node that represents a "less than" numeric comparison.
/// </summary>
LessThan,
/// <summary>
/// A node that represents a "less than or equal" numeric comparison.
/// </summary>
LessThanOrEqual,
/// <summary>
/// A node that represents creating a new IEnumerable object and initializing it from a list of elements.
/// </summary>
ListInit,
/// <summary>
/// A node that represents reading from a field or property.
/// </summary>
MemberAccess,
/// <summary>
/// A node that represents creating a new object and initializing one or more of its members.
/// </summary>
MemberInit,
/// <summary>
/// A node that represents an arithmetic remainder operation.
/// </summary>
Modulo,
/// <summary>
/// A node that represents arithmetic multiplication without overflow checking.
/// </summary>
Multiply,
/// <summary>
/// A node that represents arithmetic multiplication with overflow checking.
/// </summary>
MultiplyChecked,
/// <summary>
/// A node that represents an arithmetic negation operation.
/// </summary>
Negate,
/// <summary>
/// A node that represents a unary plus operation. The result of a predefined unary plus operation is simply the value of the operand, but user-defined implementations may have non-trivial results.
/// </summary>
UnaryPlus,
/// <summary>
/// A node that represents an arithmetic negation operation that has overflow checking.
/// </summary>
NegateChecked,
/// <summary>
/// A node that represents calling a constructor to create a new object.
/// </summary>
New,
/// <summary>
/// A node that represents creating a new one-dimensional array and initializing it from a list of elements.
/// </summary>
NewArrayInit,
/// <summary>
/// A node that represents creating a new array where the bounds for each dimension are specified.
/// </summary>
NewArrayBounds,
/// <summary>
/// A node that represents a bitwise complement operation.
/// </summary>
Not,
/// <summary>
/// A node that represents an inequality comparison.
/// </summary>
NotEqual,
/// <summary>
/// A node that represents a bitwise OR operation.
/// </summary>
Or,
/// <summary>
/// A node that represents a short-circuiting conditional OR operation.
/// </summary>
OrElse,
/// <summary>
/// A node that represents a reference to a parameter or variable defined in the context of the expression.
/// </summary>
Parameter,
/// <summary>
/// A node that represents raising a number to a power.
/// </summary>
Power,
/// <summary>
/// A node that represents an expression that has a constant value of type Expression. A Quote node can contain references to parameters defined in the context of the expression it represents.
/// </summary>
Quote,
/// <summary>
/// A node that represents a bitwise right-shift operation.
/// </summary>
RightShift,
/// <summary>
/// A node that represents arithmetic subtraction without overflow checking.
/// </summary>
Subtract,
/// <summary>
/// A node that represents arithmetic subtraction with overflow checking.
/// </summary>
SubtractChecked,
/// <summary>
/// A node that represents an explicit reference or boxing conversion where null reference (Nothing in Visual Basic) is supplied if the conversion fails.
/// </summary>
TypeAs,
/// <summary>
/// A node that represents a type test.
/// </summary>
TypeIs,
/// <summary>
/// A node that represents an assignment.
/// </summary>
Assign,
/// <summary>
/// A node that represents a block of expressions.
/// </summary>
Block,
/// <summary>
/// A node that represents a debugging information.
/// </summary>
DebugInfo,
/// <summary>
/// A node that represents a unary decrement.
/// </summary>
Decrement,
/// <summary>
/// A node that represents a dynamic operation.
/// </summary>
Dynamic,
/// <summary>
/// A node that represents a default value.
/// </summary>
Default,
/// <summary>
/// A node that represents an extension expression.
/// </summary>
Extension,
/// <summary>
/// A node that represents a goto.
/// </summary>
Goto,
/// <summary>
/// A node that represents a unary increment.
/// </summary>
Increment,
/// <summary>
/// A node that represents an index operation.
/// </summary>
Index,
/// <summary>
/// A node that represents a label.
/// </summary>
Label,
/// <summary>
/// A node that represents a list of runtime variables.
/// </summary>
RuntimeVariables,
/// <summary>
/// A node that represents a loop.
/// </summary>
Loop,
/// <summary>
/// A node that represents a switch operation.
/// </summary>
Switch,
/// <summary>
/// A node that represents a throwing of an exception.
/// </summary>
Throw,
/// <summary>
/// A node that represents a try-catch expression.
/// </summary>
Try,
/// <summary>
/// A node that represents an unbox value type operation.
/// </summary>
Unbox,
/// <summary>
/// A node that represents an arithmetic addition compound assignment without overflow checking.
/// </summary>
AddAssign,
/// <summary>
/// A node that represents a bitwise AND compound assignment.
/// </summary>
AndAssign,
/// <summary>
/// A node that represents an arithmetic division compound assignment .
/// </summary>
DivideAssign,
/// <summary>
/// A node that represents a bitwise XOR compound assignment.
/// </summary>
ExclusiveOrAssign,
/// <summary>
/// A node that represents a bitwise left-shift compound assignment.
/// </summary>
LeftShiftAssign,
/// <summary>
/// A node that represents an arithmetic remainder compound assignment.
/// </summary>
ModuloAssign,
/// <summary>
/// A node that represents arithmetic multiplication compound assignment without overflow checking.
/// </summary>
MultiplyAssign,
/// <summary>
/// A node that represents a bitwise OR compound assignment.
/// </summary>
OrAssign,
/// <summary>
/// A node that represents raising a number to a power compound assignment.
/// </summary>
PowerAssign,
/// <summary>
/// A node that represents a bitwise right-shift compound assignment.
/// </summary>
RightShiftAssign,
/// <summary>
/// A node that represents arithmetic subtraction compound assignment without overflow checking.
/// </summary>
SubtractAssign,
/// <summary>
/// A node that represents an arithmetic addition compound assignment with overflow checking.
/// </summary>
AddAssignChecked,
/// <summary>
/// A node that represents arithmetic multiplication compound assignment with overflow checking.
/// </summary>
MultiplyAssignChecked,
/// <summary>
/// A node that represents arithmetic subtraction compound assignment with overflow checking.
/// </summary>
SubtractAssignChecked,
/// <summary>
/// A node that represents an unary prefix increment.
/// </summary>
PreIncrementAssign,
/// <summary>
/// A node that represents an unary prefix decrement.
/// </summary>
PreDecrementAssign,
/// <summary>
/// A node that represents an unary postfix increment.
/// </summary>
PostIncrementAssign,
/// <summary>
/// A node that represents an unary postfix decrement.
/// </summary>
PostDecrementAssign,
/// <summary>
/// A node that represents a exact type test.
/// </summary>
TypeEqual,
/// <summary>
/// A node that represents a ones complement.
/// </summary>
OnesComplement,
/// <summary>
/// A node that represents a true condition value.
/// </summary>
IsTrue,
/// <summary>
/// A node that represents a false condition value.
/// </summary>
IsFalse,
// *** END GENERATED CODE ***
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,377 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Diagnostics;
using System.Dynamic.Utils;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Specifies what kind of jump this <see cref="GotoExpression"/> represents.
/// </summary>
public enum GotoExpressionKind {
/// <summary>
/// A <see cref="GotoExpression"/> that represents a jump to some location.
/// </summary>
Goto,
/// <summary>
/// A <see cref="GotoExpression"/> that represents a return statement.
/// </summary>
Return,
/// <summary>
/// A <see cref="GotoExpression"/> that represents a break statement.
/// </summary>
Break,
/// <summary>
/// A <see cref="GotoExpression"/> that represents a continue statement.
/// </summary>
Continue,
}
/// <summary>
/// Represents an unconditional jump. This includes return statements, break and continue statements, and other jumps.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.GotoExpressionProxy))]
#endif
public sealed class GotoExpression : Expression {
private readonly GotoExpressionKind _kind;
private readonly Expression _value;
private readonly LabelTarget _target;
private readonly Type _type;
internal GotoExpression(GotoExpressionKind kind, LabelTarget target, Expression value, Type type) {
_kind = kind;
_value = value;
_target = target;
_type = type;
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public sealed override Type Type {
get { return _type; }
}
/// <summary>
/// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
/// </summary>
/// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.Goto; }
}
/// <summary>
/// The value passed to the target, or null if the target is of type
/// System.Void.
/// </summary>
public Expression Value {
get { return _value; }
}
/// <summary>
/// The target label where this node jumps to.
/// </summary>
public LabelTarget Target {
get { return _target; }
}
/// <summary>
/// The kind of the goto. For information purposes only.
/// </summary>
public GotoExpressionKind Kind {
get { return _kind; }
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitGoto(this);
}
/// <summary>
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
/// </summary>
/// <param name="target">The <see cref="Target" /> property of the result.</param>
/// <param name="value">The <see cref="Value" /> property of the result.</param>
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public GotoExpression Update(LabelTarget target, Expression value) {
if (target == Target && value == Value) {
return this;
}
return Expression.MakeGoto(Kind, target, value, Type);
}
}
public partial class Expression {
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a break statement.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>, and a null value to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Break(LabelTarget target) {
return MakeGoto(GotoExpressionKind.Break, target, null, typeof(void));
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a break statement. The value passed to the label upon jumping can be specified.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="value">The value that will be passed to the associated label upon jumping.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// and <paramref name="value"/> to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Break(LabelTarget target, Expression value) {
return MakeGoto(GotoExpressionKind.Break, target, value, typeof(void));
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a break statement with the specified type.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// and the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>.
/// </returns>
public static GotoExpression Break(LabelTarget target, Type type) {
return MakeGoto(GotoExpressionKind.Break, target, null, type);
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a break statement with the specified type.
/// The value passed to the label upon jumping can be specified.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="value">The value that will be passed to the associated label upon jumping.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Break,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
/// and <paramref name="value"/> to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Break(LabelTarget target, Expression value, Type type) {
return MakeGoto(GotoExpressionKind.Break, target, value, type);
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a continue statement.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// and a null value to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Continue(LabelTarget target) {
return MakeGoto(GotoExpressionKind.Continue, target, null, typeof(void));
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a continue statement with the specified type.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
/// and a null value to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Continue(LabelTarget target, Type type) {
return MakeGoto(GotoExpressionKind.Continue, target, null, type);
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a return statement.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Return,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// and a null value to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Return(LabelTarget target) {
return MakeGoto(GotoExpressionKind.Return, target, null, typeof(void));
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a return statement with the specified type.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Return,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
/// and a null value to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Return(LabelTarget target, Type type) {
return MakeGoto(GotoExpressionKind.Return, target, null, type);
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a return statement. The value passed to the label upon jumping can be specified.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="value">The value that will be passed to the associated label upon jumping.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// and <paramref name="value"/> to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Return(LabelTarget target, Expression value) {
return MakeGoto(GotoExpressionKind.Return, target, value, typeof(void));
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a return statement with the specified type.
/// The value passed to the label upon jumping can be specified.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="value">The value that will be passed to the associated label upon jumping.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Continue,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
/// and <paramref name="value"/> to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Return(LabelTarget target, Expression value, Type type) {
return MakeGoto(GotoExpressionKind.Return, target, value, type);
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a goto.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
/// the <see cref="P:GotoExpression.Target"/> property set to the specified value,
/// and a null value to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Goto(LabelTarget target) {
return MakeGoto(GotoExpressionKind.Goto, target, null, typeof(void));
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a goto with the specified type.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
/// the <see cref="P:GotoExpression.Target"/> property set to the specified value,
/// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
/// and a null value to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Goto(LabelTarget target, Type type) {
return MakeGoto(GotoExpressionKind.Goto, target, null, type);
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a goto. The value passed to the label upon jumping can be specified.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="value">The value that will be passed to the associated label upon jumping.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// and <paramref name="value"/> to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Goto(LabelTarget target, Expression value) {
return MakeGoto(GotoExpressionKind.Goto, target, value, typeof(void));
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a goto with the specified type.
/// The value passed to the label upon jumping can be specified.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="value">The value that will be passed to the associated label upon jumping.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to Goto,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
/// and <paramref name="value"/> to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression Goto(LabelTarget target, Expression value, Type type) {
return MakeGoto(GotoExpressionKind.Goto, target, value, type);
}
/// <summary>
/// Creates a <see cref="GotoExpression"/> representing a jump of the specified <see cref="GotoExpressionKind"/>.
/// The value passed to the label upon jumping can also be specified.
/// </summary>
/// <param name="kind">The <see cref="GotoExpressionKind"/> of the <see cref="GotoExpression"/>.</param>
/// <param name="target">The <see cref="LabelTarget"/> that the <see cref="GotoExpression"/> will jump to.</param>
/// <param name="value">The value that will be passed to the associated label upon jumping.</param>
/// <param name="type">An <see cref="System.Type"/> to set the <see cref="P:Expression.Type"/> property equal to.</param>
/// <returns>
/// A <see cref="GotoExpression"/> with <see cref="P:GotoExpression.Kind"/> equal to <paramref name="kind"/>,
/// the <see cref="P:GotoExpression.Target"/> property set to <paramref name="target"/>,
/// the <see cref="P:Expression.Type"/> property set to <paramref name="type"/>,
/// and <paramref name="value"/> to be passed to the target label upon jumping.
/// </returns>
public static GotoExpression MakeGoto(GotoExpressionKind kind, LabelTarget target, Expression value, Type type) {
ValidateGoto(target, ref value, "target", "value");
return new GotoExpression(kind, target, value, type);
}
private static void ValidateGoto(LabelTarget target, ref Expression value, string targetParameter, string valueParameter) {
ContractUtils.RequiresNotNull(target, targetParameter);
if (value == null) {
if (target.Type != typeof(void)) throw Error.LabelMustBeVoidOrHaveExpression();
} else {
ValidateGotoType(target.Type, ref value, valueParameter);
}
}
// Standard argument validation, taken from ValidateArgumentTypes
private static void ValidateGotoType(Type expectedType, ref Expression value, string paramName) {
RequiresCanRead(value, paramName);
if (expectedType != typeof(void)) {
if (!TypeUtils.AreReferenceAssignable(expectedType, value.Type)) {
// C# autoquotes return values, so we'll do that here
if (!TryQuote(expectedType, ref value)) {
throw Error.ExpressionTypeDoesNotMatchLabel(value.Type, expectedType);
}
}
}
}
}
}

View File

@@ -0,0 +1,77 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
#if CLR2
namespace Microsoft.Scripting.Ast {
using Microsoft.Scripting.Utils;
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Provides an internal interface for accessing the arguments that multiple tree
/// nodes (DynamicExpression, ElementInit, MethodCallExpression, InvocationExpression, NewExpression,
/// and InexExpression).
///
/// This enables two optimizations which reduce the size of the trees. The first is it enables
/// the nodes to hold onto an IList of T instead of a ReadOnlyCollection. This saves the cost
/// of allocating the ReadOnlyCollection for each node. The second is that it enables specialized
/// subclasses to be created which hold onto a specific number of arguments. For example Block2,
/// Block3, Block4. These nodes can therefore avoid allocating both a ReadOnlyCollection and an
/// array for storing their elements saving 32 bytes per node.
///
/// Meanwhile the nodes can continue to expose the original LINQ properties of ReadOnlyCollections. They
/// do this by re-using 1 field for storing both the array or an element that would normally be stored
/// in the array.
///
/// For the array case the collection is typed to IList of T instead of ReadOnlyCollection of T.
/// When the node is initially constructed it is an array. When the compiler accesses the members it
/// uses this interface. If a user accesses the members the array is promoted to a ReadOnlyCollection.
///
/// For the object case we store the 1st argument in a field typed to object and when the node is initially
/// constructed this holds directly onto the Expression. When the compiler accesses the members
/// it again uses this interface and the accessor for the 1st argument uses Expression.ReturnObject to
/// return the object which handles the Expression or ReadOnlyCollection case. When the user accesses
/// the ReadOnlyCollection then the object field is updated to hold directly onto the ReadOnlyCollection.
///
/// It is important that the Expressions consistently return the same ReadOnlyCollection otherwise the
/// re-writer will be broken and it would be a breaking change from LINQ v1. The problem is that currently
/// users can rely on object identity to tell if the node has changed. Storing the readonly collection in
/// an overloaded field enables us to both reduce memory usage as well as maintain compatibility and an
/// easy to use external API.
/// </summary>
internal interface IArgumentProvider {
Expression GetArgument(int index);
int ArgumentCount {
get;
}
}
static class ArgumentProviderOps {
internal static T[] Map<T>(this IArgumentProvider collection, Func<Expression, T> select) {
int count = collection.ArgumentCount;
T[] result = new T[count];
count = 0;
for (int i = 0; i < count; i++) {
result[i] = select(collection.GetArgument(i));
}
return result;
}
}
}

View File

@@ -0,0 +1,457 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Dynamic.Utils;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents indexing a property or array.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.IndexExpressionProxy))]
#endif
public sealed class IndexExpression : Expression, IArgumentProvider {
private readonly Expression _instance;
private readonly PropertyInfo _indexer;
private IList<Expression> _arguments;
internal IndexExpression(
Expression instance,
PropertyInfo indexer,
IList<Expression> arguments) {
if (indexer == null) {
Debug.Assert(instance != null && instance.Type.IsArray);
Debug.Assert(instance.Type.GetArrayRank() == arguments.Count);
}
_instance = instance;
_indexer = indexer;
_arguments = arguments;
}
/// <summary>
/// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
/// </summary>
/// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.Index; }
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public sealed override Type Type {
get {
if (_indexer != null) {
return _indexer.PropertyType;
}
return _instance.Type.GetElementType();
}
}
/// <summary>
/// An object to index.
/// </summary>
public Expression Object {
get { return _instance; }
}
/// <summary>
/// Gets the <see cref="PropertyInfo"/> for the property if the expression represents an indexed property, returns null otherwise.
/// </summary>
public PropertyInfo Indexer {
get { return _indexer; }
}
/// <summary>
/// Gets the arguments to be used to index the property or array.
/// </summary>
public ReadOnlyCollection<Expression> Arguments {
get { return ReturnReadOnly(ref _arguments); }
}
/// <summary>
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
/// </summary>
/// <param name="object">The <see cref="Object" /> property of the result.</param>
/// <param name="arguments">The <see cref="Arguments" /> property of the result.</param>
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public IndexExpression Update(Expression @object, IEnumerable<Expression> arguments) {
if (@object == Object && arguments == Arguments) {
return this;
}
return Expression.MakeIndex(@object, Indexer, arguments);
}
Expression IArgumentProvider.GetArgument(int index) {
return _arguments[index];
}
int IArgumentProvider.ArgumentCount {
get {
return _arguments.Count;
}
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitIndex(this);
}
internal Expression Rewrite(Expression instance, Expression[] arguments) {
Debug.Assert(instance != null);
Debug.Assert(arguments == null || arguments.Length == _arguments.Count);
return Expression.MakeIndex(instance, _indexer, arguments ?? _arguments);
}
}
public partial class Expression {
/// <summary>
/// Creates an <see cref="IndexExpression"/> that represents accessing an indexed property in an object.
/// </summary>
/// <param name="instance">The object to which the property belongs. Should be null if the property is static(shared).</param>
/// <param name="indexer">An <see cref="Expression"/> representing the property to index.</param>
/// <param name="arguments">An IEnumerable{Expression} contaning the arguments to be used to index the property.</param>
/// <returns>The created <see cref="IndexExpression"/>.</returns>
public static IndexExpression MakeIndex(Expression instance, PropertyInfo indexer, IEnumerable<Expression> arguments) {
if (indexer != null) {
return Property(instance, indexer, arguments);
} else {
return ArrayAccess(instance, arguments);
}
}
#region ArrayAccess
/// <summary>
/// Creates an <see cref="IndexExpression"></see> to access an array.
/// </summary>
/// <param name="array">An expression representing the array to index.</param>
/// <param name="indexes">An array containing expressions used to index the array.</param>
/// <remarks>The expression representing the array can be obtained by using the MakeMemberAccess method,
/// or through NewArrayBounds or NewArrayInit.</remarks>
/// <returns>The created <see cref="IndexExpression"/>.</returns>
public static IndexExpression ArrayAccess(Expression array, params Expression[] indexes) {
return ArrayAccess(array, (IEnumerable<Expression>)indexes);
}
/// <summary>
/// Creates an <see cref="IndexExpression"></see> to access an array.
/// </summary>
/// <param name="array">An expression representing the array to index.</param>
/// <param name="indexes">An <see cref="IEnumerable{Expression}"/> containing expressions used to index the array.</param>
/// <remarks>The expression representing the array can be obtained by using the MakeMemberAccess method,
/// or through NewArrayBounds or NewArrayInit.</remarks>
/// <returns>The created <see cref="IndexExpression"/>.</returns>
public static IndexExpression ArrayAccess(Expression array, IEnumerable<Expression> indexes) {
RequiresCanRead(array, "array");
Type arrayType = array.Type;
if (!arrayType.IsArray) {
throw Error.ArgumentMustBeArray();
}
var indexList = indexes.ToReadOnly();
if (arrayType.GetArrayRank() != indexList.Count) {
throw Error.IncorrectNumberOfIndexes();
}
foreach (Expression e in indexList) {
RequiresCanRead(e, "indexes");
if (e.Type != typeof(int)) {
throw Error.ArgumentMustBeArrayIndexType();
}
}
return new IndexExpression(array, null, indexList);
}
#endregion
#region Property
/// <summary>
/// Creates an <see cref="IndexExpression"/> representing the access to an indexed property.
/// </summary>
/// <param name="instance">The object to which the property belongs. If the property is static/shared, it must be null.</param>
/// <param name="propertyName">The name of the indexer.</param>
/// <param name="arguments">An array of <see cref="Expression"/> objects that are used to index the property.</param>
/// <returns>The created <see cref="IndexExpression"/>.</returns>
public static IndexExpression Property(Expression instance, string propertyName, params Expression[] arguments) {
RequiresCanRead(instance, "instance");
ContractUtils.RequiresNotNull(propertyName, "indexerName");
PropertyInfo pi = FindInstanceProperty(instance.Type, propertyName, arguments);
return Property(instance, pi, arguments);
}
#region methods for finding a PropertyInfo by its name
/// <summary>
/// The method finds the instance property with the specified name in a type. The property's type signature needs to be compatible with
/// the arguments if it is a indexer. If the arguments is null or empty, we get a normal property.
/// </summary>
private static PropertyInfo FindInstanceProperty(Type type, string propertyName, Expression[] arguments) {
// bind to public names first
BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy;
PropertyInfo pi = FindProperty(type, propertyName, arguments, flags);
if (pi == null) {
flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy;
pi = FindProperty(type, propertyName, arguments, flags);
}
if (pi == null) {
if (arguments == null || arguments.Length == 0) {
throw Error.InstancePropertyWithoutParameterNotDefinedForType(propertyName, type);
} else {
throw Error.InstancePropertyWithSpecifiedParametersNotDefinedForType(propertyName, GetArgTypesString(arguments), type);
}
}
return pi;
}
private static string GetArgTypesString(Expression[] arguments) {
StringBuilder argTypesStr = new StringBuilder();
var isFirst = true;
argTypesStr.Append("(");
foreach (var t in arguments.Select(arg => arg.Type)) {
if (!isFirst) {
argTypesStr.Append(", ");
}
argTypesStr.Append(t.Name);
isFirst = false;
}
argTypesStr.Append(")");
return argTypesStr.ToString();
}
private static PropertyInfo FindProperty(Type type, string propertyName, Expression[] arguments, BindingFlags flags) {
MemberInfo[] members = type.FindMembers(MemberTypes.Property, flags, Type.FilterNameIgnoreCase, propertyName);
if (members == null || members.Length == 0)
return null;
PropertyInfo pi;
var propertyInfos = members.Map(t => (PropertyInfo)t);
int count = FindBestProperty(propertyInfos, arguments, out pi);
if (count == 0)
return null;
if (count > 1)
throw Error.PropertyWithMoreThanOneMatch(propertyName, type);
return pi;
}
private static int FindBestProperty(IEnumerable<PropertyInfo> properties, Expression[] args, out PropertyInfo property) {
int count = 0;
property = null;
foreach (PropertyInfo pi in properties) {
if (pi != null && IsCompatible(pi, args)) {
if (property == null) {
property = pi;
count = 1;
}
else {
count++;
}
}
}
return count;
}
private static bool IsCompatible(PropertyInfo pi, Expression[] args) {
MethodInfo mi;
mi = pi.GetGetMethod(true);
ParameterInfo[] parms;
if (mi != null) {
parms = mi.GetParametersCached();
} else {
mi = pi.GetSetMethod(true);
//The setter has an additional parameter for the value to set,
//need to remove the last type to match the arguments.
parms = mi.GetParametersCached().RemoveLast();
}
if (mi == null) {
return false;
}
if (args == null) {
return parms.Length == 0;
}
if (parms.Length != args.Length)
return false;
for (int i = 0; i < args.Length; i++) {
if (args[i] == null) return false;
if (!TypeUtils.AreReferenceAssignable(parms[i].ParameterType, args[i].Type)) {
return false;
}
}
return true;
}
#endregion
/// <summary>
/// Creates an <see cref="IndexExpression"/> representing the access to an indexed property.
/// </summary>
/// <param name="instance">The object to which the property belongs. If the property is static/shared, it must be null.</param>
/// <param name="indexer">The <see cref="PropertyInfo"/> that represents the property to index.</param>
/// <param name="arguments">An array of <see cref="Expression"/> objects that are used to index the property.</param>
/// <returns>The created <see cref="IndexExpression"/>.</returns>
public static IndexExpression Property(Expression instance, PropertyInfo indexer, params Expression[] arguments) {
return Property(instance, indexer, (IEnumerable<Expression>)arguments);
}
/// <summary>
/// Creates an <see cref="IndexExpression"/> representing the access to an indexed property.
/// </summary>
/// <param name="instance">The object to which the property belongs. If the property is static/shared, it must be null.</param>
/// <param name="indexer">The <see cref="PropertyInfo"/> that represents the property to index.</param>
/// <param name="arguments">An <see cref="IEnumerable{T}"/> of <see cref="Expression"/> objects that are used to index the property.</param>
/// <returns>The created <see cref="IndexExpression"/>.</returns>
public static IndexExpression Property(Expression instance, PropertyInfo indexer, IEnumerable<Expression> arguments) {
var argList = arguments.ToReadOnly();
ValidateIndexedProperty(instance, indexer, ref argList);
return new IndexExpression(instance, indexer, argList);
}
// CTS places no restrictions on properties (see ECMA-335 8.11.3),
// so we validate that the property conforms to CLS rules here.
//
// Does reflection help us out at all? Expression.Property skips all of
// these checks, so either it needs more checks or we need less here.
private static void ValidateIndexedProperty(Expression instance, PropertyInfo property, ref ReadOnlyCollection<Expression> argList) {
// If both getter and setter specified, all their parameter types
// should match, with exception of the last setter parameter which
// should match the type returned by the get method.
// Accessor parameters cannot be ByRef.
ContractUtils.RequiresNotNull(property, "property");
if (property.PropertyType.IsByRef) throw Error.PropertyCannotHaveRefType();
if (property.PropertyType == typeof(void)) throw Error.PropertyTypeCannotBeVoid();
ParameterInfo[] getParameters = null;
MethodInfo getter = property.GetGetMethod(true);
if (getter != null) {
getParameters = getter.GetParametersCached();
ValidateAccessor(instance, getter, getParameters, ref argList);
}
MethodInfo setter = property.GetSetMethod(true);
if (setter != null) {
ParameterInfo[] setParameters = setter.GetParametersCached();
if (setParameters.Length == 0) throw Error.SetterHasNoParams();
// valueType is the type of the value passed to the setter (last parameter)
Type valueType = setParameters[setParameters.Length - 1].ParameterType;
if (valueType.IsByRef) throw Error.PropertyCannotHaveRefType();
if (setter.ReturnType != typeof(void)) throw Error.SetterMustBeVoid();
if (property.PropertyType != valueType) throw Error.PropertyTyepMustMatchSetter();
if (getter != null) {
if (getter.IsStatic ^ setter.IsStatic) throw Error.BothAccessorsMustBeStatic();
if (getParameters.Length != setParameters.Length - 1) throw Error.IndexesOfSetGetMustMatch();
for (int i = 0; i < getParameters.Length; i++) {
if (getParameters[i].ParameterType != setParameters[i].ParameterType) throw Error.IndexesOfSetGetMustMatch();
}
} else {
ValidateAccessor(instance, setter, setParameters.RemoveLast(), ref argList);
}
}
if (getter == null && setter == null) {
throw Error.PropertyDoesNotHaveAccessor(property);
}
}
private static void ValidateAccessor(Expression instance, MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection<Expression> arguments) {
ContractUtils.RequiresNotNull(arguments, "arguments");
ValidateMethodInfo(method);
if ((method.CallingConvention & CallingConventions.VarArgs) != 0) throw Error.AccessorsCannotHaveVarArgs();
if (method.IsStatic) {
if (instance != null) throw Error.OnlyStaticMethodsHaveNullInstance();
} else {
if (instance == null) throw Error.OnlyStaticMethodsHaveNullInstance();
RequiresCanRead(instance, "instance");
ValidateCallInstanceType(instance.Type, method);
}
ValidateAccessorArgumentTypes(method, indexes, ref arguments);
}
private static void ValidateAccessorArgumentTypes(MethodInfo method, ParameterInfo[] indexes, ref ReadOnlyCollection<Expression> arguments) {
if (indexes.Length > 0) {
if (indexes.Length != arguments.Count) {
throw Error.IncorrectNumberOfMethodCallArguments(method);
}
Expression[] newArgs = null;
for (int i = 0, n = indexes.Length; i < n; i++) {
Expression arg = arguments[i];
ParameterInfo pi = indexes[i];
RequiresCanRead(arg, "arguments");
Type pType = pi.ParameterType;
if (pType.IsByRef) throw Error.AccessorsCannotHaveByRefArgs();
TypeUtils.ValidateType(pType);
if (!TypeUtils.AreReferenceAssignable(pType, arg.Type)) {
if (!TryQuote(pType, ref arg)) {
throw Error.ExpressionTypeDoesNotMatchMethodParameter(arg.Type, pType, method);
}
}
if (newArgs == null && arg != arguments[i]) {
newArgs = new Expression[arguments.Count];
for (int j = 0; j < i; j++) {
newArgs[j] = arguments[j];
}
}
if (newArgs != null) {
newArgs[i] = arg;
}
}
if (newArgs != null) {
arguments = new TrueReadOnlyCollection<Expression>(newArgs);
}
} else if (arguments.Count > 0) {
throw Error.IncorrectNumberOfMethodCallArguments(method);
}
}
#endregion
}
}

View File

@@ -0,0 +1,205 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Dynamic.Utils;
using System.Reflection;
#if SILVERLIGHT
using System.Core;
#endif
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents an expression that applies a delegate or lambda expression to a list of argument expressions.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.InvocationExpressionProxy))]
#endif
public sealed class InvocationExpression : Expression, IArgumentProvider {
private IList<Expression> _arguments;
private readonly Expression _lambda;
private readonly Type _returnType;
internal InvocationExpression(Expression lambda, IList<Expression> arguments, Type returnType) {
_lambda = lambda;
_arguments = arguments;
_returnType = returnType;
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents.
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public sealed override Type Type {
get { return _returnType; }
}
/// <summary>
/// Returns the node type of this Expression. Extension nodes should return
/// ExpressionType.Extension when overriding this method.
/// </summary>
/// <returns>The <see cref="ExpressionType"/> of the expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.Invoke; }
}
/// <summary>
/// Gets the delegate or lambda expression to be applied.
/// </summary>
public Expression Expression {
get { return _lambda; }
}
/// <summary>
/// Gets the arguments that the delegate or lambda expression is applied to.
/// </summary>
public ReadOnlyCollection<Expression> Arguments {
get { return ReturnReadOnly(ref _arguments); }
}
/// <summary>
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
/// </summary>
/// <param name="expression">The <see cref="Expression" /> property of the result.</param>
/// <param name="arguments">The <see cref="Arguments" /> property of the result.</param>
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public InvocationExpression Update(Expression expression, IEnumerable<Expression> arguments) {
if (expression == Expression && arguments == Arguments) {
return this;
}
return Expression.Invoke(expression, arguments);
}
Expression IArgumentProvider.GetArgument(int index) {
return _arguments[index];
}
int IArgumentProvider.ArgumentCount {
get {
return _arguments.Count;
}
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitInvocation(this);
}
internal InvocationExpression Rewrite(Expression lambda, Expression[] arguments) {
Debug.Assert(lambda != null);
Debug.Assert(arguments == null || arguments.Length == _arguments.Count);
return Expression.Invoke(lambda, arguments ?? _arguments);
}
internal LambdaExpression LambdaOperand {
get {
return (_lambda.NodeType == ExpressionType.Quote)
? (LambdaExpression)((UnaryExpression)_lambda).Operand
: (_lambda as LambdaExpression);
}
}
}
public partial class Expression {
///<summary>
///Creates an <see cref="T:System.Linq.Expressions.InvocationExpression" /> that
///applies a delegate or lambda expression to a list of argument expressions.
///</summary>
///<returns>
///An <see cref="T:System.Linq.Expressions.InvocationExpression" /> that
///applies the specified delegate or lambda expression to the provided arguments.
///</returns>
///<param name="expression">
///An <see cref="T:System.Linq.Expressions.Expression" /> that represents the delegate
///or lambda expression to be applied.
///</param>
///<param name="arguments">
///An array of <see cref="T:System.Linq.Expressions.Expression" /> objects
///that represent the arguments that the delegate or lambda expression is applied to.
///</param>
///<exception cref="T:System.ArgumentNullException">
///<paramref name="expression" /> is null.</exception>
///<exception cref="T:System.ArgumentException">
///<paramref name="expression" />.Type does not represent a delegate type or an <see cref="T:System.Linq.Expressions.Expression`1" />.-or-The <see cref="P:System.Linq.Expressions.Expression.Type" /> property of an element of <paramref name="arguments" /> is not assignable to the type of the corresponding parameter of the delegate represented by <paramref name="expression" />.</exception>
///<exception cref="T:System.InvalidOperationException">
///<paramref name="arguments" /> does not contain the same number of elements as the list of parameters for the delegate represented by <paramref name="expression" />.</exception>
public static InvocationExpression Invoke(Expression expression, params Expression[] arguments) {
return Invoke(expression, (IEnumerable<Expression>)arguments);
}
///<summary>
///Creates an <see cref="T:System.Linq.Expressions.InvocationExpression" /> that
///applies a delegate or lambda expression to a list of argument expressions.
///</summary>
///<returns>
///An <see cref="T:System.Linq.Expressions.InvocationExpression" /> that
///applies the specified delegate or lambda expression to the provided arguments.
///</returns>
///<param name="expression">
///An <see cref="T:System.Linq.Expressions.Expression" /> that represents the delegate
///or lambda expression to be applied.
///</param>
///<param name="arguments">
///An <see cref="T:System.Collections.Generic.IEnumerable`1" /> of <see cref="T:System.Linq.Expressions.Expression" /> objects
///that represent the arguments that the delegate or lambda expression is applied to.
///</param>
///<exception cref="T:System.ArgumentNullException">
///<paramref name="expression" /> is null.</exception>
///<exception cref="T:System.ArgumentException">
///<paramref name="expression" />.Type does not represent a delegate type or an <see cref="T:System.Linq.Expressions.Expression`1" />.-or-The <see cref="P:System.Linq.Expressions.Expression.Type" /> property of an element of <paramref name="arguments" /> is not assignable to the type of the corresponding parameter of the delegate represented by <paramref name="expression" />.</exception>
///<exception cref="T:System.InvalidOperationException">
///<paramref name="arguments" /> does not contain the same number of elements as the list of parameters for the delegate represented by <paramref name="expression" />.</exception>
public static InvocationExpression Invoke(Expression expression, IEnumerable<Expression> arguments) {
RequiresCanRead(expression, "expression");
var args = arguments.ToReadOnly();
var mi = GetInvokeMethod(expression);
ValidateArgumentTypes(mi, ExpressionType.Invoke, ref args);
return new InvocationExpression(expression, args, mi.ReturnType);
}
/// <summary>
/// Gets the delegate's Invoke method; used by InvocationExpression.
/// </summary>
/// <param name="expression">The expression to be invoked.</param>
internal static MethodInfo GetInvokeMethod(Expression expression) {
Type delegateType = expression.Type;
if (!expression.Type.IsSubclassOf(typeof(MulticastDelegate))) {
Type exprType = TypeUtils.FindGenericType(typeof(Expression<>), expression.Type);
if (exprType == null) {
throw Error.ExpressionTypeNotInvocable(expression.Type);
}
delegateType = exprType.GetGenericArguments()[0];
}
return delegateType.GetMethod("Invoke");
}
}
}

View File

@@ -0,0 +1,117 @@
/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Diagnostics;
#if CLR2
namespace Microsoft.Scripting.Ast {
#else
namespace System.Linq.Expressions {
#endif
/// <summary>
/// Represents a label, which can be placed in any <see cref="Expression"/> context. If
/// it is jumped to, it will get the value provided by the corresponding
/// <see cref="GotoExpression"/>. Otherwise, it gets the value in <see cref="LabelExpression.DefaultValue"/>. If the
/// <see cref="Type"/> equals System.Void, no value should be provided.
/// </summary>
#if !SILVERLIGHT
[DebuggerTypeProxy(typeof(Expression.LabelExpressionProxy))]
#endif
public sealed class LabelExpression : Expression {
private readonly Expression _defaultValue;
private readonly LabelTarget _target;
internal LabelExpression(LabelTarget label, Expression defaultValue) {
_target = label;
_defaultValue = defaultValue;
}
/// <summary>
/// Gets the static type of the expression that this <see cref="Expression" /> represents. (Inherited from <see cref="Expression"/>.)
/// </summary>
/// <returns>The <see cref="Type"/> that represents the static type of the expression.</returns>
public sealed override Type Type {
get { return _target.Type; }
}
/// <summary>
/// Returns the node type of this <see cref="Expression" />. (Inherited from <see cref="Expression" />.)
/// </summary>
/// <returns>The <see cref="ExpressionType"/> that represents this expression.</returns>
public sealed override ExpressionType NodeType {
get { return ExpressionType.Label; }
}
/// <summary>
/// The <see cref="LabelTarget"/> which this label is associated with.
/// </summary>
public LabelTarget Target {
get { return _target; }
}
/// <summary>
/// The value of the <see cref="LabelExpression"/> when the label is reached through
/// normal control flow (e.g. is not jumped to).
/// </summary>
public Expression DefaultValue {
get { return _defaultValue; }
}
/// <summary>
/// Dispatches to the specific visit method for this node type.
/// </summary>
protected internal override Expression Accept(ExpressionVisitor visitor) {
return visitor.VisitLabel(this);
}
/// <summary>
/// Creates a new expression that is like this one, but using the
/// supplied children. If all of the children are the same, it will
/// return this expression.
/// </summary>
/// <param name="target">The <see cref="Target" /> property of the result.</param>
/// <param name="defaultValue">The <see cref="DefaultValue" /> property of the result.</param>
/// <returns>This expression if no children changed, or an expression with the updated children.</returns>
public LabelExpression Update(LabelTarget target, Expression defaultValue) {
if (target == Target && defaultValue == DefaultValue) {
return this;
}
return Expression.Label(target, defaultValue);
}
}
public partial class Expression {
/// <summary>
/// Creates a <see cref="LabelExpression"/> representing a label with no default value.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> which this <see cref="LabelExpression"/> will be associated with.</param>
/// <returns>A <see cref="LabelExpression"/> with no default value.</returns>
public static LabelExpression Label(LabelTarget target) {
return Label(target, null);
}
/// <summary>
/// Creates a <see cref="LabelExpression"/> representing a label with the given default value.
/// </summary>
/// <param name="target">The <see cref="LabelTarget"/> which this <see cref="LabelExpression"/> will be associated with.</param>
/// <param name="defaultValue">The value of this <see cref="LabelExpression"/> when the label is reached through normal control flow.</param>
/// <returns>A <see cref="LabelExpression"/> with the given default value.</returns>
public static LabelExpression Label(LabelTarget target, Expression defaultValue) {
ValidateGoto(target, ref defaultValue, "label", "defaultValue");
return new LabelExpression(target, defaultValue);
}
}
}

Some files were not shown because too many files have changed in this diff Show More