|
/* ****************************************************************************
*
* 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.Diagnostics;
using System.Dynamic.Utils;
#if CLR2
namespace Microsoft.Scripting.Ast.Compiler {
#else
namespace System.Linq.Expressions.Compiler {
#endif
partial class LambdaCompiler {
private readonly StackGuard _guard = new StackGuard();
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
private void EmitExpression(Expression node, CompilationFlags flags) {
// When compling deep trees, we run the risk of triggering a terminating StackOverflowException,
// so we use the StackGuard utility here to probe for sufficient stack and continue the work on
// another thread when we run out of stack space.
if (!_guard.TryEnterOnCurrentStack())
{
_guard.RunOnEmptyStack((LambdaCompiler @this, Expression n, CompilationFlags f) => @this.EmitExpression(n, f), this, node, flags);
return;
}
Debug.Assert(node != null);
bool emitStart = (flags & CompilationFlags.EmitExpressionStartMask) == CompilationFlags.EmitExpressionStart;
CompilationFlags startEmitted = emitStart ? EmitExpressionStart(node) : CompilationFlags.EmitNoExpressionStart;
// only pass tail call flags to emit the expression
flags = flags & CompilationFlags.EmitAsTailCallMask;
switch (node.NodeType) {
#region Generated Expression Compiler
// *** BEGIN GENERATED CODE ***
// generated by function: gen_compiler from: generate_tree.py
case ExpressionType.Add:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.AddChecked:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.And:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.AndAlso:
EmitAndAlsoBinaryExpression(node, flags);
break;
case ExpressionType.ArrayLength:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.ArrayIndex:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Call:
EmitMethodCallExpression(node, flags);
break;
case ExpressionType.Coalesce:
EmitCoalesceBinaryExpression(node);
break;
case ExpressionType.Conditional:
EmitConditionalExpression(node, flags);
break;
case ExpressionType.Constant:
EmitConstantExpression(node);
break;
case ExpressionType.Convert:
EmitConvertUnaryExpression(node, flags);
break;
case ExpressionType.ConvertChecked:
EmitConvertUnaryExpression(node, flags);
break;
case ExpressionType.Divide:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Equal:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.ExclusiveOr:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.GreaterThan:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.GreaterThanOrEqual:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Invoke:
EmitInvocationExpression(node, flags);
break;
case ExpressionType.Lambda:
EmitLambdaExpression(node);
break;
case ExpressionType.LeftShift:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.LessThan:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.LessThanOrEqual:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.ListInit:
EmitListInitExpression(node);
break;
case ExpressionType.MemberAccess:
EmitMemberExpression(node);
break;
case ExpressionType.MemberInit:
EmitMemberInitExpression(node);
break;
case ExpressionType.Modulo:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Multiply:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.MultiplyChecked:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Negate:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.UnaryPlus:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.NegateChecked:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.New:
EmitNewExpression(node);
break;
case ExpressionType.NewArrayInit:
EmitNewArrayExpression(node);
break;
case ExpressionType.NewArrayBounds:
EmitNewArrayExpression(node);
break;
case ExpressionType.Not:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.NotEqual:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Or:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.OrElse:
EmitOrElseBinaryExpression(node, flags);
break;
case ExpressionType.Parameter:
EmitParameterExpression(node);
break;
case ExpressionType.Power:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Quote:
EmitQuoteUnaryExpression(node);
break;
case ExpressionType.RightShift:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.Subtract:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.SubtractChecked:
EmitBinaryExpression(node, flags);
break;
case ExpressionType.TypeAs:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.TypeIs:
EmitTypeBinaryExpression(node);
break;
case ExpressionType.Assign:
EmitAssignBinaryExpression(node);
break;
case ExpressionType.Block:
EmitBlockExpression(node, flags);
break;
case ExpressionType.DebugInfo:
EmitDebugInfoExpression(node);
break;
case ExpressionType.Decrement:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.Dynamic:
EmitDynamicExpression(node);
break;
case ExpressionType.Default:
EmitDefaultExpression(node);
break;
case ExpressionType.Extension:
EmitExtensionExpression(node);
break;
case ExpressionType.Goto:
EmitGotoExpression(node, flags);
break;
case ExpressionType.Increment:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.Index:
EmitIndexExpression(node);
break;
case ExpressionType.Label:
EmitLabelExpression(node, flags);
break;
case ExpressionType.RuntimeVariables:
EmitRuntimeVariablesExpression(node);
break;
case ExpressionType.Loop:
EmitLoopExpression(node);
break;
case ExpressionType.Switch:
EmitSwitchExpression(node, flags);
break;
case ExpressionType.Throw:
EmitThrowUnaryExpression(node);
break;
case ExpressionType.Try:
EmitTryExpression(node);
break;
case ExpressionType.Unbox:
EmitUnboxUnaryExpression(node);
break;
case ExpressionType.TypeEqual:
EmitTypeBinaryExpression(node);
break;
case ExpressionType.OnesComplement:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.IsTrue:
EmitUnaryExpression(node, flags);
break;
case ExpressionType.IsFalse:
EmitUnaryExpression(node, flags);
break;
// *** END GENERATED CODE ***
#endregion
default:
throw ContractUtils.Unreachable;
}
if (emitStart) {
EmitExpressionEnd(startEmitted);
}
}
private static bool IsChecked(ExpressionType op) {
switch (op) {
#region Generated Checked Operations
// *** BEGIN GENERATED CODE ***
// generated by function: gen_checked_ops from: generate_tree.py
case ExpressionType.AddChecked:
case ExpressionType.ConvertChecked:
case ExpressionType.MultiplyChecked:
case ExpressionType.NegateChecked:
case ExpressionType.SubtractChecked:
case ExpressionType.AddAssignChecked:
case ExpressionType.MultiplyAssignChecked:
case ExpressionType.SubtractAssignChecked:
// *** END GENERATED CODE ***
#endregion
return true;
}
return false;
}
}
}
|